gscore

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 12 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

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

func (cfg Config) WithDefaults() Config

WithDefaults returns cfg with zero-valued fields filled in.

type Hook

type Hook struct {
	Name     string
	Priority int
	Phase    Phase
	Run      func(ctx context.Context) error
}

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

func New(cfg Config) *Manager

New constructs a Manager. The returned Manager's RootContext is live until Trigger fires.

func (*Manager) AddHook

func (m *Manager) AddHook(h Hook)

AddHook registers a hook to run during phase h.Phase.

func (*Manager) IsReady

func (m *Manager) IsReady() bool

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) ListenAndWait

func (m *Manager) ListenAndWait() error

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) RegisterCloser

func (m *Manager) RegisterCloser(name string, phase Phase, 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).

func (*Manager) RegisterDB

func (m *Manager) RegisterDB(db *gorm.DB)

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

func (m *Manager) RootContext() context.Context

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

func (m *Manager) SetReady(v bool)

SetReady forces the readiness flag. Useful for tests or for marking "not ready" before the process is even started.

func (*Manager) Trigger

func (m *Manager) Trigger()

Trigger initiates the shutdown sequence programmatically (e.g. from a health-check failure or an unrecoverable error). Subsequent calls are no-ops. It returns immediately; callers should Wait for completion.

func (*Manager) Wait

func (m *Manager) Wait() error

Wait blocks until the shutdown sequence has finished (or os.Exit was invoked by the force-kill ceiling). The returned error is the first fatal error encountered, or nil on a clean shutdown.

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
)

func (Phase) String

func (p Phase) String() string

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.

Jump to

Keyboard shortcuts

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