From 0979c9c37a5cf9b617e6fceb0d87e6ae565b770e Mon Sep 17 00:00:00 2001 From: Kelly Date: Sun, 14 Dec 2025 18:50:25 -0700 Subject: [PATCH] Revert "feat(scheduler): Support sub-hour interval_minutes in task_schedules" This reverts commit b607fd7f44df17ecbe8551dd281356d3fe393d52. --- .../121_schedule_interval_minutes.sql | 15 -- backend/src/services/task-scheduler.ts | 128 ++++++------------ 2 files changed, 40 insertions(+), 103 deletions(-) delete mode 100644 backend/migrations/121_schedule_interval_minutes.sql diff --git a/backend/migrations/121_schedule_interval_minutes.sql b/backend/migrations/121_schedule_interval_minutes.sql deleted file mode 100644 index 17383a73..00000000 --- a/backend/migrations/121_schedule_interval_minutes.sql +++ /dev/null @@ -1,15 +0,0 @@ --- Migration 121: Add interval_minutes to task_schedules for sub-hour scheduling --- Part of Real-Time Inventory Tracking feature --- Created: 2024-12-14 - --- Add interval_minutes column for sub-hour scheduling (15min, 30min, etc.) --- When set, takes precedence over interval_hours -ALTER TABLE task_schedules ADD COLUMN IF NOT EXISTS interval_minutes INT DEFAULT NULL; - --- Add comment for documentation -COMMENT ON COLUMN task_schedules.interval_minutes IS 'Sub-hour scheduling interval in minutes (takes precedence over interval_hours when set)'; - --- Create index for finding schedules by interval type -CREATE INDEX IF NOT EXISTS idx_task_schedules_interval_minutes -ON task_schedules(interval_minutes) -WHERE interval_minutes IS NOT NULL; diff --git a/backend/src/services/task-scheduler.ts b/backend/src/services/task-scheduler.ts index 9ce5f65e..8aff0e0c 100644 --- a/backend/src/services/task-scheduler.ts +++ b/backend/src/services/task-scheduler.ts @@ -22,7 +22,6 @@ interface TaskSchedule { role: TaskRole; enabled: boolean; interval_hours: number; - interval_minutes: number | null; // For sub-hour scheduling (takes precedence over interval_hours) last_run_at: Date | null; next_run_at: Date | null; state_code: string | null; @@ -168,66 +167,28 @@ class TaskScheduler { console.log(`[TaskScheduler] Schedule ${schedule.name} created ${tasksCreated} tasks`); // Per TASK_WORKFLOW_2024-12-10.md: Update last_run_at and calculate next_run_at - // Prefer interval_minutes over interval_hours for sub-hour scheduling - // Add jitter (0-20% of interval) to prevent predictable crawl patterns - let nextRunQuery: string; - let nextRunParams: any[]; - - if (schedule.interval_minutes) { - // Sub-hour scheduling with jitter - const jitterMinutes = Math.floor(Math.random() * (schedule.interval_minutes * 0.2)); - const totalMinutes = schedule.interval_minutes + jitterMinutes; - nextRunQuery = ` - UPDATE task_schedules - SET - last_run_at = NOW(), - next_run_at = NOW() + ($1 || ' minutes')::interval, - last_task_count = $2, - updated_at = NOW() - WHERE id = $3 - `; - nextRunParams = [totalMinutes, tasksCreated, schedule.id]; - console.log(`[TaskScheduler] Schedule ${schedule.name} next run in ${totalMinutes}min (${schedule.interval_minutes}min + ${jitterMinutes}min jitter)`); - } else { - // Standard hour-based scheduling - nextRunQuery = ` - UPDATE task_schedules - SET - last_run_at = NOW(), - next_run_at = NOW() + ($1 || ' hours')::interval, - last_task_count = $2, - updated_at = NOW() - WHERE id = $3 - `; - nextRunParams = [schedule.interval_hours, tasksCreated, schedule.id]; - } - - await client.query(nextRunQuery, nextRunParams); + await client.query(` + UPDATE task_schedules + SET + last_run_at = NOW(), + next_run_at = NOW() + ($1 || ' hours')::interval, + last_task_count = $2, + updated_at = NOW() + WHERE id = $3 + `, [schedule.interval_hours, tasksCreated, schedule.id]); } catch (err: any) { console.error(`[TaskScheduler] Schedule ${schedule.name} failed:`, err.message); // Still update next_run_at to prevent infinite retry loop - // Use interval_minutes if set, otherwise interval_hours - if (schedule.interval_minutes) { - await client.query(` - UPDATE task_schedules - SET - next_run_at = NOW() + ($1 || ' minutes')::interval, - last_error = $2, - updated_at = NOW() - WHERE id = $3 - `, [schedule.interval_minutes, err.message, schedule.id]); - } else { - await client.query(` - UPDATE task_schedules - SET - next_run_at = NOW() + ($1 || ' hours')::interval, - last_error = $2, - updated_at = NOW() - WHERE id = $3 - `, [schedule.interval_hours, err.message, schedule.id]); - } + await client.query(` + UPDATE task_schedules + SET + next_run_at = NOW() + ($1 || ' hours')::interval, + last_error = $2, + updated_at = NOW() + WHERE id = $3 + `, [schedule.interval_hours, err.message, schedule.id]); } } @@ -550,37 +511,33 @@ class TaskScheduler { try { const result = await pool.query(` SELECT - ts.id, - ts.name, - ts.role, - ts.enabled, - ts.interval_hours, - ts.interval_minutes, - ts.last_run_at, - ts.next_run_at, - ts.state_code, - ts.dispensary_id, - ts.priority, - ts.method, - COALESCE(ts.is_immutable, false) as is_immutable, - ts.description, - ts.platform, - ts.last_task_count, - ts.last_error, - ts.created_at, - ts.updated_at, - d.name as dispensary_name - FROM task_schedules ts - LEFT JOIN dispensaries d ON ts.dispensary_id = d.id + id, + name, + role, + enabled, + interval_hours, + last_run_at, + next_run_at, + state_code, + priority, + method, + COALESCE(is_immutable, false) as is_immutable, + description, + platform, + last_task_count, + last_error, + created_at, + updated_at + FROM task_schedules ORDER BY - CASE ts.role + CASE role WHEN 'store_discovery' THEN 1 WHEN 'product_discovery' THEN 2 WHEN 'analytics_refresh' THEN 3 ELSE 4 END, - ts.state_code NULLS FIRST, - ts.name + state_code NULLS FIRST, + name `); return result.rows as TaskSchedule[]; } catch { @@ -604,8 +561,8 @@ class TaskScheduler { /** * Update a schedule - * Allows updating: enabled, interval_hours, interval_minutes, priority - * Does NOT allow updating: name, role, state_code, dispensary_id, is_immutable + * Allows updating: enabled, interval_hours, priority + * Does NOT allow updating: name, role, state_code, is_immutable */ async updateSchedule(id: number, updates: Partial): Promise { const setClauses: string[] = []; @@ -620,11 +577,6 @@ class TaskScheduler { setClauses.push(`interval_hours = $${paramIndex++}`); values.push(updates.interval_hours); } - // Allow setting interval_minutes (can be null to disable sub-hour scheduling) - if ('interval_minutes' in updates) { - setClauses.push(`interval_minutes = $${paramIndex++}`); - values.push(updates.interval_minutes); - } if (updates.priority !== undefined) { setClauses.push(`priority = $${paramIndex++}`); values.push(updates.priority);