Documentation
¶
Overview ¶
Package gscore is the framework-agnostic engine behind the gsfiber (Fiber v2) and gsfiberv3 (Fiber v3) graceful-shutdown adapters. It orchestrates the shutdown lifecycle: signal capture, pre-stop delay, readiness flip, HTTP drain, ordered hooks, GORM pool close, and a force-kill ceiling.
The public adapter packages are thin wrappers that translate a framework's Shutdown method into the generic Shutdowner interface accepted here.
Index ¶
- type CloserRegistrar
- type Config
- type Hook
- type Logger
- type Manager
- func (m *Manager) AddHook(h Hook)
- func (m *Manager) IsReady() bool
- func (m *Manager) IsStarted() bool
- func (m *Manager) ListenAndWait() error
- func (m *Manager) MarkStarted()
- func (m *Manager) RegisterCloser(name string, phase int, timeout time.Duration, ...)
- func (m *Manager) RegisterCloserAt(name string, phase Phase, timeout time.Duration, ...)
- func (m *Manager) RegisterCloserWithPriority(name string, phase int, priority int, timeout time.Duration, ...)
- func (m *Manager) RegisterCloserWithPriorityAt(name string, phase Phase, priority int, timeout time.Duration, ...)
- func (m *Manager) RegisterDB(db *gorm.DB)
- func (m *Manager) RegisterServer(s Shutdowner)
- func (m *Manager) RootContext() context.Context
- func (m *Manager) SetReady(v bool)
- func (m *Manager) StartedAt() time.Time
- func (m *Manager) Trigger()
- func (m *Manager) Wait() error
- type Phase
- type Shutdowner
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CloserRegistrar ¶ added in v0.7.0
type CloserRegistrar interface {
RegisterCloser(name string, phase int, timeout time.Duration, fn func(ctx context.Context) error)
RegisterCloserWithPriority(name string, phase int, priority int, timeout time.Duration, fn func(ctx context.Context) error)
}
CloserRegistrar is the minimal interface that gscore.Manager satisfies for registering graceful-shutdown closers. Sub-packages (txcore, apmcore, logcore, gormautobatch, gsredis, gsrueidis) declare a local type alias to this interface to avoid importing gscore directly.
type Config ¶
type Config struct {
// Signals that trigger Start to return and shutdown to begin. Defaults
// to SIGINT + SIGTERM when nil.
Signals []os.Signal
// PreStopDelay is a sleep injected after a signal is received but
// before any phase runs. Gives kube-proxy / load balancers time to
// observe the failing readiness probe and stop routing new traffic.
// Zero disables the delay.
PreStopDelay time.Duration
// Per-phase timeouts. Zero means "use ForceKillAfter as a soft cap"
// (i.e. no per-phase deadline beyond the global one).
DrainTimeout time.Duration
HookTimeout time.Duration // applied per phase, not per hook
DBCloseTimeout time.Duration
// ForceKillAfter bounds the whole shutdown sequence. When exceeded,
// the Manager logs an error and calls os.Exit(1). Zero disables.
ForceKillAfter time.Duration
// Logger receives per-phase events. Nil = silent.
Logger Logger
// OnHookError is invoked whenever a hook returns a non-nil error.
// It does not stop the sequence. Nil = errors only go to the logger.
OnHookError func(name string, phase Phase, err error)
}
Config configures a Manager. All durations are independent; the global ForceKillAfter bounds the entire sequence as a hard ceiling.
func (Config) WithDefaults ¶
WithDefaults returns cfg with zero-valued fields filled in.
type Hook ¶
Hook is a user-registered shutdown action. Lower Priority runs first within the same phase; equal priorities run in registration order.
type Logger ¶
type Logger interface {
Info(msg string, kv ...any)
Warn(msg string, kv ...any)
Error(msg string, kv ...any)
}
Logger is the structured-logging surface the Manager calls during the shutdown sequence. Implementations should be safe for concurrent use.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager coordinates the shutdown sequence. It is safe to construct once at boot and share across goroutines; Trigger and Wait may be called concurrently.
func New ¶
New constructs a Manager. The returned Manager's RootContext is live until Trigger fires.
func (*Manager) IsReady ¶
IsReady reports the readiness flag. It is true at construction and flipped to false the moment a shutdown signal is observed. Kubernetes readiness probes should reflect this value.
func (*Manager) IsStarted ¶ added in v0.7.1
IsStarted reports whether MarkStarted has been called. Kubernetes startup probes should reflect this value: while false the pod is still initializing and liveness/readiness probes are suspended by Kubernetes.
func (*Manager) ListenAndWait ¶
ListenAndWait blocks until one of cfg.Signals is received OR Trigger is called from elsewhere, then runs the shutdown sequence and returns. Typical use is `defer mgr.ListenAndWait()` at the end of main, after starting the server in a goroutine.
func (*Manager) MarkStarted ¶ added in v0.7.1
func (m *Manager) MarkStarted()
MarkStarted signals that the application has finished initializing (migrations ran, caches warmed up, etc.) and is ready to serve traffic. Call this once at the end of your boot sequence, before blocking on ListenAndWait. It also records the current wall-clock time so that StartedAt can report the exact moment the startup probe flipped to 200.
func (*Manager) RegisterCloser ¶
func (m *Manager) RegisterCloser(name string, phase int, timeout time.Duration, fn func(ctx context.Context) error)
RegisterCloser registers a generic resource close action for the given phase. Closers run sequentially within the phase (after that phase's hooks), each bounded by its own timeout — so a slow Redis client cannot starve a fast Kafka producer that comes after it.
Typical placements:
- PhasePostDrain: outbound clients that the handler chain used (HTTP clients, gRPC connections) and that the DB close does not depend on.
- PhasePostDB: Redis / cache / search clients consumed during DB commit-time callbacks (e.g. txctx.OnCommit). Closing them only after PhaseDB guarantees those callbacks completed.
timeout=0 falls back to Config.HookTimeout. Empty name is auto-filled. A nil fn is a no-op (the entry is dropped).
phase accepts int so that sub-packages (txcore, apmcore, logcore, gormautobatch) can satisfy the CloserRegistrar interface without importing gscore. Pass the Phase constants as int: int(gscore.PhasePostDrain). For typed usage call RegisterCloserAt instead.
func (*Manager) RegisterCloserAt ¶ added in v0.7.0
func (m *Manager) RegisterCloserAt(name string, phase Phase, timeout time.Duration, fn func(ctx context.Context) error)
RegisterCloserAt is like RegisterCloser but accepts the typed Phase constant directly, which is more ergonomic when calling from within the gscore package or from packages that import gscore explicitly.
func (*Manager) RegisterCloserWithPriority ¶ added in v0.7.0
func (m *Manager) RegisterCloserWithPriority(name string, phase int, priority int, timeout time.Duration, fn func(ctx context.Context) error)
RegisterCloserWithPriority is like RegisterCloser but also sets a priority. Within the same phase, closers with lower priority values run first; closers with equal priorities run in registration order. RegisterCloser uses priority 0.
func (*Manager) RegisterCloserWithPriorityAt ¶ added in v0.7.0
func (m *Manager) RegisterCloserWithPriorityAt(name string, phase Phase, priority int, timeout time.Duration, fn func(ctx context.Context) error)
RegisterCloserWithPriorityAt is like RegisterCloserWithPriority but accepts the typed Phase constant directly.
func (*Manager) RegisterDB ¶
RegisterDB adds a GORM DB whose underlying *sql.DB will be Close()'d during PhaseDB. Multiple DBs are closed sequentially in registration order.
func (*Manager) RegisterServer ¶
func (m *Manager) RegisterServer(s Shutdowner)
RegisterServer adds an HTTP-like server to be drained during PhaseDrain. Multiple servers are drained concurrently with a shared deadline.
func (*Manager) RootContext ¶
RootContext returns a context.Context that is cancelled the moment the shutdown sequence begins. Outbound HTTP clients, workers, and any long-running operation should derive their context from this so they observe shutdown via ctx.Done().
func (*Manager) SetReady ¶
SetReady forces the readiness flag. Useful for tests or for marking "not ready" before the process is even started.
func (*Manager) StartedAt ¶ added in v0.8.3
StartedAt returns the wall-clock time at which MarkStarted was called. It returns the zero time if MarkStarted has not been called yet.
type Phase ¶
type Phase int
Phase identifies a stage of the shutdown sequence. Hooks are grouped by phase; phases run sequentially in the order below.
const ( // PhasePreStop runs first, before HTTP drain. Use it for actions that // must happen while the server is still serving (e.g. flushing an // in-memory queue back to a durable store). PhasePreStop Phase = iota // PhaseDrain runs the HTTP server drain. PhaseDrain // PhasePostDrain runs after the HTTP server is fully drained but before // the database pool is closed. Most outbound-call cleanups belong here. PhasePostDrain // PhaseDB runs the GORM pool close. PhaseDB // PhasePostDB runs last, after the database is closed. Use it for // resources that do not depend on the DB (Kafka producers, log // flushers, metric exporters). PhasePostDB )
type Shutdowner ¶
type Shutdowner interface {
// ShutdownWithContext must stop accepting new connections and wait for
// in-flight requests to finish, returning when ctx is done or all
// requests drained.
ShutdownWithContext(ctx context.Context) error
}
Shutdowner is the minimal contract an HTTP server (or anything similar) must satisfy to be drained by the Manager. Both Fiber v2 (*fiber.App) and Fiber v3 (*fiber.App) implement Shutdown / ShutdownWithContext directly; the adapter packages adapt the exact signature.