Expand description
Backup envelope: framing for tenant backup bytes.
All multi-byte integers are little-endian.
┌─ HEADER ────────────────────────────────────────────────────┐
│ magic : 4 bytes = b"NDBB" │
│ version : u8 = 1 │
│ _reserved : 3 bytes = 0 │
│ tenant_id : u32 │
│ src_vshards : u16 (source cluster's VSHARD_COUNT) │
│ _reserved : 2 bytes = 0 │
│ hash_seed : u64 (source cluster's hash seed, 0 today) │
│ watermark : u64 (snapshot LSN; 0 if not captured) │
│ section_cnt : u16 │
│ _reserved : 6 bytes = 0 │
│ header_crc : u32 (crc32c over the preceding 40 bytes) │
└─────────────────────────────────────────────────────────────┘
┌─ SECTION × section_cnt ─────────────────────────────────────┐
│ origin_node : u64 │
│ body_len : u32 (≤ MAX_SECTION_BYTES) │
│ body : body_len bytes │
│ body_crc : u32 (crc32c over body) │
└─────────────────────────────────────────────────────────────┘
┌─ TRAILER ───────────────────────────────────────────────────┐
│ trailer_crc : u32 (crc32c over header bytes + every │
│ section's framed bytes) │
└─────────────────────────────────────────────────────────────┘Total envelope size is bounded by MAX_TOTAL_BYTES. The decoder
short-circuits before allocating per body / per envelope, so a
caller-supplied byte stream cannot drive unbounded allocation.
Structs§
- Envelope
- Decoded envelope.
- Envelope
Meta - Header metadata captured at backup time.
- Envelope
Writer - Build an envelope by pushing sections one at a time, then
finalize(). - Section
- One contiguous body produced by one origin node.
- Source
Tombstone Entry - Single source-side tombstone entry.
purge_lsnis the Origin WAL LSN at which the hard-delete committed — restore uses it as a per-collection replay barrier so rows older than the purge don’t resurrect. - Stored
Collection Blob - Single catalog-row entry in a catalog-rows section. The outer
container is
Vec<StoredCollectionBlob>msgpack-encoded into the section body. Bytes are the zerompk-encodedStoredCollectionfrom thenodedbcrate —nodedb-typesintentionally doesn’t depend on thenodedbcatalog types, so the blob is opaque here.
Enums§
Constants§
- DEFAULT_
MAX_ SECTION_ BYTES - Default cap on a single section body: 16 GiB.
- DEFAULT_
MAX_ TOTAL_ BYTES - Default cap on total envelope size: 16 GiB. Tunable per call.
- HEADER_
LEN - Header is fixed-size — 44 bytes (40 framed + 4 crc).
- MAGIC
- SECTION_
ORIGIN_ CATALOG_ ROWS - Sentinel
origin_node_idvalues that mark sections carrying metadata rather than per-node engine data. The envelope format is backward-compatible: V1 readers that don’t know about these sentinels still decode the envelope (the bytes just aren’t applied at restore time), but the section CRCs still validate. Restore handlers recognize the sentinel and route the body to the correct catalog writer. - SECTION_
ORIGIN_ SOURCE_ TOMBSTONES - SECTION_
OVERHEAD - Per-section framing overhead: origin(8) + len(4) + crc(4).
- TRAILER_
LEN - Trailing crc.
- VERSION
Functions§
- parse
- Parse and fully validate an envelope.