diff --git a/lib/api/api.go b/lib/api/api.go index 7732f3898dd..e552368f0d3 100644 --- a/lib/api/api.go +++ b/lib/api/api.go @@ -93,6 +93,7 @@ type service struct { listenerAddr net.Addr exitChan chan *svcutil.FatalErr miscDB *db.NamespacedKV + shutdownTimeout time.Duration guiErrors logger.Recorder systemLog logger.Recorder @@ -130,6 +131,7 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam startedOnce: make(chan struct{}), exitChan: make(chan *svcutil.FatalErr, 1), miscDB: miscDB, + shutdownTimeout: 100 * time.Millisecond, } } @@ -458,7 +460,7 @@ func (s *service) Serve(ctx context.Context) error { } // Give it a moment to shut down gracefully, e.g. if we are restarting // due to a config change through the API, let that finish successfully. - timeout, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + timeout, cancel := context.WithTimeout(context.Background(), s.shutdownTimeout) defer cancel() if err := srv.Shutdown(timeout); err == timeout.Err() { srv.Close() diff --git a/lib/api/api_test.go b/lib/api/api_test.go index 2f387f0ffa7..f82a04f047d 100644 --- a/lib/api/api_test.go +++ b/lib/api/api_test.go @@ -957,6 +957,10 @@ func TestApiCache(t *testing.T) { } func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) { + return startHTTPWithShutdownTimeout(cfg, 0) +} + +func startHTTPWithShutdownTimeout(cfg config.Wrapper, shutdownTimeout time.Duration) (string, context.CancelFunc, error) { m := new(modelmocks.Model) assetDir := "../../gui" eventSub := new(eventmocks.BufferedSubscription) @@ -984,6 +988,10 @@ func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) { svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, mockedSummary, errorLog, systemLog, false, kdb).(*service) svc.started = addrChan + if shutdownTimeout > 0*time.Millisecond { + svc.shutdownTimeout = shutdownTimeout + } + // Actually start the API service supervisor := suture.New("API test", suture.Spec{ PassThroughPanics: true, diff --git a/lib/testutil/testutil.go b/lib/testutil/testutil.go index 67ca492abdd..be4912c375c 100644 --- a/lib/testutil/testutil.go +++ b/lib/testutil/testutil.go @@ -8,6 +8,7 @@ package testutil import ( "errors" + "os" "sync" "testing" @@ -63,6 +64,14 @@ func (NoopCloser) Close() error { return nil } +func IfNotCI[T any](notCiValue T, ciValue T) T { + if os.Getenv("CI") == "true" { + return ciValue + } else { + return notCiValue + } +} + func ConcatSlices[T any](slices ...[]T) []T { // TODO when go >= 1.22.0: Replace with slices.Concat concatLen := 0