|
5 | 5 | import BarPlot from "../components/BarPlot.svelte"; |
6 | 6 | import Accordion from "../components/Accordion.svelte"; |
7 | 7 | import LoadingTrackio from "../components/LoadingTrackio.svelte"; |
8 | | - import { getLogs } from "../lib/api.js"; |
| 8 | + import { getLogsBatch } from "../lib/api.js"; |
| 9 | + import { |
| 10 | + getMetricsPollIntervalMs, |
| 11 | + isRateLimitCooldownActive, |
| 12 | + isTabHidden, |
| 13 | + } from "../lib/hostPolling.js"; |
9 | 14 | import { |
10 | 15 | processRunData, |
11 | 16 | getMetricColumns, |
|
27 | 32 | showHeaders = true, |
28 | 33 | appBootstrapReady = false, |
29 | 34 | plotOrder = [], |
| 35 | + realtimeEnabled = true, |
30 | 36 | // eslint-disable-next-line no-useless-assignment -- bindable out-prop to parent |
31 | 37 | metricColumns = $bindable([]), |
32 | 38 | } = $props(); |
|
168 | 174 | return; |
169 | 175 | } |
170 | 176 |
|
171 | | - let fetched = false; |
172 | | - for (const run of selectedRuns) { |
| 177 | + const needFetch = selectedRuns.filter((run) => { |
173 | 178 | const runKey = run.id ?? run.name; |
174 | | - if (!rawDataCache.has(runKey)) { |
175 | | - const logs = await getLogs(project, run); |
176 | | - rawDataCache.set(runKey, logs); |
177 | | - fetched = true; |
| 179 | + return !rawDataCache.has(runKey); |
| 180 | + }); |
| 181 | + let fetched = false; |
| 182 | + if (needFetch.length > 0) { |
| 183 | + try { |
| 184 | + const batch = await getLogsBatch(project, needFetch); |
| 185 | + for (const entry of batch) { |
| 186 | + const runKey = entry.run_id ?? entry.run; |
| 187 | + rawDataCache.set(runKey, entry.logs); |
| 188 | + fetched = true; |
| 189 | + } |
| 190 | + } catch (e) { |
| 191 | + console.error("Failed to load metric logs:", e); |
178 | 192 | } |
179 | 193 | } |
180 | 194 |
|
|
185 | 199 | } |
186 | 200 |
|
187 | 201 | async function refreshCachedRuns() { |
| 202 | + if (!realtimeEnabled) return; |
188 | 203 | if (!project || selectedRuns.length === 0) return; |
| 204 | + if (isTabHidden()) return; |
| 205 | + if (isRateLimitCooldownActive()) return; |
189 | 206 |
|
190 | | - let changed = false; |
191 | | - for (const run of selectedRuns) { |
192 | | - const logs = await getLogs(project, run); |
193 | | - const runKey = run.id ?? run.name; |
194 | | - const prev = rawDataCache.get(runKey); |
195 | | - if (!prev || logs.length !== prev.length) { |
196 | | - rawDataCache.set(runKey, logs); |
197 | | - changed = true; |
| 207 | + try { |
| 208 | + const batch = await getLogsBatch(project, selectedRuns); |
| 209 | + let changed = false; |
| 210 | + for (const entry of batch) { |
| 211 | + const runKey = entry.run_id ?? entry.run; |
| 212 | + const logs = entry.logs; |
| 213 | + const prev = rawDataCache.get(runKey); |
| 214 | + if (!prev || logs.length !== prev.length) { |
| 215 | + rawDataCache.set(runKey, logs); |
| 216 | + changed = true; |
| 217 | + } |
198 | 218 | } |
199 | | - } |
200 | | - if (changed) { |
201 | | - processFromCache(); |
| 219 | + if (changed) { |
| 220 | + processFromCache(); |
| 221 | + } |
| 222 | + } catch (e) { |
| 223 | + console.error("Failed to refresh metric logs:", e); |
202 | 224 | } |
203 | 225 | } |
204 | 226 |
|
|
230 | 252 | xLim = [lo, hi]; |
231 | 253 | } |
232 | 254 | } |
233 | | - refreshTimer = setInterval(refreshCachedRuns, 1000); |
| 255 | + refreshTimer = setInterval( |
| 256 | + refreshCachedRuns, |
| 257 | + getMetricsPollIntervalMs(), |
| 258 | + ); |
234 | 259 | return () => { |
235 | 260 | if (refreshTimer) clearInterval(refreshTimer); |
236 | 261 | }; |
|
0 commit comments