Repository navigation
server-zd: upload sealed history segments to object storage - #1363
Merged
Merged
Conversation
longquanzheng
force-pushed
the
history-offload/b6-uploader
branch
from
November 7, 2026 05:54
19cf8c1 to
9be26b1
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
longquanzheng
force-pushed
the
history-offload/b5-segment-seal
branch
from
November 7, 2026 06:07
492902a to
bdf20a0
Compare
longquanzheng
force-pushed
the
history-offload/b6-uploader
branch
from
November 7, 2026 06:24
9be26b1 to
06eb787
Compare
While a partition offloads history, the lease holder now uploads every committed SEALED history segment to the primary object store under history/ and proposes the HistorySegmentUploaded acknowledgments in seq order. - One upload task per run (TrackedWork::HistoryUpload). The committed HistorySegmentSealed effect starts it, partition rebuild starts it from the HistoryUploadPending index after a restart, takeover, or snapshot restore, and a periodic rescan restarts stopped work. - Each segment is read from committed state and encoded on a blocking thread, then written with CreateOnly. An existing object that fully decodes, on a blocking thread, with the same content checksum is acknowledged. Any other existing object is replaced with If-Match, logged as an error, and counted. - Encoded bytes live only together with an upload slot, so no object bytes are held while an acknowledgment or a backoff waits, and memory stays bounded by history.uploadConcurrency (default 16). - Every history object call ends when the node stops, so no request outlives its owner. - Retryable object storage failures retry with backoff and never delay commands. A failure without a retry, such as a permanent rejection or corrupt state, is logged and counted, and every trigger then skips the run until the next rescan allows it again. Nothing is acknowledged meanwhile. Uploads stop without a retry once the run is gone or purging. - The rescan logs, counts, and skips a run whose rows cannot be read, so the other runs of its partition are still rescanned. - Uploads continue after the offload mode is turned off, so every sealed segment is eventually acknowledged. - Retention postpones a closed run while it has a SEALED segment. The purge of a run that kept segment state waits one minute, so the client side of every earlier write has ended, then deletes the run's objects by catalog key, sweeps the run's history/ prefix, and retries a permanent rejection each minute before RunPurge. A write the store had already accepted can still leak an object of the purged run; a later orphan sweep is to remove it. - New metrics: upload backlog segments, bytes, and oldest seal age; uploads by outcome; uploaded bytes; checksum mismatches; rescan errors; and the history object kind of object store requests. - The format compatibility workload acknowledges the short-lived run's sealed segment before its retention fires, and testdata/v1 is regenerated with its generator. Refs #1325
longquanzheng
force-pushed
the
history-offload/b6-uploader
branch
from
November 7, 2026 06:31
06eb787 to
16bc650
Compare
This was referenced Nov 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
history/, and proposeHistorySegmentUploadedacknowledgments in seq order. One effect task per run is started by the committedHistorySegmentSealedeffect, by partition rebuild from theHistoryUploadPendingindex (restart, takeover, snapshot restore), and by a 60-second rescan.history.uploadConcurrencywhile acknowledgments wait.history/prefix, before the hard-delete prefix andRunPurge. A write the object store had already accepted may still land after the purge; it leaves an unreadable object of a purged run, which a later periodic orphan sweep removes.dexzd_history_upload_backlog_segments,dexzd_history_upload_backlog_bytes,dexzd_history_upload_oldest_sealed_age_seconds,dexzd_history_uploads_total{outcome},dexzd_history_upload_bytes_total,dexzd_history_upload_checksum_mismatches_total,dexzd_history_upload_rescan_errors_total, andobject_kind="history".history.uploadConcurrency(default 16, 1–1024).Why
Refs #1325. Stacked on #1356, which seals history segments in apply and accepts upload acknowledgments, but nothing uploads them yet. While history offload is enabled, window pruning keeps every row after a run's uploaded seq, so without an uploader local history grows without bound. This PR adds the uploader, so sealed segments reach object storage and pruning can advance. Retention must wait for uploads: purging stops uploads, so a segment sealed before the purge would never be stored. A segment's key and content depend only on committed state, so a new owner that repeats an upload finds the same content.
Compatibility
history.uploadConcurrency; new metrics;object_kindgains the valuehistory.testdata/v1is regenerated with its generator and its pin updated.Testing
history/prefix; purging runs; snapshot restore before acknowledgment; a stopping owner abandons its pending write before the new owner purges; concurrency 2 with 20 runs whose acks are blocked; content kept through mode-off pruning (all already_present); permanent failures retried only by the rescan, including 10 rapid seals; a corrupt run does not stop the partition's rescan.serve_processwith s3local: 503 onhistory/PUTs while Flows keep completing, then a waiting standby restores a snapshot, takes over, and uploads every segment.serve_processmetrics series ceiling is raised by the 10 new series (195 measured, ceiling 202).cargo fmt --check,cargo clippy --workspace --all-targets -D warnings, tests of apply, engine (lib, engine, format_compat), metrics, history-segment, server (lib, serve_process), simulation, e2e;make rust-rules-check;make copyright-check;cd docs && npm run check.