Repository navigation
docs: pattern for transactional downstream loads using the sink ID header - #40120
val-materialize wants to merge 3 commits into
Conversation
Adds an Export data > Patterns section and a page describing how to gate downstream reads of a Kafka sink on the sink's progress frontier, joining data and progress records with the `materialize-sink-id` header. Part of SS-504. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@val-materialize lmk when this is ready for review! |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Open question for reviewers: the The Considerations section says downstream consumers must read with What I'm unsure about:
If someone can confirm how the Snowflake connector handles isolation level, I'll either add the exact setting or simplify the bullet. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| parent: 'sink-patterns' | ||
| --- | ||
|
|
||
| When you load a [Kafka sink](/sql/create-sink/kafka/) into another data store, |
There was a problem hiding this comment.
Rephrase as: When you load messages from Kafka, into another data store
| `org.apache.kafka.connect.storage.StringConverter`, so configure the progress | ||
| topic that way, and parse its value as JSON. | ||
|
|
||
| ```sql |
There was a problem hiding this comment.
hmm I didn't understand this part! Is this the query I run in in Snowflake? I think I'd be more verbose with this tutorial; let's explain all the steps from:
- Creating a sink in Materialize to Kafka
- Creating a transactional update from Kafka => Snowflake (or other destination)
Adds a new Export data > Patterns section with one page, Transactional downstream updates using Kafka. The page shows how a consumer loading a Kafka sink into another store (Snowflake example) can expose only timestamps the sink has fully committed, by gating on the sink's progress frontier and joining data and progress records via the
materialize-sink-idheader.Where each fact comes from
materialize-timestamp(value is the timestamp as a decimal string)src/storage/src/sink/kafka.rs(KafkaTxProducer::send,time.to_string())materialize-sink-idheader value is the sink'sGlobalId(for exampleu123), emitted whenkafka_sink_emit_sink_id_headeris onsrc/storage/src/sink/kafka.rs(sink_id_header: ... sink_id.to_string());src/storage-types/src/dyncfgs.rsmz-sink-{sink_id}src/storage-client/src/sink.rs(ProgressKey::new){"frontier":[<ts>],"version":<n>};frontieris the exclusive upper of committed timessrc/storage/src/sink/kafka.rs(ProgressRecord,serialize_frontier,commit_transaction,progress_record_migrationtest)src/storage/src/sink/kafka.rs(commit_transaction)src/storage/src/sink/kafka.rs(sink loop,Event::Progressbranch)_materialize-progress-{env}-{connection}, shared by all sinks on a connection; name exposed inmz_kafka_connections.sink_progress_topicsrc/storage-types/src/connections.rs(progress_topic);doc/user/content/sql/create-sink/kafka.md;doc/user/content/sql/system-catalog/mz_catalog.mdisolation.level=read_committed; exactly-once detailsdoc/user/content/sql/create-sink/kafka.md(Exactly-once processing)materialize-header prefix is reservedsrc/storage/src/sink/kafka.rs;doc/user/content/sql/create-sink/kafka.mdRECORD_CONTENT, headers inRECORD_METADATA:headers, and the key inRECORD_METADATA:keyonly withStringConverterNotes for reviewers
materialize-sink-idheader and theHEADERSoption are GA in v26.48 (SS-517 - Enable Kafka sink headers feature and sink-id header by default #39908 turns both flags on by default), so the page has no private preview caveat. The Kafka sink docs drop their preview callouts in doc: mark the materialize-sink-id header and HEADERS option as GA #39829, and the v26.48.0 release notes (v26.48.0 release notes #40113) link to this page.key.converter, which the Snowflake docs confirm.Part of SS-504.
🤖 Generated with Claude Code