| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package service
- import (
- "context"
- "log/slog"
- infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
- )
- const (
- OpenAIQuotaResetWarningCacheRefreshFailed = "reset_credit_cache_refresh_failed"
- OpenAIQuotaResetWarningAccountRecoveryFailed = "account_state_recovery_failed"
- OpenAIQuotaResetWarningAccountRefreshFailed = "account_state_refresh_failed"
- )
- type openAIQuotaResetWorkflowQuota interface {
- QueryUsage(ctx context.Context, accountID int64) (*OpenAIQuotaUsage, error)
- CachePostResetSnapshot(ctx context.Context, accountID int64, usage *OpenAIQuotaUsage) error
- }
- type openAIQuotaResetWorkflowRecoverer interface {
- RecoverAccountState(ctx context.Context, accountID int64, options AccountRecoveryOptions) (*SuccessfulTestRecoveryResult, error)
- }
- // OpenAIQuotaResetPostProcessResult 汇总手动和自动用卡后的共享恢复结果。
- // WarningCode 允许上游消费成功但本地恢复部分失败时仍然准确呈现状态。
- type OpenAIQuotaResetPostProcessResult struct {
- Quota *OpenAIQuotaUsage
- Account *Account
- CacheRefreshed bool
- AccountStateRecovered bool
- WarningCode string
- }
- // RunOpenAIQuotaResetPostProcess 按“解除限流、刷新额度缓存、刷新账号行”的固定顺序
- // 执行消费后恢复,避免手动和自动入口在失败语义上逐渐分叉。
- func RunOpenAIQuotaResetPostProcess(
- ctx context.Context,
- accountID int64,
- quota openAIQuotaResetWorkflowQuota,
- recoverer openAIQuotaResetWorkflowRecoverer,
- loadAccount func(context.Context, int64) (*Account, error),
- ) OpenAIQuotaResetPostProcessResult {
- result := OpenAIQuotaResetPostProcessResult{}
- if recoverer == nil {
- result.WarningCode = OpenAIQuotaResetWarningAccountRecoveryFailed
- return result
- }
- if _, err := recoverer.RecoverAccountState(ctx, accountID, AccountRecoveryOptions{InvalidateToken: true}); err != nil {
- slog.Warn("openai_quota_reset_account_recovery_failed", "account_id", accountID, "error_code", infraerrors.Reason(err))
- result.WarningCode = OpenAIQuotaResetWarningAccountRecoveryFailed
- return result
- }
- result.AccountStateRecovered = true
- if quota != nil {
- usage, usageErr := quota.QueryUsage(ctx, accountID)
- switch {
- case usageErr != nil || usage == nil:
- slog.Warn("openai_quota_reset_cache_refresh_failed", "account_id", accountID, "error_code", infraerrors.Reason(usageErr))
- result.WarningCode = OpenAIQuotaResetWarningCacheRefreshFailed
- default:
- if err := quota.CachePostResetSnapshot(ctx, accountID, usage); err != nil {
- slog.Warn("openai_quota_reset_cache_refresh_failed", "account_id", accountID, "error_code", infraerrors.Reason(err))
- result.WarningCode = OpenAIQuotaResetWarningCacheRefreshFailed
- } else {
- result.Quota = usage
- result.CacheRefreshed = true
- }
- }
- }
- if loadAccount == nil {
- return result
- }
- account, err := loadAccount(ctx, accountID)
- if err != nil {
- slog.Warn("openai_quota_reset_account_refresh_failed", "account_id", accountID, "error_code", infraerrors.Reason(err))
- if result.WarningCode == "" {
- result.WarningCode = OpenAIQuotaResetWarningAccountRefreshFailed
- }
- return result
- }
- result.Account = account
- return result
- }
|