Help us shape the future of Go! Take the 2026 Go Developer Survey

lifecycle

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package lifecycle owns application execution and composition admission.

Index

Constants

View Source
const (
	StateNew      = "new"
	StateStarting = "starting"
	StateRunning  = "running"
	StateStopping = "stopping"
	StateStopped  = "stopped"
	StateFailed   = "failed"
)

Execution phases are private to the owning application implementation.

Variables

View Source
var ErrInvalidPhase = errors.New("invalid application phase")

ErrInvalidPhase identifies calls outside the admitted execution phase.

View Source
var ErrNilFunc = errors.New("nil function")

ErrNilFunc identifies missing callbacks and empty check names.

Functions

func Protect

func Protect(fn func() error) (err error)

Protect runs fn and converts a panic into an error reported with its stack.

Types

type Runtime

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

Runtime owns one startup, runner group, and reverse-order cleanup stack.

func New

func New(logger *slog.Logger, timeout time.Duration,
	signal func(context.Context, string, error),
	start, stop func(context.Context) error,
	monitor func() func(context.Context) error,
	discardChecks func(),
) *Runtime

New constructs an idle execution without running callbacks.

func (*Runtime) Live

func (runtime *Runtime) Live() bool

Live reports whether the runner group is active and has not failed.

func (*Runtime) Run

func (runtime *Runtime) Run(ctx context.Context, compose ...func(*Scope)) error

Run starts the runtime, waits for runners or ctx, then shuts down with the configured shutdown timeout. Composition has the same ordering, failure, and panic semantics as Runtime.Start. Lifecycle failures are already logged when Run returns. Telemetry has been finalized, so callers should use the result for exit status or recovery rather than logging it again. Telemetry finalization failures reach the log handler directly because export is no longer available.

func (*Runtime) Shutdown

func (runtime *Runtime) Shutdown(ctx context.Context) error

Shutdown cancels the runners, waits for them until ctx ends, and then runs every cleanup callback exactly once in reverse order, even if waiting timed out. Cleanup receives an uncanceled context with the remaining budget of ctx but at least ten seconds. The runtime ends in StateStopped only after telemetry finalization. Concurrent and later calls return the result of that single pass. Shutdown after a failed Start returns nil because Start already cleaned up.

When telemetry is configured it is shut down last, after the "app stopped" log and the [Stopped] event, with the remaining budget of ctx but at least ten seconds, on every exit path; its error is joined into the result. These budgets are context deadlines, not forced interruption: a callback that ignores cancellation can keep cleanup or finalization from returning.

While starting, Shutdown cancels startup and waits for its owner to roll back; ctx bounds that wait. Shutdown must not be called synchronously from composition, Startup, a runner, or a Cleanup callback.

func (*Runtime) Snapshot

func (runtime *Runtime) Snapshot() (string, time.Time)

Snapshot returns the phase and successful startup timestamp atomically.

func (*Runtime) Start

func (runtime *Runtime) Start(ctx context.Context, compose ...func(*Scope)) error

Start composes dependencies synchronously in order, starts telemetry, then executes Startup callbacks in order and launches runners and health checks. All composers finish before any Startup callback runs. On failure or context cancellation every registered Cleanup runs once in reverse order with a bounded uncanceled context, followed by telemetry finalization. Failures are logged by the runtime before telemetry finalization; errors before telemetry starts reach the configured log handler only. Starting is dispatched after composition and telemetry startup, before user Startup callbacks, so its listeners can log through active telemetry.

ctx supplies startup cancellation only; synchronous composition and startup callbacks must cooperate with it. Runners use a context that keeps ctx's values but is canceled solely by Shutdown or a runner failure. Composition programmer panics trigger best-effort rollback and are re-panicked; Startup, runner, and Cleanup panics retain the lifecycle panic-to-error behavior. Do not call Shutdown synchronously from composition or Startup.

func (*Runtime) Wait

func (runtime *Runtime) Wait(ctx context.Context) error

Wait blocks until the runner group finishes or ctx ends, then returns the first runner failure, if any. Without runners it blocks until ctx ends or Shutdown begins. Caller cancellation alone is a normal wait completion and does not return ctx.Err or stop the runtime. Call Shutdown afterwards, or use Run to combine startup, waiting, and shutdown.

type Scope

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

Scope owns synchronous registration permissions for one Start execution. Registration is synchronous: do not retain the composer for use by workers. Cleanup and Defer may also be called inside an executing Startup callback; Require and child composition validation remain composition-only.

func (*Scope) Check

func (composer *Scope) Check(name string, fn func(context.Context) error, add func())

Check registers a nonempty, unique name and readiness callback during synchronous composition. Checks run once monitoring begins after Startup. Empty names or nil callbacks panic with ErrNilFunc; duplicate names panic through add and late registrations with ErrInvalidPhase.

func (*Scope) Cleanup

func (composer *Scope) Cleanup(fn func(context.Context) error)

Cleanup registers an immediately active release, independent of whether any Startup callback runs. All releases run once in reverse registration order on failure or shutdown, before telemetry finalization, with bounded uncanceled context. Errors and recovered panics are joined without skipping releases. Registration is allowed during composition and executing Startup callbacks.

func (*Scope) Context

func (composer *Scope) Context() context.Context

Context returns the startup context shared by composition and Startup. Shutdown cancels it while startup is in progress. Runners receive their own lifecycle context; do not retain this one for background work.

func (*Scope) Defer

func (composer *Scope) Defer(release func())

Defer registers an infallible release on the same stack as Scope.Cleanup. It runs once on failure or shutdown in reverse registration order, not when the enclosing Go function returns. Registration is allowed during composition and executing Startup callbacks. A nil release panics with ErrNilFunc; release panics are handled like other cleanup panics. Use Cleanup when release needs a context or can return an error.

func (*Scope) Require

func (composer *Scope) Require(err error)

Require aborts composition with err; nil is a no-op. The first failure is recorded before raising an execution-specific private panic, so recovering that panic does not make Start succeed. Calling outside an executing composer panics with ErrInvalidPhase, even for nil. Ordinary panics still propagate.

func (*Scope) Run

func (composer *Scope) Run(fn func(context.Context) error)

Run registers a worker launched only after all Startup callbacks succeed. An unexpected error or panic cancels all workers; errors after cancellation are normal stops. Register only during synchronous composition.

func (*Scope) Startup

func (composer *Scope) Startup(fn func(context.Context) error)

Startup registers a callback run after every composer succeeds and telemetry starts. Callbacks run sequentially in registration order; an error prevents later startups and all runners. Panics become errors with a stack trace. Registration is permitted only during synchronous composition.

func (*Scope) Validate

func (composer *Scope) Validate()

Validate rejects expired scopes and rethrows a recorded execution abort.

func (*Scope) Wiring

func (composer *Scope) Wiring() bool

Wiring reports whether this scope currently admits composition operations.

type ScopeFunc

type ScopeFunc = func(*Scope)

ScopeFunc composes concrete runtime dependencies during Start or Run. Callbacks execute once, synchronously in order, before any Startup callback. Nil callbacks are programmer errors and panic after best-effort rollback.

Jump to

Keyboard shortcuts

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