From b1c1955082374f1d094bcfe63b5a2753c9b9bb9a Mon Sep 17 00:00:00 2001 From: Kelly Date: Sat, 13 Dec 2025 01:18:07 -0700 Subject: [PATCH] feat: Add POST /api/tasks/retry-failed endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resets failed tasks back to pending for retry. Options: role (filter), max_age_hours (default 24), limit (default 100) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/src/routes/tasks.ts | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/backend/src/routes/tasks.ts b/backend/src/routes/tasks.ts index ea420f73..fc2a6762 100644 --- a/backend/src/routes/tasks.ts +++ b/backend/src/routes/tasks.ts @@ -841,6 +841,56 @@ router.post('/recover-stale', async (req: Request, res: Response) => { } }); +/** + * POST /api/tasks/retry-failed + * Reset failed tasks back to pending for retry + * + * Body: + * - role: string (optional, filter by role) + * - max_age_hours: number (optional, default 24 - only retry tasks from last N hours) + * - limit: number (optional, default 100) + */ +router.post('/retry-failed', async (req: Request, res: Response) => { + try { + const { role, max_age_hours = 24, limit = 100 } = req.body; + + let query = ` + UPDATE worker_tasks + SET status = 'pending', + worker_id = NULL, + claimed_at = NULL, + started_at = NULL, + completed_at = NULL, + error_message = NULL, + retry_count = retry_count + 1, + updated_at = NOW() + WHERE status = 'failed' + AND created_at > NOW() - INTERVAL '${parseInt(max_age_hours)} hours' + `; + const params: any[] = []; + + if (role) { + query += ` AND role = $1`; + params.push(role); + } + + query += ` RETURNING id, role, dispensary_id`; + + const { rows } = await pool.query(query, params); + + console.log(`[Tasks] Retried ${rows.length} failed tasks`); + + res.json({ + success: true, + tasks_retried: rows.length, + tasks: rows.slice(0, 20), // Return first 20 for visibility + }); + } catch (error: unknown) { + console.error('Error retrying failed tasks:', error); + res.status(500).json({ error: 'Failed to retry tasks' }); + } +}); + /** * GET /api/tasks/role/:role/last-completion * Get the last completion time for a role