- Fix EventSource is not defined error in queue dashboard - Add browser guards for all EventSource usage - Replace static constants (EventSource.OPEN/CLOSED) with numeric values - Fix setInterval SSR violation in LLM health indicator - Replace $effect anti-pattern with onMount in share page - Add comprehensive SvelteKit SSR best practices documentation - Add SSR audit and testing verification All changes follow SvelteKit best practices and are verified against official documentation. Production build succeeds with no SSR errors. Closes: FixEventSourceSSR See: docs/outcomes/FixEventSourceSSR.md
63 lines
1.6 KiB
Svelte
63 lines
1.6 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
|
|
interface HealthState {
|
|
status: 'checking' | 'healthy' | 'unhealthy' | 'error';
|
|
message: string;
|
|
lastChecked: Date | null;
|
|
}
|
|
|
|
let { pollInterval = 30000 } = $props<{
|
|
pollInterval?: number;
|
|
}>();
|
|
|
|
let health = $state<HealthState>({
|
|
status: 'checking',
|
|
message: '',
|
|
lastChecked: null
|
|
});
|
|
|
|
async function checkHealth() {
|
|
try {
|
|
const res = await fetch('/api/llm-health');
|
|
const data = await res.json();
|
|
health = {
|
|
status: data.status === 'healthy' ? 'healthy' : 'unhealthy',
|
|
message: data.message,
|
|
lastChecked: new Date()
|
|
};
|
|
} catch (e) {
|
|
health = {
|
|
status: 'error',
|
|
message: e instanceof Error ? e.message : 'Network error',
|
|
lastChecked: new Date()
|
|
};
|
|
}
|
|
}
|
|
|
|
// Use onMount instead of $effect for timer-based side effects
|
|
// onMount only runs in browser, no SSR guard needed
|
|
onMount(() => {
|
|
checkHealth(); // Initial check
|
|
const interval = setInterval(checkHealth, pollInterval);
|
|
return () => clearInterval(interval);
|
|
});
|
|
</script>
|
|
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<div class="flex items-center gap-1">
|
|
{#if health.status === 'checking'}
|
|
🟡 <span>Checking LLM...</span>
|
|
{:else if health.status === 'healthy'}
|
|
🟢 <span class="text-green-600">LLM Ready</span>
|
|
{:else if health.status === 'unhealthy'}
|
|
🔴 <span class="text-red-600">LLM Unavailable</span>
|
|
{:else}
|
|
🔴 <span class="text-red-600">LLM Error</span>
|
|
{/if}
|
|
</div>
|
|
<div class="text-xs text-gray-500" title={health.message}>
|
|
{health.lastChecked ? `Last: ${health.lastChecked.toLocaleTimeString()}` : ''}
|
|
</div>
|
|
</div>
|