tower/buffer/layer.rs
1use super::service::Buffer;
2use std::{fmt, marker::PhantomData};
3use tower_layer::Layer;
4use tower_service::Service;
5
6/// Adds an mpsc buffer in front of an inner service.
7///
8/// The default Tokio executor is used to run the given service,
9/// which means that this layer can only be used on the Tokio runtime.
10///
11/// See the module documentation for more details.
12pub struct BufferLayer<Request> {
13 bound: usize,
14 _p: PhantomData<fn(Request)>,
15}
16
17impl<Request> BufferLayer<Request> {
18 /// Creates a new [`BufferLayer`] with the provided `bound`.
19 ///
20 /// `bound` gives the maximal number of requests that can be queued for the service before
21 /// backpressure is applied to callers.
22 ///
23 /// # A note on choosing a `bound`
24 ///
25 /// When [`Buffer`]'s implementation of [`poll_ready`] returns [`Poll::Ready`], it reserves a
26 /// slot in the channel for the forthcoming [`call`]. However, if this call doesn't arrive,
27 /// this reserved slot may be held up for a long time. As a result, it's advisable to set
28 /// `bound` to be at least the maximum number of concurrent requests the [`Buffer`] will see.
29 /// If you do not, all the slots in the buffer may be held up by futures that have just called
30 /// [`poll_ready`] but will not issue a [`call`], which prevents other senders from issuing new
31 /// requests.
32 ///
33 /// [`Poll::Ready`]: std::task::Poll::Ready
34 /// [`call`]: crate::Service::call
35 /// [`poll_ready`]: crate::Service::poll_ready
36 pub const fn new(bound: usize) -> Self {
37 BufferLayer {
38 bound,
39 _p: PhantomData,
40 }
41 }
42}
43
44impl<S, Request> Layer<S> for BufferLayer<Request>
45where
46 S: Service<Request> + Send + 'static,
47 S::Future: Send,
48 S::Error: Into<crate::BoxError> + Send + Sync,
49 Request: Send + 'static,
50{
51 type Service = Buffer<Request, S::Future>;
52
53 fn layer(&self, service: S) -> Self::Service {
54 Buffer::new(service, self.bound)
55 }
56}
57
58impl<Request> fmt::Debug for BufferLayer<Request> {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 f.debug_struct("BufferLayer")
61 .field("bound", &self.bound)
62 .finish()
63 }
64}
65
66impl<Request> Clone for BufferLayer<Request> {
67 fn clone(&self) -> Self {
68 Self {
69 bound: self.bound,
70 _p: PhantomData,
71 }
72 }
73}
74
75impl<Request> Copy for BufferLayer<Request> {}