Skip to main content

ObjectStore

Trait ObjectStore 

Source
pub trait ObjectStore: Send + Sync {
Show 31 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 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, '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 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§

Source

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.

Source

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, epoch and flush_uuid describe 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.

Source

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,

Source

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,

Source

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).

Source

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.

Source

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,

Source

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,

Source

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.

Source

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.

Source

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.

Source

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,

Source

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.

Source

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.

Source

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.

Source

fn min_part_size(&self) -> u64

Backend part granularity for the A11 part-size grid.

Source

fn max_parts(&self) -> usize

Provided Methods§

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

fn presign_put<'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 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 carries no content check. Whoever holds it may put anything at that key until it expires, so the caller must issue it only for a key whose NAME already constrains the content — a content-addressed one — and must verify after the fact.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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".

Implementors§