breakers

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package breakers provides named, dynamically-controllable on/off switches for individual functional surfaces of the rendezvous process. Operators flip a switch by writing a JSON file (<store-dir>/breakers.json); a file watcher reloads the state every 2 s and call sites consult the breaker before serving the affected request type.

Three states per breaker:

closed     — normal operation (default). Allow.
half_open  — log a warning, but allow. Use for canary testing
             or to observe call frequency without disrupting
             traffic.
open       — deny. The serving site returns an appropriate
             error to the caller (typically a 503-equivalent
             with the operator-supplied reason).

Names are flat strings, conventionally dotted paths reflecting the component and action being gated (e.g. "registry.register", "beacon.punch", "snapshot.write"). The Manager is permissive: it accepts any name on the read path; a missing breaker is treated as "closed" (allow). Unknown names in the JSON file are kept but silently unused — write-time tolerance lets operators stage a name before its call site is wired.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Watch

func Watch(
	m *Manager,
	path string,
	interval time.Duration,
	stop <-chan struct{},
)

Watch polls path for mtime+size changes every interval and atomically reloads breakers into the Manager when the file changes.

Operational contract — pinned by tests; identical in spirit to the rate-limit whitelist watcher:

  • Never blocks startup, the registry, the beacon, or any request path. Runs in its own goroutine; the only state it mutates is the Manager, via Replace.
  • Fail-open: missing file is fine (no breakers installed; every name returns Allow=closed via Manager's default-allow). Parse, stat, or apply errors are logged at WARN and leave whatever map is currently installed in place.
  • Idempotent: same file content (unchanged mtime + size) is a no-op.
  • File removal reverts the Manager to an empty map on the next tick (logged INFO).

File format — JSON object, name → {state, reason?}:

{
  "registry.register":       {"state": "closed"},
  "beacon.punch":            {"state": "open",     "reason": "maintenance"},
  "dashboard.public_stats":  {"state": "half_open","reason": "soaking pre-lockdown"}
}

state must be one of "closed", "half_open", "open" (case-insensitive, with the same aliases ParseState accepts). reason is operator-facing free text surfaced in error messages when a breaker is open.

Types

type Breaker

type Breaker struct {
	Name        string    `json:"name"`
	State       State     `json:"-"` // serialised via custom marshalling
	StateString string    `json:"state"`
	Reason      string    `json:"reason,omitempty"`
	UpdatedAt   time.Time `json:"updated_at,omitempty"`
}

Breaker is a snapshot of one named switch's state.

type Manager

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

Manager holds the live breaker map. Safe for concurrent use.

func New

func New() *Manager

New returns an empty Manager. No breakers are pre-registered; Allow on any unknown name returns (true, Closed) — the default- allow semantic ensures a missing JSON file or a misspelled name can never cut off service.

func (*Manager) Allow

func (m *Manager) Allow(name string) (bool, State)

Allow consults the named breaker and returns:

(true, Closed)   — normal operation
(true, HalfOpen) — caller should log a warning, then proceed
(false, Open)    — caller must NOT proceed; return an error

An unknown name is treated as Closed (default-allow) so a request path is never blocked by a typo. The state is returned alongside the bool so the caller can log appropriately without a second lookup.

func (*Manager) Reason

func (m *Manager) Reason(name string) string

Reason returns the operator-supplied reason for the named breaker's current state, or "" if no breaker is registered. Use in error messages surfaced to callers when Allow returns false.

func (*Manager) Replace

func (m *Manager) Replace(breakers map[string]*Breaker)

Replace atomically swaps the full breaker map. Used by the file watcher to apply a fresh JSON snapshot in one shot.

func (*Manager) Set

func (m *Manager) Set(name string, state State, reason string)

Set installs or replaces one breaker. Audit-logged via the Manager's updated-at timestamp; callers who want a separate event sink should wrap this method.

func (*Manager) SetClock

func (m *Manager) SetClock(fn func() time.Time)

SetClock overrides the time source (tests).

func (*Manager) Size

func (m *Manager) Size() int

Size returns the current count of registered breakers.

func (*Manager) Snapshot

func (m *Manager) Snapshot() []Breaker

Snapshot returns a copy of every registered breaker. Safe to mutate. Order is insertion-stable only within a single call; callers needing a sorted view should sort the slice themselves.

type State

type State int

State enumerates the three configurable states a breaker can be in.

const (
	// Closed means normal operation: Allow returns (true, Closed).
	Closed State = iota
	// HalfOpen means warn-but-allow: Allow returns (true, HalfOpen).
	// Call sites should log a warning so operators can observe.
	HalfOpen
	// Open means deny: Allow returns (false, Open). Call sites should
	// surface the breaker's reason in any error returned to the caller.
	Open
)

func ParseState

func ParseState(s string) (State, error)

ParseState parses a wire-format state string. Accepts the canonical "closed" / "half_open" / "open" plus a few common aliases ("half-open", "halfopen") so the JSON file is forgiving. Unknown values return an error so a typo doesn't silently become Closed.

func (State) String

func (s State) String() string

String returns the wire-format name ("closed", "half_open", "open"), matching the JSON file format.

Jump to

Keyboard shortcuts

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