Severity: Info
Summary
ServiceManager declares ServiceStopTimeoutSeconds = 60 as a private file-local constant. Every other timeout threshold in the service lifecycle (Min/Max/Default for start and stop, heartbeat, pre-launch, etc.) lives in AppConfig, so this one constant is an outlier that forces a code edit + rebuild to tune.
File and lines
src/Servy.Core/Services/ServiceManager.cs:29:
private const int ServiceStopTimeoutSeconds = 60;
Uses (lines 397, 398, 399, 578):
var totalWaitTime = (options.StopTimeout ?? ServiceStopTimeoutSeconds) + AppConfig.ScmTimeoutBufferSeconds;
var previousWaitTime = (serviceDto?.PreviousStopTimeout ?? ServiceStopTimeoutSeconds) + AppConfig.ScmTimeoutBufferSeconds;
totalWaitTime = Math.Max(Math.Max(totalWaitTime, previousWaitTime), ServiceStopTimeoutSeconds);
...
while (sc.Status != ServiceControllerStatus.Stopped && sw.Elapsed.TotalSeconds < ServiceStopTimeoutSeconds)
Note that the first three uses already reach into AppConfig.ScmTimeoutBufferSeconds on the same line — the constant right next to them is the only one not in AppConfig.
Explanation
Closed #522 ("Multiple files — Magic numbers without named constants (batch)") cleaned up several similar cases, but this one remains. It's the default upper bound for how long ServiceManager waits for SCM-reported Stopped, used as the fallback when per-service StopTimeout is null. That's the kind of value operators want to tune without a rebuild: on slow disks / heavy teardown hooks, 60 seconds can be too short; conversely, on embedded hosts, 60 seconds is too patient.
Suggested fix
Move the value into AppConfig.cs alongside the existing stop-timeout family:
// AppConfig.cs
public const int DefaultServiceStopTimeoutSeconds = 60;
Then update ServiceManager.cs to reference it:
// line 29 — remove the local const, replace all four uses
var totalWaitTime = (options.StopTimeout ?? AppConfig.DefaultServiceStopTimeoutSeconds) + AppConfig.ScmTimeoutBufferSeconds;
var previousWaitTime = (serviceDto?.PreviousStopTimeout ?? AppConfig.DefaultServiceStopTimeoutSeconds) + AppConfig.ScmTimeoutBufferSeconds;
totalWaitTime = Math.Max(Math.Max(totalWaitTime, previousWaitTime), AppConfig.DefaultServiceStopTimeoutSeconds);
...
while (sc.Status != ServiceControllerStatus.Stopped
&& sw.Elapsed.TotalSeconds < AppConfig.DefaultServiceStopTimeoutSeconds)
Pure refactor — no behavior change.
Severity: Info
Summary
ServiceManagerdeclaresServiceStopTimeoutSeconds = 60as a private file-local constant. Every other timeout threshold in the service lifecycle (Min/Max/Default for start and stop, heartbeat, pre-launch, etc.) lives inAppConfig, so this one constant is an outlier that forces a code edit + rebuild to tune.File and lines
src/Servy.Core/Services/ServiceManager.cs:29:Uses (lines 397, 398, 399, 578):
Note that the first three uses already reach into
AppConfig.ScmTimeoutBufferSecondson the same line — the constant right next to them is the only one not inAppConfig.Explanation
Closed #522 ("Multiple files — Magic numbers without named constants (batch)") cleaned up several similar cases, but this one remains. It's the default upper bound for how long
ServiceManagerwaits for SCM-reportedStopped, used as the fallback when per-serviceStopTimeoutis null. That's the kind of value operators want to tune without a rebuild: on slow disks / heavy teardown hooks, 60 seconds can be too short; conversely, on embedded hosts, 60 seconds is too patient.Suggested fix
Move the value into
AppConfig.csalongside the existing stop-timeout family:Then update
ServiceManager.csto reference it:Pure refactor — no behavior change.