Struct TimeoutLayer

Source
pub struct TimeoutLayer { /* private fields */ }
Expand description

Add timeout for every operation to avoid slow or unexpected hang operations.

For example, a dead connection could hang a databases sql query. TimeoutLayer will break this connection and returns an error so users can handle it by retrying or print to users.

§Notes

TimeoutLayer treats all operations in two kinds:

  • Non IO Operation like stat, delete they operate on a single file. We control them by setting timeout.
  • IO Operation like read, Reader::read and Writer::write, they operate on data directly, we control them by setting io_timeout.

§Default

  • timeout: 60 seconds
  • io_timeout: 10 seconds

§Panics

TimeoutLayer will drop the future if the timeout is reached. This might cause the internal state of the future to be broken. If underlying future moves ownership into the future, it will be dropped and will neven return back.

For example, while using TimeoutLayer with RetryLayer at the same time, please make sure timeout layer showed up before retry layer.



let op = Operator::new(services::Memory::default())?
    // This is fine, since timeout happen during retry.
    .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
    .layer(RetryLayer::new())
    // This is wrong. Since timeout layer will drop future, leaving retry layer in a bad state.
    .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
    .finish();
Ok(())

§Examples

The following examples will create a timeout layer with 10 seconds timeout for all non-io operations, 3 seconds timeout for all io operations.



let _ = Operator::new(services::Memory::default())?
    .layer(
        TimeoutLayer::default()
            .with_timeout(Duration::from_secs(10))
            .with_io_timeout(Duration::from_secs(3)),
    )
    .finish();
Ok(())

§Implementation Notes

TimeoutLayer is using tokio::time::timeout to implement timeout for operations. And IO Operations insides reader, writer will use Pin<Box<tokio::time::Sleep>> to track the timeout.

This might introduce a bit overhead for IO operations, but it’s the only way to implement timeout correctly. We used to implement timeout layer in zero cost way that only stores a std::time::Instant and check the timeout by comparing the instant with current time. However, it doesn’t work for all cases.

For examples, users TCP connection could be in Busy ESTAB state. In this state, no IO event will be emitted. The runtime will never poll our future again. From the application side, this future is hanging forever until this TCP connection is closed for reaching the linux net.ipv4.tcp_retries2 times.

Implementations§

Source§

impl TimeoutLayer

Source

pub fn new() -> Self

Create a new TimeoutLayer with default settings.

Source

pub fn with_timeout(self, timeout: Duration) -> Self

Set timeout for TimeoutLayer with given value.

This timeout is for all non-io operations like stat, delete.

Source

pub fn with_io_timeout(self, timeout: Duration) -> Self

Set io timeout for TimeoutLayer with given value.

This timeout is for all io operations like read, Reader::read and Writer::write.

Source

pub fn with_speed(self, _: u64) -> Self

👎Deprecated: with speed is not supported anymore, please use with_io_timeout instead

Set speed for TimeoutLayer with given value.

§Notes

The speed should be the lower bound of the IO speed. Set this value too large could result in all write operations failing.

§Panics

This function will panic if speed is 0.

Trait Implementations§

Source§

impl Clone for TimeoutLayer

Source§

fn clone(&self) -> TimeoutLayer

Returns a duplicate 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 Default for TimeoutLayer

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<A: Access> Layer<A> for TimeoutLayer

Source§

type LayeredAccess = TimeoutAccessor<A>

The layered accessor that returned by this layer.
Source§

fn layer(&self, inner: A) -> Self::LayeredAccess

Intercept the operations on the underlying storage.

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ServiceExt for T

Source§

fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>
where Self: Sized,

Apply a transformation to the response body. Read more
Source§

fn decompression(self) -> Decompression<Self>
where Self: Sized,

Decompress response bodies. Read more
Source§

fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using HTTP status codes. Read more
Source§

fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using gRPC headers. Read more
Source§

fn follow_redirects(self) -> FollowRedirect<Self>
where Self: Sized,

Follow redirect resposes using the Standard policy. Read more
Source§

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

Source§

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>,

Source§

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>,

Source§

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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<T> MaybeSend for T
where T: Send,