mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-11 14:41:21 +00:00
fix(billing): settle tiered retries with final group (#6518)
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/QuantumNous/new-api/pkg/billingexpr"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||
"github.com/QuantumNous/new-api/relaykit/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TieredResultWrapper wraps billingexpr.TieredResult for use at the service layer.
|
||||
@@ -90,8 +94,60 @@ func BuildTieredTokenParams(usage *dto.Usage, isClaudeUsageSemantic bool, usedVa
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTieredBillingGroup(relayInfo *relaycommon.RelayInfo) (*billingexpr.BillingSnapshot, error) {
|
||||
if relayInfo == nil {
|
||||
return nil, nil
|
||||
}
|
||||
snap := relayInfo.TieredBillingSnapshot
|
||||
if snap == nil || snap.BillingMode != "tiered_expr" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
groupRatio := relayInfo.PriceData.GroupRatioInfo.GroupRatio
|
||||
if snap.GroupRatio == groupRatio {
|
||||
return snap, nil
|
||||
}
|
||||
|
||||
estimatedQuotaAfterGroup := snap.EstimatedQuotaBeforeGroup * groupRatio
|
||||
estimatedQuota, err := billingexpr.QuotaRoundStrict(estimatedQuotaAfterGroup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snap.GroupRatio = groupRatio
|
||||
snap.EstimatedQuotaAfterGroup = estimatedQuota
|
||||
return snap, nil
|
||||
}
|
||||
|
||||
// PrepareTieredBillingForSelectedGroup refreshes routing-dependent billing
|
||||
// state before an upstream attempt. An existing session reserves any higher
|
||||
// estimate before sending. If the initial group was free and skipped
|
||||
// pre-consume, switching to a paid group creates the session at that point.
|
||||
func PrepareTieredBillingForSelectedGroup(c *gin.Context, relayInfo *relaycommon.RelayInfo) *types.NewAPIError {
|
||||
snap, err := refreshTieredBillingGroup(relayInfo)
|
||||
if err != nil {
|
||||
return types.NewErrorWithStatusCode(
|
||||
err,
|
||||
types.ErrorCodeModelPriceError,
|
||||
http.StatusBadRequest,
|
||||
types.ErrOptionWithSkipRetry(),
|
||||
)
|
||||
}
|
||||
if snap == nil || snap.GroupRatio == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if relayInfo.Billing == nil {
|
||||
return PreConsumeBilling(c, snap.EstimatedQuotaAfterGroup, relayInfo)
|
||||
}
|
||||
if err := relayInfo.Billing.Reserve(snap.EstimatedQuotaAfterGroup); err != nil {
|
||||
return types.NewError(err, types.ErrorCodeUpdateDataError, types.ErrOptionWithSkipRetry())
|
||||
}
|
||||
relayInfo.FinalPreConsumedQuota = relayInfo.Billing.GetPreConsumedQuota()
|
||||
return nil
|
||||
}
|
||||
|
||||
// TryTieredSettle checks if the request uses tiered_expr billing and, if so,
|
||||
// computes the actual quota using the frozen BillingSnapshot. Returns:
|
||||
// computes the actual quota using the captured BillingSnapshot. Returns:
|
||||
// - ok=true, quota, result when tiered billing applies
|
||||
// - ok=false, 0, nil when it doesn't (caller should fall through to existing logic)
|
||||
func TryTieredSettle(relayInfo *relaycommon.RelayInfo, params billingexpr.TokenParams) (ok bool, quota int, result *billingexpr.TieredResult) {
|
||||
|
||||
Reference in New Issue
Block a user