risingwave_common_service/
await_tree_middleware.rs1use std::sync::Arc;
16use std::sync::atomic::{AtomicU64, Ordering};
17use std::task::{Context, Poll};
18
19use either::Either;
20use futures::Future;
21use tonic::body::Body;
22use tower::{Layer, Service};
23
24pub type AwaitTreeRegistryRef = await_tree::Registry;
26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub struct GrpcCall {
30 pub desc: String,
31}
32
33#[derive(Clone)]
34pub struct AwaitTreeMiddlewareLayer {
35 registry: Option<AwaitTreeRegistryRef>,
36}
37
38impl AwaitTreeMiddlewareLayer {
39 pub fn new(registry: AwaitTreeRegistryRef) -> Self {
40 Self {
41 registry: Some(registry),
42 }
43 }
44
45 pub fn new_optional(registry: Option<AwaitTreeRegistryRef>) -> Self {
46 Self { registry }
47 }
48}
49
50impl<S> Layer<S> for AwaitTreeMiddlewareLayer {
51 type Service = AwaitTreeMiddleware<S>;
52
53 fn layer(&self, service: S) -> Self::Service {
54 AwaitTreeMiddleware {
55 inner: service,
56 registry: self.registry.clone(),
57 next_id: Default::default(),
58 }
59 }
60}
61
62#[derive(Clone)]
63pub struct AwaitTreeMiddleware<S> {
64 inner: S,
65 registry: Option<AwaitTreeRegistryRef>,
66 next_id: Arc<AtomicU64>,
67}
68
69impl<S> Service<http::Request<Body>> for AwaitTreeMiddleware<S>
70where
71 S: Service<http::Request<Body>> + Clone,
72{
73 type Error = S::Error;
74 type Response = S::Response;
75
76 type Future = impl Future<Output = Result<Self::Response, Self::Error>>;
77
78 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
79 self.inner.poll_ready(cx)
80 }
81
82 fn call(&mut self, req: http::Request<Body>) -> Self::Future {
83 let Some(registry) = self.registry.clone() else {
84 return Either::Left(self.inner.call(req));
85 };
86
87 let clone = self.inner.clone();
91 let mut inner = std::mem::replace(&mut self.inner, clone);
92
93 let id = self.next_id.fetch_add(1, Ordering::SeqCst);
94 let desc = if let Some(authority) = req.uri().authority() {
95 format!("{authority} - {id}")
96 } else {
97 format!("?? - {id}")
98 };
99 let key = GrpcCall { desc };
100
101 Either::Right(async move {
102 let root = registry.register(key, req.uri().path());
103
104 root.instrument(inner.call(req)).await
105 })
106 }
107}
108
109#[cfg(not(madsim))]
110impl<S: tonic::server::NamedService> tonic::server::NamedService for AwaitTreeMiddleware<S> {
111 const NAME: &'static str = S::NAME;
112}