conjure_runtime/
client.rs1use crate::builder::CachedConfig;
15use crate::service::gzip::{DecodedBody, GzipLayer};
16use crate::service::http_error::HttpErrorLayer;
17use crate::service::map_error::MapErrorLayer;
18use crate::service::metrics::MetricsLayer;
19use crate::service::node::{NodeMetricsLayer, NodeSelectorLayer, NodeUriLayer};
20use crate::service::proxy::ProxyLayer;
21use crate::service::raw::{RawClient, RawResponseBody};
22use crate::service::response_body::ResponseBodyLayer;
23use crate::service::retry::RetryLayer;
24use crate::service::root_span::RootSpanLayer;
25use crate::service::trace_propagation::TracePropagationLayer;
26use crate::service::user_agent::UserAgentLayer;
27use crate::service::wait_for_spans::{WaitForSpansBody, WaitForSpansLayer};
28use crate::service::Service;
29use crate::service::{Identity, Layer, ServiceBuilder, Stack};
30use crate::weak_cache::Cached;
31use crate::{builder, BodyWriter, Builder, ResponseBody};
32use arc_swap::ArcSwap;
33use conjure_error::Error;
34#[cfg(not(target_arch = "wasm32"))]
35use conjure_http::client::{AsyncClient, AsyncRequestBody};
36use conjure_http::client::{AsyncService, ConjureRuntime};
37#[cfg(target_arch = "wasm32")]
38use conjure_http::client::{
39 LocalAsyncClient as AsyncClient, LocalAsyncRequestBody as AsyncRequestBody,
40};
41use conjure_runtime_config::ServiceConfig;
42use http::{Request, Response};
43use refreshable::Subscription;
44use std::sync::Arc;
45
46macro_rules! layers {
47 () => { Identity };
48 ($layer:ty, $($rem:tt)*) => { Stack<$layer, layers!($($rem)*)> };
49}
50
51type BaseLayer = layers!(
52 ResponseBodyLayer,
53 MetricsLayer,
54 RootSpanLayer,
55 RetryLayer,
56 HttpErrorLayer,
57 WaitForSpansLayer,
58 NodeSelectorLayer,
59 NodeUriLayer,
60 NodeMetricsLayer,
61 ProxyLayer,
62 TracePropagationLayer,
63 UserAgentLayer,
64 GzipLayer,
65 MapErrorLayer,
66);
67
68type BaseService = <BaseLayer as Layer<RawClient>>::Service;
69
70pub(crate) type BaseBody = WaitForSpansBody<DecodedBody<RawResponseBody>>;
71
72pub(crate) struct ClientState {
73 service: BaseService,
74}
75
76impl ClientState {
77 pub(crate) fn new(builder: &Builder<builder::Complete>) -> Result<ClientState, Error> {
78 let client = RawClient::new(builder)?;
79
80 let service = ServiceBuilder::new()
81 .layer(ResponseBodyLayer)
82 .layer(MetricsLayer::new(builder))
83 .layer(RootSpanLayer)
84 .layer(RetryLayer::new(builder))
85 .layer(HttpErrorLayer::new(builder))
86 .layer(WaitForSpansLayer)
87 .layer(NodeSelectorLayer::new(builder)?)
88 .layer(NodeUriLayer)
89 .layer(NodeMetricsLayer)
90 .layer(ProxyLayer::new(builder)?)
91 .layer(TracePropagationLayer)
92 .layer(UserAgentLayer::new(builder))
93 .layer(GzipLayer)
94 .layer(MapErrorLayer)
95 .service(client);
96
97 Ok(ClientState { service })
98 }
99}
100
101#[derive(Clone)]
103pub struct Client {
104 state: Arc<ArcSwap<Cached<CachedConfig, ClientState>>>,
105 _subscription: Option<Arc<Subscription<ServiceConfig, Error>>>,
106}
107
108impl Client {
109 #[inline]
111 pub fn builder() -> Builder<builder::ServiceStage> {
112 Builder::new()
113 }
114}
115
116impl Client {
117 pub(crate) fn new(
118 state: Arc<ArcSwap<Cached<CachedConfig, ClientState>>>,
119 subscription: Option<Subscription<ServiceConfig, Error>>,
120 ) -> Client {
121 Client {
122 state,
123 _subscription: subscription.map(Arc::new),
124 }
125 }
126}
127
128impl AsyncService<Client> for Client {
129 fn new(client: Client, _: &Arc<ConjureRuntime>) -> Self {
130 client
131 }
132}
133
134impl AsyncClient for Client {
135 type BodyWriter = BodyWriter;
136
137 type ResponseBody = ResponseBody;
138
139 async fn send(
140 &self,
141 request: Request<AsyncRequestBody<'_, Self::BodyWriter>>,
142 ) -> Result<Response<Self::ResponseBody>, Error> {
143 self.state.load().service.call(request).await
144 }
145}