-
Notifications
You must be signed in to change notification settings - Fork 11.2k
fix(billing): 异步任务退款时同步减少 used_quota #6795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -232,30 +232,6 @@ func RelaySwapFace(c *gin.Context, info *relaycommon.RelayInfo) *dto.MidjourneyR | |
| if err != nil { | ||
| return &mjResp.Response | ||
| } | ||
| defer func() { | ||
| if mjResp.StatusCode == 200 && mjResp.Response.Code == 1 { | ||
| err := service.PostConsumeQuota(info, priceData.Quota, 0, true) | ||
| if err != nil { | ||
| common.SysLog("error consuming token remain quota: " + err.Error()) | ||
| } | ||
|
|
||
| tokenName := c.GetString("token_name") | ||
| logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, constant.MjActionSwapFace) | ||
| other := service.GenerateMjOtherInfo(info, priceData) | ||
| model.RecordConsumeLog(c, info.UserId, model.RecordConsumeLogParams{ | ||
| ChannelId: info.ChannelId, | ||
| ModelName: modelName, | ||
| TokenName: tokenName, | ||
| Quota: priceData.Quota, | ||
| Content: logContent, | ||
| TokenId: info.TokenId, | ||
| Group: info.UsingGroup, | ||
| Other: other, | ||
| }) | ||
| model.UpdateUserUsedQuotaAndRequestCount(info.UserId, priceData.Quota) | ||
| model.UpdateChannelUsedQuota(info.ChannelId, priceData.Quota) | ||
| } | ||
| }() | ||
| midjResponse := &mjResp.Response | ||
| midjourneyTask := &model.Midjourney{ | ||
| UserId: info.UserId, | ||
|
|
@@ -274,12 +250,42 @@ func RelaySwapFace(c *gin.Context, info *relaycommon.RelayInfo) *dto.MidjourneyR | |
| Progress: "0%", | ||
| FailReason: "", | ||
| ChannelId: c.GetInt("channel_id"), | ||
| Quota: priceData.Quota, | ||
| } | ||
| billingPrepared, billingErr := service.PrepareMidjourneyTaskBilling( | ||
| info, | ||
| midjourneyTask, | ||
| priceData.Quota, | ||
| mjResp.StatusCode == http.StatusOK && midjResponse.Code == 1, | ||
| ) | ||
| if billingErr != nil { | ||
| common.SysLog("error consuming Midjourney quota: " + billingErr.Error()) | ||
| } | ||
|
Comment on lines
+260
to
262
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win The preparation-stage error is logged as a consumption error in both Midjourney handlers.
📍 Affects 1 file
🤖 Prompt for AI Agents |
||
| err = midjourneyTask.Insert() | ||
| if err != nil { | ||
| return service.MidjourneyErrorWrapper(constant.MjRequestError, "insert_midjourney_task_failed") | ||
| } | ||
| billingApplied, billingErr := service.SettleMidjourneyTaskBilling(info, midjourneyTask, billingPrepared) | ||
| if billingErr != nil { | ||
| common.SysLog("error settling Midjourney quota: " + billingErr.Error()) | ||
| } | ||
| if billingApplied { | ||
| billingChannelId := midjourneyTask.GetBillingChannelId() | ||
| tokenName := c.GetString("token_name") | ||
| logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, constant.MjActionSwapFace) | ||
| other := service.GenerateMjOtherInfo(info, priceData) | ||
| model.RecordConsumeLog(c, info.UserId, model.RecordConsumeLogParams{ | ||
| ChannelId: billingChannelId, | ||
| ModelName: modelName, | ||
| TokenName: tokenName, | ||
| Quota: midjourneyTask.Quota, | ||
| Content: logContent, | ||
| TokenId: midjourneyTask.TokenId, | ||
| Group: info.UsingGroup, | ||
| Other: other, | ||
| }) | ||
| model.UpdateUserUsedQuotaAndRequestCount(info.UserId, midjourneyTask.Quota) | ||
| model.UpdateChannelUsedQuota(billingChannelId, midjourneyTask.Quota) | ||
| } | ||
| c.Writer.WriteHeader(mjResp.StatusCode) | ||
| respBody, err := json.Marshal(midjResponse) | ||
| if err != nil { | ||
|
|
@@ -539,30 +545,6 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt | |
| } | ||
| midjResponse := &midjResponseWithStatus.Response | ||
|
|
||
| defer func() { | ||
| if consumeQuota && midjResponseWithStatus.StatusCode == 200 { | ||
| err := service.PostConsumeQuota(relayInfo, priceData.Quota, 0, true) | ||
| if err != nil { | ||
| common.SysLog("error consuming token remain quota: " + err.Error()) | ||
| } | ||
| tokenName := c.GetString("token_name") | ||
| logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s,ID %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, midjRequest.Action, midjResponse.Result) | ||
| other := service.GenerateMjOtherInfo(relayInfo, priceData) | ||
| model.RecordConsumeLog(c, relayInfo.UserId, model.RecordConsumeLogParams{ | ||
| ChannelId: relayInfo.ChannelId, | ||
| ModelName: modelName, | ||
| TokenName: tokenName, | ||
| Quota: priceData.Quota, | ||
| Content: logContent, | ||
| TokenId: relayInfo.TokenId, | ||
| Group: relayInfo.UsingGroup, | ||
| Other: other, | ||
| }) | ||
| model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, priceData.Quota) | ||
| model.UpdateChannelUsedQuota(relayInfo.ChannelId, priceData.Quota) | ||
| } | ||
| }() | ||
|
|
||
| // 文档:https://github.com/novicezk/midjourney-proxy/blob/main/docs/api.md | ||
| //1-提交成功 | ||
| // 21-任务已存在(处理中或者有结果了) {"code":21,"description":"任务已存在","result":"0741798445574458","properties":{"status":"SUCCESS","imageUrl":"https://xxxx"}} | ||
|
|
@@ -587,7 +569,6 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt | |
| Progress: "0%", | ||
| FailReason: "", | ||
| ChannelId: c.GetInt("channel_id"), | ||
| Quota: priceData.Quota, | ||
| } | ||
| if midjResponse.Code == 3 { | ||
| //无实例账号自动禁用渠道(No available account instance) | ||
|
|
@@ -632,13 +613,44 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt | |
| midjourneyTask.Progress = "100%" | ||
| midjourneyTask.Status = "SUCCESS" | ||
| } | ||
| billingPrepared, billingErr := service.PrepareMidjourneyTaskBilling( | ||
| relayInfo, | ||
| midjourneyTask, | ||
| priceData.Quota, | ||
| consumeQuota && midjResponseWithStatus.StatusCode == http.StatusOK, | ||
| ) | ||
| if billingErr != nil { | ||
| common.SysLog("error consuming Midjourney quota: " + billingErr.Error()) | ||
| } | ||
| err = midjourneyTask.Insert() | ||
| if err != nil { | ||
| return &dto.MidjourneyResponse{ | ||
| Code: 4, | ||
| Description: "insert_midjourney_task_failed", | ||
| } | ||
| } | ||
| billingApplied, billingErr := service.SettleMidjourneyTaskBilling(relayInfo, midjourneyTask, billingPrepared) | ||
| if billingErr != nil { | ||
| common.SysLog("error settling Midjourney quota: " + billingErr.Error()) | ||
| } | ||
| if billingApplied { | ||
| billingChannelId := midjourneyTask.GetBillingChannelId() | ||
| tokenName := c.GetString("token_name") | ||
| logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s,ID %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, midjRequest.Action, midjResponse.Result) | ||
| other := service.GenerateMjOtherInfo(relayInfo, priceData) | ||
| model.RecordConsumeLog(c, relayInfo.UserId, model.RecordConsumeLogParams{ | ||
| ChannelId: billingChannelId, | ||
| ModelName: modelName, | ||
| TokenName: tokenName, | ||
| Quota: midjourneyTask.Quota, | ||
| Content: logContent, | ||
| TokenId: midjourneyTask.TokenId, | ||
| Group: relayInfo.UsingGroup, | ||
| Other: other, | ||
| }) | ||
| model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, midjourneyTask.Quota) | ||
| model.UpdateChannelUsedQuota(billingChannelId, midjourneyTask.Quota) | ||
| } | ||
|
|
||
| if midjResponse.Code == 22 { //22-排队中,说明任务已存在 | ||
| //修改返回值 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: QuantumNous/new-api
Length of output: 183
🏁 Script executed:
Repository: QuantumNous/new-api
Length of output: 50376
🏁 Script executed:
Repository: QuantumNous/new-api
Length of output: 32804
🏁 Script executed:
Repository: QuantumNous/new-api
Length of output: 50375
🏁 Script executed:
Repository: QuantumNous/new-api
Length of output: 290
Exclude billing fields from full-row Midjourney updates.
RelayMidjourneyNotifyusesSave, andUpdateWithStatuswritesSelect("*"). A stale task loaded beforeRefundMidjourneyQuotacan restore clearedquota,token_id, andbilling_channel_id, enabling a duplicate refund. Exclude billing fields from status and notification updates, or add a version/CAS guard to every full-row writer.🤖 Prompt for AI Agents