ccm,ocm: block utilization decrease within same rate-limit window
updateStateFromHeaders unconditionally applied header utilization values even when they were lower than the current state, causing poll-sourced values to be overwritten by stale header values. Parse reset timestamps before utilization and only allow decreases when the reset timestamp changes (indicating a new rate-limit window). Also add math.Ceil to CCM external credential for consistency with default credential.
This commit is contained in:
@@ -368,15 +368,18 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) {
|
||||
oldFiveHour := c.state.fiveHourUtilization
|
||||
oldWeekly := c.state.weeklyUtilization
|
||||
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists {
|
||||
c.state.fiveHourReset = value
|
||||
}
|
||||
if utilization := headers.Get("anthropic-ratelimit-unified-5h-utilization"); utilization != "" {
|
||||
value, err := strconv.ParseFloat(utilization, 64)
|
||||
if err == nil {
|
||||
// Remote CCM writes aggregated utilization as 0.0-1.0; convert to percentage
|
||||
c.state.fiveHourUtilization = value * 100
|
||||
}
|
||||
}
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists {
|
||||
c.state.fiveHourReset = value
|
||||
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists {
|
||||
c.state.weeklyReset = value
|
||||
}
|
||||
if utilization := headers.Get("anthropic-ratelimit-unified-7d-utilization"); utilization != "" {
|
||||
value, err := strconv.ParseFloat(utilization, 64)
|
||||
@@ -384,9 +387,6 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) {
|
||||
c.state.weeklyUtilization = value * 100
|
||||
}
|
||||
}
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists {
|
||||
c.state.weeklyReset = value
|
||||
}
|
||||
c.state.lastUpdated = time.Now()
|
||||
if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) {
|
||||
c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%")
|
||||
|
||||
@@ -338,32 +338,39 @@ func (c *defaultCredential) updateStateFromHeaders(headers http.Header) {
|
||||
oldFiveHour := c.state.fiveHourUtilization
|
||||
oldWeekly := c.state.weeklyUtilization
|
||||
|
||||
fiveHourResetChanged := false
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists {
|
||||
if value.After(c.state.fiveHourReset) {
|
||||
fiveHourResetChanged = true
|
||||
c.state.fiveHourReset = value
|
||||
}
|
||||
}
|
||||
if utilization := headers.Get("anthropic-ratelimit-unified-5h-utilization"); utilization != "" {
|
||||
value, err := strconv.ParseFloat(utilization, 64)
|
||||
if err == nil {
|
||||
newValue := math.Ceil(value * 100)
|
||||
if newValue < c.state.fiveHourUtilization {
|
||||
c.logger.Error("header 5h utilization for ", c.tag, " is lower than current: ", newValue, " < ", c.state.fiveHourUtilization)
|
||||
if newValue >= c.state.fiveHourUtilization || fiveHourResetChanged {
|
||||
c.state.fiveHourUtilization = newValue
|
||||
}
|
||||
c.state.fiveHourUtilization = newValue
|
||||
}
|
||||
}
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists {
|
||||
c.state.fiveHourReset = value
|
||||
|
||||
weeklyResetChanged := false
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists {
|
||||
if value.After(c.state.weeklyReset) {
|
||||
weeklyResetChanged = true
|
||||
c.state.weeklyReset = value
|
||||
}
|
||||
}
|
||||
if utilization := headers.Get("anthropic-ratelimit-unified-7d-utilization"); utilization != "" {
|
||||
value, err := strconv.ParseFloat(utilization, 64)
|
||||
if err == nil {
|
||||
newValue := math.Ceil(value * 100)
|
||||
if newValue < c.state.weeklyUtilization {
|
||||
c.logger.Error("header weekly utilization for ", c.tag, " is lower than current: ", newValue, " < ", c.state.weeklyUtilization)
|
||||
if newValue >= c.state.weeklyUtilization || weeklyResetChanged {
|
||||
c.state.weeklyUtilization = newValue
|
||||
}
|
||||
c.state.weeklyUtilization = newValue
|
||||
}
|
||||
}
|
||||
if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists {
|
||||
c.state.weeklyReset = value
|
||||
}
|
||||
c.state.lastUpdated = time.Now()
|
||||
if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) {
|
||||
c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%")
|
||||
|
||||
@@ -395,13 +395,6 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) {
|
||||
activeLimitIdentifier = "codex"
|
||||
}
|
||||
|
||||
fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent")
|
||||
if fiveHourPercent != "" {
|
||||
value, err := strconv.ParseFloat(fiveHourPercent, 64)
|
||||
if err == nil {
|
||||
c.state.fiveHourUtilization = value
|
||||
}
|
||||
}
|
||||
fiveHourResetAt := headers.Get("x-" + activeLimitIdentifier + "-primary-reset-at")
|
||||
if fiveHourResetAt != "" {
|
||||
value, err := strconv.ParseInt(fiveHourResetAt, 10, 64)
|
||||
@@ -409,13 +402,14 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) {
|
||||
c.state.fiveHourReset = time.Unix(value, 0)
|
||||
}
|
||||
}
|
||||
weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent")
|
||||
if weeklyPercent != "" {
|
||||
value, err := strconv.ParseFloat(weeklyPercent, 64)
|
||||
fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent")
|
||||
if fiveHourPercent != "" {
|
||||
value, err := strconv.ParseFloat(fiveHourPercent, 64)
|
||||
if err == nil {
|
||||
c.state.weeklyUtilization = value
|
||||
c.state.fiveHourUtilization = value
|
||||
}
|
||||
}
|
||||
|
||||
weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at")
|
||||
if weeklyResetAt != "" {
|
||||
value, err := strconv.ParseInt(weeklyResetAt, 10, 64)
|
||||
@@ -423,6 +417,13 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) {
|
||||
c.state.weeklyReset = time.Unix(value, 0)
|
||||
}
|
||||
}
|
||||
weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent")
|
||||
if weeklyPercent != "" {
|
||||
value, err := strconv.ParseFloat(weeklyPercent, 64)
|
||||
if err == nil {
|
||||
c.state.weeklyUtilization = value
|
||||
}
|
||||
}
|
||||
c.state.lastUpdated = time.Now()
|
||||
if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) {
|
||||
c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%")
|
||||
|
||||
@@ -345,32 +345,47 @@ func (c *defaultCredential) updateStateFromHeaders(headers http.Header) {
|
||||
activeLimitIdentifier = "codex"
|
||||
}
|
||||
|
||||
fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent")
|
||||
if fiveHourPercent != "" {
|
||||
value, err := strconv.ParseFloat(fiveHourPercent, 64)
|
||||
if err == nil {
|
||||
c.state.fiveHourUtilization = value
|
||||
}
|
||||
}
|
||||
fiveHourResetChanged := false
|
||||
fiveHourResetAt := headers.Get("x-" + activeLimitIdentifier + "-primary-reset-at")
|
||||
if fiveHourResetAt != "" {
|
||||
value, err := strconv.ParseInt(fiveHourResetAt, 10, 64)
|
||||
if err == nil {
|
||||
c.state.fiveHourReset = time.Unix(value, 0)
|
||||
newReset := time.Unix(value, 0)
|
||||
if newReset.After(c.state.fiveHourReset) {
|
||||
fiveHourResetChanged = true
|
||||
c.state.fiveHourReset = newReset
|
||||
}
|
||||
}
|
||||
}
|
||||
fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent")
|
||||
if fiveHourPercent != "" {
|
||||
value, err := strconv.ParseFloat(fiveHourPercent, 64)
|
||||
if err == nil {
|
||||
if value >= c.state.fiveHourUtilization || fiveHourResetChanged {
|
||||
c.state.fiveHourUtilization = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
weeklyResetChanged := false
|
||||
weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at")
|
||||
if weeklyResetAt != "" {
|
||||
value, err := strconv.ParseInt(weeklyResetAt, 10, 64)
|
||||
if err == nil {
|
||||
newReset := time.Unix(value, 0)
|
||||
if newReset.After(c.state.weeklyReset) {
|
||||
weeklyResetChanged = true
|
||||
c.state.weeklyReset = newReset
|
||||
}
|
||||
}
|
||||
}
|
||||
weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent")
|
||||
if weeklyPercent != "" {
|
||||
value, err := strconv.ParseFloat(weeklyPercent, 64)
|
||||
if err == nil {
|
||||
c.state.weeklyUtilization = value
|
||||
}
|
||||
}
|
||||
weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at")
|
||||
if weeklyResetAt != "" {
|
||||
value, err := strconv.ParseInt(weeklyResetAt, 10, 64)
|
||||
if err == nil {
|
||||
c.state.weeklyReset = time.Unix(value, 0)
|
||||
if value >= c.state.weeklyUtilization || weeklyResetChanged {
|
||||
c.state.weeklyUtilization = value
|
||||
}
|
||||
}
|
||||
}
|
||||
c.state.lastUpdated = time.Now()
|
||||
|
||||
Reference in New Issue
Block a user