lifecycle

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package lifecycle provides the ContextCloser interface and adapters for managing resource teardown with context-aware shutdown budgets.

ContextCloser vs io.Closer

Go's standard io.Closer only exposes Close() error, which prevents callers from sharing a single shutdown-budget context across multiple resources. When Bootstrap phase10 holds a shutCtx = context.WithTimeout(Background, shutdownTimeout), each io.Closer called without that ctx can independently hang, causing the total shutdown time to exceed the intended budget.

ContextCloser solves this by accepting the ctx at call time:

type ContextCloser interface {
    Close(ctx context.Context) error
}

Migration guide

Existing io.Closer implementations can be adapted incrementally:

  1. Use IgnoreCtx to bridge an io.Closer into a ContextCloser without any implementation change. The ctx is discarded, so the budget is honored only at the Bootstrap level, not within the resource.

  2. Implement Close(ctx context.Context) error natively on the resource so that ctx.Done() can abort long drain operations (e.g., waiting for in-flight handlers to complete in rabbitmq.Subscriber).

Design decisions

  • io.Closer fallback is preserved (via IgnoreCtx) so external dependencies (pgx.Pool, redis.Client) that are io.Closer-only can participate in the teardown chain without forking their types.
  • resources that must complete teardown unconditionally (e.g., in-memory channel close) should ignore the ctx intentionally and document the reason.

ref: uber-go/fx app.go StopTimeout and Lifecycle.Append OnStop(ctx) ref: nats-io/nats.go Subscription.Drain (per-subscription state encapsulation)

ManagedResource

ManagedResource bundles ContextCloser with health probe functions and an optional background Worker into a single resource abstraction. Bootstrap consumes ManagedResource via WithManagedResource to register /readyz checkers, start/stop the worker, and close the resource in LIFO order during shutdown. See managed_resource.go for the full contract.

Implementation checklist:

  • Resource owner types implement all three methods directly: Checkers, Worker, and Close. Subresources that use a caller-owned connection or pool stay out of the contract and must be listed in the adapter archtest opt-out table with a category and reason.
  • Checkers return stable snake_case probe names. Adapter readiness probes use the suffix "_ready" (for example, "rabbitmq_ready" and "vault_transit_ready"). Multi-role workers may use component-role names only when a single "_ready" probe would hide distinct failure domains.
  • Checker functions must accept the caller's context, avoid unbounded I/O, and return nil only when the specific dependency needed by the adapter is usable. Prefer business-path probes over generic process health.
  • Worker returns nil when no bootstrap-managed goroutine is needed. A nil Worker is a contract statement, not a fallback path.
  • Close must be idempotent, must honor ctx for network/drain operations, and should log structured diagnostics before discarding state that helps explain shutdown or reconnect behavior.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContextCloser

type ContextCloser interface {
	Close(ctx context.Context) error
}

ContextCloser wraps io.Closer with a context parameter so callers can share shutdown budgets (e.g., Uber fx StopTimeout, bootstrap shutCtx) across layered teardown chains.

ref: uber-go/fx app.go Lifecycle.Append OnStop(ctx context.Context) error ref: rabbitmq/amqp091-go channel.go Channel.Close (IsClosed short-circuit)

func IgnoreCtx

func IgnoreCtx(c io.Closer) ContextCloser

IgnoreCtx adapts an io.Closer into a ContextCloser by discarding the ctx. Used as a bridge during incremental migration; callers that accept either interface should prefer a native ContextCloser implementation.

IgnoreCtx(nil) returns nil — callers must check before calling Close.

type ManagedResource

type ManagedResource interface {
	// Probes returns the typed readiness probes contributed by this resource.
	// Each probe carries a healthz.ProbeName (typed const, sanctioned by
	// archtest PROBENAME-SEALED-FUNNEL-01 — no bare strings) and a
	// context-aware Check function (nil return = healthy, non-nil = degraded
	// or down). The context carries the /readyz deadline so probes honor
	// cancellation. An empty/nil slice is valid (no probes contributed).
	//
	// Probes() supersedes the legacy Checkers() map[string]func — the typed
	// slice form closes the bare-string ingress that the composition-root
	// NewProbeName conversion previously had to absorb, so adapter ProbeName
	// consts are now the single authoritative source for every probe name
	// reaching /readyz.
	Probes() []healthz.Probe

	// Worker returns the optional background worker for this resource.
	// Returning nil means no background goroutine is needed; bootstrap skips
	// WithWorkers registration for this resource.
	Worker() worker.Worker

	// Close releases the resource, bounded by ctx. Called in LIFO order relative
	// to registration during shutdown. ctx carries the shared phase10 shutdown
	// budget; implementations SHOULD honor ctx.Done for drain operations.
	// Errors are logged as slog.Warn but do not abort the shutdown of other
	// resources (best-effort).
	//
	// ref: ContextCloser — same ctx-aware Close semantics; ManagedResource
	// bundles probes + worker alongside.
	Close(ctx context.Context) error
}

ManagedResource collects the lifecycle concerns of an external resource (pool, relay, RMQ connection) into a single interface. Bootstrap unpacks the three aspects — typed health probes, background workers, and LIFO teardown — so callers only implement one interface per resource instead of three separate bootstrap options.

ref: uber-go/fx internal/lifecycle/lifecycle.go@master:L124-L310 — Hook OnStart/OnStop registered in declaration order, stopped in LIFO order. ref: go-kratos/kratos transport/transport.go@main:L14-L17 — Server interface as a resource-management contract.

Jump to

Keyboard shortcuts

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