pub trait AttachmentStore: Send + Sync {
// Required methods
fn put<'life0, 'async_trait>(
&'life0 self,
bytes: Vec<u8>,
meta: AttachmentCreateMeta,
) -> Pin<Box<dyn Future<Output = Result<AttachmentRef, AttachmentStoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait;
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<StoredAttachment, AttachmentStoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<(), AttachmentStoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn list<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait;
// Provided methods
fn persistence(&self) -> AttachmentStorePersistence { ... }
fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<Option<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait { ... }
}Expand description
A flat, content-addressed blob store: host-supplied dumb infrastructure.
The store maps a content hash to its bytes and nothing more. It has no
notion of sessions — identical bytes written by any number of sessions
resolve to one physical blob, and that dedup is intended. Reference
tracking and the session boundary live one layer up in
SessionAttachmentStore and the AttachmentManifest; lifecycle
(which blobs may be deleted) lives above that in the host, via
reclaim_unreferenced_attachments.
Conventions every backend upholds: put is idempotent (identical bytes are
a no-op returning the same ref), delete is idempotent, and a missing blob
maps to AttachmentStoreError::NotFound.
Required Methods§
fn put<'life0, 'async_trait>(
&'life0 self,
bytes: Vec<u8>,
meta: AttachmentCreateMeta,
) -> Pin<Box<dyn Future<Output = Result<AttachmentRef, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<StoredAttachment, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Sourcefn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<(), AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<(), AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Remove one blob. Idempotent: deleting an absent blob is a no-op. This is the primitive mark-and-sweep GC uses to reclaim unreferenced content; per-session lifecycle is expressed by dropping manifest refs, never by calling this directly for a live session.
Sourcefn list<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn list<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Enumerate every blob currently held. Used only by mark-and-sweep GC. Large deployments may hold many blobs; backends should stream/batch internally where possible. Order is unspecified.
Provided Methods§
fn persistence(&self) -> AttachmentStorePersistence
Sourcefn head<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<Option<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 AttachmentId,
) -> Pin<Box<dyn Future<Output = Result<Option<StoredBlobRef>, AttachmentStoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Re-fetch one blob’s current freshness signal, or None if it is absent.
The mark-and-sweep GC calls this immediately before deleting a candidate:
the last_modified_epoch_ms captured by the list snapshot is stale by
delete time, so a blob that a fresh put (a new intent for the same
content id) touched after the snapshot must be spared. The default
implementation scans list; backends override it with a cheap
stat/HEAD.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".