All checks were successful
check / check (push) Successful in 3m3s
fx defaults to a 15s stop timeout and the Dockerfile sets no grace override, so Docker SIGKILLed at 10s and the bounded shutdown #130 built — including the log line that tells an operator a component is wedged — was unreachable in the image this repo produces. Sets fx.StopTimeout to 5s, and lowers the HTTP drain to 3s so a full-length drain no longer exhausts the whole sequence budget and skip every later hook, database close included. The Sentry flush, which runs in the same hook and honours no context, is clamped to the remaining stop budget less a 2s tail reserve, so a stalled flush drops Sentry events rather than the database close. Also fixes a latent coin flip in the shared stop-hook waiter, which reported "shutdown timed out" about half the time for a component that drained cleanly against an already-expired context. Independently reviewed three times. The final reviewer derived a stronger invariant than the implementation claims — the server hook's absolute end is bounded at stopTimeout minus the reserve regardless of drain length or of time consumed by preceding hooks — and confirmed the guard's 10ms sweep cannot step over the maximum, since both breakpoints land on its grid. Both Sentry probe arms, the docker stop demo and every mutation were reproduced independently. Known residual, filed separately: the HTTP drain itself is not clamped by the reserve, so slow preceding hooks can still jointly exhaust the budget. Demonstrated with a 2.2s sweeper delay.
22 lines
567 B
Go
22 lines
567 B
Go
package lifecycle
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
)
|
|
|
|
// WaitDone exposes waitDone to the external test package. Only the
|
|
// unexported waiter can be handed a channel that is already closed
|
|
// before the call, which is the state the preamble exists for;
|
|
// through WaitForShutdown the waiter goroutine may or may not have
|
|
// closed the channel yet, so the case is not reachable
|
|
// deterministically from outside.
|
|
func WaitDone(
|
|
ctx context.Context,
|
|
log *slog.Logger,
|
|
component string,
|
|
done <-chan struct{},
|
|
) error {
|
|
return waitDone(ctx, log, component, done)
|
|
}
|