fix(ratelimit): clear window token counters on reset from response headers
UpdateFromHeaders was silently updating ResetsAt without clearing token counters. When a window rolled over, the poll method would see ResetsAt already updated and skip the reset. Extract setResetTime helper used by both code paths.
This commit is contained in:
@@ -71,7 +71,7 @@ func (t *Tracker) UpdateFromHeaders(h http.Header) {
|
||||
}
|
||||
if v := h.Get("Anthropic-Ratelimit-Unified-5h-Reset"); v != "" {
|
||||
if ts, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
t.fiveHour.ResetsAt = time.Unix(ts, 0).UTC().Truncate(time.Minute)
|
||||
t.setResetTime(&t.fiveHour, time.Unix(ts, 0).UTC().Truncate(time.Minute), "5h")
|
||||
}
|
||||
}
|
||||
if v := h.Get("Anthropic-Ratelimit-Unified-7d-Utilization"); v != "" {
|
||||
@@ -81,7 +81,7 @@ func (t *Tracker) UpdateFromHeaders(h http.Header) {
|
||||
}
|
||||
if v := h.Get("Anthropic-Ratelimit-Unified-7d-Reset"); v != "" {
|
||||
if ts, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
t.sevenDay.ResetsAt = time.Unix(ts, 0).UTC().Truncate(time.Minute)
|
||||
t.setResetTime(&t.sevenDay, time.Unix(ts, 0).UTC().Truncate(time.Minute), "7d")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,24 +190,25 @@ func (t *Tracker) updateWindow(w *Window, rl *RateLimit, name string) {
|
||||
if rl.ResetsAt != nil {
|
||||
parsed, err := time.Parse(time.RFC3339Nano, *rl.ResetsAt)
|
||||
if err != nil {
|
||||
// Fallback to RFC3339 without fractional seconds
|
||||
parsed, err = time.Parse(time.RFC3339, *rl.ResetsAt)
|
||||
}
|
||||
parsed = parsed.UTC().Truncate(time.Minute)
|
||||
if err == nil && parsed != w.ResetsAt && !w.ResetsAt.IsZero() {
|
||||
// Window reset detected — zero token counters
|
||||
if err == nil {
|
||||
t.setResetTime(w, parsed.UTC().Truncate(time.Minute), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tracker) setResetTime(w *Window, newReset time.Time, name string) {
|
||||
if !w.ResetsAt.IsZero() && newReset != w.ResetsAt {
|
||||
log.Info().
|
||||
Str("window", name).
|
||||
Int64("prev_tokens_in", w.TokensIn.Load()).
|
||||
Int64("prev_tokens_out", w.TokensOut.Load()).
|
||||
Time("old_reset", w.ResetsAt).
|
||||
Time("new_reset", parsed).
|
||||
Time("new_reset", newReset).
|
||||
Msg("window reset detected")
|
||||
w.TokensIn.Store(0)
|
||||
w.TokensOut.Store(0)
|
||||
}
|
||||
if err == nil {
|
||||
w.ResetsAt = parsed
|
||||
}
|
||||
}
|
||||
w.ResetsAt = newReset
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user