fix(opencode): cap Retry-After hint for billing probe schedule

This commit is contained in:
ASWJ
2026-10-06 23:56:27 +08:00
parent aa3b049000
commit 480f668ba9
2 changed files with 14 additions and 9 deletions
@@ -1105,6 +1105,12 @@ func (s *UpstreamBillingProbeService) currentTime() time.Time {
}
func nextProbeDelay(intervalMinutes int, retryAfterDuration time.Duration) time.Duration {
if retryAfterDuration < 0 {
retryAfterDuration = 0
}
if retryAfterDuration > upstreamBillingProbeMaxDelay {
retryAfterDuration = upstreamBillingProbeMaxDelay
}
interval := time.Duration(intervalMinutes) * time.Minute
if interval < upstreamBillingProbeMinIntervalMinutes*time.Minute {
interval = upstreamBillingProbeMinIntervalMinutes * time.Minute
@@ -1120,8 +1126,8 @@ func nextProbeDelay(intervalMinutes int, retryAfterDuration time.Duration) time.
interval += time.Duration(rand.Int64N(int64(jitterRange)*2+1)) - jitterRange
}
if retryAfterDuration > interval {
// Retry-After is an explicit upstream instruction; do not shorten it
// with the local maximum delay.
// Retry-After is an explicit upstream instruction; honor it over the
// local backoff interval, clamped to the same 24h ceiling.
return retryAfterDuration
}
if interval > upstreamBillingProbeMaxDelay {
@@ -1133,8 +1139,7 @@ func nextProbeDelay(intervalMinutes int, retryAfterDuration time.Duration) time.
// unsupportedProbeDelay 拉长 unsupported 账号的重探间隔,让无效候选自然退出
// 热队列,不再和真正接入 sub2api 的中转账号抢每周期的探测名额。
// 仍按 upstreamBillingProbeMaxDelay 封顶,保证上游后来接入 sub2api 时最迟一天
// 内会被重新发现;base 本身已达上限(例如 Retry-After 明确要求更久)时原样返回,
// 不缩短上游指令。
// 内会被重新发现;base 本身亦受 24h 封顶保护。
func unsupportedProbeDelay(intervalMinutes int, retryAfterDuration time.Duration) time.Duration {
base := nextProbeDelay(intervalMinutes, retryAfterDuration)
if base >= upstreamBillingProbeMaxDelay {
@@ -767,13 +767,13 @@ func TestUpstreamBillingProbeFailurePreservesLastSuccessAndRetryAfter(t *testing
require.Equal(t, initialRate, *account.RateMultiplier)
}
func TestUpstreamBillingProbeRetryAfterIsNotShortened(t *testing.T) {
func TestUpstreamBillingProbeRetryAfterIsCappedAtMaxDelay(t *testing.T) {
delay := nextProbeDelay(30, 48*time.Hour)
require.Equal(t, 48*time.Hour, delay)
require.Equal(t, upstreamBillingProbeMaxDelay, delay)
}
// unsupported 的重探间隔明显长于普通失败,但始终有上界:上游后来接入 sub2api
// 时最迟一天内会被重新发现,且不会缩短上游 Retry-After 指令。
// 时最迟一天内会被重新发现,且上游超长 Retry-After 亦受 24h 封顶保护。
func TestUpstreamBillingProbeUnsupportedDelayIsStretchedAndBounded(t *testing.T) {
// 默认 30 分钟 interval:普通失败 24~36 分钟,unsupported 为其 8 倍。
stretched := unsupportedProbeDelay(30, 0)
@@ -785,8 +785,8 @@ func TestUpstreamBillingProbeUnsupportedDelayIsStretchedAndBounded(t *testing.T)
require.LessOrEqual(t, unsupportedProbeDelay(upstreamBillingProbeMaxIntervalMinutes, 0), upstreamBillingProbeMaxDelay)
require.Positive(t, unsupportedProbeDelay(upstreamBillingProbeMinIntervalMinutes, 0))
// Retry-After 更长时原样保留,不被封顶缩短;更短时至少不早于该指令。
require.Equal(t, 48*time.Hour, unsupportedProbeDelay(30, 48*time.Hour))
// Retry-After 更长时受封顶保护,不超过 upstreamBillingProbeMaxDelay;更短时至少不早于该指令。
require.Equal(t, upstreamBillingProbeMaxDelay, unsupportedProbeDelay(30, 48*time.Hour))
require.GreaterOrEqual(t, unsupportedProbeDelay(30, time.Hour), time.Hour)
}