fix: resolve critical app functionality issues
Complete implementation of fixes for queue processing, SSE connection display, service worker installation, and failing tests. Key Changes: - Fix queue processor startup with proper import and subscription mechanism - Implement centralized API error handling middleware for proper HTTP status codes - Enhance service worker configuration for PWA compliance and reliability - Fix SSE connection display with reactive state management - Add comprehensive test coverage and health check endpoints Results: - All 169 tests now passing (previously 16 failing) - Queue items process immediately from pending to success/error states - Real-time SSE connection status with auto-reconnection logic - Proper PWA functionality with working service worker registration - API endpoints return correct HTTP status codes (400/404/409) instead of 500 errors This resolves the critical issues preventing core app functionality and enables proper production deployment.
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
let error = $state<string | null>(null);
|
||||
let filter = $state<string>('all');
|
||||
let eventSource = $state<EventSource | null>(null);
|
||||
let connectionStatus = $state<'connecting' | 'connected' | 'disconnected'>('disconnected');
|
||||
let lastPing = $state<string | null>(null);
|
||||
|
||||
// Get highlighted item ID from URL params (when redirected from Share page)
|
||||
let highlightId = $derived($page.url.searchParams.get('highlight'));
|
||||
@@ -25,7 +27,8 @@
|
||||
]);
|
||||
|
||||
// Filter items based on selected filter
|
||||
let filteredItems = $derived(() => {
|
||||
// Using $derived.by to execute the function and derive the result array
|
||||
let filteredItems = $derived.by(() => {
|
||||
if (filter === 'all') return items;
|
||||
if (filter === 'error') return items.filter(item => item.status === 'error' || item.status === 'unhealthy');
|
||||
return items.filter(item => item.status === filter);
|
||||
@@ -40,7 +43,9 @@
|
||||
|
||||
onDestroy(() => {
|
||||
if (eventSource) {
|
||||
console.log('[SSE] Closing connection on component destroy');
|
||||
eventSource.close();
|
||||
connectionStatus = 'disconnected';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -65,14 +70,26 @@
|
||||
}
|
||||
|
||||
function startSSEConnection() {
|
||||
if (!browser) return; // Guard: EventSource is browser-only API
|
||||
if (!browser) {
|
||||
console.error('Cannot start SSE connection on server side');
|
||||
return; // Guard: EventSource is browser-only API
|
||||
}
|
||||
|
||||
connectionStatus = 'connecting';
|
||||
console.log('[SSE] Connecting to queue stream...');
|
||||
|
||||
try {
|
||||
eventSource = new EventSource('/api/queue/stream');
|
||||
|
||||
eventSource.addEventListener('open', () => {
|
||||
console.log('[SSE] Connection opened');
|
||||
connectionStatus = 'connected';
|
||||
});
|
||||
|
||||
eventSource.addEventListener('connection', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('Queue stream connected:', data.message);
|
||||
console.log('[SSE] Connection confirmed:', data.message);
|
||||
connectionStatus = 'connected';
|
||||
});
|
||||
|
||||
eventSource.addEventListener('queue-update', (event) => {
|
||||
@@ -81,24 +98,29 @@
|
||||
});
|
||||
|
||||
eventSource.addEventListener('error', (event) => {
|
||||
console.error('SSE connection error:', event);
|
||||
console.error('[SSE] Connection error:', event);
|
||||
connectionStatus = 'disconnected';
|
||||
|
||||
// Attempt to reconnect after 5 seconds
|
||||
setTimeout(() => {
|
||||
// EventSource.CLOSED = 2 (use numeric constant for SSR safety)
|
||||
if (eventSource?.readyState === 2) {
|
||||
console.log('[SSE] Attempting reconnection...');
|
||||
startSSEConnection();
|
||||
}
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
eventSource.addEventListener('ping', (event) => {
|
||||
// Keep-alive ping, just log for debugging
|
||||
// Keep-alive ping, update last ping timestamp
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('SSE ping received at:', data.timestamp);
|
||||
lastPing = data.timestamp;
|
||||
console.log('[SSE] Keep-alive ping received at:', data.timestamp);
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.error('Failed to start SSE connection:', e);
|
||||
console.error('[SSE] Failed to start SSE connection:', e);
|
||||
connectionStatus = 'disconnected';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,11 +324,21 @@
|
||||
<!-- Connection Status -->
|
||||
<div class="fixed bottom-4 right-4">
|
||||
<div class="flex items-center space-x-2 px-3 py-2 bg-white border rounded-lg shadow-sm text-sm">
|
||||
<!-- EventSource.OPEN = 1 (use numeric constant for SSR safety) -->
|
||||
<div class="w-2 h-2 rounded-full {eventSource?.readyState === 1 ? 'bg-green-400' : 'bg-red-400'}"></div>
|
||||
<div class="w-2 h-2 rounded-full {
|
||||
connectionStatus === 'connected' ? 'bg-green-400' :
|
||||
connectionStatus === 'connecting' ? 'bg-yellow-400' :
|
||||
'bg-red-400'
|
||||
}"></div>
|
||||
<span class="text-gray-600">
|
||||
{eventSource?.readyState === 1 ? 'Live updates' : 'Disconnected'}
|
||||
{connectionStatus === 'connected' ? 'Live updates' :
|
||||
connectionStatus === 'connecting' ? 'Connecting...' :
|
||||
'Disconnected'}
|
||||
</span>
|
||||
{#if lastPing}
|
||||
<span class="text-xs text-gray-400">
|
||||
({new Date(lastPing).toLocaleTimeString()})
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user