Skip to content

hoglake sink: write the flush identity into the snapshot message - #146

Merged
jghoman merged 1 commit into
mainfrom
jakob/hoglake-commit-message
Sep 24, 2026
Merged

jghoman merged 1 commit into
mainfrom
jakob/hoglake-commit-message

Conversation

@jghoman

@jghoman jghoman commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

hoglake snapshots from millpond carried author (millpond/<table>/<ordinal>) and an empty message. The sink already receives the flush identity, kafka_offsets as (topic, partition, first, last), and used it only to seed the idempotency key. Nothing recorded which Kafka offsets a snapshot contains, which is what an operator needs to answer "is offset X in the lake", audit a replay after a crash, or reconcile a gap.

The message

records=26402 files=31 partitions=31 arrow_bytes=268435456 trigger=size millpond=22cda30 table=e6e3e679-…
offsets clickhouse_events_json p3:4128819-4155470 p19:4130021-4156802 … (32)
  • Line 1: fixed key order. partitions is the number of partition tuples the flush touched (0 on an unpartitioned table; equal to files under the one-file-per-tuple fanout). arrow_bytes is measured after consolidation, so it is approximately the flush gate value. trigger is size, interval, final (shutdown) or unknown. table is the table incarnation, so a replayed range after a drop and recreate is distinguishable from the dead incarnation's snapshot.
  • Line 2: every partition range sorted by partition number, one line per topic, with a trailing count. Bounded at 16 KiB, which holds all 512 partitions of the events topic on one pod (measured 10.7 KiB); past that the line ends ... (+k more).
  • Formatted before prepare_append_files, so a formatter error cannot orphan an uploaded object, and frozen into the prepared payload, so a retry under the same idempotency key re-sends identical text.

DuckLake fleets

No behaviour change on the write path: _sink_write_kwargs passes nothing to the DuckLake sink. One metric label is new on every destination: the shutdown flush now reports batches_flushed_total{trigger="final"} instead of counting under trigger="time". The repo dashboard aggregates by (trigger); no alert selects on the label.

Tests

1270 unit (+43), 65 non-hoglake integration, 45 hoglake integration (the message is read back from GET /v1/catalogs/{c}/snapshots, including the live table UUID and one snapshot with the same message after a lost commit response). Two review rounds; mutations on the partition count, range ordering, capture point of arrow_bytes, the truncation guard and the trigger rename are each red.

Prod-us shape: 32 ranges per pod, 665 bytes per message.

A hoglake snapshot from millpond carried an author and an empty message.
The commit now records what the flush was: records, files, partition
tuples, Arrow bytes, the flush trigger, the millpond version, the table
incarnation, and the Kafka offset range of every partition in the flush.
The offset ranges are the only record of which Kafka position a snapshot
contains. The message is formatted before the upload, so it can never
orphan an object, and it is frozen into the prepared payload, so a
replay re-sends the same text.
@jghoman
jghoman merged commit 764d857 into main Sep 24, 2026
17 checks passed
@jghoman
jghoman deleted the jakob/hoglake-commit-message branch September 24, 2026 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant