fix(adapters): upstream response decode fidelity (FWD-07, FWD-08, FWD-10, FWD-12) — core, tests follow

This commit is contained in:
2026-08-29 10:26:03 +00:00
parent 5df91cda25
commit 9bb8487c6d
4 changed files with 302 additions and 119 deletions
+23 -10
View File
@@ -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(())
}
}