From e3f22c737fd500b9ec3e7963327544b948f2cdc5 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 17 Oct 2026 12:20:24 +0200 Subject: [PATCH] Round a merge window key's time to live up to a whole second, as the server rounds down (issue 973) --- cmd/mesh-controller/merge_window_bus.go | 4 +++- cmd/mesh-controller/merge_window_bus_test.go | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cmd/mesh-controller/merge_window_bus.go b/cmd/mesh-controller/merge_window_bus.go index 5634b642..84ff718e 100644 --- a/cmd/mesh-controller/merge_window_bus.go +++ b/cmd/mesh-controller/merge_window_bus.go @@ -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 diff --git a/cmd/mesh-controller/merge_window_bus_test.go b/cmd/mesh-controller/merge_window_bus_test.go index 29138906..a2c24dc0 100644 --- a/cmd/mesh-controller/merge_window_bus_test.go +++ b/cmd/mesh-controller/merge_window_bus_test.go @@ -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) + } +}