Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ func (w *LoopWorker) Start(ctx context.Context) error {
return err
}
}
if !w.autoReady {
if err := runtime.SetReady(false); err != nil {
return err
}
}

// Preserve Start context values for telemetry/correlation, but detach from
// Start cancellation because the loop outlives the Start call. Stop uses this
Expand All @@ -179,7 +184,7 @@ func (w *LoopWorker) Start(ctx context.Context) error {
go w.runLoop(loopCtx, runtime, done)

if !w.autoReady {
return runtime.SetReady(false)
return nil
}
if err := runtime.SetReady(true); err != nil {
w.markStopping(done)
Expand Down
41 changes: 41 additions & 0 deletions loop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import (
"time"
)

type loopReadyFailRuntime struct {
fakeWorkerRuntime
readyFailure error
}

func (r loopReadyFailRuntime) SetReady(ready bool) error {
if !ready {
return r.readyFailure
}
return nil
}

func TestLoopWorkerStartRejectsNilLoop(t *testing.T) {
worker := NewLoopWorker(nil)
err := worker.Start(withWorkerRuntime(context.Background(), fakeWorkerRuntime{}))
Expand Down Expand Up @@ -187,6 +199,35 @@ func TestLoopWorkerLoopCanMarkReadyWhenAutoReadyDisabled(t *testing.T) {
}
}

func TestLoopWorkerAutoReadyDisabledSetsNotReadyBeforeLoop(t *testing.T) {
readyFailure := errors.New("ready false failed")
worker := NewLoopWorker(
func(ctx context.Context, _ WorkerRuntime) error {
<-ctx.Done()
return ctx.Err()
},
WithLoopAutoReady(false),
)

err := worker.Start(withWorkerRuntime(context.Background(), loopReadyFailRuntime{
readyFailure: readyFailure,
}))
if !errors.Is(err, readyFailure) {
t.Fatalf("Start error = %v, want %v", err, readyFailure)
}

worker.mu.Lock()
state := worker.state
done := worker.done
worker.mu.Unlock()
if state != loopIdle {
t.Fatalf("loop worker state = %s, want %s", state, loopIdle)
}
if done != nil {
t.Fatal("loop worker done channel is set, want nil")
}
}

func TestLoopWorkerStopCancelsLoopAndRunsStopHookOnce(t *testing.T) {
loopDone := make(chan struct{})
var stopCalls atomic.Int32
Expand Down