diff --git a/job/lifecycle.go b/job/lifecycle.go index ed63d65..f5fe05e 100644 --- a/job/lifecycle.go +++ b/job/lifecycle.go @@ -21,12 +21,20 @@ type jobLifecycle struct { // jobs is a doubly linked-list of started jobs. The head is the latest // started jobs, e.g. they're in the order they should be stopped. jobs *queuedJob + + // stopped is true if the lifecycle has been stopped and no new jobs + // can be added. + stopped bool } func (r *jobLifecycle) insertAndStart(job *queuedJob) { r.mu.Lock() defer r.mu.Unlock() + if r.stopped { + return + } + if r.jobs != nil { r.jobs.prev = job } @@ -70,6 +78,7 @@ func (r *jobLifecycle) stop(ctx cell.HookContext, log *slog.Logger) error { jobsToStop = append(jobsToStop, job) } r.jobs = nil + r.stopped = true r.mu.Unlock() for _, job := range jobsToStop { job.Stop(ctx) diff --git a/job/lifecycle_test.go b/job/lifecycle_test.go index a7ff841..f6ab02a 100644 --- a/job/lifecycle_test.go +++ b/job/lifecycle_test.go @@ -9,6 +9,7 @@ import ( "log/slog" "sync" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -106,6 +107,33 @@ func TestJobLifecycleStopReturnsContextError(t *testing.T) { assert.ErrorIs(t, lifecycle.stop(ctx, hivetest.Logger(t)), context.Canceled) } +func TestJobLifecycleJobNotStartedAfterStop(t *testing.T) { + t.Parallel() + + // Create a stopped registry + r := ®istry{logger: lifecycleTestLogger()} + require.NoError(t, r.Start(context.Background())) + require.NoError(t, r.Stop(context.Background())) + + // Adding jobs now won't start them + qj := &queuedJob{ + registry: r, + job: &completingLifecycleJob{started: make(chan struct{})}, + } + r.runtimeLifecycle.insertAndStart(qj) + + // The job list should be empty + require.Nil(t, r.runtimeLifecycle.jobs) + + // Wait 50ms and verify it did not start. + select { + case <-qj.job.(*completingLifecycleJob).started: + t.Fatalf("job should not start after registry was stopped") + case <-time.After(50 * time.Millisecond): + } + +} + type blockingLifecycleJob struct { name string started chan struct{}