Round a merge window key's time to live up to a whole second, as the server rounds down (issue 973)

This commit is contained in:
2026-10-17 12:20:24 +02:00
parent 2b99d455fc
commit e3f22c737f
2 changed files with 16 additions and 1 deletions
+3 -1
View File
@@ -57,11 +57,13 @@ func windowDeadlines(b inventory.Plan, now time.Time) (quiet, most time.Duration
if b.Delivery == nil || b.Delivery.Batch == nil || windowClosed(b, now) {
return 0, 0, false
}
// Rounded up to a whole second, at least one: the server rounds a key's time to live down to whole seconds, so
// a fraction would close the key before the record's time and the look would cut nothing.
least := func(d time.Duration) time.Duration {
if d < time.Second {
return time.Second
}
return d
return (d + time.Second - 1) / time.Second * time.Second
}
w := b.Delivery.Batch
return least(w.ClosesAt.Sub(now)), least(w.AtMost.Sub(now)), true
@@ -136,3 +136,16 @@ func TestTheDeadlinesOfABatchsKeys(t *testing.T) {
}
}
}
// A deadline that is not a whole number of seconds is rounded up, never down: the server rounds a key's time to live
// down to whole seconds, so 89.999999 s would expire at 89 s, before the window is closed by the record's times, and
// the look would cut nothing (review of issue 973).
func TestAFractionalDeadlineIsRoundedUpToTheNextWholeSecond(t *testing.T) {
now := time.Date(2026, 10, 17, 12, 0, 0, 0, time.UTC)
b := inventory.Plan{State: inventory.PlanAssembling, Delivery: &inventory.PlanDelivery{Batch: &inventory.PlanBatch{
ClosesAt: now.Add(89*time.Second + 999999*time.Microsecond), AtMost: now.Add(599*time.Second + time.Nanosecond)}}}
quiet, most, armed := windowDeadlines(b, now)
if !armed || quiet != 90*time.Second || most != 600*time.Second {
t.Errorf("deadlines %v, %v (armed %v); want 1m30s, 10m0s", quiet, most, armed)
}
}