/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tower-0.5.2/src/load/completion.rs
Line | Count | Source |
1 | | //! Application-specific request completion semantics. |
2 | | |
3 | | use futures_core::ready; |
4 | | use pin_project_lite::pin_project; |
5 | | use std::{ |
6 | | future::Future, |
7 | | pin::Pin, |
8 | | task::{Context, Poll}, |
9 | | }; |
10 | | |
11 | | /// Attaches `H`-typed completion tracker to `V` typed values. |
12 | | /// |
13 | | /// Handles (of type `H`) are intended to be RAII guards that primarily implement [`Drop`] and update |
14 | | /// load metric state as they are dropped. This trait allows implementors to "forward" the handle |
15 | | /// to later parts of the request-handling pipeline, so that the handle is only dropped when the |
16 | | /// request has truly completed. |
17 | | /// |
18 | | /// This utility allows load metrics to have a protocol-agnostic means to track streams past their |
19 | | /// initial response future. For example, if `V` represents an HTTP response type, an |
20 | | /// implementation could add `H`-typed handles to each response's extensions to detect when all the |
21 | | /// response's extensions have been dropped. |
22 | | /// |
23 | | /// A base `impl<H, V> TrackCompletion<H, V> for CompleteOnResponse` is provided to drop the handle |
24 | | /// once the response future is resolved. This is appropriate when a response is discrete and |
25 | | /// cannot comprise multiple messages. |
26 | | /// |
27 | | /// In many cases, the `Output` type is simply `V`. However, [`TrackCompletion`] may alter the type |
28 | | /// in order to instrument it appropriately. For example, an HTTP [`TrackCompletion`] may modify |
29 | | /// the body type: so a [`TrackCompletion`] that takes values of type |
30 | | /// [`http::Response<A>`][response] may output values of type [`http::Response<B>`][response]. |
31 | | /// |
32 | | /// [response]: https://docs.rs/http/latest/http/response/struct.Response.html |
33 | | pub trait TrackCompletion<H, V>: Clone { |
34 | | /// The instrumented value type. |
35 | | type Output; |
36 | | |
37 | | /// Attaches a `H`-typed handle to a `V`-typed value. |
38 | | fn track_completion(&self, handle: H, value: V) -> Self::Output; |
39 | | } |
40 | | |
41 | | /// A [`TrackCompletion`] implementation that considers the request completed when the response |
42 | | /// future is resolved. |
43 | | #[derive(Clone, Copy, Debug, Default)] |
44 | | #[non_exhaustive] |
45 | | pub struct CompleteOnResponse; |
46 | | |
47 | | pin_project! { |
48 | | /// Attaches a `C`-typed completion tracker to the result of an `F`-typed [`Future`]. |
49 | | #[derive(Debug)] |
50 | | pub struct TrackCompletionFuture<F, C, H> { |
51 | | #[pin] |
52 | | future: F, |
53 | | handle: Option<H>, |
54 | | completion: C, |
55 | | } |
56 | | } |
57 | | |
58 | | // ===== impl InstrumentFuture ===== |
59 | | |
60 | | impl<F, C, H> TrackCompletionFuture<F, C, H> { |
61 | | /// Wraps a future, propagating the tracker into its value if successful. |
62 | 0 | pub const fn new(completion: C, handle: H, future: F) -> Self { |
63 | 0 | TrackCompletionFuture { |
64 | 0 | future, |
65 | 0 | completion, |
66 | 0 | handle: Some(handle), |
67 | 0 | } |
68 | 0 | } |
69 | | } |
70 | | |
71 | | impl<F, C, H, T, E> Future for TrackCompletionFuture<F, C, H> |
72 | | where |
73 | | F: Future<Output = Result<T, E>>, |
74 | | C: TrackCompletion<H, T>, |
75 | | { |
76 | | type Output = Result<C::Output, E>; |
77 | | |
78 | 0 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
79 | 0 | let this = self.project(); |
80 | 0 | let rsp = ready!(this.future.poll(cx))?; |
81 | 0 | let h = this.handle.take().expect("handle"); |
82 | 0 | Poll::Ready(Ok(this.completion.track_completion(h, rsp))) |
83 | 0 | } |
84 | | } |
85 | | |
86 | | // ===== CompleteOnResponse ===== |
87 | | |
88 | | impl<H, V> TrackCompletion<H, V> for CompleteOnResponse { |
89 | | type Output = V; |
90 | | |
91 | 0 | fn track_completion(&self, handle: H, value: V) -> V { |
92 | 0 | drop(handle); |
93 | 0 | value |
94 | 0 | } |
95 | | } |