pub struct InMemoryReplayGuard { /* private fields */ }Expand description
A bounded, in-process ReplayGuard: an LRU map from id to the digest
accepted under it, its retention deadline, and the response it produced.
§Suitable when
One process is the sole consumer for the recipient VID it serves, and
losing the record on restart is acceptable — that is, the window in which a
replay could arrive is shorter than the process’s uptime, or the transport
will not redeliver across a restart.
§Not suitable when
The consumer is replicated. Two replicas behind a load balancer each hold
their own map, so the same document accepted by replica A is Fresh at
replica B and the consequential effect happens twice — the exact failure
item 11 exists to prevent. Replicated deployments MUST back
ReplayGuard with a store shared by every replica, which is why the seam
is a trait.
Eviction is by capacity as well as by retain_until: a burst of distinct
documents can push an older record out before its retention deadline, and a
replay arriving after that would be accepted. Size the capacity above the
number of distinct documents the widest acceptance window can hold.
Implementations§
Source§impl InMemoryReplayGuard
impl InMemoryReplayGuard
Sourcepub fn new(capacity: usize) -> InMemoryReplayGuard
pub fn new(capacity: usize) -> InMemoryReplayGuard
A guard retaining at most capacity records.
§Panics
If capacity is zero. A guard that retains nothing answers Fresh to
every arrival, which is indistinguishable from having no guard at all —
and would be a silent, total defeat of item 11 rather than a visible
misconfiguration.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Number of records currently retained. Exposed for tests and metrics.
Sourcepub fn purge_expired(&self, now: DateTime<Utc>)
pub fn purge_expired(&self, now: DateTime<Utc>)
Drop every record whose retain_until has passed.
claim already treats an individual expired
record as absent, so calling this is an optimisation (it reclaims
memory) rather than a correctness requirement.
Trait Implementations§
Source§impl Default for InMemoryReplayGuard
impl Default for InMemoryReplayGuard
Source§fn default() -> InMemoryReplayGuard
fn default() -> InMemoryReplayGuard
10 000 records — a few megabytes at typical document sizes, and enough to cover a five-minute acceptance window at ~33 documents per second.
Source§impl ReplayGuard for InMemoryReplayGuard
impl ReplayGuard for InMemoryReplayGuard
Source§fn claim<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
digest: &'life2 DocumentDigest,
retain_until: Option<DateTime<Utc>>,
now: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<ReplayVerdict, ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
fn claim<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
digest: &'life2 DocumentDigest,
retain_until: Option<DateTime<Utc>>,
now: DateTime<Utc>,
) -> Pin<Box<dyn Future<Output = Result<ReplayVerdict, ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
Source§fn record_response<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
response: Option<&'life2 Value>,
) -> Pin<Box<dyn Future<Output = Result<(), ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
fn record_response<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
response: Option<&'life2 Value>,
) -> Pin<Box<dyn Future<Output = Result<(), ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
Source§fn release<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
digest: &'life2 DocumentDigest,
) -> Pin<Box<dyn Future<Output = Result<(), ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
fn release<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
digest: &'life2 DocumentDigest,
) -> Pin<Box<dyn Future<Output = Result<(), ReplayGuardError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
InMemoryReplayGuard: 'async_trait,
Auto Trait Implementations§
impl !Freeze for InMemoryReplayGuard
impl RefUnwindSafe for InMemoryReplayGuard
impl Send for InMemoryReplayGuard
impl Sync for InMemoryReplayGuard
impl Unpin for InMemoryReplayGuard
impl UnsafeUnpin for InMemoryReplayGuard
impl UnwindSafe for InMemoryReplayGuard
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
Source§impl<T> BorrowUnordered for T
impl<T> BorrowUnordered for T
fn as_unordered(&self) -> &Unordered<T>
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Clear for Twhere
T: InitializableFromZeroed + ?Sized,
impl<T> Clear for Twhere
T: InitializableFromZeroed + ?Sized,
Source§impl<T> InitializableFromZeroed for Twhere
T: Default,
impl<T> InitializableFromZeroed for Twhere
T: Default,
Source§unsafe fn initialize(place: *mut T)
unsafe fn initialize(place: *mut 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> 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::RequestSource§impl<T, U, C> IntoWithContext<U, C> for Twhere
U: FromWithContext<T, C>,
impl<T, U, C> IntoWithContext<U, C> for Twhere
U: FromWithContext<T, C>,
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> ResourceProvider<()> for T
impl<T> ResourceProvider<()> for T
Source§fn get_resource(&self) -> &()
fn get_resource(&self) -> &()
T.