This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-core/backend/pool.go

71 lines
1.9 KiB
Go

// Package backend — shared HTTP transport pool.
//
// SharedTransport returns a per-host *http.Transport that all backend instances
// targeting the same base URL share. This enables HTTP/2 multiplexing: multiple
// concurrent ChatStream calls share a single TLS connection to the same host.
package backend
import (
"crypto/tls"
"net"
"net/http"
"sync"
"time"
)
var (
transportsMu sync.Mutex
transports = make(map[string]*http.Transport)
)
// SharedTransport returns a shared *http.Transport for the given host key.
// The key should be "backend:baseURL" (e.g. "anthropic:https://api.anthropic.com").
// All callers sharing the same key share the same underlying TCP+TLS connections.
func SharedTransport(key string) *http.Transport {
transportsMu.Lock()
defer transportsMu.Unlock()
if t, ok := transports[key]; ok {
return t
}
t := &http.Transport{
ForceAttemptHTTP2: true,
MaxIdleConnsPerHost: 4,
IdleConnTimeout: 5 * time.Minute,
TLSHandshakeTimeout: 10 * time.Second,
// No ResponseHeaderTimeout — streaming responses have no header deadline.
DialContext: (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
}
transports[key] = t
return t
}
// SharedClient returns an *http.Client backed by the shared transport for key.
func SharedClient(key string) *http.Client {
return &http.Client{Transport: SharedTransport(key)}
}
// PoolStats returns the number of active transport entries.
func PoolStats() int {
transportsMu.Lock()
defer transportsMu.Unlock()
return len(transports)
}
// ClosePool closes all idle connections in all transports and clears the pool.
func ClosePool() {
transportsMu.Lock()
defer transportsMu.Unlock()
for _, t := range transports {
t.CloseIdleConnections()
}
transports = make(map[string]*http.Transport)
}