mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
- config:ShouldRetry/DelayDuration 表驱动(nil/次数=1/状态不匹配/body 不匹配/ 空子串/多信号/非法间隔) - provider:命中策略就重试直到 200、body 不匹配**不许**重试(400 也常用于真错误)、 流式只重试握手(首帧之后不重试,避免重复输出)
60 lines
2.2 KiB
Go
60 lines
2.2 KiB
Go
package config
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// ShouldRetry 是纯数据判据:状态码列表 + 响应体子串。它决定"这次失败值不值得
|
|
// 在网关内部等一会儿重试"。厂商知识绝不能进内核,所以判据必须能用一个表格测清楚。
|
|
func TestRetryPolicyShouldRetry(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
policy *RetryPolicy
|
|
status int
|
|
body string
|
|
want bool
|
|
}{
|
|
{"nil policy", nil, 500, "anything", false},
|
|
{"max_attempts=1 disables", &RetryPolicy{OnStatus: []int{400}, MaxAttempts: 1}, 400, "x", false},
|
|
{"status matches, no body filter",
|
|
&RetryPolicy{OnStatus: []int{429}, MaxAttempts: 3}, 429, "", true},
|
|
{"status mismatch",
|
|
&RetryPolicy{OnStatus: []int{429}, MaxAttempts: 3}, 400, "429", false},
|
|
{"status + body match",
|
|
&RetryPolicy{OnStatus: []int{400}, OnBodyContains: []string{"TM.00001041"}, MaxAttempts: 3},
|
|
400, `{"error_code":"TM.00001041"}`, true},
|
|
{"status matches but body does not",
|
|
&RetryPolicy{OnStatus: []int{400}, OnBodyContains: []string{"TM.00001041"}, MaxAttempts: 3},
|
|
400, `{"error_code":"TM.00001005"}`, false},
|
|
{"empty substring never matches",
|
|
&RetryPolicy{OnStatus: []int{400}, OnBodyContains: []string{""}, MaxAttempts: 3}, 400, "x", false},
|
|
{"any of several body signals",
|
|
&RetryPolicy{OnStatus: []int{400, 429}, OnBodyContains: []string{"TM.00001041", "TPM limit"}, MaxAttempts: 3},
|
|
429, `{"message":"TPM limit exceeded"}`, true},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := tc.policy.ShouldRetry(tc.status, tc.body); got != tc.want {
|
|
t.Errorf("%s: ShouldRetry(%d, %q) = %v, want %v", tc.name, tc.status, tc.body, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRetryPolicyDelay(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
policy *RetryPolicy
|
|
want time.Duration
|
|
}{
|
|
{"nil", nil, 10 * time.Second},
|
|
{"explicit", &RetryPolicy{Delay: "250ms"}, 250 * time.Millisecond},
|
|
{"garbage falls back", &RetryPolicy{Delay: "not-a-duration"}, 10 * time.Second},
|
|
{"negative falls back", &RetryPolicy{Delay: "-5s"}, 10 * time.Second},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := tc.policy.DelayDuration(); got != tc.want {
|
|
t.Errorf("%s: DelayDuration() = %v, want %v", tc.name, got, tc.want)
|
|
}
|
|
}
|
|
}
|