WIP: root background loops at context.Background() (refs #97)
Some checks failed
check / check (push) Failing after 1m2s

Incomplete: tests pass but three lint findings remain (funcorder on
registerHooks, unparam in engine_integration_test.go). Committed to
preserve work in progress; to be amended into a single clean commit.
This commit is contained in:
2026-08-09 04:55:53 +00:00
parent 4f5ecb18e5
commit ce1e46b31e
7 changed files with 482 additions and 16 deletions

View File

@@ -149,9 +149,20 @@ func New(
Transport: NewSSRFSafeTransport(),
})
e.registerHooks(lc)
return e
}
// registerHooks wires the engine's start and stop into the fx
// lifecycle. The start hook's context is deliberately ignored:
// see start for why the worker pool must not inherit it.
func (e *Engine) registerHooks(lc fx.Lifecycle) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
e.start(ctx)
//nolint:contextcheck // Not inheriting the hook context
// is the point: see start.
OnStart: func(_ context.Context) error {
e.start()
return nil
},
@@ -161,8 +172,6 @@ func New(
return nil
},
})
return e
}
// Notify signals the delivery engine that new deliveries
@@ -210,8 +219,20 @@ func (e *Engine) ScheduleRetry(
})
}
func (e *Engine) start(ctx context.Context) {
ctx, cancel := context.WithCancel(ctx)
// start launches the worker pool, restart recovery, and the
// periodic retry sweep.
//
// Their context is derived from context.Background(), NOT from
// the fx OnStart hook context. The hook context carries fx's
// start timeout (15s by default) and is cancelled once the start
// phase completes, so goroutines derived from it stop a few
// seconds into the process: every worker would return and the
// engine would silently stop delivering webhooks entirely. A
// long-lived goroutine must outlive the startup phase, so its
// lifetime is bounded by OnStop instead: stop cancels this
// context and waits on the WaitGroup.
func (e *Engine) start() {
ctx, cancel := context.WithCancel(context.Background())
e.cancel = cancel
for range e.workers {