Final cross-cutting review finding: shutCtx was shared between
server.Shutdown and dispatcher.Shutdown, with jobs.Stop's wall-clock
time burning the budget in between. Under load, dispatcher.Shutdown
could receive an already-dead ctx and skip draining in-flight async
notify dispatches (including webhook enqueues). Mirror the errCh
branch by creating a fresh 10s drainCtx for dispatcher.Shutdown.
Code review fixes for T16:
- Pass cfg.Jobs.ShutdownGrace+5s to jobs.Stop call-site context (was
hard-coded 30s, would mask configured longer grace).
- Guard jobs.Stop block on cfg.Jobs.Enabled so disabled jobs don't
spin up the no-op shutdown goroutine + timer.
- Use clock.Real().Now() in deadLetterFn for consistency with the rest
of the jobs wiring.