pub struct IdempotencyStore { /* private fields */ }Expand description
Store for tracking idempotent request deduplication.
The remote node uses this to prevent duplicate execution while an operation
is in flight and during the configured post-terminal retention window. The
guarantee does not survive store reset or terminal-record eviction.
When a SpawnRequest arrives:
- Atomically check and record the idempotency key
- If new: execute the already-recorded operation
- If duplicate: attach to the canonical task or return its cached outcome
- If conflict (same key, different params): reject
In-flight entries are retained for the operation lifetime. Once an entry is completed, it is retained for the configured TTL so retries can observe the canonical outcome. Callers must complete every admitted entry when the operation reaches a terminal state.
§Thread Safety
The store is designed for single-threaded use within the deterministic lab runtime. For production multi-threaded use, wrap in a lock.
Implementations§
Source§impl IdempotencyStore
impl IdempotencyStore
Sourcepub fn new(default_ttl: Duration) -> Self
pub fn new(default_ttl: Duration) -> Self
Creates a new idempotency store with the given default TTL.
Sourcepub fn check_and_record(
&mut self,
key: IdempotencyKey,
remote_task_id: RemoteTaskId,
request: IdempotencyRequestFingerprint,
now: Time,
) -> DedupDecision
pub fn check_and_record( &mut self, key: IdempotencyKey, remote_task_id: RemoteTaskId, request: IdempotencyRequestFingerprint, now: Time, ) -> DedupDecision
Atomically checks a request and records it when it is new.
A DedupDecision::New result guarantees that the supplied key and
canonical task ID were inserted before this method returned. Holding the
store’s exclusive borrow across both steps prevents a caller-visible
check/record gap.
Sourcepub fn complete(
&mut self,
key: &IdempotencyKey,
remote_task_id: RemoteTaskId,
outcome: RemoteOutcome,
now: Time,
) -> bool
pub fn complete( &mut self, key: &IdempotencyKey, remote_task_id: RemoteTaskId, outcome: RemoteOutcome, now: Time, ) -> bool
Updates the outcome of the canonical task and starts its terminal-result
retention window at now.
The task ID fences record generations after an expired key is admitted again. A delayed completion from the previous generation is rejected.
Returns true if the matching canonical record was found and updated.
Sourcepub fn evict_expired(&mut self, now: Time) -> usize
pub fn evict_expired(&mut self, now: Time) -> usize
Evicts terminal entries whose retention deadline has elapsed.
In-flight entries are never evicted by this method.
Returns the number of entries evicted.