diff --git a/pkg/gotenberg/supervisor.go b/pkg/gotenberg/supervisor.go index 408ca5ac..9dd33697 100644 --- a/pkg/gotenberg/supervisor.go +++ b/pkg/gotenberg/supervisor.go @@ -187,10 +187,13 @@ func (s *processSupervisor) Run(ctx context.Context, logger *zap.Logger, task fu logger.Debug("process lock acquired") s.reqQueueSize.Add(-1) s.reqCounter.Add(1) + releaseMutexChan := true defer func() { - logger.Debug("process lock released") - <-s.mutexChan + if releaseMutexChan { + logger.Debug("process lock released") + <-s.mutexChan + } }() if !s.firstStart.Load() { @@ -212,18 +215,26 @@ func (s *processSupervisor) Run(ctx context.Context, logger *zap.Logger, task fu } } + err := s.runWithDeadline(ctx, task) + if s.maxReqLimit > 0 && s.reqCounter.Load() >= s.maxReqLimit { - s.logger.Debug("max request limit reached, restarting...") - err := s.runWithDeadline(ctx, func() error { - return s.restart() - }) - if err != nil { - return fmt.Errorf("process restart before task: %w", err) - } + s.logger.Debug("max request limit reached, restarting eagerly...") + releaseMutexChan = false + + go func() { + err := s.runWithDeadline(context.Background(), func() error { + return s.restart() + }) + if err != nil { + s.logger.Error(fmt.Sprintf("process restart after task: %v", err)) + } + logger.Debug("process lock released") + <-s.mutexChan + }() } // Note: no error wrapping because it leaks on Chromium console exceptions output. - return s.runWithDeadline(ctx, task) + return err case <-ctx.Done(): logger.Debug("failed to acquire process lock before deadline") s.reqQueueSize.Add(-1) diff --git a/pkg/gotenberg/supervisor_test.go b/pkg/gotenberg/supervisor_test.go index 10f381bc..56368418 100644 --- a/pkg/gotenberg/supervisor_test.go +++ b/pkg/gotenberg/supervisor_test.go @@ -325,7 +325,7 @@ func TestProcessSupervisor_Run(t *testing.T) { expectedStopCalls: 1, }, { - scenario: "cannot restart after reaching max request limit", + scenario: "auto-restart after reaching max request limit", startError: errors.New("start error"), initiallyStarted: true, isRestarting: false, @@ -451,6 +451,10 @@ func TestProcessSupervisor_Run(t *testing.T) { return } + // Making sure restarts are finished. + ps.mutexChan <- struct{}{} + <-ps.mutexChan + if startCalls.Load() != tc.expectedStartCalls { t.Errorf("expected %d process.Start calls, got %d", tc.expectedStartCalls, startCalls.Load()) }