| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- package repository
- import (
- "context"
- "database/sql"
- "errors"
- entsql "entgo.io/ent/dialect/sql"
- "github.com/Wei-Shaw/sub2api/ent"
- "github.com/Wei-Shaw/sub2api/internal/config"
- "github.com/Wei-Shaw/sub2api/internal/service"
- "github.com/google/wire"
- "github.com/redis/go-redis/v9"
- )
- // ProvideConcurrencyCache 创建并发控制缓存,从配置读取 TTL 参数
- // 性能优化:TTL 可配置,支持长时间运行的 LLM 请求场景
- func ProvideConcurrencyCache(rdb *redis.Client, cfg *config.Config) service.ConcurrencyCache {
- waitTTLSeconds := int(cfg.Gateway.Scheduling.StickySessionWaitTimeout.Seconds())
- if cfg.Gateway.Scheduling.FallbackWaitTimeout > cfg.Gateway.Scheduling.StickySessionWaitTimeout {
- waitTTLSeconds = int(cfg.Gateway.Scheduling.FallbackWaitTimeout.Seconds())
- }
- if waitTTLSeconds <= 0 {
- waitTTLSeconds = cfg.Gateway.ConcurrencySlotTTLMinutes * 60
- }
- return NewConcurrencyCache(rdb, cfg.Gateway.ConcurrencySlotTTLMinutes, waitTTLSeconds)
- }
- // ProvideGitHubReleaseClient 创建 GitHub Release 客户端
- // 从配置中读取代理设置,支持国内服务器通过代理访问 GitHub
- func ProvideGitHubReleaseClient(cfg *config.Config) service.GitHubReleaseClient {
- return NewGitHubReleaseClient(cfg.Update.ProxyURL, cfg.Security.ProxyFallback.AllowDirectOnError)
- }
- // ProvidePricingRemoteClient 创建定价数据远程客户端
- // 从配置中读取代理设置,支持国内服务器通过代理访问 GitHub 上的定价数据
- func ProvidePricingRemoteClient(cfg *config.Config) service.PricingRemoteClient {
- return NewPricingRemoteClient(cfg.Update.ProxyURL, cfg.Security.ProxyFallback.AllowDirectOnError)
- }
- // ProvideSessionLimitCache 创建会话限制缓存
- // 用于 Anthropic OAuth/SetupToken 账号的并发会话数量控制
- func ProvideSessionLimitCache(rdb *redis.Client, cfg *config.Config) service.SessionLimitCache {
- defaultIdleTimeoutMinutes := 5 // 默认 5 分钟空闲超时
- if cfg != nil && cfg.Gateway.SessionIdleTimeoutMinutes > 0 {
- defaultIdleTimeoutMinutes = cfg.Gateway.SessionIdleTimeoutMinutes
- }
- return NewSessionLimitCache(rdb, defaultIdleTimeoutMinutes)
- }
- // ProvideSchedulerCache 创建调度快照缓存,并注入快照分块参数。
- func ProvideSchedulerCache(rdb *redis.Client, cfg *config.Config) service.SchedulerCache {
- mgetChunkSize := defaultSchedulerSnapshotMGetChunkSize
- writeChunkSize := defaultSchedulerSnapshotWriteChunkSize
- if cfg != nil {
- if cfg.Gateway.Scheduling.SnapshotMGetChunkSize > 0 {
- mgetChunkSize = cfg.Gateway.Scheduling.SnapshotMGetChunkSize
- }
- if cfg.Gateway.Scheduling.SnapshotWriteChunkSize > 0 {
- writeChunkSize = cfg.Gateway.Scheduling.SnapshotWriteChunkSize
- }
- }
- return newSchedulerCacheWithChunkSizes(rdb, mgetChunkSize, writeChunkSize)
- }
- // ProviderSet is the Wire provider set for all repositories
- var ProviderSet = wire.NewSet(
- NewIntelligentTestRepository,
- NewUserRepository,
- NewAPIKeyRepository,
- NewGroupRepository,
- NewAdminGroupRepository,
- NewCompositeModelRouteRepository,
- NewAccountRepository,
- NewAdminAccountRepository,
- NewScheduledTestPlanRepository, // 定时测试计划仓储
- NewScheduledTestResultRepository, // 定时测试结果仓储
- NewProxyRepository,
- NewRedeemCodeRepository,
- NewPromoCodeRepository,
- NewAnnouncementRepository,
- NewAnnouncementReadRepository,
- NewUsageLogRepository,
- NewUsageBillingRepository,
- NewBatchImageRepository,
- NewIdempotencyRepository,
- NewUsageCleanupRepository,
- NewDashboardAggregationRepository,
- NewSettingRepository,
- NewGlobalModelPricingRepository,
- NewSecurityPolicyRepository,
- NewSecurityPolicySessionStore,
- NewOpsRepository,
- NewAuditLogRepository,
- NewPasskeyRepository,
- NewPasskeySessionStore,
- NewUserSubscriptionRepository,
- NewUserAttributeDefinitionRepository,
- NewUserAttributeValueRepository,
- NewUserGroupRateRepository,
- NewErrorPassthroughRepository,
- NewTLSFingerprintProfileRepository,
- NewPluginRepository,
- NewChannelRepository,
- NewChannelMonitorRepository,
- NewChannelMonitorV2Repository,
- NewChannelMonitorRequestTemplateRepository,
- NewContentModerationRepository,
- NewAffiliateRepository,
- NewUserPlatformQuotaRepository, // T14: user × platform quota
- NewUserPlatformQuotaServiceAdapter, // T14: adapter → service.UserPlatformQuotaRepository
- // Cache implementations
- NewGatewayCache,
- NewBillingCache,
- NewAPIKeyCache,
- NewTempUnschedCache,
- NewTimeoutCounterCache,
- NewOpenAI403CounterCache,
- NewInternal500CounterCache,
- ProvideConcurrencyCache,
- ProvideSessionLimitCache,
- NewRPMCache,
- NewUserRPMCache,
- NewUserMsgQueueCache,
- NewDashboardCache,
- NewEmailCache,
- NewIdentityCache,
- NewRedeemCache,
- NewUpdateCache,
- NewGeminiTokenCache,
- NewImageTaskStore,
- NewBatchImageQueue,
- NewBatchImageDownloadLimiter,
- NewLeaderLockCache,
- ProvideSchedulerCache,
- NewSchedulerOutboxRepository,
- NewAuthCacheInvalidationOutboxRepository,
- NewProxyLatencyCache,
- NewTotpCache,
- NewRefreshTokenCache,
- NewErrorPassthroughCache,
- NewTLSFingerprintProfileCache,
- NewChannelCache,
- NewContentModerationHashCache,
- // Encryptors
- NewAESEncryptor,
- // Backup infrastructure
- NewPgDumper,
- NewS3BackupStoreFactory,
- // Image storage (async image task result offload)
- ProvideImageStorageFactory,
- // HTTP service ports (DI Strategy A: return interface directly)
- NewTurnstileVerifier,
- NewTencentCaptchaVerifier,
- NewAliyunCaptchaVerifier,
- ProvidePricingRemoteClient,
- ProvideGitHubReleaseClient,
- NewProxyExitInfoProber,
- NewClaudeUsageFetcher,
- NewClaudeOAuthClient,
- NewControlledHTTPUpstream,
- NewAccountTrafficCache,
- NewOpenAIOAuthClient,
- NewGrokOAuthClient,
- NewGeminiOAuthClient,
- NewGeminiCliCodeAssistClient,
- NewGeminiDriveClient,
- ProvideEnt,
- ProvideSQLDB,
- ProvideRedis,
- )
- // ProvideEnt 为依赖注入提供 Ent 客户端。
- //
- // 该函数是 InitEnt 的包装器,符合 Wire 的依赖提供函数签名要求。
- // Wire 会在编译时分析依赖关系,自动生成初始化代码。
- //
- // 依赖:config.Config
- // 提供:*ent.Client
- func ProvideEnt(cfg *config.Config) (*ent.Client, error) {
- client, _, err := InitEnt(cfg)
- return client, err
- }
- // ProvideImageStorageFactory 提供按需构造对象存储客户端的工厂。
- //
- // 这里返回工厂而不是实例:异步生图的开关与凭证可以在后台随时改动,客户端必须能在
- // 设置保存后重建,而不是在启动时定死一份。
- func ProvideImageStorageFactory() service.ImageStorageFactory {
- return func(ctx context.Context, cfg *config.ImageStorageConfig) (service.ImageStorage, error) {
- return NewS3ImageStorage(ctx, cfg)
- }
- }
- // ProvideSQLDB 从 Ent 客户端提取底层的 *sql.DB 连接。
- //
- // 某些 Repository 需要直接执行原生 SQL(如复杂的批量更新、聚合查询),
- // 此时需要访问底层的 sql.DB 而不是通过 Ent ORM。
- //
- // 设计说明:
- // - Ent 底层使用 sql.DB,通过 Driver 接口可以访问
- // - 这种设计允许在同一事务中混用 Ent 和原生 SQL
- //
- // 依赖:*ent.Client
- // 提供:*sql.DB
- func ProvideSQLDB(client *ent.Client) (*sql.DB, error) {
- if client == nil {
- return nil, errors.New("nil ent client")
- }
- // 从 Ent 客户端获取底层驱动
- drv, ok := client.Driver().(*entsql.Driver)
- if !ok {
- return nil, errors.New("ent driver does not expose *sql.DB")
- }
- // 返回驱动持有的 sql.DB 实例
- return drv.DB(), nil
- }
- // ProvideRedis 为依赖注入提供 Redis 客户端。
- //
- // Redis 用于:
- // - 分布式锁(如并发控制)
- // - 缓存(如用户会话、API 响应缓存)
- // - 速率限制
- // - 实时统计数据
- //
- // 依赖:config.Config
- // 提供:*redis.Client
- func ProvideRedis(cfg *config.Config) *redis.Client {
- return InitRedis(cfg)
- }
|