P0: - rpm_override 嵌入 Auth Cache Snapshot,消除每请求 DB 查询 (snapshot v6→v7) - 429 RPM 响应返回 Retry-After 头(当前分钟剩余秒数) P1: - ClearAll 按钮直连 DELETE API,带 loading 防重复 - 新增 GET /admin/users/:id/rpm-status 管理员 RPM 用量查询端点 优化: - checkRPM 从级联互斥改为并行取最严,user.rpm_limit 作为全局硬上限始终生效 - Override/Group 变更后自动失效 auth cache - fail-open 语义不变,Redis 故障不阻塞业务
96 lines
4.8 KiB
Go
96 lines
4.8 KiB
Go
package service
|
||
|
||
import "time"
|
||
|
||
// APIKeyAuthSnapshot API Key 认证缓存快照(仅包含认证所需字段)
|
||
type APIKeyAuthSnapshot struct {
|
||
Version int `json:"version"`
|
||
APIKeyID int64 `json:"api_key_id"`
|
||
UserID int64 `json:"user_id"`
|
||
GroupID *int64 `json:"group_id,omitempty"`
|
||
Status string `json:"status"`
|
||
IPWhitelist []string `json:"ip_whitelist,omitempty"`
|
||
IPBlacklist []string `json:"ip_blacklist,omitempty"`
|
||
User APIKeyAuthUserSnapshot `json:"user"`
|
||
Group *APIKeyAuthGroupSnapshot `json:"group,omitempty"`
|
||
|
||
// Quota fields for API Key independent quota feature
|
||
Quota float64 `json:"quota"` // Quota limit in USD (0 = unlimited)
|
||
QuotaUsed float64 `json:"quota_used"` // Used quota amount
|
||
|
||
// Expiration field for API Key expiration feature
|
||
ExpiresAt *time.Time `json:"expires_at,omitempty"` // Expiration time (nil = never expires)
|
||
|
||
// Rate limit configuration (only limits, not usage - usage read from Redis at check time)
|
||
RateLimit5h float64 `json:"rate_limit_5h"`
|
||
RateLimit1d float64 `json:"rate_limit_1d"`
|
||
RateLimit7d float64 `json:"rate_limit_7d"`
|
||
}
|
||
|
||
// APIKeyAuthUserSnapshot 用户快照
|
||
type APIKeyAuthUserSnapshot struct {
|
||
ID int64 `json:"id"`
|
||
Status string `json:"status"`
|
||
Role string `json:"role"`
|
||
Balance float64 `json:"balance"`
|
||
Concurrency int `json:"concurrency"`
|
||
|
||
// Balance notification fields (required for CheckBalanceAfterDeduction)
|
||
Email string `json:"email"`
|
||
Username string `json:"username"`
|
||
BalanceNotifyEnabled bool `json:"balance_notify_enabled"`
|
||
BalanceNotifyThresholdType string `json:"balance_notify_threshold_type"`
|
||
BalanceNotifyThreshold *float64 `json:"balance_notify_threshold,omitempty"`
|
||
BalanceNotifyExtraEmails []NotifyEmailEntry `json:"balance_notify_extra_emails,omitempty"`
|
||
TotalRecharged float64 `json:"total_recharged"`
|
||
|
||
// RPMLimit 用户级每分钟请求数上限(0 = 不限制);用于 billing_cache_service.checkRPM 兜底判断。
|
||
RPMLimit int `json:"rpm_limit"`
|
||
|
||
// UserGroupRPMOverride 该 API Key 对应的 (user, group) 专属 RPM 覆盖值。
|
||
// nil = 无 override(回退到 group/user 级);0 = 不限流;>0 = 专属上限。
|
||
UserGroupRPMOverride *int `json:"user_group_rpm_override,omitempty"`
|
||
}
|
||
|
||
// APIKeyAuthGroupSnapshot 分组快照
|
||
type APIKeyAuthGroupSnapshot struct {
|
||
ID int64 `json:"id"`
|
||
Name string `json:"name"`
|
||
Platform string `json:"platform"`
|
||
Status string `json:"status"`
|
||
SubscriptionType string `json:"subscription_type"`
|
||
RateMultiplier float64 `json:"rate_multiplier"`
|
||
DailyLimitUSD *float64 `json:"daily_limit_usd,omitempty"`
|
||
WeeklyLimitUSD *float64 `json:"weekly_limit_usd,omitempty"`
|
||
MonthlyLimitUSD *float64 `json:"monthly_limit_usd,omitempty"`
|
||
ImagePrice1K *float64 `json:"image_price_1k,omitempty"`
|
||
ImagePrice2K *float64 `json:"image_price_2k,omitempty"`
|
||
ImagePrice4K *float64 `json:"image_price_4k,omitempty"`
|
||
ClaudeCodeOnly bool `json:"claude_code_only"`
|
||
FallbackGroupID *int64 `json:"fallback_group_id,omitempty"`
|
||
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request,omitempty"`
|
||
|
||
// Model routing is used by gateway account selection, so it must be part of auth cache snapshot.
|
||
// Only anthropic groups use these fields; others may leave them empty.
|
||
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||
|
||
// 支持的模型系列(仅 antigravity 平台使用)
|
||
SupportedModelScopes []string `json:"supported_model_scopes,omitempty"`
|
||
|
||
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
||
AllowMessagesDispatch bool `json:"allow_messages_dispatch"`
|
||
DefaultMappedModel string `json:"default_mapped_model,omitempty"`
|
||
MessagesDispatchModelConfig OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config,omitempty"`
|
||
|
||
// RPMLimit 分组级每分钟请求数上限(0 = 不限制);用于 billing_cache_service.checkRPM 级联判断。
|
||
RPMLimit int `json:"rpm_limit"`
|
||
}
|
||
|
||
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
|
||
type APIKeyAuthCacheEntry struct {
|
||
NotFound bool `json:"not_found"`
|
||
Snapshot *APIKeyAuthSnapshot `json:"snapshot,omitempty"`
|
||
}
|