fix(adapters): upstream response decode fidelity (FWD-07, FWD-08, FWD-10, FWD-12) — core, tests follow
This commit is contained in:
+23
-10
@@ -175,14 +175,22 @@ pub enum HttpClientBuildError {
|
||||
}
|
||||
|
||||
pub struct SharedHttpClient {
|
||||
inner: ArcSwap<ClientWithMiddleware>,
|
||||
config: ArcSwap<HttpClientConfig>,
|
||||
inner: ArcSwap<SharedHttpInner>,
|
||||
}
|
||||
|
||||
/// Joint holder for the client and its config so a reload swaps both in
|
||||
/// one atomic `ArcSwap::store` — a reader can never observe the new
|
||||
/// config paired with the previous client (FWD-12).
|
||||
#[derive(Clone)]
|
||||
struct SharedHttpInner {
|
||||
client: Arc<ClientWithMiddleware>,
|
||||
config: Arc<HttpClientConfig>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SharedHttpClient {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("SharedHttpClient")
|
||||
.field("config", &self.config.load())
|
||||
.field("config", &self.inner.load().config)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
@@ -196,27 +204,32 @@ impl SharedHttpClient {
|
||||
pub fn new(config: HttpClientConfig) -> Result<Self, HttpClientBuildError> {
|
||||
let client = build_client_sync(&config)?;
|
||||
Ok(Self {
|
||||
inner: ArcSwap::from_pointee(client),
|
||||
config: ArcSwap::from_pointee(config),
|
||||
inner: ArcSwap::from_pointee(SharedHttpInner {
|
||||
client: Arc::new(client),
|
||||
config: Arc::new(config),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn client(&self) -> Arc<ClientWithMiddleware> {
|
||||
self.inner.load_full()
|
||||
Arc::clone(&self.inner.load().client)
|
||||
}
|
||||
|
||||
pub fn config(&self) -> Arc<HttpClientConfig> {
|
||||
self.config.load_full()
|
||||
Arc::clone(&self.inner.load().config)
|
||||
}
|
||||
|
||||
/// Rebuild the underlying client and swap it in for new callers
|
||||
/// (in-flight requests complete on the previous client). PEM reads
|
||||
/// use `tokio::fs`, so this is safe to call from async contexts
|
||||
/// without blocking a worker.
|
||||
/// without blocking a worker. Client and config swap together in a
|
||||
/// single atomic store (FWD-12).
|
||||
pub async fn reload(&self, config: HttpClientConfig) -> Result<(), HttpClientBuildError> {
|
||||
let client = build_client(&config).await?;
|
||||
self.config.store(Arc::new(config));
|
||||
self.inner.store(Arc::new(client));
|
||||
self.inner.store(Arc::new(SharedHttpInner {
|
||||
client: Arc::new(client),
|
||||
config: Arc::new(config),
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user