Skip to content

fix: ignore already known entries in polling responses - #959

Open
lstamellos wants to merge 4 commits into
Automattic:developfrom
lstamellos:fix/polling-duplicate-new-entries
Open

fix: ignore already known entries in polling responses#959
lstamellos wants to merge 4 commits into
Automattic:developfrom
lstamellos:fix/polling-duplicate-new-entries

Conversation

@lstamellos

@lstamellos lstamellos commented Aug 10, 2026

Copy link
Copy Markdown

Summary

Prevent cached polling buckets from re-queuing entries the client already knows about.

The polling start timestamp is intentionally rounded to the refresh-interval bucket for cache efficiency. This can make the requested timestamp range overlap the newest entry already known to the client, and the backend can legitimately return that entry again as type: "new".

When new entries are not auto-rendered, that duplicate can enter the pending polling state and produce a false 1 new entry available nag.

Root cause

The start-timestamp bucketing introduced in 99da1326 assumes duplicate polling entries are harmless because entry updates are deduplicated by ID.

That is true when applying entries to the rendered API state, but the pending polling queue is separate. A type: "new" entry already known to the client can therefore be queued again.

For example, with a 10-second refresh interval:

  • newest known entry timestamp: 1786367775
  • polling start bucket: 1786367770
  • backend timestamp filtering is inclusive
  • the already-known newest entry can be returned again as type: "new"
  • if the reader is scrolled away from the latest entry, it can produce a false update nag

There is also a pagination variant of the same issue: on pages after page 1, api.entries contains only the currently rendered page, while the polling baseline still tracks the global newest entry. Deduplicating only against rendered IDs is therefore not sufficient.

Fix

Filter polling response entries before dispatching POLLING_SUCCESS.

For type: "new" entries, the filter:

  • removes entries whose ID is already present in the rendered API state
  • removes entries older than the current polling baseline
  • removes the already-known baseline entry when the timestamp and ID identify it
  • preserves a genuinely new entry with a different ID, including one created in the same second

update and delete entries are always preserved. Their JSON id identifies the entry being replaced rather than the newly created backing comment, so applying the same ID-based baseline rule to those entry types would be unsafe.

The existing timestamp bucketing and cache behavior remain unchanged.

Tests

Adds unit coverage for:

  • duplicate rendered new entries
  • duplicate entries matching the polling baseline
  • entries older than the polling baseline
  • genuinely new entries
  • genuinely new entries created in the same second
  • pagination-style cases where the global newest entry is not in the rendered page
  • update and delete entries for existing IDs
  • empty rendered state

Validation

The issue was reproduced consistently on a production WordPress liveblog using the current polling implementation.

Before the fix, the first polling cycle could show 1 new entry available without any new publication.

After applying equivalent deduplication logic:

  • no false update nag is shown
  • genuine new entries auto-render normally when the latest entry is visible
  • genuine new entries correctly produce the update nag when the reader is scrolled away
  • loading the pending entry clears the nag without it being re-queued on the following poll

@lstamellos
lstamellos requested a review from a team as a code owner August 10, 2026 20:46
@lstamellos lstamellos changed the title Fix/polling duplicate new entries fix: ignore already known entries in polling responses Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant