pub struct InstrumentedEventStore { /* private fields */ }Expand description
Event-store wrapper that observes operation latency and lifecycle events without changing engine crates.
Implementations§
Source§impl InstrumentedEventStore
impl InstrumentedEventStore
Sourcepub fn new(
inner: Arc<dyn EventStore>,
metrics: Metrics,
namespace: impl Into<String>,
) -> Self
pub fn new( inner: Arc<dyn EventStore>, metrics: Metrics, namespace: impl Into<String>, ) -> Self
Wrap an event store with server-side metrics.
The store is given a private, never-pulsed outbox wake; callers that share
the engine’s stage seam with the dispatcher install the shared handle with
Self::with_outbox_wake.
Sourcepub fn with_outbox_wake(self, outbox_wake: Arc<Notify>) -> Self
pub fn with_outbox_wake(self, outbox_wake: Arc<Notify>) -> Self
Install the shared advisory outbox wake (LSUB-2).
The supplied Notify is the same handle the OutboxDispatcher awaits,
so a committed outbox-row batch wakes the dispatcher’s run loop directly.
Trait Implementations§
Source§impl Debug for InstrumentedEventStore
impl Debug for InstrumentedEventStore
Source§impl PackageStore for InstrumentedEventStore
impl PackageStore for InstrumentedEventStore
Source§fn put_package<'life0, 'async_trait>(
&'life0 self,
record: PackageRecord,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn put_package<'life0, 'async_trait>(
&'life0 self,
record: PackageRecord,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
record and atomically points the type’s route at it. Read moreSource§fn put_package_with_routes<'life0, 'life1, 'async_trait>(
&'life0 self,
record: PackageRecord,
route_workflow_types: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn put_package_with_routes<'life0, 'life1, 'async_trait>(
&'life0 self,
record: PackageRecord,
route_workflow_types: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
record and atomically points every member workflow type at
its content hash. Read moreSource§fn list_packages<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<PackageRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_packages<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<PackageRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
deployed_at order
(ties broken by (workflow_type, content_hash) text order), so
startup reload re-applies deploys deterministically.Source§fn delete_package<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_type: &'life1 str,
content_hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete_package<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_type: &'life1 str,
content_hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
(workflow_type, content_hash). Read moreSource§fn put_package_route<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_type: &'life1 str,
content_hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn put_package_route<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_type: &'life1 str,
content_hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn list_package_routes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<PackageRouteRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_package_routes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<PackageRouteRecord>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
workflow_type text order.Source§impl ReadableEventStore for InstrumentedEventStore
impl ReadableEventStore for InstrumentedEventStore
Source§fn set_owned_shards(&self, shards: Option<&[usize]>)
fn set_owned_shards(&self, shards: Option<&[usize]>)
Forward owned-shard scoping to the inner store; this decorator adds only metrics, never shard policy, so the inner backend remains the sole authority on enumeration scope.
Source§fn acquire_owned_shards(&self, shards: &[usize]) -> Result<(), StoreError>
fn acquire_owned_shards(&self, shards: &[usize]) -> Result<(), StoreError>
Forward the SS-2 shard election to the inner store; this decorator adds only metrics, never ownership policy, so the inner backend runs the election (or no-ops in single-node mode).
Source§fn acquire_owned_shard(&self, shard: usize) -> Result<(), StoreError>
fn acquire_owned_shard(&self, shard: usize) -> Result<(), StoreError>
Forward the per-shard (ADR-021 clean-partial) election to the inner store.
MUST be forwarded: the adoption fence (Engine::adopt_shards) drives the
SINGULAR per-shard seam, and the trait default is a silent no-op that would
let a survivor “adopt” a shard WITHOUT winning the election — its in-memory
live epoch is then never seeded, so every recovery write is fenced by the
surviving quorum and cross-node failover stalls (#157).
Source§fn extend_owned_shards(&self, shards: &[usize])
fn extend_owned_shards(&self, shards: &[usize])
Forward the SS-5 failover scope-widening to the inner store; this decorator adds only metrics, never ownership policy.
Source§fn is_current_owner(&self, shard: usize) -> bool
fn is_current_owner(&self, shard: usize) -> bool
Forward the residual-window ownership re-assertion (ADR-021). MUST be
forwarded: the trait default returns true, which would make the adoption
planner treat a shard it never actually won as a survivor (#157).
Source§fn publish_shard_owner(&self, shard: usize) -> Result<(), StoreError>
fn publish_shard_owner(&self, shard: usize) -> Result<(), StoreError>
Forward the SS-3 shard-owner directory publish (fenced by the election just won). MUST be forwarded: the trait default is a silent no-op, so a request reaching a different survivor would mis-resolve to the dead declared owner instead of this adopter (#157).
Source§fn read_history<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_history<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
workflow_id in ascending sequence order. Read moreSource§fn read_history_from<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
from_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_history_from<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
from_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
workflow_id restricted to events with sequence number
greater than or equal to from_seq, in ascending sequence order. Read moreSource§fn read_run_chain<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<RunSummary>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_run_chain<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<RunSummary>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
workflow_id in continuation order.Source§fn list_workflow_ids<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_workflow_ids<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn list_active<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_active<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
WorkflowStatus::Running. Read moreSource§fn list_paused<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_paused<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
WorkflowStatus::Paused. Read moreSource§fn stream_heads<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StreamHead>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stream_heads<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StreamHead>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
seq of its last event —
the stream-side half of the handshake that lets a boot trust a
visibility row instead of opening the history behind it
(crate::visibility::head). Read moreSource§fn query<'life0, 'life1, 'async_trait>(
&'life0 self,
filter: &'life1 WorkflowFilter,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowSummary>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn query<'life0, 'life1, 'async_trait>(
&'life0 self,
filter: &'life1 WorkflowFilter,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorkflowSummary>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
filter.Source§fn schedule_timer<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
timer_id: &'life2 TimerId,
fire_at: DateTime<Utc>,
armed_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn schedule_timer<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
timer_id: &'life2 TimerId,
fire_at: DateTime<Utc>,
armed_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn expired_timers<'life0, 'async_trait>(
&'life0 self,
as_of: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<TimerEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn expired_timers<'life0, 'async_trait>(
&'life0 self,
as_of: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<Vec<TimerEntry>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fire_at is less than or equal to as_of.Source§fn retire_timer<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
timer_id: &'life2 TimerId,
fire_at: DateTime<Utc>,
armed_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<TimerRetirement, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn retire_timer<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
timer_id: &'life2 TimerId,
fire_at: DateTime<Utc>,
armed_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<TimerRetirement, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
(workflow_id, timer_id) — but only
while the row still carries exactly the (fire_at, armed_seq)
identity of the arming being retired. Read moreSource§impl WritableEventStore for InstrumentedEventStore
impl WritableEventStore for InstrumentedEventStore
Source§fn append_with_outbox<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
token: WriteToken,
workflow_id: &'life1 WorkflowId,
events: &'life2 [Event],
expected_seq: u64,
outbox_rows: &'life3 [OutboxRow],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn append_with_outbox<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
token: WriteToken,
workflow_id: &'life1 WorkflowId,
events: &'life2 [Event],
expected_seq: u64,
outbox_rows: &'life3 [OutboxRow],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Forward the atomic durable-outbox append to the inner store.
The default trait method REFUSES a non-empty outbox_rows slice (to stop
an outbox-unaware backend silently dropping fan-out rows). Without this
override the engine — which writes through this decorator — would never
reach the inner haematite store’s outbox-capable append, so a commissioned
(outbox.enabled) server could not stage a single fan-out member. We
delegate to the inner store so its atomicity guarantee (events + rows
commit together) holds, and observe the same append latency bucket and
lifecycle metrics as a plain append.
Source§fn rearm_outbox_pending<'life0, 'life1, 'async_trait>(
&'life0 self,
rows: &'life1 [OutboxRow],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn rearm_outbox_pending<'life0, 'life1, 'async_trait>(
&'life0 self,
rows: &'life1 [OutboxRow],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Forward the crash-recovery outbox re-arm to the inner store.
As with Self::append_with_outbox, the refusing default would strand a
recovered fan-out member because the engine re-arms through this decorator.
Source§fn settle_outbox_row_cancelled<'life0, 'life1, 'async_trait>(
&'life0 self,
dispatch_key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn settle_outbox_row_cancelled<'life0, 'life1, 'async_trait>(
&'life0 self,
dispatch_key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Forward the fan-out cancellation settle to the inner store.
MUST be forwarded: the trait default is a SILENT Ok(()) no-op, so
without this override a cancelled fan-out ordinal’s outbox row is never
settled on an outbox.enabled server — it stays claimable and the
dispatcher re-dispatches the cancelled activity (the same silent-default
forwarding hazard as the per-shard failover seam, #157). Timed under the
shared write bucket like the sibling outbox re-arm.
Source§fn settle_workflow_outbox_rows_cancelled<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn settle_workflow_outbox_rows_cancelled<'life0, 'life1, 'async_trait>(
&'life0 self,
workflow_id: &'life1 WorkflowId,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Forward the workflow-terminal outbox settle (#253) to the inner store.
MUST be forwarded for the same reason as
Self::settle_outbox_row_cancelled: the trait default is a silent
empty-Ok no-op, and the Recorder settles a terminal workflow’s rows
through this decorator — inheriting the default would leave a dead
workflow’s rows claimable and redeliverable. Timed under the shared
write bucket like the sibling settle.
Source§fn append<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
token: WriteToken,
workflow_id: &'life1 WorkflowId,
events: &'life2 [Event],
expected_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn append<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
token: WriteToken,
workflow_id: &'life1 WorkflowId,
events: &'life2 [Event],
expected_seq: u64,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
events to workflow_id when the stored history head equals
expected_seq. Read moreAuto Trait Implementations§
impl !Freeze for InstrumentedEventStore
impl !RefUnwindSafe for InstrumentedEventStore
impl !UnwindSafe for InstrumentedEventStore
impl Send for InstrumentedEventStore
impl Sync for InstrumentedEventStore
impl Unpin for InstrumentedEventStore
impl UnsafeUnpin for InstrumentedEventStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> EventStore for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoMaybeUndefined<T> for T
impl<T> IntoMaybeUndefined<T> for T
Source§fn into_maybe_undefined(self) -> MaybeUndefined<T>
fn into_maybe_undefined(self) -> MaybeUndefined<T>
Source§impl<T> IntoOption<T> for T
impl<T> IntoOption<T> for T
Source§fn into_option(self) -> Option<T>
fn into_option(self) -> Option<T>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request