You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 06eb787
Browse filesBrowse the repository at this point in the historyBrowse files
Upload sealed history segments from the server-zd engine
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
Copy file name to clipboardExpand all lines: docs/reference/server/configuration.mdx
+22Lines changed: 22 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -338,6 +338,7 @@ disk or fail Steps.
338
338
| --- | --- | --- |
339
339
| **history.offloadEnabled** | false | Experimental. Whether partitions offload run history to object storage. |
340
340
| **history.segmentTargetBytes** | 4194304 (4 MiB) | Experimental. Since 0.1.21. Bytes of history records, checkpoints, and superseded values after which a run seals its open history segment for upload. From 1 byte to 268435456 (256 MiB). |
341
+
| **history.uploadConcurrency** | 16 | Experimental. Since 0.1.21. Most sealed history segments the lease holder reads, encodes, and uploads at once. From 1 to 1024. Each upload in flight holds about one encoded segment in memory. |
341
342
342
343
The setting applies to every partition, not to each run. When a node takes the
343
344
lease, it records the value in every partition whose recorded value differs,
@@ -358,6 +359,27 @@ local disk until each segment is uploaded; then pruning returns to the window
358
359
rule. Commands applied while offload is off belong to no segment, so turning it
359
360
on again starts a new segment after them.
360
361
362
+
The lease holder uploads each sealed segment to the primary object store, under
363
+
the **history/** prefix of the bucket that holds the commit log. It uploads a
364
+
run's segments oldest first and records each upload before the next one. A
365
+
segment's content depends only on committed state. A new lease holder therefore
366
+
writes the same object again and accepts an existing object with the same
367
+
content. An existing object with different content is replaced; the node logs an
368
+
error and increments **dexzd_history_upload_checksum_mismatches_total**.
369
+
370
+
Uploads never delay commands. While object storage fails them, they retry
371
+
with backoff, sealed segments stay on local disk, and the upload backlog metrics
372
+
grow; see [Metrics](/reference/server/metrics). A permanent rejection, such as
373
+
denied access, is retried once a minute instead. Uploads of segments sealed
374
+
earlier continue after **history.offloadEnabled** is turned off. Retention
375
+
postpones the deletion of a closed run until its sealed segments are uploaded.
376
+
Deleting a run also deletes every object under its **history/** prefix. That
377
+
deletion starts a minute after the run's deletion begins, so that uploads an
378
+
earlier lease holder abandoned have ended on its side. An upload that object
379
+
storage accepted just before can still leave an object of the deleted run; no
380
+
read returns it. Do not configure a bucket lifecycle rule that expires objects
381
+
under **history/**.
382
+
361
383
## Limits {#limits}
362
384
363
385
server-zd enforces these limits. A request that a limit rejects fails at once;
@@ -189,6 +189,13 @@ Every label value is from a closed set. No series has a Flow, Flow type, partiti
189
189
|`dexzd_search_initial_loads_total`| counter | — | Partition loads started, including loads of progress that cannot continue; the log gives the reason |
190
190
|`dexzd_search_projection_mode_skipped_partitions_total`| counter | — | Stopped partitions that kept their previous search projection mode at startup |
191
191
|`dexzd_history_offload_mode_skipped_partitions_total`| counter | — | Stopped partitions that kept their previous history offload mode at startup |
192
+
|`dexzd_history_upload_backlog_segments`| gauge | — | Sealed history segments not yet uploaded, summed over each partition's last rescan |
193
+
|`dexzd_history_upload_backlog_bytes`| gauge | — | Uncompressed bytes of the history rows and superseded values of `dexzd_history_upload_backlog_segments`|
194
+
|`dexzd_history_upload_oldest_sealed_age_seconds`| gauge | — | Age at scrape time of the oldest sealed history segment not yet uploaded, 0 when none |
195
+
|`dexzd_history_uploads_total`| counter |`outcome`: created, already_present, replaced, failed | History segment uploads, counted once acknowledged; failed attempts retry with backoff when transient, otherwise at the next rescan |
196
+
|`dexzd_history_upload_bytes_total`| counter | — | Bytes of the history segment objects this node created or replaced |
197
+
|`dexzd_history_upload_checksum_mismatches_total`| counter | — | Existing history segment objects whose content differed from committed state and were replaced |
198
+
|`dexzd_history_upload_rescan_errors_total`| counter | — | Runs or index rows that the history upload rescan could not read; the log names each and the rescan continues |
192
199
|`dexzd_search_initial_load_documents_total`| counter | — | Documents written by initial SQL visibility loads |
193
200
194
201
Worker polling uses a persistent stream, so there is no empty poll outcome. The stream event metric counts each task delivery and each stream close.
0 commit comments