Documentation
¶
Overview ¶
Package lifecycle classifies "why did this goroutine generation end" from several independent local signals (a deliberate-close flag, a clean-exit flag, ctx.Err()) into a closed Reason, so a subsystem's reconnect/exit- callback decision is one function call instead of a boolean-OR of flags. See project_plans/session-lifecycle-state-machine for the motivating incidents.
Index ¶
- func AwaitBounded(done <-chan struct{}, wait time.Duration) bool
- func EndGeneration(span trace.Span, subsystem string, reason Reason)
- func IsBenignTimeout(err error) bool
- func RecordEnd(ctx context.Context, subsystem string, reason Reason)
- func RegisterMetrics() error
- func StartGeneration(ctx context.Context, subsystem string) (context.Context, trace.Span)
- type Reason
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AwaitBounded ¶
AwaitBounded waits for done to close, returning true if it does before wait elapses and false otherwise. Generalizes the bounded-wait-then- abandon idiom needed when tearing down a generation whose goroutine may be blocked on a read Go cannot forcibly interrupt.
func EndGeneration ¶
EndGeneration tags span with reason, ends it, increments session_lifecycle_ends_total, and decrements session_lifecycle_active_generations. Pairs with StartGeneration.
func IsBenignTimeout ¶
IsBenignTimeout reports whether err is an expected poll-timeout rather than a real disconnect: a net.Error with Timeout() true, os.ErrDeadlineExceeded, or io.ErrUnexpectedEOF (a partial read before the deadline fired). Ports exactly the three typed checks session/external_streamer.go used inline, deliberately without a strings.Contains fallback — a classifier that falls through to matching error text silently breaks if a wrapped library changes its message.
func RecordEnd ¶
RecordEnd is a lighter-weight alternative to EndGeneration for a lifecycle-ending decision that does not own a dedicated generation span (e.g. a reconnect loop's own give-up branches, running mid-generation on an already-open span). Adds a span event on ctx's current span, if any — a no-op otherwise — plus the same counter increment as EndGeneration. It does not touch the active-generations gauge: callers of RecordEnd never called StartGeneration, so there is nothing to decrement.
func RegisterMetrics ¶
func RegisterMetrics() error
RegisterMetrics registers the session_lifecycle_* instruments against telemetry.GetMeter(). Idempotent via sync.Once — package init already calls this once; exported so a test can call it again safely.
Types ¶
type Reason ¶
type Reason int
Reason is a closed enum representing why a goroutine-lifecycle generation ended. Its zero value, ReasonUnknown, is safe by default: any code path that never explicitly classifies a reason (a forgotten assignment, or a future variant added without updating a predicate's switch) is treated as "stop, and notify" by ShouldContinue/ShouldFireExitCallback respectively, rather than silently reconnecting or silently swallowing an exit. Mirrors session/detection.DetectedStatus's iota-plus-exhaustive-linter idiom (see .golangci.yml's exhaustive carve-out for this package).
const ( // ReasonUnknown is Reason's zero value — see the type doc comment. ReasonUnknown Reason = iota // ReasonDeliberateClose means the whole session/session-owner is ending // on purpose. ReasonDeliberateClose // ReasonDeliberateSupersede means this generation is being torn down // deliberately for a reopen, but the owning session is not closing. ReasonDeliberateSupersede // ReasonCleanExit means the remote side already reported a clean exit // before this generation's read/receive failed. ReasonCleanExit // ReasonTransportDrop means an unexpected, non-deliberate stream/process // end — the only Reason for which ShouldContinue() returns true. ReasonTransportDrop // ReasonReconnectExhausted means a reconnect loop ran out of attempts // without reconnecting, as opposed to being interrupted by a deliberate // close. ReasonReconnectExhausted )
func (Reason) ShouldContinue ¶
ShouldContinue reports whether the calling goroutine should attempt to reconnect/retry for this Reason. Only ReasonTransportDrop returns true; every other value — including ReasonUnknown and any unhandled future variant — returns false (fail toward stopping).
func (Reason) ShouldFireExitCallback ¶
ShouldFireExitCallback reports whether a one-shot exit callback should fire for this Reason. Only ReasonDeliberateClose returns false; every other value — including ReasonUnknown and any unhandled future variant — returns true (fail toward notifying, since a silently-swallowed exit is the worse outcome for a one-shot callback contract).