libroutine

package
v0.0.69 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2025 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package routine provides utilities for managing recurring tasks (routines) with circuit breaker protection.

The primary purpose of this package is to provide a robust and managed way to run recurring background tasks that might fail, especially those interacting with external services or resources. It combines two key concepts:

1. Circuit Breaker (`Routine`): This pattern prevents an application from repeatedly performing an operation that's likely to fail. When failures reach a threshold, the "circuit" opens, and calls are blocked for a set period (`resetTimeout`). After the timeout, it enters a "half-open" state, allowing one test call. If that succeeds, the circuit closes; otherwise, it re-opens. This provides:

  • Fault Tolerance: Prevents cascading failures by isolating problems.
  • Resource Protection: Stops wasting resources (CPU, network, memory, API quotas) on calls that are continuously failing.
  • Automatic Recovery: Gives the failing service/resource time to recover before trying again automatically.

2. Managed Background Loops (`group`): This component manages multiple circuit breakers (`Routine` instances) identified by unique keys. It handles the lifecycle of running the associated task (`fn`) in a background goroutine, ensuring:

  • Organization: Keeps track of different background tasks centrally.
  • Deduplication: Ensures only one instance of a loop runs for a given key, even if `StartLoop` is called multiple times for the same key.
  • Control: Allows periodic execution (`interval`), on-demand triggering (`ForceUpdate`), context-based cancellation, and manual state resets (`ResetRoutine`).

In essence, use `routine` to reliably run background jobs that need to be resilient to temporary failures without overwhelming either your application or the dependencies they rely on. See `group.StartLoop` for the primary entry point for running managed routines.

Index

Constants

This section is empty.

Variables

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

ErrCircuitOpen is returned by Execute when the circuit breaker is in the Open state and blocking calls. Callers can use errors.Is(err, ErrCircuitOpen) to check.

Functions

func Getgroup added in v0.0.65

func Getgroup() *group

Getgroup returns the singleton instance of the group.

Types

type LoopConfig

type LoopConfig struct {
	Key          string                          // A unique string identifier for this routine. Used to prevent duplicates and manage state.
	Threshold    int                             // The number of consecutive failures of `fn` before the circuit breaker opens.
	ResetTimeout time.Duration                   // The duration the circuit breaker stays open before transitioning to half-open.
	Interval     time.Duration                   // The time duration between executions of `fn` when the circuit is closed or half-open (and the attempt succeeds).
	Operation    func(ctx context.Context) error // The function to execute periodically. It receives the context and should return an error on failure
}

type Routine

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

Routine implements a circuit breaker pattern to protect functions from repeated failures. It tracks failures, opens the circuit when a threshold is reached, and attempts to reset automatically after a timeout (via the HalfOpen state). Routines are typically managed by the group but can be used standalone if needed.

func NewRoutine

func NewRoutine(threshold int, resetTimeout time.Duration) *Routine

NewRoutine creates a new circuit breaker (`Routine`) instance.

Parameters:

  • threshold: The number of consecutive failures required to move the state from Closed to Open. Must be greater than 0.
  • resetTimeout: The period the circuit breaker will remain Open before transitioning to HalfOpen. Must be positive.

func (*Routine) Allow

func (rm *Routine) Allow() bool

Allow checks if the circuit breaker permits an operation based on its current state. It's consulted by `Execute`. Direct use is uncommon but possible for manual checks.

Returns:

  • true: If the state is Closed, or if the state is HalfOpen and no test is ongoing.
  • false: If the state is Open and the reset timeout hasn't elapsed, or if the state is HalfOpen and a test operation is already in progress.

Note: This method may transition the state from Open to HalfOpen if the timeout has passed.

func (*Routine) Execute

func (rm *Routine) Execute(ctx context.Context, fn func(ctx context.Context) error) error

Execute runs the provided function if allowed by the circuit breaker. Use this method when you need to protect a single, on-demand operation with circuit breaking, without requiring automatic looping or retries. For automatic retries, see `ExecuteWithRetry`. For recurring background tasks, see `group.StartLoop` or `Routine.Loop`.

func (*Routine) ExecuteWithRetry

func (rm *Routine) ExecuteWithRetry(ctx context.Context, interval time.Duration, iterations int, fn func(ctx context.Context) error) error

ExecuteWithRetry attempts to run the function `fn` using `Execute`, retrying on failure up to `iterations` times with a fixed `interval` between attempts. Retries stop early if `fn` succeeds or if the context `ctx` is cancelled. The circuit breaker logic applies to *each* attempt via `Execute`.

Parameters:

  • ctx: Context for cancellation. Retries stop if ctx is cancelled.
  • interval: Fixed duration to wait between retry attempts. Consider jitter/backoff for production.
  • iterations: Maximum number of execution attempts (including the first).
  • fn: The function to execute.

Returns:

  • nil: If `fn` executes successfully within the allowed attempts.
  • context.Canceled or context.DeadlineExceeded: If the context is cancelled/times out.
  • error: The last error encountered (either from `fn` or `ErrCircuitOpen`) if all attempts fail.

func (*Routine) ForceClose

func (rm *Routine) ForceClose()

ForceClose manually sets the circuit breaker state to Closed and resets the failure count and test flag. Use primarily for testing or manual operational intervention.

func (*Routine) ForceOpen

func (rm *Routine) ForceOpen()

ForceOpen sets the circuit breaker to the Open state.

func (*Routine) GetResetTimeout

func (rm *Routine) GetResetTimeout() time.Duration

GetResetTimeout returns the reset timeout duration configured for this circuit breaker.

func (*Routine) GetState

func (rm *Routine) GetState() State

GetState returns the current State (Closed, Open, HalfOpen) of the circuit breaker.

func (*Routine) GetThreshold

func (rm *Routine) GetThreshold() int

GetThreshold returns the failure threshold configured for this circuit breaker.

func (*Routine) Loop

func (rm *Routine) Loop(ctx context.Context, interval time.Duration, triggerChan <-chan struct{}, fn func(ctx context.Context) error, errHandling func(err error))

Loop continuously executes the function `fn` based on the circuit breaker state and a timer or trigger channel. This is the core execution logic used by `group.StartLoop`.

The loop runs `Execute(fn)`: 1. Immediately when the loop starts. 2. After the `interval` duration elapses. 3. Immediately when a signal is received on `triggerChan`. 4. Stops when the `ctx` context is cancelled.

Parameters:

  • ctx: Context for cancellation. The loop terminates when ctx is done.
  • interval: The duration between scheduled executions when the circuit allows.
  • triggerChan: A channel used to force immediate execution attempts (e.g., via `group.ForceUpdate`). Reads are non-blocking.
  • fn: The function to execute in each cycle.
  • errHandling: A callback function invoked when `Execute(fn)` returns an error. Use this for logging or custom error handling specific to the loop runner. Note: `ErrCircuitOpen` will also be passed here when calls are blocked.

func (*Routine) MarkFailure

func (rm *Routine) MarkFailure()

MarkFailure records a failed operation. If the state was Closed, it increments the failure count. If the count reaches the threshold, it transitions to Open. If the state was HalfOpen, it transitions back to Open. Called internally by `Execute` on failure.

func (*Routine) MarkSuccess

func (rm *Routine) MarkSuccess()

MarkSuccess resets the circuit breaker after a successful call.

type State

type State int

State represents the operational state of the Routine (circuit breaker). Circuit Breaker States:

 (Success)
 < Succeeded > --+
/               |

[CLOSED] --- Failure Threshold Reached ---> [OPEN]

^                                          |
|                                          | Reset Timeout Elapsed
| Success (Test OK)                        V

[HALF-OPEN] <---- Failure (Test Failed) ---[ Test Call ]

|
+-- Failure (Test Failed) --> (Reverts to OPEN)
const (
	// Closed allows operations to execute and counts failures.
	Closed State = iota
	// Open prevents operations from executing immediately. After a timeout,
	// it transitions to HalfOpen.
	Open
	// HalfOpen allows a single operation attempt. If successful, transitions to Closed.
	// If it fails, transitions back to Open.
	HalfOpen
)

func (State) String

func (s State) String() string

String returns a human-readable representation of the State.

Jump to

Keyboard shortcuts

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