Require a positive RETENTION_SWEEP_INTERVAL (closes #140)
All checks were successful
check / check (push) Successful in 2m59s
All checks were successful
check / check (push) Successful in 2m59s
envDuration accepted 0s and negative values, and RETENTION_SWEEP_INTERVAL feeds time.NewTicker in both the retention reaper and the archive sweeper. NewTicker panics on a non-positive period, and both tickers are created in goroutines with no recover, so a bad value aborted the process after startup had already logged "Configuration loaded". Add envPositiveDuration, mirroring envPort's wrapping of envPositiveInt, and use it for RETENTION_SWEEP_INTERVAL. It wraps ErrNonPositiveValue and names the variable, the same failure shape PORT and RECEIVER_RATE_LIMIT already have. SESSION_IDLE_TIMEOUT, the only other envDuration caller, stays on envDuration: non-positive there means idle expiry is disabled, which is documented behaviour and guarded at both use sites.
This commit is contained in:
@@ -139,7 +139,11 @@ func TestRetentionSweepInterval(t *testing.T) {
|
||||
set bool
|
||||
value string
|
||||
expectError bool
|
||||
expected time.Duration
|
||||
// sentinel, when set, must be wrapped by the startup
|
||||
// error; every error case must additionally name the
|
||||
// variable in its message.
|
||||
sentinel error
|
||||
expected time.Duration
|
||||
}{
|
||||
{
|
||||
name: caseUnsetUsesDefault,
|
||||
@@ -158,6 +162,24 @@ func TestRetentionSweepInterval(t *testing.T) {
|
||||
value: "not-a-duration",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
// A non-positive period panics the ticker in the
|
||||
// reaper and archive-sweeper goroutines, long after
|
||||
// startup has reported success, so it has to fail
|
||||
// here instead.
|
||||
name: "zero fails startup",
|
||||
set: true,
|
||||
value: "0s",
|
||||
expectError: true,
|
||||
sentinel: config.ErrNonPositiveValue,
|
||||
},
|
||||
{
|
||||
name: "negative fails startup",
|
||||
set: true,
|
||||
value: "-1h",
|
||||
expectError: true,
|
||||
sentinel: config.ErrNonPositiveValue,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -175,7 +197,9 @@ func TestRetentionSweepInterval(t *testing.T) {
|
||||
}
|
||||
|
||||
if tt.expectError {
|
||||
expectStartupError(t)
|
||||
expectStartupErrorFor(
|
||||
t, "RETENTION_SWEEP_INTERVAL", tt.sentinel,
|
||||
)
|
||||
} else {
|
||||
testRetentionSweepIntervalSuccess(t, tt.expected)
|
||||
}
|
||||
@@ -281,6 +305,22 @@ func TestSessionIdleTimeout(t *testing.T) {
|
||||
value: "not-a-duration",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
// Non-positive is "idle expiry disabled" for this
|
||||
// variable, not a configuration error: unlike
|
||||
// RETENTION_SWEEP_INTERVAL it never becomes a ticker
|
||||
// period.
|
||||
name: "zero disables idle expiry",
|
||||
set: true,
|
||||
value: "0s",
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
name: "negative disables idle expiry",
|
||||
set: true,
|
||||
value: "-1h",
|
||||
expected: -time.Hour,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user