hosterrors

package
v0.5.4 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package hosterrors is the scan-wide dead-host circuit breaker.

A host:port that keeps failing at the transport level (refused, reset, DNS, i/o timeout) is quarantined so the scan stops spending requests and worker time on it. Unlike the cache it replaced, quarantine is not forever: after a cooldown one probe request is let through, and its outcome decides whether the host recovers or stays quarantined for a longer cooldown. A host whose probes keep failing is eventually declared dead for the rest of the scan.

Closed   --(consecutive errors >= MaxHostError)--> Open(openedAt, cooldown)
Open     --(cooldown elapsed; first Admit wins)--> HalfOpen(probeAt)
HalfOpen --(MarkSuccess)-->                        Closed (errors=0, cooldown=base)
HalfOpen --(MarkFailed)-->                         Open (cooldown=min(2×cooldown, max)), trips++
HalfOpen --(probe unreported within ProbeTTL)-->   another probe may be admitted
HalfOpen --(MarkFailed, trips >= MaxTrips)-->      Dead (sticky for the scan)

The key is host:port (see httpmsg.HostPortKey), with no method: a host that refuses connections refuses them for every method.

The API is split so that looking does not consume the probe:

  • Quarantined is read-only. The executor uses it to drop work items for a quarantined host before they occupy a worker.
  • Admit mutates. The requester calls it immediately before a send; it is the call that turns Open into HalfOpen, and it lets exactly one caller through as the probe.

Index

Constants

View Source
const (
	DefaultMaxHostsCount = 10000
	DefaultCooldown      = 30 * time.Second
	DefaultMaxCooldown   = 5 * time.Minute
	DefaultMaxTrips      = 5
	DefaultProbeTTL      = 30 * time.Second
)

Defaults for the breaker timings. DefaultProbeTTL is 2 × the default request timeout (15s); callers that know the configured timeout pass 2 × that.

Variables

View Source
var ErrUnresponsiveHost = errors.New("skipping as host is unresponsive")

ErrUnresponsiveHost is returned when a host is unresponsive

Functions

This section is empty.

Types

type Cache

type Cache struct {
	MaxHostError int
	TrackError   []string
	// contains filtered or unexported fields
}

Cache is the host:port circuit breaker. All methods are safe for concurrent use; Quarantined, Admit and the healthy-host paths of MarkSuccess take no lock beyond a sync.Map load.

func New

func New(maxHostError, maxHostsCount int, trackError []string) *Cache

New returns a breaker with the default timings.

func NewWithConfig added in v0.5.3

func NewWithConfig(cfg Config) *Cache

NewWithConfig returns a breaker for cfg, filling zero fields with defaults.

func (*Cache) Admit added in v0.5.3

func (c *Cache) Admit(key string) bool

Admit reports whether a request to key may be sent now. Call it immediately before the send. For an Open host whose cooldown has elapsed it performs the Open→HalfOpen transition, and exactly one concurrent caller gets true — the probe. A half-open probe that has not reported within ProbeTTL is treated as lost, and one more caller is admitted in its place.

func (*Cache) AnyTripped added in v0.5.3

func (c *Cache) AnyTripped() bool

AnyTripped reports whether any host has ever opened. While it is false, Quarantined is false for every key, so a caller filtering many items can skip building their keys.

func (*Cache) Close

func (c *Cache) Close()

Close releases the cache's entries.

func (*Cache) LastError added in v0.5.3

func (c *Cache) LastError(key string) error

LastError returns the most recent host error recorded for key, or nil.

func (*Cache) MarkFailed

func (c *Cache) MarkFailed(key string, err error, ignoreTimeout bool)

MarkFailed records a failed request to key. Errors that are not host errors (see checkError) are ignored, except that one arriving while a probe is in flight releases the probe slot: the probe's outcome was inconclusive, so the next caller may probe instead of waiting out ProbeTTL.

func (*Cache) MarkSuccess

func (c *Cache) MarkSuccess(key string)

MarkSuccess records a successful request to key. A Closed host's error counter resets; a HalfOpen host recovers. A success while Open is a request that was in flight before the trip and is deliberately ignored: only the probe decides recovery.

func (*Cache) Quarantined added in v0.5.3

func (c *Cache) Quarantined(key string) bool

Quarantined reports whether work for key should be dropped now. Read-only: it never consumes the half-open probe. True while Open inside the cooldown, while HalfOpen with a probe in flight, and once Dead.

func (*Cache) QuarantinedCount

func (c *Cache) QuarantinedCount() int

QuarantinedCount returns how many hosts are currently not Closed (Open, HalfOpen or Dead). Informational, for logging cross-phase propagation.

func (*Cache) SetObserver added in v0.5.3

func (c *Cache) SetObserver(fn func(Transition))

SetObserver installs fn to receive every state transition. It is called outside the breaker's locks, on the goroutine that caused the change, so it must not block. Passing nil removes the observer.

func (*Cache) SetVerbose

func (c *Cache) SetVerbose(verbose bool)

SetVerbose sets the cache to log at verbose level

func (*Cache) State added in v0.5.3

func (c *Cache) State(key string) State

State returns key's current breaker state (Closed for an unknown host).

type Config added in v0.5.3

type Config struct {
	// MaxHostError is the consecutive tracked-error count that opens the
	// breaker (--max-host-error). Must be > 0.
	MaxHostError int
	// MaxHostsCount bounds the ARC that holds error counters for healthy
	// (Closed) hosts. Tripped hosts live outside it and are never evicted.
	MaxHostsCount int
	// TrackError lists extra error substrings that count as host errors.
	TrackError []string
	// Cooldown is the first quarantine period; MaxCooldown caps the doubling.
	Cooldown    time.Duration
	MaxCooldown time.Duration
	// MaxTrips is how many failed probes make a host dead. Negative disables
	// the dead state (the host keeps being re-probed at MaxCooldown).
	MaxTrips int
	// ProbeTTL is how long a half-open probe may stay unreported before another
	// probe is admitted (a probe whose caller vanished must not wedge the host).
	ProbeTTL time.Duration
	// Now is the clock; nil means time.Now. Tests inject a fake one.
	Now func() time.Time
}

Config configures a Cache. Zero values take the defaults above.

type State added in v0.5.3

type State int32

State is a host's breaker state.

const (
	// StateClosed — healthy; consecutive transport errors are being counted.
	StateClosed State = iota
	// StateOpen — quarantined until the cooldown elapses.
	StateOpen
	// StateHalfOpen — one probe request is in flight.
	StateHalfOpen
	// StateDead — every probe failed; quarantined for the rest of the scan.
	StateDead
)

func (State) String added in v0.5.3

func (s State) String() string

String returns the lower-case state name used in logs and event details.

type Transition added in v0.5.3

type Transition struct {
	Key      string
	From, To State
	// Errors is the consecutive-error count at the time of the change.
	Errors int32
	// Trips is the number of failed probes so far.
	Trips int32
	// Cooldown is the quarantine period now in force (Open only).
	Cooldown time.Duration
	// Err is the error that caused the change, nil for a recovery.
	Err error
}

Transition describes one breaker state change, delivered to the observer installed with SetObserver.

Jump to

Keyboard shortcuts

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