mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-24 13:42:15 +00:00
- Add State enum with Closed, Open, and HalfOpen states and String method - Add CircuitBreaker struct with mutex, state tracking, failure/success counters, and timeout - Add Config struct with FailureThreshold, SuccessThreshold, and Timeout fields - Add NewCircuitBreaker constructor with Config parameter - Add DefaultConfig with 5 failure threshold, 2 success threshold, and 60 second timeout
143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
package circuitbreaker
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// State represents the state of the circuit breaker
|
|
type State int
|
|
|
|
const (
|
|
StateClosed State = iota
|
|
StateOpen
|
|
StateHalfOpen
|
|
)
|
|
|
|
func (s State) String() string {
|
|
switch s {
|
|
case StateClosed:
|
|
return "Closed"
|
|
case StateOpen:
|
|
return "Open"
|
|
case StateHalfOpen:
|
|
return "HalfOpen"
|
|
default:
|
|
return "Unknown"
|
|
}
|
|
}
|
|
|
|
// CircuitBreaker implements the circuit breaker pattern
|
|
type CircuitBreaker struct {
|
|
mu sync.Mutex
|
|
state State
|
|
failureCount uint
|
|
failureThreshold uint
|
|
successThreshold uint
|
|
timeout time.Duration
|
|
lastFailureTime time.Time
|
|
halfOpenSuccesses uint
|
|
}
|
|
|
|
// Config holds the configuration for the circuit breaker
|
|
type Config struct {
|
|
FailureThreshold uint
|
|
SuccessThreshold uint
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// NewCircuitBreaker creates a new circuit breaker with the given configuration
|
|
func NewCircuitBreaker(config Config) *CircuitBreaker {
|
|
return &CircuitBreaker{
|
|
state: StateClosed,
|
|
failureThreshold: config.FailureThreshold,
|
|
successThreshold: config.SuccessThreshold,
|
|
timeout: config.Timeout,
|
|
}
|
|
}
|
|
|
|
// DefaultConfig returns a default configuration for the circuit breaker
|
|
func DefaultConfig() Config {
|
|
return Config{
|
|
FailureThreshold: 5,
|
|
SuccessThreshold: 2,
|
|
Timeout: 60 * time.Second,
|
|
}
|
|
}
|
|
|
|
// Execute runs the given function with circuit breaker protection
|
|
func (cb *CircuitBreaker) Execute(fn func() error) error {
|
|
cb.mu.Lock()
|
|
|
|
// Check if we should attempt to transition from Open to HalfOpen
|
|
if cb.state == StateOpen && time.Since(cb.lastFailureTime) > cb.timeout {
|
|
cb.state = StateHalfOpen
|
|
cb.halfOpenSuccesses = 0
|
|
}
|
|
|
|
// If circuit is open, reject the request
|
|
if cb.state == StateOpen {
|
|
cb.mu.Unlock()
|
|
return errors.New("circuit breaker is open")
|
|
}
|
|
|
|
cb.mu.Unlock()
|
|
|
|
// Execute the function
|
|
err := fn()
|
|
|
|
cb.mu.Lock()
|
|
defer cb.mu.Unlock()
|
|
|
|
if err != nil {
|
|
cb.onFailure()
|
|
return err
|
|
}
|
|
|
|
cb.onSuccess()
|
|
return nil
|
|
}
|
|
|
|
// onFailure handles a failed operation
|
|
func (cb *CircuitBreaker) onFailure() {
|
|
cb.failureCount++
|
|
cb.lastFailureTime = time.Now()
|
|
|
|
if cb.failureCount >= cb.failureThreshold {
|
|
cb.state = StateOpen
|
|
}
|
|
}
|
|
|
|
// onSuccess handles a successful operation
|
|
func (cb *CircuitBreaker) onSuccess() {
|
|
if cb.state == StateClosed {
|
|
cb.failureCount = 0
|
|
return
|
|
}
|
|
|
|
if cb.state == StateHalfOpen {
|
|
cb.halfOpenSuccesses++
|
|
if cb.halfOpenSuccesses >= cb.successThreshold {
|
|
cb.state = StateClosed
|
|
cb.failureCount = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetState returns the current state of the circuit breaker
|
|
func (cb *CircuitBreaker) GetState() State {
|
|
cb.mu.Lock()
|
|
defer cb.mu.Unlock()
|
|
return cb.state
|
|
}
|
|
|
|
// Reset resets the circuit breaker to closed state
|
|
func (cb *CircuitBreaker) Reset() {
|
|
cb.mu.Lock()
|
|
defer cb.mu.Unlock()
|
|
cb.state = StateClosed
|
|
cb.failureCount = 0
|
|
cb.halfOpenSuccesses = 0
|
|
}
|