wulf-pulse/app/admin/sync/page.tsx
root f117210c9d feat: add scheduled sync system with admin UI
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)
2026-01-26 10:24:58 -05:00

118 lines
3.9 KiB
TypeScript

/**
* Admin Sync Page
* Main page for controlling and monitoring Autotask PostgreSQL sync operations
*/
'use client';
import { useState, useEffect } from 'react';
import SyncControlPanel from '@/components/admin/SyncControlPanel';
import SyncDashboard from '@/components/admin/SyncDashboard';
import SyncHistoryTable from '@/components/admin/SyncHistoryTable';
import SyncScheduler from '@/components/admin/SyncScheduler';
import { EntityType } from '@/lib/types/sync';
import { Button } from '@/components/ui/button';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { ArrowLeft, Home, Activity, History, Calendar } from 'lucide-react';
import Link from 'next/link';
export default function AdminSyncPage() {
const [selectedEntities, setSelectedEntities] = useState<EntityType[]>([]);
const [isSyncing, setIsSyncing] = useState(false);
const [refreshKey, setRefreshKey] = useState(0);
// Auto-refresh during sync and check if sync completed
useEffect(() => {
if (isSyncing) {
const interval = setInterval(async () => {
setRefreshKey(prev => prev + 1);
// Check if sync is still in progress
try {
const response = await fetch('/api/sync/status');
if (response.ok) {
const data = await response.json();
// If no sync in progress, mark as complete
if (!data.inProgress) {
setIsSyncing(false);
}
}
} catch (error) {
console.error('Failed to check sync status:', error);
}
}, 5000); // Refresh every 5 seconds
return () => clearInterval(interval);
}
}, [isSyncing]);
const handleSyncStart = () => {
setIsSyncing(true);
};
const handleSyncComplete = () => {
setIsSyncing(false);
setRefreshKey(prev => prev + 1);
};
return (
<div className="container mx-auto py-4 md:py-8 px-4 space-y-6 md:space-y-8">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<Link href="/">
<Button variant="outline" size="sm" className="gap-2">
<ArrowLeft className="w-4 h-4" />
<Home className="w-4 h-4" />
<span className="hidden sm:inline">Back to Dashboard</span>
</Button>
</Link>
<div>
<h1 className="text-2xl md:text-3xl font-bold">Autotask Sync</h1>
<p className="text-sm md:text-base text-muted-foreground mt-1">
Sync Autotask data to PostgreSQL database
</p>
</div>
</div>
</div>
{/* Sync Control Panel */}
<SyncControlPanel
selectedEntities={selectedEntities}
onSelectedEntitiesChange={setSelectedEntities}
onSyncStart={handleSyncStart}
onSyncComplete={handleSyncComplete}
isSyncing={isSyncing}
/>
{/* Tabs for Sync Status, History, and Schedules */}
<Tabs defaultValue="status" className="w-full">
<TabsList className="grid w-full max-w-2xl grid-cols-3">
<TabsTrigger value="status" className="gap-2">
<Activity className="h-4 w-4" />
Sync Status
</TabsTrigger>
<TabsTrigger value="history" className="gap-2">
<History className="h-4 w-4" />
Sync History
</TabsTrigger>
<TabsTrigger value="schedules" className="gap-2">
<Calendar className="h-4 w-4" />
Schedules
</TabsTrigger>
</TabsList>
<TabsContent value="status" className="mt-6">
<SyncDashboard refreshKey={refreshKey} />
</TabsContent>
<TabsContent value="history" className="mt-6">
<SyncHistoryTable refreshKey={refreshKey} />
</TabsContent>
<TabsContent value="schedules" className="mt-6">
<SyncScheduler />
</TabsContent>
</Tabs>
</div>
);
}