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