feat: Circuit Breaker Plugin#204
Conversation
Summary by CodeRabbit
WalkthroughThis change introduces a new, fully implemented circuit breaker plugin for the Bifrost system. It adds the plugin's Go implementation, configuration utilities, documentation, and comprehensive unit tests. The circuit breaker monitors provider failures and slow calls, manages state transitions, and exposes metrics and manual control methods. Supporting files include a README, Go module definition, and utility logic. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant CircuitBreakerPlugin
participant Provider
Client->>CircuitBreakerPlugin: PreHook(request)
alt Circuit Closed or Half-Open (allowed)
CircuitBreakerPlugin->>Provider: Forward request
Provider-->>CircuitBreakerPlugin: Response/Error
CircuitBreakerPlugin->>CircuitBreakerPlugin: PostHook(result/error)
CircuitBreakerPlugin-->>Client: Response/Error
else Circuit Open (not expired)
CircuitBreakerPlugin-->>Client: Short-circuit error (fallback)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
plugins/circuitbreaker/go.sumis excluded by!**/*.sum
📒 Files selected for processing (5)
plugins/circuitbreaker/README.md(1 hunks)plugins/circuitbreaker/go.mod(1 hunks)plugins/circuitbreaker/main.go(1 hunks)plugins/circuitbreaker/plugin_test.go(1 hunks)plugins/circuitbreaker/utils.go(1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#144
File: transports/bifrost-http/handlers/providers.go:45-49
Timestamp: 2025-07-08T16:50:27.699Z
Learning: In the Bifrost project, breaking API changes are acceptable when features are not yet public. This applies to scenarios like changing struct fields from pointer to non-pointer types in request/response structures for unreleased features.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#152
File: transports/bifrost-http/plugins/logging/utils.go:378-399
Timestamp: 2025-07-10T13:44:14.518Z
Learning: In the Bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), Pratham-Mishra04 prefers not to add error handling for JSON unmarshaling operations, considering logging not very critical and being confident that JSON marshalling won't fail in practice.
📚 Learning: in the bifrost repository's transport dependency update workflow, when updating the core dependency ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: go 1.24 was released in february 2025 and is stable and available for use in go.mod files....
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:3-4
Timestamp: 2025-06-16T03:55:16.949Z
Learning: Go 1.24 was released in February 2025 and is stable and available for use in go.mod files.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in go module files, `go 1.24.1` (with patch version) can work fine in some setups, contrary to the g...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:3-4
Timestamp: 2025-06-16T04:27:53.538Z
Learning: In Go module files, `go 1.24.1` (with patch version) can work fine in some setups, contrary to the general rule that go directives should only include major.minor versions.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in core/bifrost.go, the count parameter in runposthooks method is intentionally kept separate from p...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.mdplugins/circuitbreaker/main.go
📚 Learning: in the bifrost codebase, errors returned from client methods like chatcompletionrequest are of type ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/end_to_end_tool_calling.go:43-45
Timestamp: 2025-06-16T04:13:55.437Z
Learning: In the Bifrost codebase, errors returned from client methods like ChatCompletionRequest are of type BifrostError, not the standard error interface. For testing these errors, use require.Nilf instead of require.NoErrorf since BifrostError doesn't work with the standard error assertion methods.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost system, error returns are of type `bifrosterror` rather than the standard go `error` ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/complete_end_to_end.go:39-41
Timestamp: 2025-06-16T04:12:05.427Z
Learning: In the Bifrost system, error returns are of type `BifrostError` rather than the standard Go `error` interface. Therefore, use `require.Nilf(t, err, ...)` instead of `require.NoError(t, err)` when checking for errors in Bifrost function calls.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost codebase, performance is prioritized over defensive copying for http service operatio...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.md
📚 Learning: in go, when importing a package, the identifier used to access it is determined by the `package` dec...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#135
File: docs/core-package.md:105-116
Timestamp: 2025-06-27T17:07:39.462Z
Learning: In Go, when importing a package, the identifier used to access it is determined by the `package` declaration in the Go source files, not the directory name. For the Bifrost project, the core directory files declare `package bifrost`, so importing `"github.com/maximhq/bifrost/core"` automatically makes it accessible as `bifrost.Init`, `bifrost.Ptr`, etc., without needing an explicit alias.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), pratham-mishra04 p...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#152
File: transports/bifrost-http/plugins/logging/utils.go:378-399
Timestamp: 2025-07-10T13:44:14.518Z
Learning: In the Bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), Pratham-Mishra04 prefers not to add error handling for JSON unmarshaling operations, considering logging not very critical and being confident that JSON marshalling won't fail in practice.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.md
📚 Learning: in the bifrost codebase, errors returned from methods like chatcompletionrequest are of type bifrost...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/simple_chat.go:39-41
Timestamp: 2025-06-16T04:13:42.755Z
Learning: In the Bifrost codebase, errors returned from methods like ChatCompletionRequest are of type BifrostError (a custom error type) rather than the standard Go error interface. Therefore, require.Nilf should be used for error assertions instead of require.NoErrorf.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: breaking changes in the bifrost codebase are managed by first merging and tagging core schema change...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Applied to files:
plugins/circuitbreaker/README.md
📚 Learning: in the bifrost test suite (tests/core-providers), parallel tests using t.parallel() are not being im...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/automatic_function_calling.go:22-22
Timestamp: 2025-06-16T04:55:11.886Z
Learning: In the Bifrost test suite (tests/core-providers), parallel tests using t.Parallel() are not being implemented currently. The team plans to add parallel test execution in future enhancements.
Applied to files:
plugins/circuitbreaker/plugin_test.go
🧬 Code Graph Analysis (1)
plugins/circuitbreaker/utils.go (3)
plugins/circuitbreaker/main.go (13)
CircuitBreakerConfig(139-149)SlidingWindowType(68-68)CountBased(71-71)TimeBased(72-72)CircuitBreaker(154-160)CircuitState(45-45)StateOpen(49-49)StateClosed(48-48)CountBasedWindow(102-108)CallResult(76-81)WindowMetrics(92-98)TimeBasedWindow(112-119)ProviderCircuitState(124-136)core/schemas/logger.go (2)
Logger(18-35)LogLevelInfo(10-10)core/logger.go (1)
NewDefaultLogger(22-26)
🪛 LanguageTool
plugins/circuitbreaker/README.md
[grammar] ~1-~1: Use correct spacing
Context: # Bifrost Circuit Breaker Plugin The Circuit Breaker plugin for Bifrost p...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...holds are exceeded to prevent cascading failures. ## Quick Start ### Download the Plugin ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~5-~5: Use correct spacing
Context: ...o prevent cascading failures. ## Quick Start ### Download the Plugin ```bash go ge...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: Use correct spacing
Context: ...ures. ## Quick Start ### Download the Plugin bash go get github.com/maximhq/bifrost/plugins/circuitbreaker ### Basic Usage ```go package main import ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~13-~13: Use correct spacing
Context: ...lugins/circuitbreaker ### Basic Usage go package main import ( "context" "time" bifrost "github.com/maximhq/bifrost/core" "github.com/maximhq/bifrost/core/schemas" circuitbreaker "github.com/maximhq/bifrost/plugins/circuitbreaker" ) func main() { // Create plugin with default configuration circuitbreakerPlugin, err := circuitbreaker.NewCircuitBreakerPlugin(circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.5, // 50% failure rate threshold SlowCallRateThreshold: 0.5, // 50% slow call rate threshold SlowCallDurationThreshold: 5 * time.Second, MinimumNumberOfCalls: 10, SlidingWindowType: circuitbreaker.CountBased, // Track last N calls SlidingWindowSize: 100, // Track last 100 calls PermittedNumberOfCallsInHalfOpenState: 5, MaxWaitDurationInHalfOpenState: 60 * time.Second, }) if err != nil { panic(err) } // Initialize Bifrost with the plugin client, err := bifrost.Init(schemas.BifrostConfig{ Account: &yourAccount, Plugins: []schemas.Plugin{circuitbreakerPlugin}, }) if err != nil { panic(err) } defer client.Cleanup() // Circuit breaker will automatically protect your requests response, err := client.ChatCompletionRequest(context.Background(), &schemas.BifrostRequest{ Provider: schemas.OpenAI, Model: "gpt-4", Input: schemas.RequestInput{ ChatCompletionInput: &[]schemas.BifrostMessage{ { Role: schemas.ModelChatMessageRoleUser, Content: schemas.MessageContent{ ContentStr: bifrost.Ptr("Hello!"), }, }, }, }, }) } ``` ### State Diagram of Circuit Breaker ![Circu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~70-~70: Use correct spacing
Context: ... }) } ``` ### State Diagram of Circuit Breaker
## Configuration ### CircuitBreakerConfig ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~75-~75: Use correct spacing
Context: ...aker-states.png) ## Configuration ### CircuitBreakerConfig | Field | Type | Default | Description |...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~87-~87: There might be a mistake here.
Context: ...evelInfo)` | Logger for circuit breaker operations | ### Sliding Window Types The circuit break...
(QB_NEW_EN_OTHER)
[grammar] ~89-~89: Use correct spacing
Context: ...reaker operations | ### Sliding Window Types The circuit breaker supports two types o...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~91-~91: There might be a mistake here.
Context: ...types of sliding windows for collecting metrics: #### Count-Based Sliding Window - Type: ...
(QB_NEW_EN_OTHER)
[grammar] ~98-~98: Use correct spacing
Context: ... the last 100 calls to evaluate failure rates #### Time-Based Sliding Window - Type: `"...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~105-~105: Use correct spacing
Context: ... the last 5 minutes to evaluate failure rates ### Configuration Examples #### Count-Based...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~107-~107: Use correct spacing
Context: ...aluate failure rates ### Configuration Examples #### Count-Based Sliding Window (Default) ``...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~109-~109: Use correct spacing
Context: ...amples #### Count-Based Sliding Window (Default) go config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // 30% failure rate threshold SlowCallRateThreshold: 0.4, // 40% slow call rate threshold SlowCallDurationThreshold: 10 * time.Second, MinimumNumberOfCalls: 20, SlidingWindowType: circuitbreaker.CountBased, // Track last N calls SlidingWindowSize: 200, // Track last 200 calls PermittedNumberOfCallsInHalfOpenState: 3, MaxWaitDurationInHalfOpenState: 30 * time.Second, } #### Time-Based Sliding Window ```go config ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~124-~124: Use correct spacing
Context: ....Second, } #### Time-Based Sliding Window go config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // 30% failure rate threshold SlowCallRateThreshold: 0.4, // 40% slow call rate threshold SlowCallDurationThreshold: 10 * time.Second, MinimumNumberOfCalls: 20, SlidingWindowType: circuitbreaker.TimeBased, // Track calls in time window SlidingWindowSize: 300, // Track calls in last 300 seconds (5 minutes) PermittedNumberOfCallsInHalfOpenState: 3, MaxWaitDurationInHalfOpenState: 30 * time.Second, } ``` ### Logging Configuration The circuit break...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~139-~139: Use correct spacing
Context: ...e: 30 * time.Second, } ``` ### Logging Configuration The circuit breaker plugin includes comp...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~141-~141: There might be a mistake here.
Context: ...tomize the logger by providing your own implementation: go // Use custom logger customLogger := yourCustomLoggerImplementation config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // ... other config options Logger: customLogger, // Use your custom logger } // Or use Bifrost's default logger with different log level config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // ... other config options Logger: bifrost.NewDefaultLogger(schemas.LogLevelDebug), // More verbose logging } ## Circuit States ### CL...
(QB_NEW_EN_OTHER)
[grammar] ~160-~160: Use correct spacing
Context: ... More verbose logging } ``` ## Circuit States ### CLOSED (Normal Operation) - Requests are...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~163-~163: There might be a mistake here.
Context: ...ation) - Requests are sent to providers normally - Circuit breaker monitors failures and sl...
(QB_NEW_EN_OTHER)
[grammar] ~164-~164: Make sure to use plural and singular nouns correctly
Context: ...re sent to providers normally - Circuit breaker monitors failures and slow calls - Metrics are c...
(QB_NEW_EN_OTHER_ERROR_IDS_10)
[grammar] ~164-~164: There might be a mistake here.
Context: ...cuit breaker monitors failures and slow calls - Metrics are collected in sliding window ...
(QB_NEW_EN_OTHER)
[grammar] ~165-~165: There might be a problem here.
Context: ...d slow calls - Metrics are collected in sliding window ### OPEN (Failure Protection) - All requests...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~168-~168: There might be a mistake here.
Context: ...tection) - All requests are immediately rejected - No provider calls are made - Prevents ca...
(QB_NEW_EN_OTHER)
[grammar] ~169-~169: There might be a mistake here.
Context: ...iately rejected - No provider calls are made - Prevents cascading failures - Automatica...
(QB_NEW_EN_OTHER)
[grammar] ~170-~170: There might be a mistake here.
Context: ...der calls are made - Prevents cascading failures - Automatically transitions to HALF_OPEN a...
(QB_NEW_EN_OTHER)
[grammar] ~171-~171: There might be a mistake here.
Context: ...lly transitions to HALF_OPEN after wait duration ### HALF_OPEN (Recovery Testing) - Limited n...
(QB_NEW_EN_OTHER)
[grammar] ~173-~173: Use articles correctly
Context: ... wait duration ### HALF_OPEN (Recovery Testing) - Limited number of requests are allowe...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~174-~174: There might be a mistake here.
Context: ... Limited number of requests are allowed through - Success/failure determines next state - ...
(QB_NEW_EN_OTHER)
[grammar] ~175-~175: There might be a problem here.
Context: ...ed through - Success/failure determines next state - Success → CLOSED (recovery complete) - F...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~177-~177: Use correct spacing
Context: ...overy complete) - Failure → OPEN (still failing) ### CircuitState Type The CircuitState ty...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~179-~179: Use correct spacing
Context: ... OPEN (still failing) ### CircuitState Type The CircuitState type is an int32 en...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~181-~181: There might be a mistake here.
Context: ...hod that provides human-readable string representations: - StateClosed → "CLOSED" - StateOpen → "OPEN" ...
(QB_NEW_EN_OTHER)
[grammar] ~187-~187: Use correct spacing
Context: ...ng circuit breaker status in monitoring dashboards. ### Error Classification The circuit breake...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~189-~189: Use correct spacing
Context: ...us in monitoring dashboards. ### Error Classification The circuit breaker distinguishes betwee...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~194-~194: Use correct spacing
Context: ...(e.g., invalid requests, authentication errors) This classification ensures that rate li...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~196-~196: Use hyphens correctly
Context: ...rors) This classification ensures that rate limiting issues and server-side problems...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~196-~196: Use correct spacing
Context: ...invalid API keys or malformed requests) don't. ## Monitoring ### Get Circuit State ```go...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~200-~200: Use correct spacing
Context: ... don't. ## Monitoring ### Get Circuit State go state := plugin.GetState(schemas.OpenAI) switch state { case circuitbreaker.StateClosed: fmt.Println("Circuit is CLOSED - normal operation") case circuitbreaker.StateOpen: fmt.Println("Circuit is OPEN - requests blocked") case circuitbreaker.StateHalfOpen: fmt.Println("Circuit is HALF_OPEN - testing recovery") } ### Get Metrics ```go metrics, err := plugi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~214-~214: Use correct spacing
Context: ...PEN - testing recovery") } ### Get Metrics go metrics, err := plugin.GetMetrics(schemas.OpenAI) if err == nil { fmt.Printf("Total Calls: %d\n", metrics.TotalCalls) fmt.Printf("Failed Calls: %d\n", metrics.FailedCalls) fmt.Printf("Failure Rate: %.2f%%\n", metrics.FailureRate100) fmt.Printf("Slow Call Rate: %.2f%%\n", metrics.SlowCallRate100) } ``` ## Advanced Operations ### Manual Circuit ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~226-~226: Use correct spacing
Context: ...cs.SlowCallRate*100) } ``` ## Advanced Operations ### Manual Circuit Control The circuit brea...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~228-~228: Use correct spacing
Context: ...Advanced Operations ### Manual Circuit Control The circuit breaker provides manual cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~230-~230: There might be a mistake here.
Context: ...rol functions for testing and emergency situations: go // Force the circuit to open state (blocks all requests) err := plugin.ForceOpen(schemas.OpenAI) if err != nil { fmt.Printf("Error forcing circuit open: %v\n", err) } // Force the circuit to closed state (allows all requests) err = plugin.ForceClose(schemas.OpenAI) if err != nil { fmt.Printf("Error forcing circuit closed: %v\n", err) } // Reset the circuit breaker (clears all metrics and returns to closed state) err = plugin.Reset(schemas.OpenAI) if err != nil { fmt.Printf("Error resetting circuit: %v\n", err) } Note: Manual cont...
(QB_NEW_EN_OTHER)
[style] ~252-~252: ‘emergency situations’ might be wordy. Consider a shorter alternative.
Context: ... sparingly and primarily for testing or emergency situations. The automatic circuit breaker logic is...
(EN_WORDINESS_PREMIUM_EMERGENCY_SITUATIONS)
[grammar] ~252-~252: Use correct spacing
Context: ...ic is designed to handle most scenarios optimally. ## Performance The Circuit Breaker plugin ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~256-~256: There might be a mistake here.
Context: ...lugin is optimized for high-performance scenarios: - Atomic Operations: Uses atomic counte...
(QB_NEW_EN_OTHER)
[grammar] ~260-~260: Use correct spacing
Context: ...-allocated data structures with minimal allocations ## Best Practices 1. Monitor Metrics: ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~262-~262: Use correct spacing
Context: ...tures with minimal allocations ## Best Practices 1. Monitor Metrics: Regularly check circu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~264-~264: There might be a mistake here.
Context: ...ularly check circuit states and failure rates 2. Adjust Thresholds: Lower thresholds fo...
(QB_NEW_EN_OTHER)
[grammar] ~265-~265: There might be a mistake here.
Context: ...sholds**: Lower thresholds for critical services, higher for non-critical 3. **Test Recov...
(QB_NEW_EN_OTHER)
[grammar] ~265-~265: There might be a mistake here.
Context: ...holds for critical services, higher for non-critical 3. Test Recovery: Verify half-open ...
(QB_NEW_EN_OTHER)
[grammar] ~266-~266: There might be a mistake here.
Context: ...half-open state works correctly in your environment 4. Use Fallbacks: Combine with Bifrost's ...
(QB_NEW_EN_OTHER)
[grammar] ~267-~267: There might be a mistake here.
Context: ...ifrost's fallback providers for maximum resilience Need help? Check the [Bifrost document...
(QB_NEW_EN_OTHER)
[grammar] ~269-~269: Use correct spacing
Context: ...../docs/plugins.md) or open an issue on GitHub.
(QB_NEW_EN_OTHER_ERROR_IDS_5)
🪛 markdownlint-cli2 (0.17.2)
plugins/circuitbreaker/README.md
70-70: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
93-93: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
94-94: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
100-100: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
101-101: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
162-162: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
163-163: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
167-167: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
168-168: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
173-173: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
174-174: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
192-192: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
🔇 Additional comments (21)
plugins/circuitbreaker/go.mod (1)
1-42: LGTM!The go.mod file is properly configured with the correct module path, valid Go version (1.24.1), and appropriate dependency on the bifrost/core module.
plugins/circuitbreaker/README.md (1)
1-271: Excellent documentation!The README provides comprehensive coverage of the circuit breaker plugin with clear examples, detailed configuration options, state explanations, and practical usage guidance. The content is well-structured and informative.
plugins/circuitbreaker/plugin_test.go (6)
11-42: LGTM!The basic functionality test properly validates plugin creation, name verification, and default configuration.
44-204: Comprehensive state transition testing!The test thoroughly validates the complete circuit breaker state machine including proper simulation of failures, state transition verification, and half-open state recovery. The use of proper BifrostError types with status codes is correct.
206-274: Clean recovery test!The test effectively validates circuit breaker recovery with proper state verification. Good use of
rangefor repeated operations.
276-316: Good slow call testing!The test properly simulates slow calls with appropriate delays and verifies that the circuit opens when the slow call threshold is exceeded.
318-385: Accurate metrics validation!The test correctly validates metrics collection with proper calculation of failure rates and call counts.
387-442: Thorough time-based window testing!The test effectively validates time-based sliding window behavior including metric expiration after the window duration.
plugins/circuitbreaker/utils.go (7)
13-75: Well-designed configuration validation!The default configuration provides sensible values, and the validation function comprehensively checks all parameters while tracking what defaults were applied. This provides good user feedback and debugging capability.
77-116: Thread-safe state management!The state management functions properly use atomic operations and include appropriate error handling for missing providers.
118-134: Correct error classification!The error classification functions properly identify server errors and rate limiting with appropriate nil checks.
136-193: Efficient count-based window implementation!The circular buffer approach is well-implemented with proper thread safety and correct handling of partial windows.
195-233: Performance-optimized time-based window!The implementation efficiently handles high-frequency calls with periodic cleanup and smart triggering conditions. The cleanup logic properly maintains only relevant entries within the time window.
235-284: Accurate metrics calculation with cleanup!The implementation ensures accurate metrics by triggering cleanup when needed and properly filtering calls within the time window.
286-299: Safe context value extraction!The utility functions properly handle missing context values with appropriate fallbacks.
plugins/circuitbreaker/main.go (6)
1-99: Well-documented package with clear type definitions!The package documentation provides excellent context, and the type definitions are well-structured with helpful methods like String() for debugging.
100-185: Excellent concurrent data structure design!The separation of atomic variables for high-frequency operations and mutex-protected data for complex operations shows good understanding of concurrent programming patterns.
186-288: Correct double-checked locking implementation!The getOrCreateProviderState method properly implements the double-checked locking pattern for thread-safe, performant provider state creation.
289-350: Well-implemented PreHook with informative error messages!The PreHook correctly handles all circuit states and provides detailed, actionable error messages to help users understand why requests are blocked.
352-483: Robust PostHook with correct state transition logic!The implementation properly records metrics, evaluates state transitions based on thresholds, and maintains thread safety throughout. The error classification correctly treats server errors (5xx) and rate limiting (429) as failures.
484-518: Complete metrics and cleanup implementation!The GetMetrics method provides comprehensive observability data, and Cleanup properly resets the plugin state.
b4981a7 to
5906232
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (2)
plugins/circuitbreaker/README.md (2)
70-71: Fix markdown formatting and verify image file exists.The image file referenced at line 71 appears to be missing based on past review comments. Also, add blank lines around headings for proper markdown formatting.
#!/bin/bash # Verify if the circuit breaker states image exists fd -t f "circuit-breaker-states.png" docs/media/plugins/ || echo "Image file not found"
93-106: Fix markdown formatting around lists and headings.Add blank lines before and after lists and headings for proper markdown rendering.
Also applies to: 162-178
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (2)
docs/media/plugins/circuit-breaker-states.pngis excluded by!**/*.pngplugins/circuitbreaker/go.sumis excluded by!**/*.sum
📒 Files selected for processing (5)
plugins/circuitbreaker/README.md(1 hunks)plugins/circuitbreaker/go.mod(1 hunks)plugins/circuitbreaker/main.go(1 hunks)plugins/circuitbreaker/plugin_test.go(1 hunks)plugins/circuitbreaker/utils.go(1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#158
File: .github/workflows/transports-release.yml:30-43
Timestamp: 2025-07-18T11:12:28.861Z
Learning: Pratham-Mishra04 relies on branch protection rules and mandatory code reviews for security in the bifrost repository, preferring process controls over technical security measures like environment variable isolation for GitHub Actions workflows. All commits are reviewed before merging to main branch.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#84
File: transports/bifrost-http/main.go:2-2
Timestamp: 2025-06-15T16:05:13.489Z
Learning: For the Bifrost project, HTTP transport integration routers for new providers (like Mistral and Ollama) are implemented in separate PRs from the core provider support, following a focused PR strategy.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#202
File: transports/bifrost-http/plugins/governance/resolver.go:183-191
Timestamp: 2025-08-03T20:36:21.906Z
Learning: In the Bifrost governance plugin (transports/bifrost-http/plugins/governance/resolver.go), Pratham-Mishra04 considers the current string matching approach for determining rate limit violation decision types (DecisionTokenLimited vs DecisionRequestLimited) adequate and not important enough to refactor with more robust explicit checks, preferring functional simplicity over theoretical robustness improvements.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#202
File: transports/bifrost-http/plugins/governance/tracker.go:146-146
Timestamp: 2025-08-03T20:50:48.247Z
Learning: In the Bifrost governance tracker (transports/bifrost-http/plugins/governance/tracker.go), Pratham-Mishra04 implements database persistence for reset operations using arrays to collect reset entities (resetRateLimits and resetBudgets) and then batch persist them using t.db.Save() with proper error aggregation in the PerformStartupResets method.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#144
File: transports/bifrost-http/handlers/providers.go:45-49
Timestamp: 2025-07-08T16:50:27.699Z
Learning: In the Bifrost project, breaking API changes are acceptable when features are not yet public. This applies to scenarios like changing struct fields from pointer to non-pointer types in request/response structures for unreleased features.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#152
File: transports/bifrost-http/plugins/logging/utils.go:378-399
Timestamp: 2025-07-10T13:44:14.518Z
Learning: In the Bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), Pratham-Mishra04 prefers not to add error handling for JSON unmarshaling operations, considering logging not very critical and being confident that JSON marshalling won't fail in practice.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
📚 Learning: in the bifrost repository's transport dependency update workflow, when updating the core dependency ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: go 1.24 was released in february 2025 and is stable and available for use in go.mod files....
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:3-4
Timestamp: 2025-06-16T03:55:16.949Z
Learning: Go 1.24 was released in February 2025 and is stable and available for use in go.mod files.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in go module files, `go 1.24.1` (with patch version) can work fine in some setups, contrary to the g...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/go.mod:3-4
Timestamp: 2025-06-16T04:27:53.538Z
Learning: In Go module files, `go 1.24.1` (with patch version) can work fine in some setups, contrary to the general rule that go directives should only include major.minor versions.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in core/bifrost.go, the count parameter in runposthooks method is intentionally kept separate from p...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#79
File: core/bifrost.go:94-103
Timestamp: 2025-06-14T04:06:58.240Z
Learning: In core/bifrost.go, the count parameter in RunPostHooks method is intentionally kept separate from p.executedPreHooks to support circuit breaker plugins that may need to trigger PostHooks for only a subset of executed plugins when detecting failure conditions mid-execution.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.mdplugins/circuitbreaker/main.go
📚 Learning: in the bifrost codebase, errors returned from client methods like chatcompletionrequest are of type ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/end_to_end_tool_calling.go:43-45
Timestamp: 2025-06-16T04:13:55.437Z
Learning: In the Bifrost codebase, errors returned from client methods like ChatCompletionRequest are of type BifrostError, not the standard error interface. For testing these errors, use require.Nilf instead of require.NoErrorf since BifrostError doesn't work with the standard error assertion methods.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost system, error returns are of type `bifrosterror` rather than the standard go `error` ...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/complete_end_to_end.go:39-41
Timestamp: 2025-06-16T04:12:05.427Z
Learning: In the Bifrost system, error returns are of type `BifrostError` rather than the standard Go `error` interface. Therefore, use `require.Nilf(t, err, ...)` instead of `require.NoError(t, err)` when checking for errors in Bifrost function calls.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost codebase, performance is prioritized over defensive copying for http service operatio...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/mistral.go:168-170
Timestamp: 2025-06-15T14:24:49.882Z
Learning: In the Bifrost codebase, performance is prioritized over defensive copying for HTTP service operations. Specifically, shallow slice assignments in provider response handling are acceptable due to object pool reset patterns and JSON unmarshaling behavior that minimize practical data corruption risks.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.md
📚 Learning: in go, when importing a package, the identifier used to access it is determined by the `package` dec...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#135
File: docs/core-package.md:105-116
Timestamp: 2025-06-27T17:07:39.462Z
Learning: In Go, when importing a package, the identifier used to access it is determined by the `package` declaration in the Go source files, not the directory name. For the Bifrost project, the core directory files declare `package bifrost`, so importing `"github.com/maximhq/bifrost/core"` automatically makes it accessible as `bifrost.Init`, `bifrost.Ptr`, etc., without needing an explicit alias.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), pratham-mishra04 p...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#152
File: transports/bifrost-http/plugins/logging/utils.go:378-399
Timestamp: 2025-07-10T13:44:14.518Z
Learning: In the Bifrost logging plugin (transports/bifrost-http/plugins/logging/utils.go), Pratham-Mishra04 prefers not to add error handling for JSON unmarshaling operations, considering logging not very critical and being confident that JSON marshalling won't fail in practice.
Applied to files:
plugins/circuitbreaker/go.modplugins/circuitbreaker/README.md
📚 Learning: in the bifrost codebase, errors returned from methods like chatcompletionrequest are of type bifrost...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/simple_chat.go:39-41
Timestamp: 2025-06-16T04:13:42.755Z
Learning: In the Bifrost codebase, errors returned from methods like ChatCompletionRequest are of type BifrostError (a custom error type) rather than the standard Go error interface. Therefore, require.Nilf should be used for error assertions instead of require.NoErrorf.
Applied to files:
plugins/circuitbreaker/go.mod
📚 Learning: in the bifrost test suite (tests/core-providers), parallel tests using t.parallel() are not being im...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/automatic_function_calling.go:22-22
Timestamp: 2025-06-16T04:55:11.886Z
Learning: In the Bifrost test suite (tests/core-providers), parallel tests using t.Parallel() are not being implemented currently. The team plans to add parallel test execution in future enhancements.
Applied to files:
plugins/circuitbreaker/plugin_test.go
📚 Learning: pratham-mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdo...
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#138
File: docs/usage/go-package/mcp.md:408-412
Timestamp: 2025-07-01T12:40:08.576Z
Learning: Pratham-Mishra04 is okay with keeping bullet list formatting that uses colons after dashes in markdown documentation, even if it triggers linter warnings, preferring functionality over strict formatting rules.
Applied to files:
plugins/circuitbreaker/README.md
🪛 LanguageTool
plugins/circuitbreaker/README.md
[grammar] ~1-~1: Use correct spacing
Context: # Bifrost Circuit Breaker Plugin The Circuit Breaker plugin for Bifrost p...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~3-~3: Use correct spacing
Context: ...holds are exceeded to prevent cascading failures. ## Quick Start ### Download the Plugin ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~5-~5: Use correct spacing
Context: ...o prevent cascading failures. ## Quick Start ### Download the Plugin ```bash go ge...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: Use correct spacing
Context: ...ures. ## Quick Start ### Download the Plugin bash go get github.com/maximhq/bifrost/plugins/circuitbreaker ### Basic Usage ```go package main import ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~13-~13: Use correct spacing
Context: ...lugins/circuitbreaker ### Basic Usage go package main import ( "context" "time" bifrost "github.com/maximhq/bifrost/core" "github.com/maximhq/bifrost/core/schemas" circuitbreaker "github.com/maximhq/bifrost/plugins/circuitbreaker" ) func main() { // Create plugin with default configuration circuitbreakerPlugin, err := circuitbreaker.NewCircuitBreakerPlugin(circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.5, // 50% failure rate threshold SlowCallRateThreshold: 0.5, // 50% slow call rate threshold SlowCallDurationThreshold: 5 * time.Second, MinimumNumberOfCalls: 10, SlidingWindowType: circuitbreaker.CountBased, // Track last N calls SlidingWindowSize: 100, // Track last 100 calls PermittedNumberOfCallsInHalfOpenState: 5, MaxWaitDurationInHalfOpenState: 60 * time.Second, }) if err != nil { panic(err) } // Initialize Bifrost with the plugin client, err := bifrost.Init(schemas.BifrostConfig{ Account: &yourAccount, Plugins: []schemas.Plugin{circuitbreakerPlugin}, }) if err != nil { panic(err) } defer client.Cleanup() // Circuit breaker will automatically protect your requests response, err := client.ChatCompletionRequest(context.Background(), &schemas.BifrostRequest{ Provider: schemas.OpenAI, Model: "gpt-4", Input: schemas.RequestInput{ ChatCompletionInput: &[]schemas.BifrostMessage{ { Role: schemas.ModelChatMessageRoleUser, Content: schemas.MessageContent{ ContentStr: bifrost.Ptr("Hello!"), }, }, }, }, }) } ``` ### State Diagram of Circuit Breaker ![Circu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~70-~70: Use correct spacing
Context: ... }) } ``` ### State Diagram of Circuit Breaker
## Configuration ### CircuitBreakerConfig ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~75-~75: Use correct spacing
Context: ...aker-states.png) ## Configuration ### CircuitBreakerConfig | Field | Type | Default | Description |...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~87-~87: There might be a mistake here.
Context: ...evelInfo)` | Logger for circuit breaker operations | ### Sliding Window Types The circuit break...
(QB_NEW_EN_OTHER)
[grammar] ~89-~89: Use correct spacing
Context: ...reaker operations | ### Sliding Window Types The circuit breaker supports two types o...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~91-~91: There might be a mistake here.
Context: ...types of sliding windows for collecting metrics: #### Count-Based Sliding Window - Type: ...
(QB_NEW_EN_OTHER)
[grammar] ~98-~98: Use correct spacing
Context: ... the last 100 calls to evaluate failure rates #### Time-Based Sliding Window - Type: `"...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~105-~105: Use correct spacing
Context: ... the last 5 minutes to evaluate failure rates ### Configuration Examples #### Count-Based...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~107-~107: Use correct spacing
Context: ...aluate failure rates ### Configuration Examples #### Count-Based Sliding Window (Default) ``...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~109-~109: Use correct spacing
Context: ...amples #### Count-Based Sliding Window (Default) go config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // 30% failure rate threshold SlowCallRateThreshold: 0.4, // 40% slow call rate threshold SlowCallDurationThreshold: 10 * time.Second, MinimumNumberOfCalls: 20, SlidingWindowType: circuitbreaker.CountBased, // Track last N calls SlidingWindowSize: 200, // Track last 200 calls PermittedNumberOfCallsInHalfOpenState: 3, MaxWaitDurationInHalfOpenState: 30 * time.Second, } #### Time-Based Sliding Window ```go config ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~124-~124: Use correct spacing
Context: ....Second, } #### Time-Based Sliding Window go config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // 30% failure rate threshold SlowCallRateThreshold: 0.4, // 40% slow call rate threshold SlowCallDurationThreshold: 10 * time.Second, MinimumNumberOfCalls: 20, SlidingWindowType: circuitbreaker.TimeBased, // Track calls in time window SlidingWindowSize: 300, // Track calls in last 300 seconds (5 minutes) PermittedNumberOfCallsInHalfOpenState: 3, MaxWaitDurationInHalfOpenState: 30 * time.Second, } ``` ### Logging Configuration The circuit break...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~139-~139: Use correct spacing
Context: ...e: 30 * time.Second, } ``` ### Logging Configuration The circuit breaker plugin includes comp...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~141-~141: There might be a mistake here.
Context: ...tomize the logger by providing your own implementation: go // Use custom logger customLogger := yourCustomLoggerImplementation config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // ... other config options Logger: customLogger, // Use your custom logger } // Or use Bifrost's default logger with different log level config := circuitbreaker.CircuitBreakerConfig{ FailureRateThreshold: 0.3, // ... other config options Logger: bifrost.NewDefaultLogger(schemas.LogLevelDebug), // More verbose logging } ## Circuit States ### CL...
(QB_NEW_EN_OTHER)
[grammar] ~160-~160: Use correct spacing
Context: ... More verbose logging } ``` ## Circuit States ### CLOSED (Normal Operation) - Requests are...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~163-~163: There might be a mistake here.
Context: ...ation) - Requests are sent to providers normally - Circuit breaker monitors failures and sl...
(QB_NEW_EN_OTHER)
[grammar] ~164-~164: Make sure to use plural and singular nouns correctly
Context: ...re sent to providers normally - Circuit breaker monitors failures and slow calls - Metrics are c...
(QB_NEW_EN_OTHER_ERROR_IDS_10)
[grammar] ~164-~164: There might be a mistake here.
Context: ...cuit breaker monitors failures and slow calls - Metrics are collected in sliding window ...
(QB_NEW_EN_OTHER)
[grammar] ~165-~165: There might be a problem here.
Context: ...d slow calls - Metrics are collected in sliding window ### OPEN (Failure Protection) - All requests...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~168-~168: There might be a mistake here.
Context: ...tection) - All requests are immediately rejected - No provider calls are made - Prevents ca...
(QB_NEW_EN_OTHER)
[grammar] ~169-~169: There might be a mistake here.
Context: ...iately rejected - No provider calls are made - Prevents cascading failures - Automatica...
(QB_NEW_EN_OTHER)
[grammar] ~170-~170: There might be a mistake here.
Context: ...der calls are made - Prevents cascading failures - Automatically transitions to HALF_OPEN a...
(QB_NEW_EN_OTHER)
[grammar] ~171-~171: There might be a mistake here.
Context: ...lly transitions to HALF_OPEN after wait duration ### HALF_OPEN (Recovery Testing) - Limited n...
(QB_NEW_EN_OTHER)
[grammar] ~173-~173: Use articles correctly
Context: ... wait duration ### HALF_OPEN (Recovery Testing) - Limited number of requests are allowe...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~174-~174: There might be a mistake here.
Context: ... Limited number of requests are allowed through - Success/failure determines next state - ...
(QB_NEW_EN_OTHER)
[grammar] ~175-~175: There might be a problem here.
Context: ...ed through - Success/failure determines next state - Success → CLOSED (recovery complete) - F...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~177-~177: Use correct spacing
Context: ...overy complete) - Failure → OPEN (still failing) ### CircuitState Type The CircuitState ty...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~179-~179: Use correct spacing
Context: ... OPEN (still failing) ### CircuitState Type The CircuitState type is an int32 en...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~181-~181: There might be a mistake here.
Context: ...hod that provides human-readable string representations: - StateClosed → "CLOSED" - StateOpen → "OPEN" ...
(QB_NEW_EN_OTHER)
[grammar] ~187-~187: Use correct spacing
Context: ...ng circuit breaker status in monitoring dashboards. ### Error Classification The circuit breake...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~189-~189: Use correct spacing
Context: ...us in monitoring dashboards. ### Error Classification The circuit breaker distinguishes betwee...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~194-~194: Use correct spacing
Context: ...(e.g., invalid requests, authentication errors) This classification ensures that rate li...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~196-~196: Use hyphens correctly
Context: ...rors) This classification ensures that rate limiting issues and server-side problems...
(QB_NEW_EN_OTHER_ERROR_IDS_29)
[grammar] ~196-~196: Use correct spacing
Context: ...invalid API keys or malformed requests) don't. ## Monitoring ### Get Circuit State ```go...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~200-~200: Use correct spacing
Context: ... don't. ## Monitoring ### Get Circuit State go state := plugin.GetState(schemas.OpenAI) switch state { case circuitbreaker.StateClosed: fmt.Println("Circuit is CLOSED - normal operation") case circuitbreaker.StateOpen: fmt.Println("Circuit is OPEN - requests blocked") case circuitbreaker.StateHalfOpen: fmt.Println("Circuit is HALF_OPEN - testing recovery") } ### Get Metrics ```go metrics, err := plugi...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~214-~214: Use correct spacing
Context: ...PEN - testing recovery") } ### Get Metrics go metrics, err := plugin.GetMetrics(schemas.OpenAI) if err == nil { fmt.Printf("Total Calls: %d\n", metrics.TotalCalls) fmt.Printf("Failed Calls: %d\n", metrics.FailedCalls) fmt.Printf("Failure Rate: %.2f%%\n", metrics.FailureRate100) fmt.Printf("Slow Call Rate: %.2f%%\n", metrics.SlowCallRate100) } ``` ## Advanced Operations ### Manual Circuit ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~226-~226: Use correct spacing
Context: ...cs.SlowCallRate*100) } ``` ## Advanced Operations ### Manual Circuit Control The circuit brea...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~228-~228: Use correct spacing
Context: ...Advanced Operations ### Manual Circuit Control The circuit breaker provides manual cont...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~230-~230: There might be a mistake here.
Context: ...rol functions for testing and emergency situations: go // Force the circuit to open state (blocks all requests) err := plugin.ForceOpen(schemas.OpenAI) if err != nil { fmt.Printf("Error forcing circuit open: %v\n", err) } // Force the circuit to closed state (allows all requests) err = plugin.ForceClose(schemas.OpenAI) if err != nil { fmt.Printf("Error forcing circuit closed: %v\n", err) } // Reset the circuit breaker (clears all metrics and returns to closed state) err = plugin.Reset(schemas.OpenAI) if err != nil { fmt.Printf("Error resetting circuit: %v\n", err) } Note: Manual cont...
(QB_NEW_EN_OTHER)
[style] ~252-~252: ‘emergency situations’ might be wordy. Consider a shorter alternative.
Context: ... sparingly and primarily for testing or emergency situations. The automatic circuit breaker logic is...
(EN_WORDINESS_PREMIUM_EMERGENCY_SITUATIONS)
[grammar] ~252-~252: Use correct spacing
Context: ...ic is designed to handle most scenarios optimally. ## Performance The Circuit Breaker plugin ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~256-~256: There might be a mistake here.
Context: ...lugin is optimized for high-performance scenarios: - Atomic Operations: Uses atomic counte...
(QB_NEW_EN_OTHER)
[grammar] ~260-~260: Use correct spacing
Context: ...-allocated data structures with minimal allocations ## Best Practices 1. Monitor Metrics: ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~262-~262: Use correct spacing
Context: ...tures with minimal allocations ## Best Practices 1. Monitor Metrics: Regularly check circu...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~264-~264: There might be a mistake here.
Context: ...ularly check circuit states and failure rates 2. Adjust Thresholds: Lower thresholds fo...
(QB_NEW_EN_OTHER)
[grammar] ~265-~265: There might be a mistake here.
Context: ...holds for critical services, higher for non-critical 3. Test Recovery: Verify half-open ...
(QB_NEW_EN_OTHER)
[grammar] ~266-~266: There might be a mistake here.
Context: ...half-open state works correctly in your environment 4. Use Fallbacks: Combine with Bifrost's ...
(QB_NEW_EN_OTHER)
[grammar] ~267-~267: There might be a mistake here.
Context: ...ifrost's fallback providers for maximum resilience Need help? Check the [Bifrost document...
(QB_NEW_EN_OTHER)
[grammar] ~269-~269: Use correct spacing
Context: ...../docs/plugins.md) or open an issue on GitHub.
(QB_NEW_EN_OTHER_ERROR_IDS_5)
🪛 markdownlint-cli2 (0.17.2)
plugins/circuitbreaker/README.md
70-70: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
93-93: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
94-94: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
100-100: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
101-101: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
162-162: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
163-163: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
167-167: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
168-168: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
173-173: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
174-174: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
192-192: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
🔇 Additional comments (2)
plugins/circuitbreaker/go.mod (1)
1-42: LGTM!The go.mod file is correctly configured with appropriate module path, Go version 1.24.1, and the required bifrost core dependency. The indirect dependencies are inherited from the core module and are expected.
plugins/circuitbreaker/main.go (1)
1-518: Excellent circuit breaker implementation!The plugin is well-designed with:
- Comprehensive thread-safe state management using atomic operations
- Clear separation between per-provider states
- Detailed error messages that guide users to alternatives
- Proper implementation of the circuit breaker pattern with all three states
- Performance optimizations including double-checked locking and atomic counters
- Flexible sliding window implementations for both count and time-based metrics
5906232 to
74c74af
Compare

Add Circuit Breaker Plugin for Bifrost
This PR introduces a new Circuit Breaker plugin for Bifrost that provides automatic failure detection and recovery for provider requests. The plugin monitors request failures and slow calls, automatically opening the circuit when thresholds are exceeded to prevent cascading failures.
Features
Implementation Details
Configuration
Documentation
The plugin is designed to be lightweight with minimal overhead in normal operation while providing robust failure protection and automatic recovery capabilities for production AI workloads.