-- name: EnqueueJob :one INSERT INTO jobs (id, type, payload, status, scheduled_at, attempts, max_attempts) VALUES ($1, $2, $3, 'pending', $4, 0, $5) RETURNING *; -- name: LeaseNextJob :one -- SKIP LOCKED 让多 worker 并行抢不冲突;只返回单行。 UPDATE jobs SET status='running', leased_at=now(), leased_by=$1, attempts=attempts+1, updated_at=now() WHERE id = ( SELECT id FROM jobs WHERE status='pending' AND scheduled_at <= now() ORDER BY scheduled_at ASC FOR UPDATE SKIP LOCKED LIMIT 1 ) RETURNING *; -- name: CompleteJob :execrows -- 围栏谓词:只有持有当前租约的 worker 才能写回,防止被 reaper 重新租出后旧 worker 覆盖新一轮状态。 UPDATE jobs SET status='completed', completed_at=now(), leased_at=NULL, leased_by=NULL, last_error=NULL, updated_at=now() WHERE id=$1 AND leased_by=$2 AND status='running'; -- name: FailJobWithRetry :execrows -- 围栏谓词同上。 UPDATE jobs SET status='pending', scheduled_at=$2, leased_at=NULL, leased_by=NULL, last_error=$3, updated_at=now() WHERE id=$1 AND leased_by=$4 AND status='running'; -- name: DeadLetterJob :execrows -- 围栏谓词同上。 UPDATE jobs SET status='dead', completed_at=now(), leased_at=NULL, leased_by=NULL, last_error=$2, updated_at=now() WHERE id=$1 AND leased_by=$3 AND status='running'; -- name: GetJob :one SELECT * FROM jobs WHERE id=$1; -- name: ReapStuckRunningJobs :many -- 复位 worker 崩了卡 running 的任务。 UPDATE jobs SET status='pending', leased_at=NULL, leased_by=NULL, scheduled_at=now(), updated_at=now() WHERE status='running' AND leased_at < $1 RETURNING id; -- name: PurgeCompletedJobs :execrows DELETE FROM jobs WHERE status IN ('completed','dead') AND completed_at < $1; -- name: ListDeadJobs :many SELECT * FROM jobs WHERE status='dead' AND completed_at >= $1 ORDER BY completed_at DESC LIMIT $2;