5.3 KiB
5.3 KiB
Dashboard Metrics Auto-Sync Implementation
Overview
Dashboard metrics (Nøgletal) er nu konfigureret til at opdateres automatisk hver time gennem det eksisterende sync job.
Architecture
1. Hourly Sync Job (OrdrestyringSyncService)
- Kører hver time automatisk
- Synkroniserer: Cases, Users, Hours, Materials, Debtors, Dashboard Metrics
- Lokalisering:
/backend/src/services/ordrestyringSyncService.js
2. Dashboard Metrics Cache
- Database Table:
ordrestyring_local.dashboard_cache - Cache Key:
noegletal_dashboard_metrics - TTL (Time-to-Live): 1 time (selvfølgende med sync interval)
- Data Size: ~417 bytes
CREATE TABLE dashboard_cache (
id INT AUTO_INCREMENT PRIMARY KEY,
cache_key VARCHAR(255) UNIQUE NOT NULL,
cache_data LONGTEXT NOT NULL,
expires_at DATETIME NOT NULL,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_cache_key (cache_key),
INDEX idx_expires_at (expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. API Endpoint Optimization
- Route:
GET /api/dashboard/noegletal - Lokalisering:
/backend/unified-server.js(lines 1366-1442) - Logik:
- Check cache først (hvis valid - return immediately)
- Hvis cache invalid/expired → fetch fresh data fra API
- Return formatted response
Data Flow
Every Hour:
Ordrestyring GraphQL API
↓
ordrestyringService.calculateDashboardMetrics()
↓
ordrestyringSyncService.syncDashboardMetrics()
↓
dashboard_cache table (1-hour TTL)
On Frontend Request:
GET /api/dashboard/noegletal
↓
Check dashboard_cache first ⚡ (instant)
↓
If expired → fetch from API (1.7 sec)
↓
Return to dashboard
Current Metrics Cached
{
"pendingOffers": 21,
"currentMonthOffers": 11,
"currentMonthValue": 785841400,
"yearToDateOffers": 200,
"yearToDateValue": 4140316489,
"statusDistribution": {
"Nyt tilbud": 1,
"Sendt": 20,
"Konverteret": 59,
"Aflyst": 115,
"Åben": 3,
"Opfølgning udført": 2
},
"conversionMetrics": {
"pending": 26,
"converted": 59,
"rejected": 115
},
"conversionPercentages": {
"pending": 13,
"converted": 30,
"rejected": 57
},
"totalOffers": 200
}
Performance Impact
| Scenario | Response Time | Source |
|---|---|---|
| Cache Hit | ~10-50ms | Database cache lookup |
| Cache Miss | ~1700ms | Fresh GraphQL query |
| Hourly Sync | ~1600ms | Scheduled background job |
Implementation Details
Added to ordrestyringSyncService.js
// Lines 139-141: Added to performSync()
this.syncDashboardMetrics() // Cache dashboard metrics hourly
// Lines 583-617: New method
async syncDashboardMetrics() {
// Queries GraphQL API for metrics
// Caches result in database_cache table
// 1-hour expiration
}
Updated /api/dashboard/noegletal endpoint
// Lines 1366-1442
- Try to get cached metrics first
- If cache valid (< 1 hour) → return immediately
- If expired → fetch fresh from GraphQL API
- Always return latest available data
Manual Testing
Trigger sync manually:
node -e "
const OrdrestyringSyncService = require('./backend/src/services/ordrestyringSyncService');
const service = new OrdrestyringSyncService();
service.syncDashboardMetrics().then(result => {
console.log('Sync result:', result);
process.exit(0);
});
"
Verify cache:
mysql -h 127.0.0.1 -u tilbudgivern_service -p"${DB_PASSWORD}" ordrestyring_local \
-e "SELECT cache_key, updated_at, LENGTH(cache_data) as size FROM dashboard_cache;"
Test endpoint:
curl http://localhost:4031/api/dashboard/noegletal | jq '.data'
Monitoring
- Sync Job Logs: Check PM2 logs for
syncDashboardMetricsentries - Cache Status: Query
dashboard_cachetable forexpires_atstatus - Performance: Check response times in browser DevTools
Future Enhancements
- Adaptive Caching: Adjust TTL based on data change frequency
- Metrics Versioning: Track historical metrics trends
- Dashboard Notifications: Alert on significant changes (e.g., >10 new offers)
- Cache Warming: Pre-warm cache 5 minutes before expiry
- Multi-Tenant Support: Cache per-client if needed
Troubleshooting
Dashboard shows old data?
- Check cache expiry:
SELECT expires_at FROM dashboard_cache WHERE cache_key = 'noegletal_dashboard_metrics' - If expired, sync job will refresh on next hour
- Manual sync: Use command above
Cache not updating?
- Verify sync service is running:
pm2 list | grep tilbudgivern - Check logs:
pm2 logs tilbudgivern-unified --lines 50 - Verify database connection:
mysql ordrestyring_local -e "SHOW TABLES LIKE 'dashboard_cache';"
Slow responses even with cache?
- Check database load:
SHOW PROCESSLIST; - Verify GraphQL API status: Test endpoint directly
- Check network latency to API server
Related Files
- Backend Service:
/backend/src/services/ordrestyringSyncService.js - API Endpoint:
/backend/unified-server.js(lines 1366-1442) - Frontend Component:
/frontend/src/components/NoeglatalDashboard.js - Database:
ordrestyring_local.dashboard_cachetable
Deployment Status
✅ DEPLOYED - November 16, 2025, 20:09 UTC
- Sync service: Running (every hour)
- Cache table: Created and functional
- API endpoint: Updated with cache logic
- PM2 restart: #73