resilience

package
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2026 License: GPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package resilience provides circuit breaker and provider failover primitives.

The central type is CircuitBreaker, a classic three-state breaker (closed → open → half-open) that protects callers from cascading failures. FallbackGroup composes multiple instances of any provider type with per-entry circuit breakers so that a failing primary is automatically bypassed in favour of healthy fallbacks.

All types are safe for concurrent use.

Index

Constants

This section is empty.

Variables

View Source
var ErrAllFailed = errors.New("all providers failed")

ErrAllFailed is returned when every entry in a FallbackGroup fails or has an open circuit breaker.

View Source
var ErrCircuitOpen = errors.New("circuit breaker is open")

ErrCircuitOpen is returned by CircuitBreaker.Execute when the breaker is in the open state and the reset timeout has not yet elapsed.

Functions

func ExecuteWithResult

func ExecuteWithResult[T any, R any](fg *FallbackGroup[T], fn func(T) (R, error)) (R, error)

ExecuteWithResult tries fn against each entry in the group until one succeeds, returning both the result value and error. This is a package-level function because Go does not support method-level type parameters.

Types

type CircuitBreaker

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

CircuitBreaker implements the three-state circuit breaker pattern. It is safe for concurrent use from multiple goroutines.

func NewCircuitBreaker

func NewCircuitBreaker(cfg CircuitBreakerConfig) *CircuitBreaker

NewCircuitBreaker creates a CircuitBreaker with the supplied configuration. Zero-value config fields are replaced with sensible defaults.

func (*CircuitBreaker) Execute

func (cb *CircuitBreaker) Execute(fn func() error) error

Execute runs fn if the breaker allows it. In the open state it returns ErrCircuitOpen without calling fn. In the half-open state a limited number of probe calls are permitted.

func (*CircuitBreaker) Reset

func (cb *CircuitBreaker) Reset()

Reset manually forces the breaker back to StateClosed, clearing all failure counters.

func (*CircuitBreaker) State

func (cb *CircuitBreaker) State() State

State returns the current State of the breaker. If the breaker is open and the reset timeout has elapsed, the returned state is StateHalfOpen (the actual transition happens on the next [Execute] call).

type CircuitBreakerConfig

type CircuitBreakerConfig struct {
	// Name is a human-readable label used in log messages.
	Name string

	// MaxFailures is the number of consecutive failures in the closed state
	// before the breaker opens. Default: 5.
	MaxFailures int

	// ResetTimeout is how long the breaker stays open before transitioning to
	// half-open. Default: 30s.
	ResetTimeout time.Duration

	// HalfOpenMax is the maximum number of probe calls allowed in the half-open
	// state before the breaker decides whether to close or re-open. Default: 3.
	HalfOpenMax int
}

CircuitBreakerConfig holds tuning knobs for a CircuitBreaker.

type FallbackConfig

type FallbackConfig struct {
	CircuitBreaker CircuitBreakerConfig
}

FallbackConfig configures the per-entry circuit breaker created for each provider in a FallbackGroup.

type FallbackGroup

type FallbackGroup[T any] struct {
	// contains filtered or unexported fields
}

FallbackGroup wraps a primary and zero or more fallback instances of the same provider type. When the primary fails (or its circuit breaker is open), the next healthy fallback is tried in registration order.

FallbackGroup.Execute and ExecuteWithResult are safe for concurrent use. FallbackGroup.AddFallback must be called during initialisation, before any concurrent Execute calls — it is NOT safe to call concurrently with Execute.

func NewFallbackGroup

func NewFallbackGroup[T any](primary T, primaryName string, cfg FallbackConfig) *FallbackGroup[T]

NewFallbackGroup creates a FallbackGroup with primary as the first entry. Additional fallbacks are registered via FallbackGroup.AddFallback.

func (*FallbackGroup[T]) AddFallback

func (fg *FallbackGroup[T]) AddFallback(name string, fallback T)

AddFallback appends a fallback provider. Fallbacks are tried in the order they are added, after the primary.

AddFallback must only be called during initialisation, before any concurrent calls to FallbackGroup.Execute or ExecuteWithResult.

func (*FallbackGroup[T]) Execute

func (fg *FallbackGroup[T]) Execute(fn func(T) error) error

Execute tries fn against each entry in order until one succeeds. Circuit-breaker-open entries are skipped. Returns ErrAllFailed wrapped with the last error if every entry fails.

type LLMFallback

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

LLMFallback implements llm.Provider with automatic failover across multiple LLM backends. Each backend has its own circuit breaker; when the primary fails or its breaker is open, the next healthy fallback is tried.

func NewLLMFallback

func NewLLMFallback(primary llm.Provider, primaryName string, cfg FallbackConfig) *LLMFallback

NewLLMFallback creates an LLMFallback with primary as the preferred backend.

func (*LLMFallback) AddFallback

func (f *LLMFallback) AddFallback(name string, provider llm.Provider)

AddFallback registers an additional LLM provider as a fallback.

func (*LLMFallback) Capabilities

func (f *LLMFallback) Capabilities() llm.ModelCapabilities

Capabilities returns the capabilities of the first entry (the primary). This does not participate in failover because capabilities are static metadata.

func (*LLMFallback) Complete

Complete sends the request to the first healthy provider and returns its response. If the primary fails, subsequent fallbacks are tried.

func (*LLMFallback) CountTokens

func (f *LLMFallback) CountTokens(messages []llm.Message) (int, error)

CountTokens delegates to the first healthy provider's token counter.

func (*LLMFallback) StreamCompletion

func (f *LLMFallback) StreamCompletion(ctx context.Context, req llm.CompletionRequest) (<-chan llm.Chunk, error)

StreamCompletion sends the request to the first healthy provider and returns a streaming chunk channel. Note: only the initial connection attempt is covered by failover; once a stream is established, mid-stream errors are the caller's responsibility.

type STTFallback

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

STTFallback implements stt.Provider with automatic failover across multiple STT backends. Each backend has its own circuit breaker.

func NewSTTFallback

func NewSTTFallback(primary stt.Provider, primaryName string, cfg FallbackConfig) *STTFallback

NewSTTFallback creates an STTFallback with primary as the preferred backend.

func (*STTFallback) AddFallback

func (f *STTFallback) AddFallback(name string, provider stt.Provider)

AddFallback registers an additional STT provider as a fallback.

func (*STTFallback) StartStream

func (f *STTFallback) StartStream(ctx context.Context, cfg stt.StreamConfig) (stt.SessionHandle, error)

StartStream opens a streaming transcription session against the first healthy provider. If the primary fails to start the stream, subsequent fallbacks are tried.

type State

type State int

State represents the current operating mode of a CircuitBreaker.

const (
	// StateClosed is the normal operating state — all calls are forwarded.
	StateClosed State = iota

	// StateOpen indicates the breaker has tripped due to consecutive failures.
	// Calls are rejected immediately with [ErrCircuitOpen] until the reset
	// timeout elapses.
	StateOpen

	// StateHalfOpen is the probe state entered after the reset timeout. A limited
	// number of calls are allowed through; if they succeed the breaker closes,
	// otherwise it re-opens.
	StateHalfOpen
)

func (State) String

func (s State) String() string

String returns the human-readable name of the state.

type TTSFallback

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

TTSFallback implements tts.Provider with automatic failover across multiple TTS backends. Each backend has its own circuit breaker.

func NewTTSFallback

func NewTTSFallback(primary tts.Provider, primaryName string, cfg FallbackConfig) *TTSFallback

NewTTSFallback creates a TTSFallback with primary as the preferred backend.

func (*TTSFallback) AddFallback

func (f *TTSFallback) AddFallback(name string, provider tts.Provider)

AddFallback registers an additional TTS provider as a fallback.

func (*TTSFallback) CloneVoice

func (f *TTSFallback) CloneVoice(ctx context.Context, samples [][]byte) (*tts.VoiceProfile, error)

CloneVoice creates a new voice profile using the first healthy provider.

func (*TTSFallback) ListVoices

func (f *TTSFallback) ListVoices(ctx context.Context) ([]tts.VoiceProfile, error)

ListVoices returns available voices from the first healthy provider.

func (*TTSFallback) SynthesizeStream

func (f *TTSFallback) SynthesizeStream(ctx context.Context, text <-chan string, voice tts.VoiceProfile) (<-chan []byte, error)

SynthesizeStream consumes text fragments and returns a channel of audio bytes, trying the first healthy provider. Only the initial stream setup is covered by failover; mid-stream errors are the caller's responsibility.

Jump to

Keyboard shortcuts

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