mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-11 14:41:21 +00:00
fix: prevent duplicate suno task refunds via cas status update (#6074)
* fix: prevent duplicate suno task refunds via cas status update * fix: reconcile failed task refunds --------- Co-authored-by: CaIon <i@caion.me>
This commit is contained in:
@@ -270,6 +270,13 @@ func getSubscriptionUsed(t *testing.T, id int) int64 {
|
||||
return sub.AmountUsed
|
||||
}
|
||||
|
||||
func getTaskQuota(t *testing.T, id int64) int {
|
||||
t.Helper()
|
||||
var task model.Task
|
||||
require.NoError(t, model.DB.Select("quota").Where("id = ?", id).First(&task).Error)
|
||||
return task.Quota
|
||||
}
|
||||
|
||||
func getLastLog(t *testing.T) *model.Log {
|
||||
t.Helper()
|
||||
var log model.Log
|
||||
@@ -304,8 +311,9 @@ func TestRefundTaskQuota_Wallet(t *testing.T) {
|
||||
seedChannel(t, channelID)
|
||||
|
||||
task := makeTask(userID, channelID, preConsumed, tokenID, BillingSourceWallet, 0)
|
||||
require.NoError(t, model.DB.Create(task).Error)
|
||||
|
||||
RefundTaskQuota(ctx, task, "task failed: upstream error")
|
||||
assert.True(t, RefundTaskQuota(ctx, task, "task failed: upstream error"))
|
||||
|
||||
// User quota should increase by preConsumed
|
||||
assert.Equal(t, initQuota+preConsumed, getUserQuota(t, userID))
|
||||
@@ -320,6 +328,8 @@ func TestRefundTaskQuota_Wallet(t *testing.T) {
|
||||
assert.Equal(t, model.LogTypeRefund, log.Type)
|
||||
assert.Equal(t, preConsumed, log.Quota)
|
||||
assert.Equal(t, "test-model", log.ModelName)
|
||||
assert.Zero(t, task.Quota)
|
||||
assert.Zero(t, getTaskQuota(t, task.ID))
|
||||
}
|
||||
|
||||
func TestRefundTaskQuota_Subscription(t *testing.T) {
|
||||
@@ -337,8 +347,9 @@ func TestRefundTaskQuota_Subscription(t *testing.T) {
|
||||
seedSubscription(t, subID, userID, subTotal, subUsed)
|
||||
|
||||
task := makeTask(userID, channelID, preConsumed, tokenID, BillingSourceSubscription, subID)
|
||||
require.NoError(t, model.DB.Create(task).Error)
|
||||
|
||||
RefundTaskQuota(ctx, task, "subscription task failed")
|
||||
assert.True(t, RefundTaskQuota(ctx, task, "subscription task failed"))
|
||||
|
||||
// Subscription used should decrease by preConsumed
|
||||
assert.Equal(t, subUsed-int64(preConsumed), getSubscriptionUsed(t, subID))
|
||||
@@ -349,6 +360,7 @@ func TestRefundTaskQuota_Subscription(t *testing.T) {
|
||||
log := getLastLog(t)
|
||||
require.NotNil(t, log)
|
||||
assert.Equal(t, model.LogTypeRefund, log.Type)
|
||||
assert.Zero(t, getTaskQuota(t, task.ID))
|
||||
}
|
||||
|
||||
func TestRefundTaskQuota_ZeroQuota(t *testing.T) {
|
||||
@@ -360,7 +372,7 @@ func TestRefundTaskQuota_ZeroQuota(t *testing.T) {
|
||||
|
||||
task := makeTask(userID, 0, 0, 0, BillingSourceWallet, 0)
|
||||
|
||||
RefundTaskQuota(ctx, task, "zero quota task")
|
||||
assert.True(t, RefundTaskQuota(ctx, task, "zero quota task"))
|
||||
|
||||
// No change to user quota
|
||||
assert.Equal(t, 5000, getUserQuota(t, userID))
|
||||
@@ -380,8 +392,9 @@ func TestRefundTaskQuota_NoToken(t *testing.T) {
|
||||
seedChannel(t, channelID)
|
||||
|
||||
task := makeTask(userID, channelID, preConsumed, 0, BillingSourceWallet, 0) // TokenId=0
|
||||
require.NoError(t, model.DB.Create(task).Error)
|
||||
|
||||
RefundTaskQuota(ctx, task, "no token task failed")
|
||||
assert.True(t, RefundTaskQuota(ctx, task, "no token task failed"))
|
||||
|
||||
// User quota refunded
|
||||
assert.Equal(t, initQuota+preConsumed, getUserQuota(t, userID))
|
||||
@@ -390,6 +403,23 @@ func TestRefundTaskQuota_NoToken(t *testing.T) {
|
||||
log := getLastLog(t)
|
||||
require.NotNil(t, log)
|
||||
assert.Equal(t, model.LogTypeRefund, log.Type)
|
||||
assert.Zero(t, getTaskQuota(t, task.ID))
|
||||
}
|
||||
|
||||
func TestRefundTaskQuota_FundingFailureKeepsPendingMarker(t *testing.T) {
|
||||
truncate(t)
|
||||
ctx := context.Background()
|
||||
|
||||
const userID, preConsumed = 5, 1200
|
||||
seedUser(t, userID, 5000)
|
||||
task := makeTask(userID, 0, preConsumed, 0, BillingSourceSubscription, 9999)
|
||||
task.Status = model.TaskStatusFailure
|
||||
require.NoError(t, model.DB.Create(task).Error)
|
||||
|
||||
assert.False(t, RefundTaskQuota(ctx, task, "subscription missing"))
|
||||
assert.Equal(t, preConsumed, task.Quota)
|
||||
assert.Equal(t, preConsumed, getTaskQuota(t, task.ID))
|
||||
assert.Equal(t, int64(0), countLogs(t))
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
@@ -608,6 +638,7 @@ func TestCASGuardedRefund_Win(t *testing.T) {
|
||||
var reloaded model.Task
|
||||
require.NoError(t, model.DB.First(&reloaded, task.ID).Error)
|
||||
assert.EqualValues(t, model.TaskStatusFailure, reloaded.Status)
|
||||
assert.Zero(t, reloaded.Quota)
|
||||
|
||||
// Refund should have happened
|
||||
assert.Equal(t, initQuota+preConsumed, getUserQuota(t, userID))
|
||||
|
||||
Reference in New Issue
Block a user