fix(billing): improve quota handling and error reporting for pre-consume operations

This commit is contained in:
CaIon
2026-07-11 13:14:22 +08:00
parent 621927f710
commit d9595831bf
12 changed files with 246 additions and 61 deletions
+1 -2
View File
@@ -19,9 +19,8 @@ const (
// 会话存储在 relayInfo.Billing 上,供后续 Settle / Refund 使用。
func PreConsumeBilling(c *gin.Context, preConsumedQuota int, relayInfo *relaycommon.RelayInfo) *types.NewAPIError {
if relayInfo != nil && relayInfo.QuotaClamp != nil {
clamp := relayInfo.QuotaClamp
return types.NewErrorWithStatusCode(
fmt.Errorf("pre-consume quota is out of range: operation=%s kind=%s value=%g", clamp.Op, clamp.Kind, clamp.Original),
relayInfo.QuotaClamp,
types.ErrorCodeModelPriceError,
http.StatusBadRequest,
types.ErrOptionWithSkipRetry(),
+4
View File
@@ -92,6 +92,10 @@ func TestPreConsumeBillingRejectsSaturatedQuotaBeforeDeduction(t *testing.T) {
require.NotNil(t, apiErr)
require.Equal(t, types.ErrorCodeModelPriceError, apiErr.GetErrorCode())
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode)
require.Same(t, info.QuotaClamp, apiErr.Err)
var clamp *common.QuotaClamp
require.ErrorAs(t, apiErr, &clamp)
require.Same(t, info.QuotaClamp, clamp)
require.Nil(t, info.Billing)
}
+28
View File
@@ -490,3 +490,31 @@ func TestTryTieredSettleNoClampInRange(t *testing.T) {
require.NotNil(t, result)
require.Nil(t, relayInfo.QuotaClamp, "in-range settlement must not record a clamp")
}
func TestCalculateTextQuotaSummaryFixedPriceAppliesImageCountOnceAndAllowsOverride(t *testing.T) {
gin.SetMode(gin.TestMode)
ctx, _ := gin.CreateTestContext(httptest.NewRecorder())
priceData := types.PriceData{
ModelPrice: 0.12,
UsePrice: true,
GroupRatioInfo: types.GroupRatioInfo{
GroupRatio: 1,
},
}
priceData.AddOtherRatio("n", 3)
relayInfo := &relaycommon.RelayInfo{
OriginModelName: "dall-e-3",
PriceData: priceData,
StartTime: time.Now(),
}
usage := &dto.Usage{PromptTokens: 1, TotalTokens: 1}
summary := calculateTextQuotaSummary(ctx, relayInfo, usage)
require.Equal(t, 180000, summary.Quota)
// An adaptor-reported actual count replaces the requested count rather
// than multiplying it a second time.
relayInfo.PriceData.AddOtherRatio("n", 2)
summary = calculateTextQuotaSummary(ctx, relayInfo, usage)
require.Equal(t, 120000, summary.Quota)
}