pub trait BlobTransitionObserver: Send + Sync {
// Required methods
fn on_blob_upload_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn on_blob_uploaded<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait;
fn on_blob_upload_failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
error: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait;
// Provided methods
fn on_blob_preparation_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait { ... }
fn on_blob_preparation_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait { ... }
fn on_blob_upload_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait { ... }
fn should_skip_uploads(&self) -> bool { ... }
fn wait_until_uploads_paused<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait { ... }
fn wait_until_uploads_resumed<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
Self: 'async_trait { ... }
fn on_root_made_local<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait { ... }
fn on_blob_materialize_progress<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
blob_id: &'life3 str,
done: u64,
total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where 'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait { ... }
}Expand description
Notified about coven’s blob transitions, for host-specific bookkeeping and UI: per-blob upload progress while a make_remote uploads, per-blob materialize progress while a make_local copies files back, and the synchronous make-local completion the host turns into its own UI event.
The host no longer drives the transition — coven owns flipping the gate and
deciding when a cycle publishes — so this observer only reports. The upload
callbacks fire as the drain works: preparation starts while the plaintext is
verified and sealed into its durable spool, on_blob_upload_started fires
only when that prepared spool is handed to the provider,
on_blob_upload_progress fires zero or more times as encrypted bytes reach
the cloud (backends that can’t report sub-file progress call it once at the end
with bytes_done == bytes_total), on_blob_uploaded on success (notification
only — the durable queue records Created and the Store publication later
activates the root),
and on_blob_upload_failed when an attempt fails and its entry stays queued.
A make-remote’s root state is durable and belongs in
CloudOutboxLiveQuery, not an observer callback that can be lost across a
restart. on_root_made_local reports the synchronous opposite direction;
on_blob_materialize_progress moves its per-file progress bar.
The upload-pause methods let the host suspend the upload pipeline without touching the queue or discarding an open provider upload. The drain checks the absolute state before admitting work, stops polling active preparation, and stops active provider request bodies from yielding bytes while paused; resume continues those same operations.
Required Methods§
Sourcefn on_blob_upload_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn on_blob_upload_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
The durable spool is prepared and its provider upload is starting now.
Sourcefn on_blob_uploaded<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn on_blob_uploaded<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
The blob was uploaded to the cloud successfully — notification only. coven owns the durable Created handoff and the Store publication that completes the make_remote.
Sourcefn on_blob_upload_failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
error: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn on_blob_upload_failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
error: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
An upload attempt failed; the entry remains queued for retry.
Provided Methods§
Sourcefn on_blob_preparation_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn on_blob_preparation_started<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
The plaintext source is being verified and sealed into its durable upload spool. Fires only for a Pending journal; a restart-resumed Prepared journal proceeds directly to upload.
Sourcefn on_blob_preparation_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn on_blob_preparation_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
bytes_done of bytes_total plaintext source bytes have been consumed
by preparation. Values are cumulative and monotonic.
Sourcefn on_blob_upload_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn on_blob_upload_progress<'life0, 'life1, 'async_trait>(
&'life0 self,
upload: &'life1 RowBlobRef,
bytes_done: u64,
bytes_total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
bytes_done of bytes_total encrypted bytes have reached the cloud for
this in-flight blob. bytes_done is cumulative and monotonic within one
upload attempt. The default is a no-op so observers that don’t surface
sub-file progress don’t need a stub.
Sourcefn should_skip_uploads(&self) -> bool
fn should_skip_uploads(&self) -> bool
Whether upload work is currently paused. The drain checks this before
admission and while provider work is active. The default is false so
existing implementations don’t need a stub.
Sourcefn wait_until_uploads_paused<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn wait_until_uploads_paused<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Complete when the absolute upload-pause state becomes paused. The default never completes because the default state never pauses.
Sourcefn wait_until_uploads_resumed<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn wait_until_uploads_resumed<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Complete when the absolute upload-pause state becomes running. An
observer that can return true from Self::should_skip_uploads must
override this so a suspended transfer can resume.
Sourcefn on_root_made_local<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn on_root_made_local<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
coven completed a make_local of (root_table, root_id): every blob is back
to a local file (a user file for user-provided, the local store for
host-provided), the gate is flipped false (the subtree retracts from peers),
and the cloud blobs are queued for tombstoning. The default is a no-op.
Sourcefn on_blob_materialize_progress<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
blob_id: &'life3 str,
done: u64,
total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
fn on_blob_materialize_progress<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
root_table: &'life1 str,
root_id: &'life2 str,
blob_id: &'life3 str,
done: u64,
total: u64,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
done of total of a make_local’s blobs have been materialized back to a
local file, so the host can move a per-file progress bar. The default is a
no-op.