pub struct RetriableMessage<TKey, TMessage>{
pub key: TKey,
pub message: Option<TMessage>,
pub strategy: MessageRetryStrategy,
pub retry_hook: Option<Arc<dyn Fn(&TKey) + RefUnwindSafe + Send + Sync>>,
/* private fields */
}Expand description
A retriable message is a job message which will automatically be resubmitted to the factory in the event of a factory worker dropping the message due to failure (panic or unhandled error). This wraps the inner message in a struct which captures the drop, and if there’s still some retries left, will reschedule the work to the factory with captured state information.
IMPORTANT CAVEATS:
- Regular loadshed events will cause this message to be retried if there is still retries left
and the job isn’t expired unless you explicitely call
completed()in the discard handler. - Consumable types are not well supported here without some wrapping in Option types, which is
because the value is handled everywhere as
&mut refdue to the drop implementation requiring that it be so. This means that RPCs using crate::concurrency::oneshots likely won’t work without some real painful ergonomics. - Upon successful handling of the job, you need to mark it as
completed()at the end of your handling or discarding logic to state that it shouldn’t be retried on drop.
Fields§
§key: TKeyThe key to the retriable job
message: Option<TMessage>The message, which will be retried until it’s completed.
strategy: MessageRetryStrategyThe retry strategy
retry_hook: Option<Arc<dyn Fn(&TKey) + RefUnwindSafe + Send + Sync>>A function which will be executed upon the job’s retry flow being executed (helpful for logging, etc)
SAFETY: We utilize std::panic::catch_unwind here to best-effort prevent a potential user-level panic from causing a process abort. However if the handler logic panics, then the retry hook won’t be executed, but the job will still be retried.
Implementations§
Source§impl<TKey, TMessage> RetriableMessage<TKey, TMessage>
impl<TKey, TMessage> RetriableMessage<TKey, TMessage>
Sourcepub fn new(
key: TKey,
message: TMessage,
strategy: MessageRetryStrategy,
) -> RetriableMessage<TKey, TMessage>
pub fn new( key: TKey, message: TMessage, strategy: MessageRetryStrategy, ) -> RetriableMessage<TKey, TMessage>
Construct a new retriable message with the provided number of retries. If the retries are None, that means retry forever. [Some(0)] will mean no retries
Sourcepub fn set_retry_hook(
&mut self,
f: impl Fn(&TKey) + Send + Sync + RefUnwindSafe + 'static,
)
pub fn set_retry_hook( &mut self, f: impl Fn(&TKey) + Send + Sync + RefUnwindSafe + 'static, )
Attach a handler which will be executed when the job is retried (resubmitted to the factory).
Sourcepub fn from_job(
_: Job<TKey, TMessage>,
strategy: MessageRetryStrategy,
factory: ActorRef<FactoryMessage<TKey, RetriableMessage<TKey, TMessage>>>,
) -> Job<TKey, RetriableMessage<TKey, TMessage>>
pub fn from_job( _: Job<TKey, TMessage>, strategy: MessageRetryStrategy, factory: ActorRef<FactoryMessage<TKey, RetriableMessage<TKey, TMessage>>>, ) -> Job<TKey, RetriableMessage<TKey, TMessage>>
Convert a regular Job into a RetriableMessage capturing all the necessary state in order to perform retries on drop.
job: The Job to convertstrategy: The MessageRetryStrategy to use for this retriable messagefactory: The ActorRef of the factory which the job will be submitted to.
Returns a Job with message payload of RetriableMessage which can be retried should it be dropped prior
to having job.msg.completed() called.
Sourcepub fn capture_retry_state(
&mut self,
options: &JobOptions,
factory: ActorRef<FactoryMessage<TKey, RetriableMessage<TKey, TMessage>>>,
)
pub fn capture_retry_state( &mut self, options: &JobOptions, factory: ActorRef<FactoryMessage<TKey, RetriableMessage<TKey, TMessage>>>, )
Capture the necessary state information in order to perform retries automatically
options: The JobOptions of the original jobfactory: The ActorRef of the factory the job will be submitted to
Sourcepub fn completed(&mut self)
pub fn completed(&mut self)
Mark this message to not be retried upon being dropped, since it was handled successfully.
IMPORTANT: This should be called at the end of the handling logic, prior to returning from the worker’s message handler AND/OR from the discard logic. If you don’t provide a custom discard handler for jobs, then they will be auto-retried until a potential TTL is hit (or forever) and you may risk a spin-lock where an TTL expired job is submitted back to the factory, expire shedded again, dropped, and therefore retried forever. This is especially dangerous if you state that jobs should be retried forever.
Trait Implementations§
Source§impl<TKey, TMsg> Debug for RetriableMessage<TKey, TMsg>
impl<TKey, TMsg> Debug for RetriableMessage<TKey, TMsg>
Auto Trait Implementations§
impl<TKey, TMessage> Freeze for RetriableMessage<TKey, TMessage>
impl<TKey, TMessage> !RefUnwindSafe for RetriableMessage<TKey, TMessage>
impl<TKey, TMessage> Send for RetriableMessage<TKey, TMessage>
impl<TKey, TMessage> Sync for RetriableMessage<TKey, TMessage>where
TMessage: Sync,
impl<TKey, TMessage> Unpin for RetriableMessage<TKey, TMessage>
impl<TKey, TMessage> UnsafeUnpin for RetriableMessage<TKey, TMessage>where
TKey: UnsafeUnpin,
TMessage: UnsafeUnpin,
impl<TKey, TMessage> !UnwindSafe for RetriableMessage<TKey, TMessage>
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> 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> 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