Skip to content

Commit d645fc1

Browse files
committed
fix(ui): reduce SSE reconnect churn and polling overhead on navigation
1 parent b8cf1b6 commit d645fc1

File tree

6 files changed

+26
-9
lines changed

6 files changed

+26
-9
lines changed

admin/config/transmit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { defineConfig } from '@adonisjs/transmit'
33
import { redis } from '@adonisjs/transmit/transports'
44

55
export default defineConfig({
6-
pingInterval: false,
6+
pingInterval: '30s',
77
transport: {
88
driver: redis({
99
host: env.get('REDIS_HOST'),

admin/inertia/app/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ createInertiaApp({
4040
createRoot(el).render(
4141
<QueryClientProvider client={queryClient}>
4242
<ThemeProvider>
43-
<TransmitProvider baseUrl={window.location.origin} enableLogging={true}>
43+
<TransmitProvider baseUrl={window.location.origin} enableLogging={environment === 'development'}>
4444
<NotificationsProvider>
4545
<ModalsProvider>
4646
<App {...props} />

admin/inertia/hooks/useDownloads.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ const useDownloads = (props: useDownloadsProps) => {
1717
const queryData = useQuery({
1818
queryKey: queryKey,
1919
queryFn: () => api.listDownloadJobs(props.filetype),
20-
refetchInterval: 2000, // Refetch every 2 seconds to get updated progress
20+
refetchInterval: (query) => {
21+
const data = query.state.data
22+
// Only poll when there are active downloads; otherwise use a slower interval
23+
return data && data.length > 0 ? 2000 : 30000
24+
},
2125
enabled: props.enabled ?? true,
2226
})
2327

admin/inertia/hooks/useEmbedJobs.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ const useEmbedJobs = (props: { enabled?: boolean } = {}) => {
77
const queryData = useQuery({
88
queryKey: ['embed-jobs'],
99
queryFn: () => api.getActiveEmbedJobs().then((data) => data ?? []),
10-
refetchInterval: 2000,
10+
refetchInterval: (query) => {
11+
const data = query.state.data
12+
// Only poll when there are active jobs; otherwise use a slower interval
13+
return data && data.length > 0 ? 2000 : 30000
14+
},
1115
enabled: props.enabled ?? true,
1216
})
1317

admin/inertia/hooks/useOllamaModelDownloads.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect, useRef, useState } from 'react'
22
import { useTransmit } from 'react-adonis-transmit'
33

44
export type OllamaModelDownload = {
@@ -10,6 +10,7 @@ export type OllamaModelDownload = {
1010
export default function useOllamaModelDownloads() {
1111
const { subscribe } = useTransmit()
1212
const [downloads, setDownloads] = useState<Map<string, OllamaModelDownload>>(new Map())
13+
const timeoutsRef = useRef<Set<ReturnType<typeof setTimeout>>>(new Set())
1314

1415
useEffect(() => {
1516
const unsubscribe = subscribe('ollama-model-download', (data: OllamaModelDownload) => {
@@ -19,13 +20,15 @@ export default function useOllamaModelDownloads() {
1920
if (data.percent >= 100) {
2021
// If download is complete, keep it for a short time before removing to allow UI to show 100% progress
2122
updated.set(data.model, data)
22-
setTimeout(() => {
23+
const timeout = setTimeout(() => {
24+
timeoutsRef.current.delete(timeout)
2325
setDownloads((current) => {
2426
const next = new Map(current)
2527
next.delete(data.model)
2628
return next
2729
})
2830
}, 2000)
31+
timeoutsRef.current.add(timeout)
2932
} else {
3033
updated.set(data.model, data)
3134
}
@@ -36,7 +39,10 @@ export default function useOllamaModelDownloads() {
3639

3740
return () => {
3841
unsubscribe()
42+
timeoutsRef.current.forEach(clearTimeout)
43+
timeoutsRef.current.clear()
3944
}
45+
// eslint-disable-next-line react-hooks/exhaustive-deps
4046
}, [subscribe])
4147

4248
const downloadsArray = Array.from(downloads.values())

admin/inertia/pages/settings/benchmark.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Head, Link, usePage } from '@inertiajs/react'
2-
import { useState, useEffect } from 'react'
2+
import { useState, useEffect, useRef } from 'react'
33
import SettingsLayout from '~/layouts/SettingsLayout'
44
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
55
import CircularGauge from '~/components/systeminfo/CircularGauge'
@@ -40,6 +40,7 @@ export default function BenchmarkPage(props: {
4040
const aiInstalled = useServiceInstalledStatus(SERVICE_NAMES.OLLAMA)
4141
const [progress, setProgress] = useState<BenchmarkProgressWithID | null>(null)
4242
const [isRunning, setIsRunning] = useState(props.benchmark.status !== 'idle')
43+
const refetchLatestRef = useRef(refetchLatest)
4344
const [showDetails, setShowDetails] = useState(false)
4445
const [showHistory, setShowHistory] = useState(false)
4546
const [showAIRequiredAlert, setShowAIRequiredAlert] = useState(false)
@@ -60,6 +61,7 @@ export default function BenchmarkPage(props: {
6061
},
6162
initialData: props.benchmark.latestResult,
6263
})
64+
refetchLatestRef.current = refetchLatest
6365

6466
// Fetch all benchmark results for history
6567
const { data: benchmarkHistory } = useQuery({
@@ -306,14 +308,15 @@ export default function BenchmarkPage(props: {
306308
setProgress(data)
307309
if (data.status === 'completed' || data.status === 'error') {
308310
setIsRunning(false)
309-
refetchLatest()
311+
refetchLatestRef.current()
310312
}
311313
})
312314

313315
return () => {
314316
unsubscribe()
315317
}
316-
}, [subscribe, refetchLatest])
318+
// eslint-disable-next-line react-hooks/exhaustive-deps
319+
}, [subscribe])
317320

318321
const formatBytes = (bytes: number) => {
319322
const gb = bytes / (1024 * 1024 * 1024)

0 commit comments

Comments
 (0)