Skip to content

ShapeStream replay suppression can discard data messages #4722

Description

@joshdchang

Versions

  • Client: TypeScript, 1.5.23 and 1.5.24; also reproducible on current main at 4051e0fd
  • Electric: not server-version-specific; reproduced with a deterministic ShapeStream fetch mock using valid Shape responses

Bug description

When electric_up_to_date_tracker contains a recent cursor for a shape, a fresh ShapeStream enters replay mode. If the cached response contains change messages followed by an up-to-date control message with that same cursor, ReplayingState requests suppression and ShapeStream.#onMessages returns before publishing anything from the batch.

The next live response can advance the cursor and publish an up-to-date control message without repeating the snapshot rows. Consumers therefore observe an up-to-date stream whose local projection is missing rows that were present in the suppressed cached batch.

This is deterministic with the following response sequence:

  1. Seed the tracker with cursor-1 for the shape.
  2. Return a cached batch containing [insert(row), up-to-date] and electric-cursor: cursor-1.
  3. Return a live batch containing only [up-to-date] and electric-cursor: cursor-2.
  4. The subscriber receives the second up-to-date message but never receives row.

The negative control, using the exact same first response without a tracker entry, delivers both the row and up-to-date message normally.

Expected behavior

Replay handling should suppress only the duplicate cached up-to-date control message. Every data message in that batch must still be delivered to stream subscribers, and the fresh up-to-date message should be delivered once the cursor advances.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions