Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
eae1b57
feat: circuit breakers
SkArchon Jun 16, 2025
0f8e6cd
feat: circuit breakers
SkArchon Jun 17, 2025
e6bd119
fix: tests
SkArchon Jun 17, 2025
75af19f
fix: changes
SkArchon Jun 17, 2025
8c3fb84
fix: circuit breaker
SkArchon Jun 17, 2025
d1288b2
fix: circuit breaker
SkArchon Jun 17, 2025
3a7317a
fix: cleanup mod
SkArchon Jun 17, 2025
6c1a657
fix: dependencies
SkArchon Jun 17, 2025
6a85b7a
fix: revert testenv
SkArchon Jun 17, 2025
213ef83
fix: linting
SkArchon Jun 17, 2025
6a9449d
fix: reset defaults
SkArchon Jun 17, 2025
eb41fff
fix: linter changes
SkArchon Jun 17, 2025
6ecb667
fix: added prometheus tests
SkArchon Jun 17, 2025
b18751d
fix: refactoring
SkArchon Jun 17, 2025
c5640d2
chore: temporary skip
SkArchon Jun 18, 2025
59905c5
chore: temp skip
SkArchon Jun 18, 2025
49e0cf2
chore: temp skip
SkArchon Jun 18, 2025
64dafb2
fix: temp skips
SkArchon Jun 18, 2025
3810736
fix: add enable
SkArchon Jun 18, 2025
981bfe0
fix: review comments
SkArchon Jun 18, 2025
1da66af
fix: update go.mod
SkArchon Jun 18, 2025
d0ff492
fix: tests
SkArchon Jun 20, 2025
5851867
fix: review comments
SkArchon Jun 21, 2025
fadc186
fix: review comments
SkArchon Jun 30, 2025
c4eefb6
fix: review comments
SkArchon Jun 30, 2025
e5ae625
fix: review comments
SkArchon Jun 30, 2025
6892dc5
fix: review comments
SkArchon Jun 30, 2025
4d53170
Merge remote-tracking branch 'origin/main' into milinda/eng-7100-simp…
SkArchon Jun 30, 2025
070875c
fix: review comments
SkArchon Jun 30, 2025
bd82262
fix: typo comment
SkArchon Jun 30, 2025
b2e966f
Merge branch 'main' into milinda/eng-7100-simple-circuit-breaker-for-…
StarpTech Jul 1, 2025
df2da77
fix: reflect optional
SkArchon Jul 1, 2025
0dc59d8
fix: review comments
SkArchon Jul 1, 2025
590af7b
fix: review comments
SkArchon Jul 1, 2025
7006d26
fix: refactoring
SkArchon Jul 1, 2025
b0280f7
fix: added context package
SkArchon Jul 1, 2025
6d32f83
fix: review comments
SkArchon Jul 1, 2025
44747e4
fix: subgraph name
SkArchon Jul 1, 2025
841e48e
fix: tests
SkArchon Jul 1, 2025
25e8ee0
fix: configuration
SkArchon Jul 1, 2025
9a2f4ec
fix: tests
SkArchon Jul 1, 2025
fa3ad6e
fix: add lock
SkArchon Jul 1, 2025
4f5349d
fix: review comments
SkArchon Jul 4, 2025
e467a2d
fix: updates
SkArchon Jul 6, 2025
fb990ca
Merge remote-tracking branch 'origin/main' into milinda/eng-7100-simp…
SkArchon Jul 6, 2025
f1ad2b5
fix: tests
SkArchon Jul 6, 2025
9d9d193
fix: tests
SkArchon Jul 6, 2025
ea9f922
fix: linter
SkArchon Jul 6, 2025
351a65c
fix: update tests
SkArchon Jul 6, 2025
da3200f
fix: refactoring
SkArchon Jul 6, 2025
b3e972f
fix: tests
SkArchon Jul 7, 2025
43e1292
fix: enable cbs for all tests
SkArchon Jul 7, 2025
737eb02
fix: set the concurrent max requests
SkArchon Jul 7, 2025
2410e15
fix: update configurations
SkArchon Jul 7, 2025
8082187
fix: metric updates
SkArchon Jul 7, 2025
326a2c2
fix: tests
SkArchon Jul 7, 2025
ffa5d4f
fix: circuit breaker
SkArchon Jul 7, 2025
004983d
fix: revert commit
SkArchon Jul 7, 2025
08b8624
fix: revert testenv
SkArchon Jul 7, 2025
e0a4af0
fix: revert testenv
SkArchon Jul 7, 2025
c646ca4
fix: revert
SkArchon Jul 7, 2025
fe51c0e
fix: updates
SkArchon Jul 7, 2025
cef2aba
fix: enable
SkArchon Jul 7, 2025
003aedf
fix: comments
SkArchon Jul 7, 2025
5145c35
fix: comments
SkArchon Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,022 changes: 1,022 additions & 0 deletions router-tests/circuit_breaker_test.go

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion router-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.23.0
require (
github.com/MicahParks/jwkset v0.9.0
github.com/buger/jsonparser v1.1.1
github.com/caarlos0/env/v11 v11.3.1
github.com/cloudflare/backoff v0.0.0-20240920015135-e46b80a3a7d0
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/google/uuid v1.6.0
Expand Down Expand Up @@ -48,8 +49,8 @@ require (
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bufbuild/protocompile v0.14.1 // indirect
github.com/caarlos0/env/v11 v11.3.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cep21/circuit/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cilium/ebpf v0.16.0 // indirect
github.com/coder/websocket v1.8.13 // indirect
Expand Down
2 changes: 2 additions & 0 deletions router-tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5m
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cep21/circuit/v4 v4.0.0 h1:g1AzMmRLuwCst0eccy1nGsD/CL2XKbDnaPUHVHDvVmI=
github.com/cep21/circuit/v4 v4.0.0/go.mod h1:Bb1fHpuiRu+AIgKf7DTM1c5U94qTZtKouKcDwtZYCXk=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
Expand Down
49 changes: 37 additions & 12 deletions router/core/graph_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"crypto/ecdsa"
"errors"
"fmt"
"github.com/wundergraph/cosmo/router/internal/circuit"
"github.com/wundergraph/cosmo/router/internal/traceclient"
"net/http"
"net/url"
"path/filepath"
Expand Down Expand Up @@ -82,17 +84,18 @@ type (
mux *chi.Mux
// inFlightRequests is used to track the number of requests currently being processed
// does not include websocket (hijacked) connections
inFlightRequests *atomic.Uint64
graphMuxList []*graphMux
graphMuxListLock sync.Mutex
runtimeMetrics *rmetric.RuntimeMetrics
otlpEngineMetrics *rmetric.EngineMetrics
prometheusEngineMetrics *rmetric.EngineMetrics
connectionMetrics *rmetric.ConnectionMetrics
instanceData InstanceData
pubSubProviders []datasource.Provider
traceDialer *TraceDialer
pluginHost *routerplugin.Host
inFlightRequests *atomic.Uint64
graphMuxList []*graphMux
graphMuxListLock sync.Mutex
runtimeMetrics *rmetric.RuntimeMetrics
otlpEngineMetrics *rmetric.EngineMetrics
prometheusEngineMetrics *rmetric.EngineMetrics
connectionMetrics *rmetric.ConnectionMetrics
instanceData InstanceData
pubSubProviders []datasource.Provider
traceDialer *TraceDialer
pluginHost *routerplugin.Host
subgraphCircuitBreakerOptions *SubgraphCircuitBreakerOptions
}
)

Expand Down Expand Up @@ -141,7 +144,8 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC
HostName: r.hostName,
ListenAddress: r.listenAddr,
},
storageProviders: &r.storageProviders,
storageProviders: &r.storageProviders,
subgraphCircuitBreakerOptions: r.subgraphCircuitBreakerOptions,
}

baseOtelAttributes := []attribute.KeyValue{
Expand Down Expand Up @@ -753,6 +757,21 @@ func (s *graphServer) buildGraphMux(ctx context.Context,
gm.metricStore = m
}

// Feature flags can fail independently of the base subgraph, thus we should have circuit breakers per feature flag + subgraph
managerOpts := circuit.ManagerOpts{}
if s.subgraphCircuitBreakerOptions != nil {
managerOpts = circuit.ManagerOpts{
BaseConfig: s.subgraphCircuitBreakerOptions.CircuitBreaker,
SubgraphCircuitBreakers: s.subgraphCircuitBreakerOptions.SubgraphMap,
Subgraphs: configSubgraphs,
FeatureFlagName: featureFlagName,
MetricStore: gm.metricStore,
UseMetrics: metricsEnabled,
BaseOtelAttributes: baseMetricAttributes,
}
}
circuitBreakerManager := circuit.NewManager(managerOpts)

subgraphs, err := configureSubgraphOverwrites(
engineConfig,
configSubgraphs,
Expand Down Expand Up @@ -798,7 +817,12 @@ func (s *graphServer) buildGraphMux(ctx context.Context,
subgraphResolver := NewSubgraphResolver(subgraphs)
httpRouter.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if featureFlagName != "" {
r = r.WithContext(context.WithValue(r.Context(), traceclient.CurrentFeatureFlagContextKey{}, featureFlagName))
}

r = r.WithContext(withSubgraphResolver(r.Context(), subgraphResolver))

requestLogger := s.logger.With(logging.WithRequestID(middleware.GetReqID(r.Context())))
// If this is a batched request attach id to the logger
if batchedOperationId, ok := r.Context().Value(BatchedOperationId{}).(string); ok {
Expand Down Expand Up @@ -1032,6 +1056,7 @@ func (s *graphServer) buildGraphMux(ctx context.Context,
LocalhostFallbackInsideDocker: s.localhostFallbackInsideDocker,
Logger: s.logger,
EnableTraceClient: enableTraceClient,
CircuitBreaker: circuitBreakerManager,
},
}

Expand Down
26 changes: 26 additions & 0 deletions router/core/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ type (
SubgraphMap map[string]*TransportRequestOptions
}

SubgraphCircuitBreakerOptions struct {
*config.CircuitBreaker
SubgraphMap map[string]*config.CircuitBreaker
}

GraphQLMetricsConfig struct {
Enabled bool
CollectorEndpoint string
Expand Down Expand Up @@ -1728,6 +1733,12 @@ func WithSubgraphTransportOptions(opts *SubgraphTransportOptions) Option {
}
}

func WithSubgraphCircuitBreakerOptions(opts *SubgraphCircuitBreakerOptions) Option {
return func(r *Router) {
r.subgraphCircuitBreakerOptions = opts
}
}

func WithSubgraphRetryOptions(enabled bool, maxRetryCount int, retryMaxDuration, retryInterval time.Duration) Option {
return func(r *Router) {
r.retryOptions = retrytransport.RetryOptions{
Expand Down Expand Up @@ -1841,6 +1852,21 @@ func NewSubgraphTransportOptions(cfg config.TrafficShapingRules) *SubgraphTransp
return base
}

func NewSubgraphCircuitBreakerOptions(cfg config.TrafficShapingRules) *SubgraphCircuitBreakerOptions {
entry := &SubgraphCircuitBreakerOptions{
SubgraphMap: map[string]*config.CircuitBreaker{},
}
if cfg.All.CircuitBreaker.Enabled {
entry.CircuitBreaker = &cfg.All.CircuitBreaker
}
for k, v := range cfg.Subgraphs {
if v.CircuitBreaker.Enabled {
entry.SubgraphMap[k] = &v.CircuitBreaker
}
}
return entry
}

func DefaultSubgraphTransportOptions() *SubgraphTransportOptions {
return &SubgraphTransportOptions{
TransportRequestOptions: DefaultTransportRequestOptions(),
Expand Down
1 change: 1 addition & 0 deletions router/core/router_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type Config struct {
postOriginHandlers []TransportPostHandler
headerRules *config.HeaderRules
subgraphTransportOptions *SubgraphTransportOptions
subgraphCircuitBreakerOptions *SubgraphCircuitBreakerOptions
graphqlMetricsConfig *GraphQLMetricsConfig
routerTrafficConfig *config.RouterTrafficConfiguration
batchingConfig *BatchingConfig
Expand Down
1 change: 1 addition & 0 deletions router/core/supervisor_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ func optionsFromResources(logger *zap.Logger, config *config.Config) []Option {
WithRouterTrafficConfig(&config.TrafficShaping.Router),
WithFileUploadConfig(&config.FileUpload),
WithSubgraphTransportOptions(NewSubgraphTransportOptions(config.TrafficShaping)),
WithSubgraphCircuitBreakerOptions(NewSubgraphCircuitBreakerOptions(config.TrafficShaping)),
WithSubgraphRetryOptions(
config.TrafficShaping.All.BackoffJitterRetry.Enabled,
config.TrafficShaping.All.BackoffJitterRetry.MaxAttempts,
Expand Down
31 changes: 21 additions & 10 deletions router/core/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"github.com/wundergraph/cosmo/router/internal/circuit"
"io"
"net/http"
"net/url"
Expand Down Expand Up @@ -36,7 +37,7 @@ import (
"go.uber.org/zap"

"github.com/wundergraph/cosmo/router/internal/docker"
"github.com/wundergraph/cosmo/router/internal/retrytransport"
retrytransport "github.com/wundergraph/cosmo/router/internal/retrytransport"
)

type (
Expand Down Expand Up @@ -68,12 +69,23 @@ func NewCustomTransport(
metricStore metric.Store,
connectionMetricStore metric.ConnectionMetricStore,
enableSingleFlight bool,
breaker *circuit.Manager,
enableTraceClient bool,
) *CustomTransport {
ct := &CustomTransport{
metricStore: metricStore,
}

// The round trip method is almost always called via the http.Client roundTripper interface
// as a result we cannot pass in the request context logger directly, since this will break the interface
// The roundTripper is also not in the core package so it does not have access to the
// getRequestContext function since its private to only the core package
// As a workaround we pass in a function that can be used to get the logger from within the round tripper
getRequestContextLogger := func(req *http.Request) *zap.Logger {
reqContext := getRequestContext(req.Context())
return reqContext.Logger()
}

if enableTraceClient {
getExprContext := func(ctx context.Context) *expr.Context {
reqContext := getRequestContext(ctx)
Expand All @@ -85,16 +97,11 @@ func NewCustomTransport(
baseRoundTripper = traceclient.NewTraceInjectingRoundTripper(baseRoundTripper, connectionMetricStore, getExprContext)
}

if breaker.IsEnabled() {
baseRoundTripper = circuit.NewCircuitTripper(baseRoundTripper, breaker, getRequestContextLogger)
}

if retryOptions.Enabled {
// The round trip method is almost always called via the http.Client RoundTripper interface
// as a result we cannot pass in the request context logger directly, since this will break the interface
// The RoundTripper is also not in the core package so it does not have access to the
// getRequestContext function since its private to only the core package
// As a workaround we pass in a function that can be used to get the logger from within the round tripper
getRequestContextLogger := func(req *http.Request) *zap.Logger {
reqContext := getRequestContext(req.Context())
return reqContext.Logger()
}
ct.roundTripper = retrytransport.NewRetryHTTPTransport(baseRoundTripper, retryOptions, getRequestContextLogger)
} else {
ct.roundTripper = baseRoundTripper
Expand Down Expand Up @@ -335,6 +342,7 @@ type TransportFactory struct {
localhostFallbackInsideDocker bool
metricStore metric.Store
connectionMetricStore metric.ConnectionMetricStore
circuitBreaker *circuit.Manager
logger *zap.Logger
tracerProvider *sdktrace.TracerProvider
tracePropagators propagation.TextMapPropagator
Expand All @@ -351,6 +359,7 @@ type TransportOptions struct {
LocalhostFallbackInsideDocker bool
MetricStore metric.Store
ConnectionMetricStore metric.ConnectionMetricStore
CircuitBreaker *circuit.Manager
Logger *zap.Logger
TracerProvider *sdktrace.TracerProvider
TracePropagators propagation.TextMapPropagator
Expand All @@ -375,6 +384,7 @@ func NewTransport(opts *TransportOptions) *TransportFactory {
logger: opts.Logger,
tracerProvider: opts.TracerProvider,
tracePropagators: opts.TracePropagators,
circuitBreaker: opts.CircuitBreaker,
enableTraceClient: opts.EnableTraceClient,
}
}
Expand Down Expand Up @@ -420,6 +430,7 @@ func (t TransportFactory) RoundTripper(enableSingleFlight bool, baseTransport ht
t.metricStore,
t.connectionMetricStore,
enableSingleFlight,
t.circuitBreaker,
t.enableTraceClient,
)

Expand Down
1 change: 1 addition & 0 deletions router/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ require (
github.com/MicahParks/keyfunc/v3 v3.3.5
github.com/alicebob/miniredis/v2 v2.34.0
github.com/caarlos0/env/v11 v11.3.1
github.com/cep21/circuit/v4 v4.0.0
github.com/dgraph-io/ristretto/v2 v2.1.0
github.com/expr-lang/expr v1.17.3
github.com/goccy/go-json v0.10.3
Expand Down
2 changes: 2 additions & 0 deletions router/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5m
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cep21/circuit/v4 v4.0.0 h1:g1AzMmRLuwCst0eccy1nGsD/CL2XKbDnaPUHVHDvVmI=
github.com/cep21/circuit/v4 v4.0.0/go.mod h1:Bb1fHpuiRu+AIgKf7DTM1c5U94qTZtKouKcDwtZYCXk=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4=
Expand Down
65 changes: 65 additions & 0 deletions router/internal/circuit/breaker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package circuit

import (
"context"
"fmt"
"github.com/wundergraph/cosmo/router/internal/traceclient"
"go.uber.org/zap"
"net/http"
)

type Breaker struct {
roundTripper http.RoundTripper
loggerFunc func(req *http.Request) *zap.Logger
circuitBreaker *Manager
}

func NewCircuitTripper(roundTripper http.RoundTripper, breaker *Manager, logger func(req *http.Request) *zap.Logger) *Breaker {
return &Breaker{
circuitBreaker: breaker,
loggerFunc: logger,
roundTripper: roundTripper,
}
}

func (rt *Breaker) RoundTrip(req *http.Request) (resp *http.Response, err error) {
ctx := req.Context()

var subgraph string
subgraphCtxVal := ctx.Value(traceclient.CurrentSubgraphContextKey{})
if subgraphCtxVal != nil {
subgraph = subgraphCtxVal.(string)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

var prefix string
prefixCtxVal := ctx.Value(traceclient.CurrentFeatureFlagContextKey{})
if prefixCtxVal != nil {
prefix = prefixCtxVal.(string)
}

cbKey := fmt.Sprintf("%s::%s", prefix, subgraph)

// If there is no circuit defined for this subgraph
circuit := rt.circuitBreaker.GetCircuitBreaker(cbKey)
if circuit == nil {
return rt.roundTripper.RoundTrip(req)
}

preRunStatus := circuit.IsOpen()

err = circuit.Run(context.Background(), func(_ context.Context) error {
Comment thread
StarpTech marked this conversation as resolved.
Outdated
resp, err = rt.roundTripper.RoundTrip(req)
Comment thread
StarpTech marked this conversation as resolved.
return err
})

postRunStatus := circuit.IsOpen()

logger := rt.loggerFunc(req)
if preRunStatus != postRunStatus {
logger.Debug("Circuit breaker status changed", zap.String("subgraph", subgraph), zap.Bool("isOpen", postRunStatus))
Comment thread
SkArchon marked this conversation as resolved.
Outdated
} else if preRunStatus {
logger.Debug("Circuit breaker open, request callback did not execute", zap.String("subgraph", subgraph))
}

return resp, err
}
Loading
Loading