The v2 module path is github.com/sony/gobreaker/v2 and the breaker is
generic. The code instantiates it with any, which matches the v1
Execute signature.
Three bugs fixed:
1. **Test suite timeout** — The main-package test suite timed out at 120s
because each failing request triggered 7 retries with exponential
backoff (500ms base → 10s max ≈ 25.5s per request). Tests that trip
the circuit breaker (3 requests × 25.5s = 76.5s) plus
TestStartHTTPProxy_ErrorHandlerConfigured (another 25.5s) pushed
cumulative time past the limit.
Fix: add `Client.RetryBaseDelayMs` / `Client.RetryMaxDelayMs` config
fields (env: CLIENT_RETRY_BASE_DELAY_MS / CLIENT_RETRY_MAX_DELAY_MS,
defaults 500ms / 10000ms). Tests override these to 10ms so retry
exhaustion completes in milliseconds. Full suite now runs in ~35s.
2. **effectiveCircuitBackoff float overflow** — On amd64, converting
`+Inf` (float64) to `time.Duration` (int64) saturates to MinInt64,
not MaxInt64. The existing "< base" guard then returned `base` instead
of `maxSaneCircuitBackoff`, breaking the sanity ceiling for an uncapped
config with a high trip count. Fix: detect `math.IsInf / math.IsNaN`
before the cast and return the ceiling directly.
3. **TestStartHTTPProxy_ErrorHandlerConfigured** — standalone top-level
test calling parseConfig() directly, bypassing the TestSuite override.
Now sets and restores RetryBaseDelayMs/RetryMaxDelayMs explicitly.
Co-authored-by: lukaszraczylo <[email protected]>
The WebSocket route skipped the ban and rate-limit checks that the HTTP
path enforced, and returned errors set no custom status, so circuit-open
became HTTP 500. The route now runs the same ban and rate-limit checks
before the upgrade, and a custom error handler maps errors to the
correct status, including 503 for circuit-open. The API and admin
listeners honour the BIND_ADDRESS option.
The shutdown component could observe the app before Listen ran.
fasthttp then treated Shutdown as a no-op and reset its stop flag.
The proxy started to serve after shutdown was requested.
Publish httpProxyApp from the OnListen hook and clear it after
Listen returns. Honor the shutdown context and retry until the
drain completes or the context expires. Gate the tests on the
publish signal with a bounded context.
On signal, main waited on wg for StartHTTPProxy's server.Listen, which never
returns because nothing called server.Shutdown(); it timed out after 10s and
process-exited, abruptly killing in-flight GraphQL requests.
Expose the proxy Fiber app and register an http-proxy Shutdown component so
server.Listen returns after Shutdown, letting connections drain. Guard the
shared app handle with a mutex (written by the StartHTTPProxy goroutine, read
by the shutdown component). Verified with build, vet, full test and full
race suite.
BREAKING CHANGE: upgrades the HTTP framework from gofiber/fiber/v2 to gofiber/fiber/v3, and gofiber/websocket/v2 to gofiber/contrib/v3/websocket.
- Handlers now take fiber.Ctx (interface) instead of *fiber.Ctx. - DisableStartupMessage moved from fiber.Config to fiber.ListenConfig on the proxy/api/monitoring Listen calls. - cors AllowOrigins is now []string; c.BodyParser -> c.Bind().Body(). - app.Test takes fiber.TestConfig instead of an int timeout (tests updated). - WebSocket swapped to contrib/v3/websocket (same Conn/New/Config/IsCloseError/IsWebSocketUpgrade API; Conn.Query preserved). - Adopts fasthttp v1.71.0 (pulled by fiber v3), resolving the v1.71 Host-header enforcement that broke the prior pinned-v1.69 workaround.
fix(connpool): the background keep-alive goroutine no longer reads the mutable global cfg (captures HostGraphQL/HealthcheckGraphQL at pool creation). Under v3 timing it raced with parseConfig/test cfg reassignment; go test -race ./... is now clean (0 data races).
test: make the circuit-breaker cache-fallback and request-coalescing integration tests deterministic (cache TTL outlives the retry loop; coalescing asserts against a measured single-request baseline instead of a hard-coded count); drop the flaky timing-ratio assertion in TestTimingAttackResistance (constant-time guarantee comes from subtle.ConstantTimeCompare, not wall-clock timing).
Verified: go build, go vet, golangci-lint (0 issues), go test -race ./... (all packages pass, 0 races), govulncheck (no vulnerabilities). App + dashboard + WebSocket verified live under v3 in single-node and cluster modes.