// Package runtime exposes process-level operational state shared between // HTTP middleware, handlers, and the shutdown loop in main: a live in-flight // request gauge for /livez, and a draining flag that flips on SIGTERM so // /health goes non-ready before we wait for in-flight requests to drain. // // All state is package-level + atomic so callers don't need to plumb a struct // through every middleware/handler. The gauge is decremented in a deferred // call regardless of panics, so a misbehaving handler can't strand the count. package runtime import "sync/atomic" var ( inFlight atomic.Int64 draining atomic.Bool ) // IncInFlight is called when a tracked request begins. Returns the new count. func IncInFlight() int64 { return inFlight.Add(1) } // DecInFlight is called when a tracked request completes. Returns the new count. func DecInFlight() int64 { return inFlight.Add(-1) } // InFlight returns the current number of tracked requests in progress. func InFlight() int64 { return inFlight.Load() } // IsDraining reports whether the process is shutting down. Used by /health // to advertise non-ready state so Traefik (or any LB doing health-based // routing) stops sending new requests to this slot before drain begins. func IsDraining() bool { return draining.Load() } // SetDraining flips the draining flag. Idempotent — safe to call from a // signal handler. func SetDraining(v bool) { draining.Store(v) }