checircuit

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 9, 2025 License: MIT Imports: 3 Imported by: 0

README

checircuit

Circuit breaker pattern implementation for fault tolerance and resilience.

Features

  • Three states: Closed, Open, Half-Open
  • Configurable failure threshold and timeout
  • State change callbacks
  • Thread-safe
  • Zero external dependencies

Installation

go get github.com/comfortablynumb/che/pkg/checircuit

Usage

Basic Example
package main

import (
    "fmt"
    "errors"
    "time"
    "github.com/comfortablynumb/che/pkg/checircuit"
)

func main() {
    cb := checircuit.New(&checircuit.Config{
        MaxFailures: 3,                  // Open after 3 failures
        Timeout:     30 * time.Second,   // Try again after 30s
        MaxRequests: 2,                  // Allow 2 requests in half-open
    })

    // Execute a function through the circuit breaker
    err := cb.Execute(func() error {
        // Your risky operation here
        return callExternalService()
    })

    if err == checircuit.ErrCircuitOpen {
        fmt.Println("Circuit is open, request rejected")
    }
}
With State Change Callback
cb := checircuit.New(&checircuit.Config{
    MaxFailures: 5,
    Timeout:     60 * time.Second,
    OnStateChange: func(from, to checircuit.State) {
        fmt.Printf("Circuit breaker: %v -> %v\n", from, to)
    },
})

// Simulate failures
for i := 0; i < 5; i++ {
    cb.Execute(func() error {
        return errors.New("service unavailable")
    })
}
// Output: Circuit breaker: Closed -> Open

// Wait for timeout
time.Sleep(61 * time.Second)

// Next request transitions to half-open
cb.Execute(func() error {
    return nil
})
// Output: Circuit breaker: Open -> HalfOpen
Monitoring State
// Check current state
state := cb.State()
switch state {
case checircuit.StateClosed:
    fmt.Println("Operating normally")
case checircuit.StateOpen:
    fmt.Println("Circuit is open, blocking requests")
case checircuit.StateHalfOpen:
    fmt.Println("Testing if service recovered")
}

// Check failure count
failures := cb.Failures()
fmt.Printf("Current failures: %d\n", failures)

// Manually reset
cb.Reset() // Forces back to Closed state
Practical Example: HTTP Client
package main

import (
    "fmt"
    "net/http"
    "time"
    "github.com/comfortablynumb/che/pkg/checircuit"
)

type ResilientClient struct {
    client  *http.Client
    breaker *checircuit.Breaker
}

func NewResilientClient() *ResilientClient {
    return &ResilientClient{
        client: &http.Client{Timeout: 5 * time.Second},
        breaker: checircuit.New(&checircuit.Config{
            MaxFailures: 5,
            Timeout:     30 * time.Second,
            MaxRequests: 3,
        }),
    }
}

func (rc *ResilientClient) Get(url string) (*http.Response, error) {
    var resp *http.Response

    err := rc.breaker.Execute(func() error {
        var err error
        resp, err = rc.client.Get(url)
        if err != nil {
            return err
        }

        if resp.StatusCode >= 500 {
            return fmt.Errorf("server error: %d", resp.StatusCode)
        }

        return nil
    })

    return resp, err
}

How It Works

The circuit breaker has three states:

  1. Closed (Normal operation)

    • Requests pass through normally
    • Failures are counted
    • Opens when failure threshold is reached
  2. Open (Failing fast)

    • All requests are rejected immediately
    • Returns ErrCircuitOpen
    • After timeout, transitions to Half-Open
  3. Half-Open (Testing recovery)

    • Allows limited number of requests through
    • If requests succeed, closes the circuit
    • If any request fails, reopens the circuit

Configuration

type Config struct {
    // MaxFailures: Number of failures before opening (default: 5)
    MaxFailures uint

    // Timeout: How long to wait before trying half-open (default: 60s)
    Timeout time.Duration

    // MaxRequests: Max requests in half-open state (default: 1)
    MaxRequests uint

    // OnStateChange: Called when state changes (optional)
    OnStateChange func(from, to State)
}

Errors

  • ErrCircuitOpen - Returned when circuit is open
  • ErrTooManyRequests - Returned when half-open has too many requests

Thread Safety

All operations are thread-safe and can be called concurrently.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrCircuitOpen is returned when the circuit breaker is open.
	ErrCircuitOpen = errors.New("circuit breaker is open")
	// ErrTooManyRequests is returned when too many requests are made in half-open state.
	ErrTooManyRequests = errors.New("too many requests")
)

Functions

This section is empty.

Types

type Breaker

type Breaker struct {
	// contains filtered or unexported fields
}

Breaker is a circuit breaker implementation.

func New

func New(config *Config) *Breaker

New creates a new circuit breaker.

func (*Breaker) Execute

func (b *Breaker) Execute(fn func() error) error

Execute runs the function if the circuit is not open.

func (*Breaker) Failures

func (b *Breaker) Failures() uint

Failures returns the current failure count.

func (*Breaker) Reset

func (b *Breaker) Reset()

Reset resets the circuit breaker to closed state.

func (*Breaker) State

func (b *Breaker) State() State

State returns the current state of the circuit breaker.

type Config

type Config struct {
	// MaxFailures is the maximum number of failures before opening. Default: 5
	MaxFailures uint

	// Timeout is how long to wait before transitioning from Open to HalfOpen. Default: 60s
	Timeout time.Duration

	// MaxRequests is the maximum requests allowed in HalfOpen state. Default: 1
	MaxRequests uint

	// OnStateChange is called when the state changes. Optional.
	OnStateChange func(from, to State)
}

Config holds the configuration for a circuit breaker.

type State

type State int

State represents the state of the circuit breaker.

const (
	// StateClosed allows requests through.
	StateClosed State = iota
	// StateOpen blocks requests.
	StateOpen
	// StateHalfOpen allows a limited number of requests to test if the service recovered.
	StateHalfOpen
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL