pub struct RequestIdempotency { /* private fields */ }Expand description
Whether one outbound request may be replayed byte-for-byte without an idempotency key — the single fact a retry middleware needs and cannot work out for itself.
Attached to every request this crate sends as a
reqwest_middleware request extension, so a middleware reads it
with extensions.get::<RequestIdempotency>(). Only observable under
the middleware feature: reqwest 0.13 keeps
reqwest::Request::extensions_mut() pub(crate), so a bare
reqwest::Client has no extension map a caller can write to (see
client::http::HttpRequestBuilder::with_extension).
Absent means “assume not idempotent.” A middleware that finds no
RequestIdempotency in the extensions is talking to something other
than this client, or to a build where the extension could not be
attached; failing closed there is the same rule the rest of this
crate follows.
§How the value is chosen
By default it is derived from the HTTP method
(RequestIdempotency::for_method, RFC 9110 §9.2.2), which is
exactly right for REST CRUD: GET/DELETE are idempotent,
POST/PATCH are not. It is not right for two cases the method
alone cannot express, and for those the caller overrides it with
CratestackClient::with_idempotency:
- RPC. Every RPC call is
POST /rpc/{op_id}, so the method carries no information at all. The op’s real answer is theidempotent_by_defaultfield on theOpDescriptorthe schema macro emits for that op (cratestack_core::OpDescriptor) —truefor reads and@queryprocedures,falsefor mutations. - REST procedures.
POST /$procs/<name>is aPOSTwhatever the procedure does, so a@queryprocedure looks non-idempotent to the method-derived default.
Note that the REST-transport descriptor
(cratestack_core::RouteTransportDescriptor) does not carry an
idempotent_by_default field today — only the RPC-transport
OpDescriptor does. Wiring either descriptor through the generated
client so callers don’t have to pass it by hand is follow-up work;
this type and CratestackClient::with_idempotency are the runtime
half that makes it expressible at all.
Implementations§
Source§impl RequestIdempotency
impl RequestIdempotency
Sourcepub const IDEMPOTENT: Self
pub const IDEMPOTENT: Self
The request may be retried as-is.
Sourcepub const NOT_IDEMPOTENT: Self
pub const NOT_IDEMPOTENT: Self
The request must not be retried without an idempotency key.
Sourcepub const fn new(idempotent: bool) -> Self
pub const fn new(idempotent: bool) -> Self
Wraps a raw flag — e.g. an OpDescriptor’s
idempotent_by_default.
pub const fn is_idempotent(self) -> bool
Sourcepub fn for_method(method: &Method) -> Self
pub fn for_method(method: &Method) -> Self
The RFC 9110 §9.2.2 answer for a method: GET, HEAD, PUT,
DELETE, OPTIONS and TRACE are idempotent; everything else
— POST and PATCH included — is not.
PATCH is deliberately in the second group: RFC 5789 §2 makes
it explicitly non-idempotent, and cratestack’s generated PATCH
route is a partial update, which a retry after an unseen success
can re-apply against a changed row.
Trait Implementations§
Source§impl Clone for RequestIdempotency
impl Clone for RequestIdempotency
Source§fn clone(&self) -> RequestIdempotency
fn clone(&self) -> RequestIdempotency
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for RequestIdempotency
Source§impl Debug for RequestIdempotency
impl Debug for RequestIdempotency
impl Eq for RequestIdempotency
Source§impl Hash for RequestIdempotency
impl Hash for RequestIdempotency
Source§impl PartialEq for RequestIdempotency
impl PartialEq for RequestIdempotency
Source§fn eq(&self, other: &RequestIdempotency) -> bool
fn eq(&self, other: &RequestIdempotency) -> bool
self and other values to be equal, and is used by ==.impl StructuralPartialEq for RequestIdempotency
Auto Trait Implementations§
impl Freeze for RequestIdempotency
impl RefUnwindSafe for RequestIdempotency
impl Send for RequestIdempotency
impl Sync for RequestIdempotency
impl Unpin for RequestIdempotency
impl UnsafeUnpin for RequestIdempotency
impl UnwindSafe for RequestIdempotency
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more