Skip to content

feat(sdk): add a non-terminal Producer flush/barrier #666

Description

@shikhar

Motivation

Producer currently emits a partial batch when a size/count threshold or linger deadline is reached, and close() forces the final partial batch before terminating. There is no way to force the current partial batch at an application-defined durability boundary while keeping the Producer open.

This matters for applications that submit records speculatively and then encounter a causal boundary that must wait for the complete prefix to become durable. A fault-tolerant WASM runtime using S2 as its journal is one concrete example:

  1. Submit granular observation records without blocking execution.
  2. Reach an externally visible output boundary.
  3. Immediately seal the partial batch and wait for the submitted prefix to become durable.
  4. Continue using the same Producer and append session.

The available choices all have an avoidable cost:

  • use the default 5 ms linger and add up to 5 ms at each latency-sensitive boundary;
  • use zero linger and risk producing many small batches;
  • call close() and recreate Producer/session at every boundary; or
  • reimplement Producer's batching over AppendSession to gain an explicit flush operation.

The last option is what the downstream runtime currently does. Producer otherwise already has the needed correctness primitives: initial match_seq_num with automatic progression, a fixed fencing token, ordered append-session submission, and per-record tickets with exact sequence positions.

Requested semantics

Please add a non-terminal flush or barrier operation. The exact API shape is open, but the required behavior is:

  • force any partial batch containing records ordered before the barrier into the underlying append session immediately, without waiting for linger;
  • allow the caller to wait until every record ordered before the barrier is durably acknowledged;
  • do not wait for records ordered after the barrier;
  • leave Producer open and usable for subsequent submissions;
  • preserve existing per-record ticket results and ordering;
  • complete immediately when there is no preceding work; and
  • propagate a terminal submission/acknowledgement error consistently to the barrier and affected record tickets.

For example, either a directly durable flush:

let a = producer.submit(record_a).await?;
let b = producer.submit(record_b).await?;

producer.flush().await?; // a and b are durable; Producer remains open

or a split submission/durability ticket:

let barrier = producer.flush().await?; // partial batch is submitted now
barrier.await?;                        // preceding prefix is durable

Concurrent submission semantics should be explicit. One reasonable definition is that the barrier covers commands ordered before it in Producer's command stream; records ordered afterward belong to a later batch/barrier.

Acceptance coverage

  • A Producer configured with a very long linger flushes a one-record partial batch promptly without closing.
  • Multiple records before the barrier retain order and receive their exact indexed acknowledgements.
  • Records submitted after the barrier are not included in its durability wait.
  • New records can be submitted and flushed after the first barrier.
  • Empty barriers complete without creating an append batch.
  • Condition failures, ambiguous session termination, and Producer shutdown cannot report the barrier successful while a covered record ticket fails.

This is the reusable, non-terminal counterpart to the immediate final flush added for Producer::close() in #233. It requires no S2 protocol change; it is a Producer batching/lifecycle primitive.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions