pub trait ObjectStore: Send + Sync {
Show 32 methods
// Required methods
fn put_whole<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
condition: &'life2 PutCondition,
stamps: &'life3 GenerationStamps,
crc64: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn copy_object<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'async_trait>(
&'life0 self,
src_key: &'life1 str,
src_if_match: Option<&'life2 str>,
dst_key: &'life3 str,
condition: &'life4 PutCondition,
stamps: &'life5 GenerationStamps,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait;
fn compose_generation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
spec: &'life1 ComposeSpec<'life2>,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn get_whole<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
if_match: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn get_range<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Bytes>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn list<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<ListedObject>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn list_uploads<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<PendingUpload>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn abort_upload<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
upload_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn bootstrap<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<BootstrapReport>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn epoch_read<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Option<EpochState>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn epoch_acquire<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
holder_id: &'life2 str,
supersede: Option<&'life3 EpochState>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn epoch_renew<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn epoch_release<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn min_part_size(&self) -> u64;
fn max_parts(&self) -> usize;
// Provided methods
fn get_range_segments<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<Bytes>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn delete_if_match<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
etag: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn delete_many<'life0, 'life1, 'async_trait>(
&'life0 self,
keys: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StoreResult<DeleteManyReport>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn head_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn get_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn delete_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn list_versions<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<ListedVersion>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn presign_get<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<String>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn presign_put<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
sha256: &'life2 [u8; 32],
) -> Pin<Box<dyn Future<Output = StoreResult<PresignedPut>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn lifecycle_rules<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<LifecycleView>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn ensure_noncurrent_retention<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
days: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<RetentionOutcome>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn epoch_enqueue<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
observed: &'life2 EpochState,
holder_id: &'life3 str,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochState>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn epoch_handoff<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn upload_gate(&self) -> Option<Arc<ByteGate>> { ... }
fn request_counts(&self) -> Option<RequestCounts> { ... }
}Required Methods§
Sourcefn put_whole<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
condition: &'life2 PutCondition,
stamps: &'life3 GenerationStamps,
crc64: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn put_whole<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
condition: &'life2 PutCondition,
stamps: &'life3 GenerationStamps,
crc64: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Whole-object publish (below the multipart threshold).
crc64 is validated server-side; stamps ride as metadata.
Sourcefn copy_object<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'async_trait>(
&'life0 self,
src_key: &'life1 str,
src_if_match: Option<&'life2 str>,
dst_key: &'life3 str,
condition: &'life4 PutCondition,
stamps: &'life5 GenerationStamps,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
fn copy_object<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'async_trait>(
&'life0 self,
src_key: &'life1 str,
src_if_match: Option<&'life2 str>,
dst_key: &'life3 str,
condition: &'life4 PutCondition,
stamps: &'life5 GenerationStamps,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
Assemble and publish one generation from local dirty bytes plus server-side clean copies. MUST abort its partial assembly on every failure path (A9) — an error return means nothing is left pending under the key by this call. Server-side copy of a WHOLE object to a DIFFERENT key.
Exists because a key IS a path in every layout this crate serves,
so moving a file moves bytes. Without it a rename is a download
and a re-upload, and PartSource::BaseCopy cannot stand in: it
copies ranges from the SAME key by construction, so a destination
that has no generation of its own has nothing to copy from.
Two rules the implementations must agree on, and the memory double must model or it will pass a test the real store fails:
- the destination’s full-object CRC is the source’s. A copy is byte-identical; a checksum that changed means the bytes did.
- the destination’s stamps are not the source’s.
generation,epochandflush_uuiddescribe a publish, and inheriting them files one object’s history under another object’s key — a reader asking “which flush wrote this?” would be told about a flush that wrote something else.
src_if_match guards the SOURCE: copying an object that moved
since the caller read it copies something the caller never saw.
condition guards the DESTINATION, exactly as on put_whole.
fn compose_generation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
spec: &'life1 ComposeSpec<'life2>,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn get_whole<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
if_match: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_whole<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
if_match: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Whole-object read, optionally guarded (hydration always guards: a 412 here is S3-WINS — the foreign-overwrite posture, opposite of the publish path).
Sourcefn get_range<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Bytes>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_range<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Bytes>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Ranged read (step 11’s streaming restore — a multi-GiB hydration must never buffer the whole object). ALWAYS guarded: each chunk’s If-Match pins the same object version end-to-end; a 412 mid-restore is the S3-wins foreign-overwrite signal. The caller never requests past the object’s end.
fn list<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<ListedObject>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn list_uploads<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<PendingUpload>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_uploads<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<PendingUpload>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
A9 hygiene: every in-progress assembly under the prefix.
Sourcefn abort_upload<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
upload_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn abort_upload<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
upload_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Abort one assembly. Aborting an already-absent upload is Ok — the sweep and the abort-on-failure paths both race the lifecycle rule.
Sourcefn bootstrap<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<BootstrapReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn bootstrap<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<BootstrapReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
A9: verify/create the bucket posture (lifecycle abort rule, versioning, encryption notes, IAM probe). Named prefix so probes stay under the tier’s namespace.
fn epoch_read<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Option<EpochState>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn epoch_acquire<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
holder_id: &'life2 str,
supersede: Option<&'life3 EpochState>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn epoch_acquire<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
holder_id: &'life2 str,
supersede: Option<&'life3 EpochState>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Claim: supersede: None creates (If-None-Match:*); Some
replaces the OBSERVED state via CAS on its token — the caller
(step 7) is responsible for having JUDGED that holder dead
against the store’s clock. The new epoch is observed+1.
Sourcefn epoch_renew<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn epoch_renew<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochLease>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Heartbeat CAS. PreconditionFailed means deposed: self-fence.
echo rides the same write (see EpochState::echo) — the
observed-state surface is deliberately a passenger on a request
the holder already pays for every ≤30 s. A caller with nothing
to report passes None, which CLEARS any previous echo rather
than preserving it: a stale echo read as live is exactly the
mixed-version hole the field exists to close.
Sourcefn epoch_release<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn epoch_release<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Mark the cell released: a clean handoff. The epoch NUMBER must
survive (deleting the cell would restart numbering at 1 and
break the monotonicity every publish stamp depends on), and the
write must be guarded on lease’s own token so a deposed
holder cannot mark a live successor’s cell.
Sourcefn min_part_size(&self) -> u64
fn min_part_size(&self) -> u64
Backend part granularity for the A11 part-size grid.
fn max_parts(&self) -> usize
Provided Methods§
Sourcefn get_range_segments<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<Bytes>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_range_segments<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
offset: u64,
len: u64,
if_match: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<Bytes>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
The same ranged read, WITHOUT flattening the response into one contiguous buffer.
get_range ends in AggregatedBytes::into_bytes, which for any
multi-frame body — i.e. always — takes SegmentedBuf’s general
branch: BytesMut::with_capacity(len); res.put(self.take(len)).
That is one full-size allocation and one full-size copy per
range, on top of the frames the SDK is already holding. At a 16
MiB chunk the allocation goes through mmap and is returned on
free, so the next range faults in fresh zeroed pages: measured
on i4i.large as system time beating user time 6:1.
The DEFAULT deliberately wraps get_range, so a store with
nothing to stream (the in-memory double) behaves exactly as it
did and no implementation is forced to care.
Sourcefn delete_if_match<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
etag: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete_if_match<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
etag: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
DELETE key only while its current ETag is etag (If-Match):
PreconditionFailed once the object has moved on, NotFound
when there is nothing to delete.
This is the garbage collector’s delete. A HEAD that recognizes an etag followed by a plain DELETE leaves a window in which another writer’s guarded PUT replaces the object, and the DELETE then removes bytes that writer’s next commit cites. With one writer per workspace nothing could land there; with several writers holding the lease only for their commit sections, an upload can.
The default REFUSES rather than falling back to delete: a
fallback would reopen exactly that window without a word, on
whichever backend happened not to override this.
Sourcefn delete_many<'life0, 'life1, 'async_trait>(
&'life0 self,
keys: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StoreResult<DeleteManyReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_many<'life0, 'life1, 'async_trait>(
&'life0 self,
keys: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StoreResult<DeleteManyReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
DELETE every key in keys, unconditionally, in as few requests
as the backend allows (S3: DeleteObjects, a thousand keys per
request). Absent keys succeed; see DeleteManyReport.
This is the immutable-handles collector’s delete (lean design
2026-09-19, rule R3): every write lands at a handle nobody else
writes, a handle a landed document stopped citing can never be
cited again, and so the If-Match that delete_if_match exists
for has nothing left to guard. The default runs delete per
key, so every backend collects; one with a batch verb overrides
it and counts one request per batch.
Sourcefn head_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn head_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<ObjectMeta>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
HEAD one specific version.
Sourcefn get_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<(ObjectMeta, Bytes)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
GET one specific version, when the backend keeps versions. Lean’s readers resolve citations by etag alone (version-pinned reads went with gated mode, 2026-09-13); the method stays for tools and probes.
Sourcefn delete_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete_version<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
version_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
DELETE one specific version — the exact reclamation flint’s own per-citation GC uses. Free, and the ONLY reaper that can tell cited from uncited; lifecycle cannot, which is why the noncurrent rule is a long backstop rather than the mechanism (D8).
Sourcefn list_versions<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<ListedVersion>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_versions<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<ListedVersion>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Every version under a prefix, current and noncurrent, oldest
first per key. The claim-time/DR fallback when orphans.json is
missing or stale — the expensive path, which is why the durable
summary is written eagerly.
Sourcefn presign_get<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn presign_get<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
A time-limited URL that GETs key with no credential of the
caller’s own.
One consumer, and it is worth naming because it is what makes the URL’s lifetime a design constraint rather than a parameter: flint forge advertises a clone BUNDLE this way, so that a thousand agents cloning at once pull the bytes from the object store instead of through one pod’s NIC (forge design §8). The URL is handed to a git client, which may hold it for the length of a clone, and S3 caps a SigV4 presigned URL at seven days — so the caller must re-sign on a schedule shorter than the TTL it asked for, and this returns the URL rather than storing it anywhere.
Defaulted to a refusal: a backend that cannot presign must say so, and the caller must fall back to serving the bytes itself rather than advertising a URL that will not resolve.
Sourcefn presign_put<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
sha256: &'life2 [u8; 32],
) -> Pin<Box<dyn Future<Output = StoreResult<PresignedPut>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn presign_put<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl_secs: u64,
sha256: &'life2 [u8; 32],
) -> Pin<Box<dyn Future<Output = StoreResult<PresignedPut>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
A time-limited URL that PUTs key with no credential of the
caller’s own.
The counterpart of ObjectStore::presign_get, and it exists
for the same consumer: flint forge’s LFS batch API hands a git
client one of these so a multi-gigabyte checkpoint travels
straight to the object store and never crosses the repository
server’s network interface.
The URL grants exactly one body, once. It is issued only for
a content-addressed key, and the signature covers the body’s
SHA-256 (x-amz-checksum-sha256, so the store refuses any other
bytes) and If-None-Match: * (so it refuses a second write).
A header the URL does not sign binds nothing — the holder leaves
it out — which is why both are SIGNED and returned in
PresignedPut::headers for the caller to hand to the client.
Without them the URL was a bearer grant to put anything at that
key for its whole lifetime (review 2026-09-23).
Sourcefn lifecycle_rules<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<LifecycleView>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn lifecycle_rules<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StoreResult<Vec<LifecycleView>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Every lifecycle rule on the bucket, reduced to LifecycleView.
Defaulted to a refusal rather than to an empty list: “no rules” and “I cannot see the rules” must never be the same answer here. An empty list is a POSITIVE claim that nothing is reaping noncurrent versions, and gated mode is accepted on the strength of it (D8).
Sourcefn ensure_noncurrent_retention<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
days: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<RetentionOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn ensure_noncurrent_retention<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
days: u64,
) -> Pin<Box<dyn Future<Output = StoreResult<RetentionOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Provision the noncurrent-version retention backstop on prefix
with read-merge-append, and report what is installed.
PutBucketLifecycleConfiguration is FULL-REPLACE: an
implementation that writes its rule alone silently deletes the
MPU-abort rule and every rule the customer owns. Read, merge,
append — the discipline bootstrap_lifecycle already follows.
Sourcefn epoch_enqueue<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
observed: &'life2 EpochState,
holder_id: &'life3 str,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn epoch_enqueue<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
observed: &'life2 EpochState,
holder_id: &'life3 str,
) -> Pin<Box<dyn Future<Output = StoreResult<EpochState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Append holder_id to the cell’s FIFO of waiters, by CAS on the
OBSERVED token, and return the cell as rewritten. A holder that
is already queued is not appended twice. The write moves the
token: a live holder’s next renew/handoff 412s, re-reads, and
adopts the new token with the longer queue (lean lease.rs).
Default: unsupported — a backend without a queue serialises
claimants by the quiet-poll rule alone.
Sourcefn epoch_handoff<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn epoch_handoff<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
key: &'life1 str,
lease: &'life2 EpochLease,
echo: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StoreResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
The per-BARRIER release (lean, design 2026-09-13 §4): mark the
cell released like ObjectStore::epoch_release, but hand it to
the queue head (handoff = waiters[0], the rest stay queued) and
KEEP echo — the cell is at rest between every barrier now, so
the last holder’s echo is the only thing that tells an operator
which binary ran the last boundary. Guarded on the lease token
like every other transition. Default: the plain release.
Sourcefn upload_gate(&self) -> Option<Arc<ByteGate>>
fn upload_gate(&self) -> Option<Arc<ByteGate>>
The store’s upload bytes-in-flight gate (gate::ByteGate),
when it was built with one. The store charges every local part
of a compose to it; a caller that reads whole bodies ITSELF
before put_whole (lean’s upload_one) takes this so those
bodies are charged to the SAME budget, and the bound is one
number rather than two that must be set together. None = the
upload path is bounded only by its counts.
Sourcefn request_counts(&self) -> Option<RequestCounts>
fn request_counts(&self) -> Option<RequestCounts>
Requests this store has sent since it was built, by kind
(counters.rs). None = a store that does not count.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".