Implements comprehensive scheduled sync system using node-cron with full admin interface for configuration and monitoring. Features: - Configurable sync schedules with cron expressions - Enable/disable schedules without deletion - Manual trigger for testing - Status monitoring (last run, next run, success/failure) - Error tracking and display - Incremental and full sync support - Multiple concurrent schedules - Admin UI with schedule management Components: 1. Sync Scheduler Service (lib/services/sync-scheduler.ts) - node-cron integration for scheduling - Database-backed schedule configuration - Automatic initialization on startup - Prevents concurrent runs of same schedule - Calculates next run times - Tracks execution status and errors 2. Database Schema (sync_schedules table) - Schedule configuration storage - Execution history tracking - Last run status and errors - Next run calculation 3. API Endpoints - GET /api/sync/schedules - List all schedules - POST /api/sync/schedules - Create schedule - GET /api/sync/schedules/[id] - Get schedule - PATCH /api/sync/schedules/[id] - Update schedule - DELETE /api/sync/schedules/[id] - Delete schedule - POST /api/sync/schedules/[id]/trigger - Manual trigger 4. Admin UI (components/admin/SyncScheduler.tsx) - View all schedules with status - Create/edit/delete schedules - Enable/disable toggle - Manual trigger button - Cron expression presets - Real-time status updates - Error message display - Next run countdown 5. Default Schedules (created on first startup, disabled) - Daily Incremental: 2 AM daily (0 2 * * *) - Weekly Full: 3 AM Sunday (0 3 * * 0) Admin Interface: - New 'Schedules' tab in sync page - Schedule cards with status badges - Enable/disable with play/pause button - Manual trigger with clock button - Edit dialog with cron presets - Create dialog for new schedules - Real-time status (running, next run, last run) - Success/failure indicators - Error message alerts Cron Features: - Full cron expression support - Validation before saving - Common presets (daily, weekly, hourly) - Next run time calculation - Automatic schedule restart on config change Monitoring: - Last run timestamp - Next run countdown (e.g., 'in 2h 15m') - Success/failure status with icons - Error messages for failed syncs - Running indicator (animated badge) - Schedule validity check Dependencies: - node-cron: ^3.0.3 - @types/node-cron: ^3.0.11 UI Components: - Alert component added (components/ui/alert.tsx) - Integrated into sync page tabs - Responsive design Documentation: - Complete guide (docs/SCHEDULED_SYNCS.md) - Cron expression reference - Best practices - Troubleshooting guide - API reference - Database schema Use Cases: 1. Daily incremental sync for recent changes 2. Weekly full sync for data integrity 3. Custom schedules for specific needs 4. Off-peak hour automation 5. Backup for webhook failures Benefits: - No manual intervention required - Consistent data freshness - Flexible scheduling - Easy monitoring - Error tracking - Manual override available Next Steps: 1. Restart application to initialize scheduler 2. Navigate to Admin → Sync → Schedules tab 3. Enable default schedules or create custom ones 4. Monitor first runs for success 5. Adjust schedules as needed Files Added/Modified: - lib/services/sync-scheduler.ts (new) - app/api/sync/schedules/route.ts (new) - app/api/sync/schedules/[id]/route.ts (new) - app/api/sync/schedules/[id]/trigger/route.ts (new) - components/admin/SyncScheduler.tsx (new) - components/ui/alert.tsx (new) - app/admin/sync/page.tsx (modified - added Schedules tab) - docs/SCHEDULED_SYNCS.md (new) - package.json (node-cron added)
79 lines
2.1 KiB
TypeScript
79 lines
2.1 KiB
TypeScript
/**
|
|
* Sync Schedules API
|
|
* Manage scheduled automatic syncs
|
|
*/
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
import { syncScheduler } from '@/lib/services/sync-scheduler';
|
|
|
|
/**
|
|
* GET /api/sync/schedules
|
|
* Get all sync schedules
|
|
*/
|
|
export async function GET() {
|
|
try {
|
|
const schedules = await syncScheduler.getSchedules();
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
schedules,
|
|
});
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
console.error('[SCHEDULES API] Error fetching schedules:', errorMessage);
|
|
|
|
return NextResponse.json(
|
|
{ error: 'Failed to fetch schedules', details: errorMessage },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/sync/schedules
|
|
* Create a new schedule
|
|
*/
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json();
|
|
|
|
// Validate required fields
|
|
if (!body.id || !body.name || !body.cron_expression || !body.sync_type) {
|
|
return NextResponse.json(
|
|
{ error: 'Missing required fields: id, name, cron_expression, sync_type' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Validate sync_type
|
|
if (!['incremental', 'full'].includes(body.sync_type)) {
|
|
return NextResponse.json(
|
|
{ error: 'Invalid sync_type. Must be "incremental" or "full"' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const schedule = await syncScheduler.createSchedule({
|
|
id: body.id,
|
|
name: body.name,
|
|
description: body.description || '',
|
|
cron_expression: body.cron_expression,
|
|
sync_type: body.sync_type,
|
|
years_back: body.years_back,
|
|
is_enabled: body.is_enabled ?? false,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
schedule,
|
|
});
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
console.error('[SCHEDULES API] Error creating schedule:', errorMessage);
|
|
|
|
return NextResponse.json(
|
|
{ error: 'Failed to create schedule', details: errorMessage },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|