- Add admin dashboard with sync controls and data browser - Implement RMM, Auvik, and Addigy organization mappings - Add chunked ticket sync with progress tracking - Implement entity sync service with rate limiting - Add analytics engine and performance optimizer - Create data browser for all PSA entities - Add navigation components and UI improvements - Implement background processing and sync services - Add comprehensive documentation and migration scripts - Update configuration items with multi-system support - Enhance contact management and purchase history - Add issue type assignment and LLM analyzer - Improve error handling and logging utilities
8.8 KiB
8.8 KiB
Sync Progress Tracking Implementation
Overview
Implemented real-time progress tracking for entity sync operations with persistent state that allows users to navigate away and return to see accurate progress.
Problem Solved
- 100-Page Limit Removed - Previously, syncs were capped at 50,000 records (100 pages × 500 records/page)
- No Progress Visibility - Users couldn't see sync progress or know when operations would complete
- Lost Progress on Navigation - Navigating away from the sync page lost all progress information
Solution Architecture
Backend Components
1. SyncProgressTracker (lib/services/sync-progress-tracker.ts)
Global singleton service that tracks sync progress in memory.
Features:
- Tracks multiple concurrent syncs
- Stores progress state with phases (fetching, mapping, upserting, deleting)
- Persists across API calls (in-memory during app lifetime)
- Auto-cleanup of old sync records (keeps last 10 per entity)
Key Methods:
startSync(syncId, entityType) // Initialize tracking
updateProgress(syncId, updates) // Update progress
completeSync(syncId, totalRecords) // Mark complete
failSync(syncId, error) // Mark failed
getProgress(syncId) // Get specific sync
getLatestSync(entityType) // Get latest for entity
2. Entity Sync Service Updates (lib/services/entity-sync.ts)
Integrated progress tracking at key phases:
async syncEntity(entity, isIncremental, yearsBack, syncId?) {
const trackingId = syncId || `${entity}_${Date.now()}`;
syncProgressTracker.startSync(trackingId, entity);
// Phase 1: Fetching
syncProgressTracker.updateProgress(trackingId, { phase: 'fetching' });
// Phase 2: Mapping
syncProgressTracker.updateProgress(trackingId, {
totalRecords: count,
phase: 'mapping'
});
// Phase 3: Upserting
syncProgressTracker.updateProgress(trackingId, { phase: 'upserting' });
// Phase 4: Deleting (full sync only)
syncProgressTracker.updateProgress(trackingId, { phase: 'deleting' });
// Complete
syncProgressTracker.completeSync(trackingId, totalRecords);
}
3. Progress API Endpoint (app/api/sync/progress/route.ts)
RESTful endpoint for polling progress:
# Get specific sync
GET /api/sync/progress?syncId=time_entries_1730000000
# Get latest sync for entity
GET /api/sync/progress?entityType=time_entries
# Get all active syncs
GET /api/sync/progress
Response:
{
"progress": {
"syncId": "time_entries_1730000000",
"entityType": "time_entries",
"status": "running",
"currentPage": 0,
"totalRecords": 75000,
"startTime": 1730000000000,
"phase": "upserting"
}
}
Frontend Components
1. EntitySyncProgress Component (components/admin/EntitySyncProgress.tsx)
Reusable progress display following shadcn/ui best practices.
Features:
- ✅ Animated progress bar (smooth transitions)
- ✅ Phase indicators with icons
- ✅ Real-time polling (every 2 seconds)
- ✅ Persistent across navigation (polls by syncId or entityType)
- ✅ Dark mode support
- ✅ Accessibility (ARIA labels)
- ✅ Auto-cleanup on completion/failure
Usage:
<EntitySyncProgress
entityType="time_entries"
syncId="time_entries_1730000000"
onComplete={() => console.log('Sync done!')}
onError={(error) => console.error(error)}
/>
Visual States:
- Running - Blue badge, spinning loader, animated progress
- Completed - Green badge, checkmark, success message
- Failed - Red badge, X icon, error message
Progress Calculation:
fetching → 25%
mapping → 50%
upserting → 75%
deleting → 90%
completed → 100%
2. SyncControlPanel Integration (components/admin/SyncControlPanel.tsx)
Integrated progress tracking for entity-specific syncs.
Auto-tracking:
- Detects single-entity syncs
- Generates unique syncId
- Shows progress component
- Auto-hides on completion
Multi-entity syncs:
- Still supported
- No individual progress (would need separate implementation)
shadcn/ui Best Practices Applied
1. Component Composition
<Card>
<CardHeader>
<CardTitle>Entity Sync</CardTitle>
<CardDescription>Phase description</CardDescription>
</CardHeader>
<CardContent>
<Progress value={animatedProgress} />
</CardContent>
</Card>
2. Smooth Animations
// Gradual progress updates
const step = (targetProgress - animatedProgress) / 10;
const interval = setInterval(() => {
setAnimatedProgress(prev => prev + step);
}, 50);
3. Dark Mode Support
className="dark:bg-gray-700 dark:border-gray-700"
4. Accessibility
<Progress
value={progress}
aria-label={`Sync progress: ${Math.round(progress)}%`}
/>
5. Loading States
{status === 'running' && (
<Loader2 className="h-5 w-5 animate-spin text-blue-500" />
)}
6. Responsive Design
<div className="grid grid-cols-2 gap-4">
{/* Stats */}
</div>
Usage Examples
1. Sync Time Entries with Progress
// From UI
1. Navigate to /admin/sync
2. Select "Time Entries" entity
3. Click "Sync Selected Entities"
4. Watch real-time progress
5. Navigate away (progress persists)
6. Return to see updated progress
2. Programmatic Sync with Tracking
import { syncProgressTracker } from '@/lib/services/sync-progress-tracker';
const syncId = `time_entries_${Date.now()}`;
// Start sync with tracking
await entitySyncService.syncEntity(
EntityType.TIME_ENTRIES,
false,
1,
syncId
);
// Poll progress
const progress = syncProgressTracker.getProgress(syncId);
console.log(progress.phase, progress.totalRecords);
3. Monitor from API
# Start sync
curl -X POST http://localhost:3000/api/sync/entity \
-H "Content-Type: application/json" \
-d '{"entities": ["time_entries"], "yearsBack": 1}'
# Poll progress
while true; do
curl http://localhost:3000/api/sync/progress?entityType=time_entries
sleep 2
done
Key Improvements
Before
- ❌ 50,000 record limit
- ❌ No progress visibility
- ❌ Lost progress on navigation
- ❌ No phase information
- ❌ No error details
After
- ✅ Unlimited records (removed page limit)
- ✅ Real-time progress tracking
- ✅ Persistent across navigation
- ✅ Detailed phase indicators
- ✅ Comprehensive error reporting
- ✅ Animated progress bar
- ✅ Dark mode support
- ✅ Accessibility compliant
Performance Considerations
Polling Frequency
- 2 seconds - Good balance between responsiveness and server load
- Stops polling when sync completes/fails
- Cleanup interval prevents memory leaks
Memory Management
- Keeps last 10 syncs per entity type
- Auto-cleanup on completion
- In-memory storage (resets on app restart)
Future Enhancements
- WebSocket support - Real-time push instead of polling
- Persistent storage - Redis/database for cross-instance tracking
- Page-level progress - Track individual API pages during fetch
- Estimated time remaining - Calculate based on current rate
Testing
Manual Test
# 1. Start a time entries sync (1 year)
# 2. Observe progress phases:
# - Fetching (0-25%)
# - Mapping (25-50%)
# - Upserting (50-75%)
# - Deleting (75-90%)
# - Completed (100%)
# 3. Navigate to another page
# 4. Return to sync page
# 5. Verify progress is still visible and accurate
API Test
# Terminal 1: Start sync
curl -X POST http://localhost:3000/api/sync/entity \
-H "Content-Type: application/json" \
-d '{"entities": ["time_entries"], "yearsBack": 1}'
# Terminal 2: Monitor progress
watch -n 2 'curl -s http://localhost:3000/api/sync/progress?entityType=time_entries | jq'
Files Modified
Backend
/lib/services/autotask-client.ts- Removed 100-page limit/lib/services/entity-sync.ts- Added progress tracking/lib/services/sync-progress-tracker.ts- New progress tracker service/app/api/sync/progress/route.ts- New progress API endpoint
Frontend
/components/admin/EntitySyncProgress.tsx- New progress component/components/admin/SyncControlPanel.tsx- Integrated progress tracking
Documentation
/docs/SYNC_PROGRESS_TRACKING.md- This file/docs/TIME_ENTRY_FIELD_MAPPING.md- Field mapping analysis/docs/TIME_ENTRIES_SORTING_FIX.md- Sorting implementation
Conclusion
The sync progress tracking system provides:
- Visibility - Users see exactly what's happening
- Persistence - Progress survives navigation
- Scalability - No record limits
- UX - Beautiful, accessible, responsive UI
- Reliability - Error handling and recovery
This implementation follows shadcn/ui best practices and provides a production-ready solution for long-running sync operations.