fix
This commit is contained in:
@@ -18,6 +18,56 @@ type StuckCleanupResult struct {
|
||||
SyncJobsMarkedFailed int64
|
||||
}
|
||||
|
||||
// OrphanReclaimResult counts rows touched by ReclaimOrphanedRunning.
|
||||
type OrphanReclaimResult struct {
|
||||
JobsRequeued int64
|
||||
ProductsReset int64
|
||||
SyncJobsRequeued int64
|
||||
}
|
||||
|
||||
// ReclaimOrphanedRunning resets in-flight work left by a dead worker process so
|
||||
// ClaimNext / feed sync claim can pick it up again. Call only when the processing
|
||||
// worker heartbeat is missing or stale (single-worker architecture) — never while
|
||||
// another live worker may own the rows.
|
||||
//
|
||||
// Unlike CleanupStuck (age-gated fail), this requeues immediately: running → pending
|
||||
// for jobs/sync jobs, and processing → pending for job products without a result.
|
||||
func ReclaimOrphanedRunning(ctx context.Context, pool *pgxpool.Pool) (OrphanReclaimResult, error) {
|
||||
var out OrphanReclaimResult
|
||||
if pool == nil {
|
||||
return out, fmt.Errorf("reclaim orphaned running: nil pool")
|
||||
}
|
||||
|
||||
ctJobs, err := pool.Exec(ctx, `
|
||||
UPDATE processing_jobs
|
||||
SET status = 'pending', started_at = NULL, error = NULL, updated_at = now()
|
||||
WHERE status = 'running'`)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("reclaim orphaned jobs: %w", err)
|
||||
}
|
||||
out.JobsRequeued = ctJobs.RowsAffected()
|
||||
|
||||
ctProd, err := pool.Exec(ctx, `
|
||||
UPDATE processing_job_products
|
||||
SET status = 'pending', error = NULL, updated_at = now()
|
||||
WHERE status = 'processing' AND processed_product_id IS NULL`)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("reclaim orphaned products: %w", err)
|
||||
}
|
||||
out.ProductsReset = ctProd.RowsAffected()
|
||||
|
||||
ctSync, err := pool.Exec(ctx, `
|
||||
UPDATE feed_sync_jobs
|
||||
SET status = 'pending', started_at = NULL, error = NULL, completed_at = NULL, updated_at = now()
|
||||
WHERE status = 'running'`)
|
||||
if err != nil {
|
||||
return out, fmt.Errorf("reclaim orphaned sync jobs: %w", err)
|
||||
}
|
||||
out.SyncJobsRequeued = ctSync.RowsAffected()
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CleanupStuck aligns worker and admin stuck-cleanup semantics:
|
||||
// mark long-running jobs failed, reset stranded processing_job_products
|
||||
// from 'processing' back to 'pending', and fail aged running feed_sync_jobs
|
||||
|
||||
Reference in New Issue
Block a user