Enum tor_error::retriable::RetryTime

source ·
#[non_exhaustive]
pub enum RetryTime { Immediate, AfterWaiting, After(Duration), At(Instant), Never, }
Expand description

A description of when an operation may be retried.

§Retry times values are contextual.

Note that retrying is necessarily contextual, depending on what exactly we’re talking about retrying.

For an example of how context matters: suppose that we try to build a circuit, and encounter a failure extending to the second hop. If we try to build a circuit through the same path immediately, it’s likely to fail again. But if we try to build a circuit through a different path, then there’s no reason to expect that same kind of error.

Thus, the same inner error condition (“failed to extend to the nth hop”) can indicate either a “Retry after waiting for a while” or “Retry immediately.”

§Retry times depend on what we think might change.

Whether retrying will help depends on what we think is likely to change in the near term.

For example, we generally assume an unreachable relay has some likelihood of becoming reachable in the near future, and therefore connecting to such a relay is worth retrying.

On the other hand, we don’t assume that the network is changing wildly over time. Thus, if there is currently no relay that supports delivering traffic to port 23 (telnet), we say that building a request for such a relay is not retriable, even though technically such a relay might appear in the next consensus.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Immediate

The operation can be retried immediately, and no delay is needed.

The recipient of this RetryTime variant may retry the operation immediately without waiting.

This case should be used cautiously: it risks making code retry in a loop without delay. It should only be used for error conditions that are necessarily produced via a process that itself introduces a delay. (For example, this case is suitable for errors caused by a remote timeout.)

§

AfterWaiting

The operation can be retried after a short delay, to prevent overloading the network.

The recipient of this RetryTime variant should delay a short amount of time before retrying. The amount of time to delay should be randomized, and should tend to grow larger the more failures there have been recently for the given operation. (The RetryDelay type from tor-basic-utils is suitable for managing this calculation.)

This case should be used for problems that tend to be “self correcting”, such as remote server failures (the server might come back up).

§

After(Duration)

The operation can be retried after a particular delay.

The recipient of this RetryTime variant should wait for at least the given duration before retrying the operation.

This case should only be used if there is some reason not to return AfterWaiting: for example, if the implementor is providing their own back-off algorithm instead of using RetryDelay.

(This is a separate variant from At, since the constructor may not have convenient access to (a mocked view of) the current time. If you know that the current time is now, then After(d) is equivalent to At(now + d).)

§

At(Instant)

The operation can be retried at some particular time in the future.

The recipient of this this RetryTime variant should wait until the current time (as returned by Instant::now or SleepProvider::now as appropriate) is at least this given instant.

This case is appropriate for when we have a failure condition caused by waiting for multiple other timeouts. (For example, if we believe that all our guards are down, then we won’t be able to try getting a guard until the next time guard is scheduled to be marked as retriable.)

§

Never

Retrying is unlikely to make this operation succeed, unless something else is fixed first.

The recipient of this RetryTime variant should generally give up, and stop retrying the given operation.

We don’t mean “literally” that the operation will never succeed: only that retrying it in the near future without fixing the underlying cause is unlikely to help.

This case is appropriate for issues like misconfiguration, internal errors, and requests for operations that the network doesn’t support.

This case is also appropriate for a problem that is “technically” retriable, but where any resolution is likelier to take days or weeks instead of minutes or hours.

Implementations§

source§

impl RetryTime

source

pub fn absolute<F>(self, now: Instant, choose_delay: F) -> AbsRetryTime
where F: FnOnce() -> Duration,

Convert this RetryTime in to an absolute time.

Requires that now is the current time, and choose_delay is a function to choose a delay for RetryTime::AfterWaiting.

source

pub fn earliest_absolute<I, F>( items: I, now: Instant, choose_delay: F ) -> Option<AbsRetryTime>
where I: Iterator<Item = RetryTime>, F: FnOnce() -> Duration,

Convert all the provided items into AbsRetryTime values, and return the earliest one.

Requires that now is the current time, and choose_delay is a function to choose a delay for RetryTime::AfterWaiting.

Differs from items.map(AbsRetryTime::absolute(now, choose_delay)).min() in that it calls choose_delay at most once.

source

pub fn earliest_approx<I>(items: I) -> Option<RetryTime>
where I: Iterator<Item = RetryTime>,

Return the “approximately earliest” item for an iterator of retry times.

This is necessarily an approximation, since we can’t be sure what time will be chosen if the retry is supposed to happen at a random time, and therefore cannot tell whether AfterWaiting comes before or after particular At and After instances.

If you need an exact answer, use earliest_absolute.

source

pub fn loose_cmp(&self, other: &Self) -> Ordering

A loose-but-total comparison operator, suitable for choosing a retry time when multiple attempts have failed.

If you need an absolute comparison operator, convert to AbsRetryTime first.

See also: LooseCmpRetryTime, a wrapper for RetryTime that uses this comparison.

Trait Implementations§

source§

impl Clone for RetryTime

source§

fn clone(&self) -> RetryTime

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for RetryTime

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'_enum> From<&'_enum RetryTime> for RetryTimeDiscriminants

source§

fn from(val: &'_enum RetryTime) -> RetryTimeDiscriminants

Converts to this type from the input type.
source§

impl From<LooseCmpRetryTime> for RetryTime

source§

fn from(original: LooseCmpRetryTime) -> Self

Converts to this type from the input type.
source§

impl From<RetryTime> for LooseCmpRetryTime

source§

fn from(original: RetryTime) -> LooseCmpRetryTime

Converts to this type from the input type.
source§

impl From<RetryTime> for RetryTimeDiscriminants

source§

fn from(val: RetryTime) -> RetryTimeDiscriminants

Converts to this type from the input type.
source§

impl PartialEq for RetryTime

source§

fn eq(&self, other: &RetryTime) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for RetryTime

source§

impl Eq for RetryTime

source§

impl StructuralPartialEq for RetryTime

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more