mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 03:52:26 +08:00
- 绑定缓存的请求与缓存管理接口收到 429 / 5xx 时,只有上游网关账号的响应原样回写
(UpstreamFailoverError.BoundUpstreamPassthrough / GeminiCachedContentUpstreamError.UpstreamGateway),
官方账号仍走错误透传规则与通用映射,不向客户端暴露配额明细
- 记录新增 channel_usage(迁移 244)保存创建时的渠道计费口径,PATCH 延长按同一口径预检、报价与记账
- 创建 / 延长费用行的 request_id 改为固定前缀 gcache:{create|patch}:{id},不被客户端或网关请求 id 覆盖,
按缓存 ID 即可检索一个缓存的全部费用行
- 调度快照凭据投影补齐 base_url / auth_mode / 上游显式缓存声明,显式缓存候选过滤一次算全,
不再逐个选号后剔除
128 lines
4.4 KiB
Go
128 lines
4.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFilterSchedulerCredentialsKeepsSubscriptionPlanType(t *testing.T) {
|
|
filtered := filterSchedulerCredentials(map[string]any{
|
|
"plan_type": "plus",
|
|
"access_token": "secret-access-token",
|
|
"refresh_token": "secret-refresh-token",
|
|
})
|
|
|
|
require.Equal(t, "plus", filtered["plan_type"])
|
|
require.NotContains(t, filtered, "access_token")
|
|
require.NotContains(t, filtered, "refresh_token")
|
|
}
|
|
|
|
func TestFilterSchedulerCredentialsKeepsGeminiExplicitCacheKeys(t *testing.T) {
|
|
filtered := filterSchedulerCredentials(map[string]any{
|
|
"api_key": "k",
|
|
"base_url": "https://gw.example.com",
|
|
"auth_mode": "apikey",
|
|
"service_account_json": "secret",
|
|
service.GeminiExplicitCacheUpstreamCredentialKey: true,
|
|
service.GeminiExplicitCacheUpstreamMaxTTLCredentialKey: 3600,
|
|
})
|
|
|
|
require.Equal(t, "https://gw.example.com", filtered["base_url"])
|
|
require.Equal(t, "apikey", filtered["auth_mode"])
|
|
require.Equal(t, true, filtered[service.GeminiExplicitCacheUpstreamCredentialKey])
|
|
require.Equal(t, 3600, filtered[service.GeminiExplicitCacheUpstreamMaxTTLCredentialKey])
|
|
require.NotContains(t, filtered, "service_account_json")
|
|
}
|
|
|
|
func TestSchedulerMetadataAccountKeepsOpenAISubscriptionIdentity(t *testing.T) {
|
|
account := service.Account{
|
|
ID: 24,
|
|
Platform: service.PlatformOpenAI,
|
|
Type: service.AccountTypeOAuth,
|
|
Credentials: map[string]any{
|
|
"plan_type": "plus",
|
|
"access_token": "secret-access-token",
|
|
},
|
|
}
|
|
|
|
metadata := buildSchedulerMetadataAccount(account)
|
|
|
|
require.True(t, metadata.IsOpenAIChatGPTSubscription())
|
|
require.Empty(t, metadata.GetCredential("access_token"))
|
|
}
|
|
|
|
func TestSchedulerMetadataAccountProjectsUpstreamBillingProbe(t *testing.T) {
|
|
lastError := strings.Repeat("upstream diagnostic ", 512)
|
|
probe := map[string]any{
|
|
"status": "ok",
|
|
"data": map[string]any{
|
|
"billing_scope": "token",
|
|
"resolved_rate_multiplier": 0.03,
|
|
"peak_rate_enabled": true,
|
|
"peak_start": "09:00",
|
|
"peak_end": "18:00",
|
|
"peak_rate_multiplier": 2.0,
|
|
"timezone": "Asia/Shanghai",
|
|
"effective_rate_multiplier": 0.03,
|
|
"remote_diagnostic": lastError,
|
|
},
|
|
"received_at": "2026-07-13T10:00:00Z",
|
|
"fresh_until": "2026-07-13T11:00:00Z",
|
|
"next_probe_at": "2026-07-13T10:30:00Z",
|
|
"http_status": 502,
|
|
"last_error": lastError,
|
|
}
|
|
account := service.Account{
|
|
ID: 42,
|
|
Extra: map[string]any{
|
|
"upstream_billing_probe": probe,
|
|
"unused_large_field": "drop-me",
|
|
},
|
|
}
|
|
|
|
metadata := buildSchedulerMetadataAccount(account)
|
|
fullPayload, metaPayload, err := marshalSchedulerCacheAccount(account)
|
|
require.NoError(t, err)
|
|
|
|
filtered, ok := metadata.Extra["upstream_billing_probe"].(map[string]any)
|
|
require.True(t, ok)
|
|
require.Equal(t, "ok", filtered["status"])
|
|
require.Equal(t, "2026-07-13T10:00:00Z", filtered["received_at"])
|
|
require.Equal(t, "2026-07-13T11:00:00Z", filtered["fresh_until"])
|
|
require.Equal(t, "2026-07-13T10:30:00Z", filtered["next_probe_at"])
|
|
require.NotContains(t, filtered, "http_status")
|
|
require.NotContains(t, filtered, "last_error")
|
|
filteredData, ok := filtered["data"].(map[string]any)
|
|
require.True(t, ok)
|
|
require.Equal(t, "token", filteredData["billing_scope"])
|
|
require.Equal(t, 0.03, filteredData["resolved_rate_multiplier"])
|
|
require.Equal(t, true, filteredData["peak_rate_enabled"])
|
|
require.Equal(t, "09:00", filteredData["peak_start"])
|
|
require.Equal(t, "18:00", filteredData["peak_end"])
|
|
require.Equal(t, 2.0, filteredData["peak_rate_multiplier"])
|
|
require.Equal(t, "Asia/Shanghai", filteredData["timezone"])
|
|
require.NotContains(t, filteredData, "effective_rate_multiplier")
|
|
require.NotContains(t, filteredData, "remote_diagnostic")
|
|
require.NotContains(t, metadata.Extra, "unused_large_field")
|
|
require.Contains(t, string(fullPayload), lastError)
|
|
require.NotContains(t, string(metaPayload), "last_error")
|
|
require.Less(t, len(metaPayload)*4, len(fullPayload))
|
|
}
|
|
|
|
func TestSchedulerMetadataAccountDropsInvalidUpstreamBillingProbe(t *testing.T) {
|
|
for _, probe := range []any{
|
|
"invalid",
|
|
map[string]any{},
|
|
map[string]any{"status": ""},
|
|
} {
|
|
metadata := buildSchedulerMetadataAccount(service.Account{
|
|
Extra: map[string]any{service.UpstreamBillingProbeExtraKey: probe},
|
|
})
|
|
|
|
require.NotContains(t, metadata.Extra, service.UpstreamBillingProbeExtraKey)
|
|
}
|
|
}
|