feat: add scheduled scans (cron-like recurring scans)
- New `scheduled_scans` table with daily/weekly/monthly frequencies - asyncio background scheduler loop checks for due schedules every 60s - 6 REST endpoints: CRUD + toggle enabled + run-now - `scheduled_scan_id` FK added to scans table; migrated automatically - Frontend: Schedules page (list + create form), Schedules nav link, "Scheduled" badge on ScanDetails when scan was triggered by a schedule Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,9 @@ CREATE TABLE IF NOT EXISTS scans (
|
||||
seat_class TEXT DEFAULT 'economy',
|
||||
adults INTEGER DEFAULT 1 CHECK(adults > 0 AND adults <= 9),
|
||||
|
||||
-- FK to scheduled_scans (NULL for manual scans)
|
||||
scheduled_scan_id INTEGER,
|
||||
|
||||
-- Constraints across columns
|
||||
CHECK(end_date >= start_date),
|
||||
CHECK(routes_scanned <= total_routes OR total_routes = 0)
|
||||
@@ -61,6 +64,10 @@ CREATE INDEX IF NOT EXISTS idx_scans_status
|
||||
CREATE INDEX IF NOT EXISTS idx_scans_created_at
|
||||
ON scans(created_at DESC); -- For recent scans query
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_scans_scheduled_scan_id
|
||||
ON scans(scheduled_scan_id)
|
||||
WHERE scheduled_scan_id IS NOT NULL;
|
||||
|
||||
-- ============================================================================
|
||||
-- Table: routes
|
||||
-- Purpose: Store discovered routes with flight statistics
|
||||
@@ -244,7 +251,9 @@ ORDER BY created_at ASC;
|
||||
-- Initial Data: None (tables start empty)
|
||||
-- ============================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- Schema version tracking (for future migrations)
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS schema_version (
|
||||
version INTEGER PRIMARY KEY,
|
||||
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
@@ -254,6 +263,64 @@ CREATE TABLE IF NOT EXISTS schema_version (
|
||||
INSERT OR IGNORE INTO schema_version (version, description)
|
||||
VALUES (1, 'Initial web app schema with scans and routes tables');
|
||||
|
||||
-- ============================================================================
|
||||
-- Table: scheduled_scans
|
||||
-- Purpose: Define recurring scan schedules (daily / weekly / monthly)
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS scheduled_scans (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
-- Scan parameters (same as scans table)
|
||||
origin TEXT NOT NULL CHECK(length(origin) = 3),
|
||||
country TEXT NOT NULL CHECK(length(country) >= 2),
|
||||
window_months INTEGER NOT NULL DEFAULT 1
|
||||
CHECK(window_months >= 1 AND window_months <= 12),
|
||||
seat_class TEXT NOT NULL DEFAULT 'economy',
|
||||
adults INTEGER NOT NULL DEFAULT 1
|
||||
CHECK(adults > 0 AND adults <= 9),
|
||||
|
||||
-- Schedule definition
|
||||
frequency TEXT NOT NULL
|
||||
CHECK(frequency IN ('daily', 'weekly', 'monthly')),
|
||||
hour INTEGER NOT NULL DEFAULT 6
|
||||
CHECK(hour >= 0 AND hour <= 23),
|
||||
minute INTEGER NOT NULL DEFAULT 0
|
||||
CHECK(minute >= 0 AND minute <= 59),
|
||||
day_of_week INTEGER CHECK(day_of_week >= 0 AND day_of_week <= 6),
|
||||
day_of_month INTEGER CHECK(day_of_month >= 1 AND day_of_month <= 28),
|
||||
|
||||
-- State
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
label TEXT,
|
||||
last_run_at TIMESTAMP,
|
||||
next_run_at TIMESTAMP NOT NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Frequency-specific field requirements
|
||||
CHECK(
|
||||
(frequency = 'weekly' AND day_of_week IS NOT NULL) OR
|
||||
(frequency = 'monthly' AND day_of_month IS NOT NULL) OR
|
||||
(frequency = 'daily')
|
||||
)
|
||||
);
|
||||
|
||||
-- Fast lookup of due schedules (partial index on enabled rows only)
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_scans_next_run
|
||||
ON scheduled_scans(next_run_at)
|
||||
WHERE enabled = 1;
|
||||
|
||||
-- Auto-update updated_at on every PATCH
|
||||
CREATE TRIGGER IF NOT EXISTS update_scheduled_scans_timestamp
|
||||
AFTER UPDATE ON scheduled_scans
|
||||
FOR EACH ROW BEGIN
|
||||
UPDATE scheduled_scans SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
END;
|
||||
|
||||
INSERT OR IGNORE INTO schema_version (version, description)
|
||||
VALUES (2, 'Add scheduled_scans table');
|
||||
|
||||
-- ============================================================================
|
||||
-- Verification Queries (for testing)
|
||||
-- ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user