onesvm-browser-server/server/internal/auth/quota.go
chii eb972dfa93 feat: 落地 browser-server 控制面并打通 mgr1 海外订阅
单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 15:05:12 +08:00

37 lines
1.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// quota.go:配额预扣/结算/释放(design-arch §2.3:预扣防超卖,耗尽 402)。
// 预扣在 gateway 认证后、入队前执行;任务终态由 scheduler 回调结算或释放。
package auth
import (
"fmt"
"time"
"onesvm.com/onesvm/browser-server/internal/contract"
"onesvm.com/onesvm/browser-server/internal/store"
)
// ReserveDaily 预扣当日额度(事务内条件 UPDATE,防超卖)。
// 返回剩余额度;不足时返回 quota 错误(402,不重试)。
func (v *Verifier) ReserveDaily(keyID int64, dailyLimit int, now time.Time) (int, *Error) {
if dailyLimit <= 0 {
return 0, &Error{Code: contract.CodeQuota, Message: "日配额为 0(未开放)"}
}
remaining, err := v.db.QuotaReserve(keyID, dailyLimit, now)
if err == store.ErrNotFound {
return 0, &Error{Code: contract.CodeQuota, Message: "日配额耗尽(402,不重试)"}
}
if err != nil {
return 0, &Error{Code: contract.CodeUpstream, Message: fmt.Sprintf("配额预扣失败: %v", err)}
}
return remaining, nil
}
// Settle 结算:预扣转实耗(任务成功后)。
func (v *Verifier) Settle(keyID int64, now time.Time) error {
return v.db.QuotaSettle(keyID, now)
}
// Release 释放预扣(任务失败回滚)。
func (v *Verifier) Release(keyID int64, now time.Time) error {
return v.db.QuotaRelease(keyID, now)
}