Skip to content

Commit 6247739

Browse files
Andrey Cheptsovclaude
andcommitted
Use monotonic time for log quota hour buckets
Avoids susceptibility to wall clock adjustments (e.g., NTP sync) by tracking elapsed hours from a monotonic start time instead of calendar-hour boundaries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c1c8150 commit 6247739

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

  • runner/internal/runner/executor

runner/internal/runner/executor/logs.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package executor
22

33
import (
44
"errors"
5+
"math"
56
"sync"
67
"time"
78

@@ -17,7 +18,8 @@ type appendWriter struct {
1718

1819
quota int // bytes per hour, 0 = unlimited
1920
bytesInHour int // bytes written in current hour bucket
20-
hourStart int64 // unix timestamp (seconds) of current hour bucket start
21+
currentHour int // monotonic hour bucket index since timeStarted
22+
timeStarted time.Time // monotonic reference point for hour buckets
2123
quotaExceeded chan struct{} // closed when quota is exceeded (out-of-band signal)
2224
exceededOnce sync.Once
2325
}
@@ -33,6 +35,7 @@ func newAppendWriter(mu *sync.RWMutex, timestamp *MonotonicTimestamp) *appendWri
3335

3436
func (w *appendWriter) SetQuota(quota int) {
3537
w.quota = quota
38+
w.timeStarted = time.Now()
3639
}
3740

3841
// QuotaExceeded returns a channel that is closed when the log quota is exceeded.
@@ -45,11 +48,10 @@ func (w *appendWriter) Write(p []byte) (n int, err error) {
4548
defer w.mu.Unlock()
4649

4750
if w.quota > 0 {
48-
now := time.Now().Unix()
49-
currentHour := (now / 3600) * 3600
50-
if currentHour != w.hourStart {
51+
hour := int(math.Floor(time.Since(w.timeStarted).Hours()))
52+
if hour != w.currentHour {
5153
w.bytesInHour = 0
52-
w.hourStart = currentHour
54+
w.currentHour = hour
5355
}
5456
if w.bytesInHour+len(p) > w.quota {
5557
w.exceededOnce.Do(func() { close(w.quotaExceeded) })

0 commit comments

Comments
 (0)