Stop loading the whole version twice on every page load
The version re-validation effect could not tell "the versions fetch has not landed yet" from "this source has no versions", because both look like an empty array. So a versionId restored from localStorage was cleared on the first render and set straight back when the fetch returned: 29 -> '' -> 29. Forecast's load effect is keyed on [versionId, sourceId], so that round trip ran initViewer twice. Two /agg requests, two full aggregations in Postgres, two Arrow payloads -- on version 29 that is the 285k-row aggregate computed twice at ~17s each, which is most of the "it hangs before it displays" and the Postgres process sitting at the top of htop. sourcesLoaded already guarded the identical effect for sources; versions just never got the same treatment. Cleared when the source changes, since the list belongs to the previous source until the new fetch lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7b90b0c07d
commit
0459fa137d
@ -13,6 +13,7 @@ export default function App() {
|
|||||||
const [sourcesLoaded, setSourcesLoaded] = useState(false)
|
const [sourcesLoaded, setSourcesLoaded] = useState(false)
|
||||||
const [sourceId, setSourceId] = useState(() => localStorage.getItem('pf_sourceId') || '')
|
const [sourceId, setSourceId] = useState(() => localStorage.getItem('pf_sourceId') || '')
|
||||||
const [versions, setVersions] = useState([])
|
const [versions, setVersions] = useState([])
|
||||||
|
const [versionsLoaded, setVersionsLoaded] = useState(false)
|
||||||
const [versionId, setVersionId] = useState(() => localStorage.getItem('pf_versionId') || '')
|
const [versionId, setVersionId] = useState(() => localStorage.getItem('pf_versionId') || '')
|
||||||
|
|
||||||
useEffect(() => { localStorage.setItem('pf_view', view) }, [view])
|
useEffect(() => { localStorage.setItem('pf_view', view) }, [view])
|
||||||
@ -30,10 +31,11 @@ export default function App() {
|
|||||||
|
|
||||||
const refreshVersions = useCallback(async (sid) => {
|
const refreshVersions = useCallback(async (sid) => {
|
||||||
const id = sid ?? sourceId
|
const id = sid ?? sourceId
|
||||||
if (!id) { setVersions([]); return [] }
|
if (!id) { setVersions([]); setVersionsLoaded(true); return [] }
|
||||||
const data = await fetch(`/api/sources/${id}/versions`).then(r => r.json())
|
const data = await fetch(`/api/sources/${id}/versions`).then(r => r.json())
|
||||||
const list = Array.isArray(data) ? data : []
|
const list = Array.isArray(data) ? data : []
|
||||||
setVersions(list)
|
setVersions(list)
|
||||||
|
setVersionsLoaded(true)
|
||||||
return list
|
return list
|
||||||
}, [sourceId])
|
}, [sourceId])
|
||||||
|
|
||||||
@ -52,18 +54,26 @@ export default function App() {
|
|||||||
}, [sources, sourcesLoaded, sourceId])
|
}, [sources, sourcesLoaded, sourceId])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sourceId) { setVersions([]); setVersionId(''); return }
|
if (!sourceId) { setVersions([]); setVersionId(''); setVersionsLoaded(true); return }
|
||||||
|
// The list belongs to the previous source until the fetch lands.
|
||||||
|
setVersionsLoaded(false)
|
||||||
refreshVersions(sourceId)
|
refreshVersions(sourceId)
|
||||||
}, [sourceId])
|
}, [sourceId])
|
||||||
|
|
||||||
// Same reasoning as sources: a deleted version must not stay selected.
|
// Same reasoning as sources: a deleted version must not stay selected.
|
||||||
|
//
|
||||||
|
// versionsLoaded matters more than it looks: without it, the empty initial
|
||||||
|
// state reads as "this source has no versions", so a versionId restored from
|
||||||
|
// localStorage is cleared and then set straight back when the fetch lands.
|
||||||
|
// Forecast's load effect is keyed on that id, so the round trip made every
|
||||||
|
// page load fetch and aggregate the whole version twice.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sourceId) return
|
if (!sourceId || !versionsLoaded) return
|
||||||
if (versions.length === 0) { setVersionId(''); return }
|
if (versions.length === 0) { setVersionId(''); return }
|
||||||
if (!versionId || !versions.some(v => String(v.id) === String(versionId))) {
|
if (!versionId || !versions.some(v => String(v.id) === String(versionId))) {
|
||||||
setVersionId(String(versions[0].id))
|
setVersionId(String(versions[0].id))
|
||||||
}
|
}
|
||||||
}, [versions, sourceId, versionId])
|
}, [versions, versionsLoaded, sourceId, versionId])
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sources, sourceId, setSourceId,
|
sources, sourceId, setSourceId,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user