diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-13 10:05:47 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-13 10:05:47 +0200 |
| commit | 6c3bc11f736040a09fd839832a6be01e434e8aab (patch) | |
| tree | 6b856c2f79d2f75ccd8ba89c638ee18839b4d061 /internal/ctxutil | |
| parent | a5a405d79fe3d9e0c6ea081b425d36bd67d8671d (diff) | |
Stop stale query work promptly on generation cancel
Diffstat (limited to 'internal/ctxutil')
| -rw-r--r-- | internal/ctxutil/sleep.go | 29 | ||||
| -rw-r--r-- | internal/ctxutil/sleep_test.go | 32 |
2 files changed, 61 insertions, 0 deletions
diff --git a/internal/ctxutil/sleep.go b/internal/ctxutil/sleep.go new file mode 100644 index 0000000..6965e8d --- /dev/null +++ b/internal/ctxutil/sleep.go @@ -0,0 +1,29 @@ +package ctxutil + +import ( + "context" + "time" +) + +// Sleep waits for the delay or exits early when the context is canceled. +// It returns true when the full delay elapsed. +func Sleep(ctx context.Context, delay time.Duration) bool { + if delay <= 0 { + select { + case <-ctx.Done(): + return false + default: + return true + } + } + + timer := time.NewTimer(delay) + defer timer.Stop() + + select { + case <-ctx.Done(): + return false + case <-timer.C: + return true + } +} diff --git a/internal/ctxutil/sleep_test.go b/internal/ctxutil/sleep_test.go new file mode 100644 index 0000000..f32b22c --- /dev/null +++ b/internal/ctxutil/sleep_test.go @@ -0,0 +1,32 @@ +package ctxutil + +import ( + "context" + "testing" + "time" +) + +func TestSleepReturnsEarlyOnCancel(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + start := time.Now() + if Sleep(ctx, time.Second) { + t.Fatal("Sleep should stop when the context is canceled") + } + if elapsed := time.Since(start); elapsed > 50*time.Millisecond { + t.Fatalf("Sleep took too long to return after cancellation: %v", elapsed) + } +} + +func TestSleepWaitsForDelay(t *testing.T) { + ctx := context.Background() + + start := time.Now() + if !Sleep(ctx, 20*time.Millisecond) { + t.Fatal("Sleep should report success when the delay elapses") + } + if elapsed := time.Since(start); elapsed < 15*time.Millisecond { + t.Fatalf("Sleep returned too early: %v", elapsed) + } +} |
