The run lifecycle
Every sink implements:Openprepares one run.- A schema-aware sink receives
EnsureSchemaonce per selected resource. Applyhandles each batch under its resource’s write policy.Commitestablishes the sink’s success boundary.Abortcleans up a run that cannot be safely continued.
Abort. That can happen only when every resource can resume and replay will
not duplicate append-only data or expose uncommitted work. A sink should still
make Abort safe because it also runs after setup and commit errors.
Applying a batch
arrowbatch.Batch contains one resource and part, an Arrow record batch, an
operation vector, sequence metadata, and an optional checkpoint delta. A simple
append sink can look like this:
writeRows computes and verifies encodedCRC over the
serialized bytes immediately before transport. A sink that does not advertise
encoded integrity omits EncodedCRC.
Borrowing and ownership
Apply borrows the batch for the duration of the call. Its Arrow rows and
operation vector are valid until Apply returns. If a sink buffers a batch for
Commit, it must call Retain before returning and eventually call Release.
This rule matters for sinks such as Iceberg that hold batches until commit. It
is also why Batch is passed by pointer.
Integrity evidence
Two checks describe different boundaries:WriteCRCis required. Recomputebatch.IntegrityCRC()at the sink’s final in-memory boundary. The pipeline compares it with the checksum calculated before callingApply.EncodedCRCis optional unlessSinkCapabilities.EncodedIntegrityis true. It covers the exact serialized bytes handed to the transport.
Honor the write policy
ApplyOptions.Policy tells the sink how to write this resource:
appendretains every accepted row.replaceproduces a fresh resource snapshot.upsertkeeps a current row per primary key.mergeapplies ordered CDC inserts, updates, and deletes.deleteremoves rows by key for the internal incremental-delete path.
ValidateBatch before writing. Policy.Keys contains resolved primary-key
columns when the mode needs them, and Policy.Version explains how an upsert
resolves competing values.
CDC can bind either append or merge. Append is change history; merge is current
state.
Batching and concurrency
The engine flushes a builder when it reaches the run’s row or byte limit. If neither is configured, it uses the sink’s preferred row count and then the engine default. The periodic flush request is observed at the next completed row; a source with an idle stream callsFlush itself.
When snapshot parallelism is greater than one, Apply can run concurrently.
Protect shared buffers and accounting, and size connection pools in Open.
Ordered CDC, incremental, and checkpointed runs are forced to one writer.
Capabilities and registration
SinkSpec.Capabilities.WritePolicies advertises the modes the sink really
implements. Capabilities can also declare whether writes survive after each
Apply or only after Commit; that durability boundary determines when a
checkpoint may advance.
Register the sink through a fresh-instance factory:
connectors/stdout
package is the smallest complete sink. It demonstrates Arrow-to-NDJSON
serialization, both integrity values, concurrency protection, and the complete
run lifecycle.