fix(billing): 重排任务复用钱包预留
平台额度跨窗口重排时保留任务已有的钱包预留,后续 Worker 领取复用同一幂等键,避免重复 reserve/release 事务。\n\n补齐排队任务取消后的原子结算释放,并允许任务 attempt 持久化软负载、满载原因和选择原因等有界路由快照。\n\n验证:go test ./...;go vet ./...;钱包预留复用与排队取消 PostgreSQL 集成测试。
This commit is contained in:
@@ -901,6 +901,12 @@ SET status = 'cancelled',
|
||||
error = NULL,
|
||||
error_code = 'task_cancelled',
|
||||
error_message = NULLIF($2::text, ''),
|
||||
billing_status = CASE
|
||||
WHEN run_mode NOT IN ('production', 'acceptance', 'acceptance_canary') OR gateway_user_id IS NULL THEN 'not_required'
|
||||
WHEN reservation_amount > 0 THEN 'pending'
|
||||
ELSE 'released'
|
||||
END,
|
||||
billing_updated_at = now(),
|
||||
remote_task_payload = '{}'::jsonb,
|
||||
locked_by = NULL,
|
||||
locked_at = NULL,
|
||||
@@ -930,7 +936,20 @@ WHERE task_id = $1::uuid
|
||||
if _, err := tx.Exec(ctx, `DELETE FROM gateway_task_admissions WHERE task_id = $1::uuid`, taskID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
payloadJSON, _ := json.Marshal(map[string]any{"taskId": taskID, "reason": "queued_cancelled"})
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO settlement_outbox (
|
||||
task_id, event_type, action, amount, currency, pricing_snapshot, payload, status, next_attempt_at
|
||||
)
|
||||
SELECT id, 'task.billing.release', 'release', reservation_amount, billing_currency,
|
||||
pricing_snapshot, $2::jsonb, 'pending', now()
|
||||
FROM gateway_tasks
|
||||
WHERE id = $1::uuid
|
||||
AND run_mode IN ('production', 'acceptance', 'acceptance_canary')
|
||||
AND gateway_user_id IS NOT NULL
|
||||
AND reservation_amount > 0
|
||||
ON CONFLICT (task_id, event_type) DO NOTHING`, taskID, string(payloadJSON))
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return GatewayTask{}, false, err
|
||||
@@ -1568,6 +1587,7 @@ func minimalTaskAttemptUsage(usage map[string]any) map[string]any {
|
||||
func minimalTaskAttemptMetrics(metrics map[string]any) map[string]any {
|
||||
return whitelistedTaskAttemptMap(metrics, []string{
|
||||
"platformPriority", "currentPriority", "loadRatio", "loadAvoided",
|
||||
"loadMetrics", "fullReasons", "selectionReason",
|
||||
"cacheAffinityKey", "cacheAdjustedPriority", "cacheAffinitySamples",
|
||||
"cacheAffinityScore", "cacheAffinityConfidence", "cacheAffinityHitRatio",
|
||||
"cacheAffinityEMAHitRatio", "cacheAffinityLastHitRatio",
|
||||
|
||||
Reference in New Issue
Block a user