feat(volces): 接入任务兼容查询与上游取消
This commit is contained in:
@@ -530,7 +530,8 @@ WHERE id = $1::uuid
|
||||
UPDATE gateway_task_attempts
|
||||
SET remote_task_id = NULLIF($2::text, ''),
|
||||
response_snapshot = COALESCE(response_snapshot, '{}'::jsonb) || jsonb_build_object('remote_task_payload', $3::jsonb)
|
||||
WHERE id = $1::uuid`,
|
||||
WHERE id = $1::uuid
|
||||
AND status = 'running'`,
|
||||
attemptID,
|
||||
remoteTaskID,
|
||||
string(payloadJSON),
|
||||
@@ -585,6 +586,72 @@ WHERE id = $1::uuid
|
||||
return task, true, nil
|
||||
}
|
||||
|
||||
// CancelSubmittedTask records a confirmed upstream cancellation. Callers must
|
||||
// first complete the provider-side DELETE so local status never claims a remote
|
||||
// task was cancelled when the upstream request was not accepted.
|
||||
func (s *Store) CancelSubmittedTask(ctx context.Context, taskID string, executionToken string, message string) (GatewayTask, bool, error) {
|
||||
message = strings.TrimSpace(message)
|
||||
if message == "" {
|
||||
message = "任务已由上游取消"
|
||||
}
|
||||
var task GatewayTask
|
||||
changed := false
|
||||
err := pgx.BeginFunc(ctx, s.pool, func(tx pgx.Tx) error {
|
||||
var err error
|
||||
task, err = scanGatewayTask(tx.QueryRow(ctx, `
|
||||
UPDATE gateway_tasks
|
||||
SET status = 'cancelled',
|
||||
error = NULLIF($2, ''),
|
||||
error_code = 'task_cancelled',
|
||||
error_message = NULLIF($2, ''),
|
||||
billing_status = CASE
|
||||
WHEN run_mode <> 'production' OR gateway_user_id IS NULL THEN 'not_required'
|
||||
WHEN reservation_amount > 0 THEN 'pending'
|
||||
ELSE 'released'
|
||||
END,
|
||||
billing_updated_at = now(),
|
||||
locked_by = NULL,
|
||||
locked_at = NULL,
|
||||
heartbeat_at = NULL,
|
||||
execution_token = NULL,
|
||||
execution_lease_expires_at = NULL,
|
||||
finished_at = now(),
|
||||
updated_at = now()
|
||||
WHERE id = $1::uuid
|
||||
AND NULLIF(remote_task_id, '') IS NOT NULL
|
||||
AND (
|
||||
(status = 'running' AND execution_token = NULLIF($3, '')::uuid)
|
||||
OR status = 'queued'
|
||||
)
|
||||
RETURNING `+gatewayTaskColumns, taskID, message, strings.TrimSpace(executionToken)))
|
||||
if IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
changed = true
|
||||
payloadJSON, _ := json.Marshal(map[string]any{"taskId": taskID, "reason": "upstream_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 = 'production'
|
||||
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
|
||||
}
|
||||
return task, changed, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListRecoverableAsyncTasks(ctx context.Context, limit int) ([]AsyncTaskQueueItem, error) {
|
||||
if limit <= 0 {
|
||||
limit = 500
|
||||
|
||||
Reference in New Issue
Block a user