pub struct ComposeSpec<'a> {
pub key: &'a str,
pub local: Option<Arc<File>>,
pub parts: Vec<PartSource>,
pub base_key: Option<&'a str>,
pub base_etag: Option<String>,
pub condition: PutCondition,
pub stamps: GenerationStamps,
pub crc64: Option<u64>,
pub progress: Option<Arc<AtomicU64>>,
}Expand description
The flusher’s order for one generation publish.
Fields§
§key: &'a str§local: Option<Arc<File>>Local source of Local parts: the OPEN DESCRIPTOR, read at
offsets, never a path reopened per part. Clean ranges are
byte-identical local and remote by definition, so crc64 is
computable from this file alone.
It is a descriptor and not a path because a path is reopened,
and everything between the caller’s open and the store’s read is
a window: mv d d.bak; ln -s /elsewhere d in it made a store
that reopened d/cfg.yaml publish bytes from outside the
workspace, with O_NOFOLLOW on the last component guarding
nothing (flint-lean review 2026-09-18, H5). The caller opens the
file once, by a walk that follows no link at any depth, and every
read — size, stamps, bytes, checksum — comes from that one
descriptor. None is legal only for a spec with no Local part
(a pure BaseCopy compose), and a Local part without it is
refused before any part moves.
parts: Vec<PartSource>Contiguous from offset 0, sizes within the backend’s part granularity (the A11 part-size grid upstream owns that).
base_key: Option<&'a str>Where the base generation LIVES, when it is not key — the A7
re-key flush publishes a renamed file under its new key while
clean ranges still copy from the old one. None = same as key.
base_etag: Option<String>Base generation’s ETag — required iff any part is BaseCopy.
condition: PutCondition§stamps: GenerationStamps§crc64: Option<u64>Full-object CRC-64/NVME of the composed content, from local truth. Backends hand it to the store for SERVER-SIDE validation at publish: a mismatch fails the publish, never warns.
None asks the store to accumulate it from the Local parts
as it reads them for upload. Parts go up in order, one at a
time, so a streaming CRC over them in that loop IS the CRC of
the object — the same local truth, without a second pass over
the file (a 40 GiB pack’s pre-pass was ~70 s on forge’s push
path, 2026-09-05). A BaseCopy part is never read locally, so
a spec with one and None is refused before any part moves.
progress: Option<Arc<AtomicU64>>Bytes landed so far, for a caller that has to prove LIVENESS
while a long compose runs: forge’s lease renewer renews a push
only while this advances, so a wedged upload lets the token go
quiet and a challenger take over — which is the one takeover a
wedged holder can get. Advanced by len after every part,
Local and BaseCopy alike. None = nobody is watching.
Implementations§
Source§impl ComposeSpec<'_>
impl ComposeSpec<'_>
Sourcepub fn note_progress(&self, bytes: u64)
pub fn note_progress(&self, bytes: u64)
Record bytes more of the object as landed.