diff --git a/svc.go b/svc.go index 5786748..5138b1e 100644 --- a/svc.go +++ b/svc.go @@ -1,6 +1,8 @@ package svc import ( + "context" + "errors" "fmt" "log" "net/http" @@ -137,7 +139,7 @@ func (s *SVC) Run() { go func(name string, w Worker) { defer s.recoverWait(name, &wg, errs) if err := w.Run(); err != nil { - s.logger.Error("Run exited with error", zap.Error(err), zap.String("worker", name)) + err = fmt.Errorf("worker %s exited: %w", name, err) errs <- err } }(name, w) @@ -147,7 +149,10 @@ func (s *SVC) Run() { select { case err := <-errs: - s.logger.Fatal("Worker Init/Run failure", zap.Error(err)) + if !errors.Is(err, context.Canceled) { + s.logger.Fatal("Worker Init/Run failure", zap.Error(err)) + } + s.logger.Warn("Worker context canceled", zap.Error(err)) case sig := <-s.signals: s.logger.Warn("Caught signal", zap.String("signal", sig.String())) case <-waitGroupToChan(&wg): diff --git a/svc_test.go b/svc_test.go index 2c0f99a..05bbad8 100644 --- a/svc_test.go +++ b/svc_test.go @@ -1,6 +1,8 @@ package svc import ( + "context" + "fmt" "testing" "time" @@ -87,6 +89,23 @@ func TestShutdown(t *testing.T) { } } +func TestContextCanceled(t *testing.T) { + dummyWorker := &WorkerMock{ + InitFunc: func(*zap.Logger) error { return nil }, + RunFunc: func() error { + return fmt.Errorf("stopped: %w", context.Canceled) + }, + TerminateFunc: func() error { return nil }, + } + + s, err := New("dummy-service", "v0.0.1") + require.NoError(t, err) + s.AddWorker("dummy-worker", dummyWorker) + + // Run should not log fatal + s.Run() +} + var _ Worker = (*WorkerMock)(nil) type WorkerMock struct {