- 支持Anthropic OAuth/SetupToken账号的5h窗口费用阈值控制 - 支持账号级别的并发会话数量限制 - 使用Redis缓存窗口费用(30秒TTL)减少数据库压力 - 费用计算基于标准费用(不含账号倍率)
64 lines
2.7 KiB
Go
64 lines
2.7 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
)
|
||
|
||
// SessionLimitCache 管理账号级别的活跃会话跟踪
|
||
// 用于 Anthropic OAuth/SetupToken 账号的会话数量限制
|
||
//
|
||
// Key 格式: session_limit:account:{accountID}
|
||
// 数据结构: Sorted Set (member=sessionUUID, score=timestamp)
|
||
//
|
||
// 会话在空闲超时后自动过期,无需手动清理
|
||
type SessionLimitCache interface {
|
||
// RegisterSession 注册会话活动
|
||
// - 如果会话已存在,刷新其时间戳并返回 true
|
||
// - 如果会话不存在且活跃会话数 < maxSessions,添加新会话并返回 true
|
||
// - 如果会话不存在且活跃会话数 >= maxSessions,返回 false(拒绝)
|
||
//
|
||
// 参数:
|
||
// accountID: 账号 ID
|
||
// sessionUUID: 从 metadata.user_id 中提取的会话 UUID
|
||
// maxSessions: 最大并发会话数限制
|
||
// idleTimeout: 会话空闲超时时间
|
||
//
|
||
// 返回:
|
||
// allowed: true 表示允许(在限制内或会话已存在),false 表示拒绝(超出限制且是新会话)
|
||
// error: 操作错误
|
||
RegisterSession(ctx context.Context, accountID int64, sessionUUID string, maxSessions int, idleTimeout time.Duration) (allowed bool, err error)
|
||
|
||
// RefreshSession 刷新现有会话的时间戳
|
||
// 用于活跃会话保持活动状态
|
||
RefreshSession(ctx context.Context, accountID int64, sessionUUID string, idleTimeout time.Duration) error
|
||
|
||
// GetActiveSessionCount 获取当前活跃会话数
|
||
// 返回未过期的会话数量
|
||
GetActiveSessionCount(ctx context.Context, accountID int64) (int, error)
|
||
|
||
// GetActiveSessionCountBatch 批量获取多个账号的活跃会话数
|
||
// 返回 map[accountID]count,查询失败的账号不在 map 中
|
||
GetActiveSessionCountBatch(ctx context.Context, accountIDs []int64) (map[int64]int, error)
|
||
|
||
// IsSessionActive 检查特定会话是否活跃(未过期)
|
||
IsSessionActive(ctx context.Context, accountID int64, sessionUUID string) (bool, error)
|
||
|
||
// ========== 5h窗口费用缓存 ==========
|
||
// Key 格式: window_cost:account:{accountID}
|
||
// 用于缓存账号在当前5h窗口内的标准费用,减少数据库聚合查询压力
|
||
|
||
// GetWindowCost 获取缓存的窗口费用
|
||
// 返回 (cost, true, nil) 如果缓存命中
|
||
// 返回 (0, false, nil) 如果缓存未命中
|
||
// 返回 (0, false, err) 如果发生错误
|
||
GetWindowCost(ctx context.Context, accountID int64) (cost float64, hit bool, err error)
|
||
|
||
// SetWindowCost 设置窗口费用缓存
|
||
SetWindowCost(ctx context.Context, accountID int64, cost float64) error
|
||
|
||
// GetWindowCostBatch 批量获取窗口费用缓存
|
||
// 返回 map[accountID]cost,缓存未命中的账号不在 map 中
|
||
GetWindowCostBatch(ctx context.Context, accountIDs []int64) (map[int64]float64, error)
|
||
}
|