Skip to content

Document SyncBackend applyOps as read-after-write visible #112

@marcus-pousette

Description

@marcus-pousette

Current baseline

The protocol already behaves as if SyncBackend.applyOps() is a read-after-write boundary.

In particular:

  • syncOnce() waits for responder-side applyOps() before sending the final done ack
  • protocol tests already assert that uploaded ops are applied before syncOnce() resolves

However, the SyncBackend interface itself does not currently say whether writes must be visible through reads before applyOps() resolves.

That mismatch has led to confusion in engine/worker-backed environments and to helper wrappers that effectively add a flush/queue layer outside the core interface.

Problem

SyncBackend.applyOps() does not currently document whether the effects of the write must already be observable through:

  • listOpRefs()
  • getOpsByOpRefs()
  • maxLamport()

before the returned promise resolves.

The ambiguity is the bug. The protocol and tests already lean on one answer, but the type-level contract does not state it clearly.

What this issue tracks now

Document and align the contract as:

  • applyOps() MUST NOT resolve until newly applied ops are visible to subsequent backend reads for the same doc
  • that visibility includes at least listOpRefs(), getOpsByOpRefs(), and maxLamport()
  • callers should not need a separate public flush()/settle() step just to observe their own completed write

Follow-up work

  • Update SyncBackend docs/comments to state this explicitly.
  • Align conformance comments/tests that still imply async backends may require post-applyOps polling.
  • Keep helper wrappers like FlushableSyncBackend as test/adapter utilities rather than the normative interface contract.

Context

This came up while debugging async/worker-backed backend behavior around PR #110. The right fix is to make the contract explicit and align the remaining comments/tests with the behavior the protocol already expects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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