mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
Outbound nexus operation and callback requests used transports without HTTP/2 health checks: the CHASM nexus transport provider returned the global http.DefaultTransport, and both callback HTTPCallerProviders used a zero-value http.Client. A silently broken connection (peer dropped it without a GOAWAY or RST) therefore stays in the pool and stalls every request multiplexed onto it until their individual deadlines expire. Add common.NewHTTPTransport, which builds a transport with http.DefaultTransport's field values and sets ReadIdleTimeout=15s / PingTimeout=5s via http2.ConfigureTransports, and use it for: - chasm/lib/nexusoperation (also covers components/nexusoperations, which bridges to the same ClientProvider) - chasm/lib/callback and components/callbacks - RPCFactory.createLocalFrontendHTTPClient, used for worker-target nexus calls and local callbacks - FrontendHTTPClientCache.newClientForCluster, used for cross-cluster callbacks The last two already hand-rolled the same copy of DefaultTransport's fields, so they now share it. The helper takes the TLS config as a parameter instead of letting callers assign it afterwards: h2 is negotiated via ALPN, so replacing TLSClientConfig after http2.ConfigureTransports would silently fall back to HTTP/1.1. It clones the config, since both frontend clients pass one cached by localStoreTlsProvider and shared with gRPC clients, and enabling h2 appends to NextProtos. Cert rotation is unaffected as it goes through the GetClientCertificate callback, which Clone carries over. Note that cleartext h2c is not negotiated, so for the two frontend clients the keepalive only applies when TLS is configured. Also drop components/nexusoperations.ResponseSizeLimiter along with the LimitedReadCloser it was the only user of. It had no callers: the CHASM clientProviderFactory is what wraps the transport now, via its own responseSizeLimiter built on http.MaxBytesReader. Being exported, the dead code escaped the unused linter. ErrResponseBodyTooLarge moves to executors.go, which still raises it from the payload size check.