Merge pull request #4508 from wucm667/fix/model-not-found-transient-misclassification

fix: 临时账号耗尽时保留 503 错误分类
This commit is contained in:
Wesley Liddick authored and GitHub committed 2026-07-18 20:41:35 +08:00
commit e002fbb349
15 files changed
+331 -36

No files matched your search

+6 -5
View File
@@ -38,11 +38,12 @@ type noAccountErrorClassification struct {
// The classifier intentionally does not consume the original error: the
// selection layer never tells us *why* the pool came up empty (rate-limited
// vs. unsupported model are both wrapped as ErrNoAvailableAccounts). Instead
// we re-check pool composition through DiagnoseModelAvailabilityForPlatform,
// which only inspects model_mapping configuration and ignores transient
// state. That guarantees a 404 is only returned when no operator action
// short of editing the account's model_mapping could make this request
// succeed.
// we re-check pool composition through DiagnoseModelAvailabilityForPlatform.
// Its dedicated database query considers only persistent eligibility
// (active status + schedulable setting) and model_mapping, bypassing scheduler
// snapshots and transient filters. That guarantees a 404 is only returned
// when persistent account/group/model configuration must change before the
// request can succeed.
//
// routingModel is the model name that account selection actually compared
// against (i.e. after group-level dispatch mapping). displayModel is the
@@ -154,6 +154,20 @@ func TestClassifyNoAccountError_HasModelSupport_KeepsRoutingMessageGenerationToC
require.False(t, cls.ModelNotFound)
}
func TestClassifyNoAccountError_ModelSupportedOnlyByRateLimitedAccount_Returns503(t *testing.T) {
c := newTestGinContextWithRequest()
// The diagnoser's configured-state lookup still sees the model-supporting
// account even though normal scheduling has excluded it during cooldown.
fd := &fakeDiagnoser{resp: service.ModelAvailabilityDiagnosis{HasAccountsInPool: true, HasModelSupport: true}}
apiKey := &service.APIKey{GroupID: ptrInt64(7)}
cls := classifyNoAccountErrorFromGin(c, fd, apiKey, "claude-opus-4-8", "claude-opus-4-8", service.PlatformAnthropic)
require.Equal(t, http.StatusServiceUnavailable, cls.Status)
require.Equal(t, "api_error", cls.ErrType)
require.False(t, cls.ModelNotFound, "temporary account cooldown must remain retryable")
}
func TestClassifyNoAccountError_NoAccountsInPool_Stays503(t *testing.T) {
c := newTestGinContextWithRequest()
fd := &fakeDiagnoser{resp: service.ModelAvailabilityDiagnosis{HasAccountsInPool: false, HasModelSupport: false}}