fix: don't poison shard cache on failure; require real draws for ready status

Two Important review findings on useDrawDistribution:
- ensureShardRegistered cached the rejected promise on fetch/registration
  failure, permanently stuck for that (model,year,state) key until a full
  page reload. Now deletes the cache entry on failure so the next caller
  retries fresh.
- status could become 'ready' even when the LEAID-bound query returned zero
  usable rows (district not present in the draws shard), silently mislabeling
  a fitSkewedInterval-only render as real posterior draws. Now requires at
  least one group with actual draws before reporting 'ready'.
This commit is contained in:
2026-08-11 09:22:01 -04:00
parent d5bf18482a
commit ea6d554e3d
+21
View File
@@ -19,6 +19,7 @@ function ensureShardRegistered(db, model, year, state) {
shardCache.set(
key,
(async () => {
try {
const url = `${HF_BASE}/model_id=${model}/YEAR=${year}/LEA_STATE=${state}/data_0.parquet`
const res = await fetch(url)
if (!res.ok) throw new Error(`Failed to fetch draw shard: HTTP ${res.status}`)
@@ -26,6 +27,13 @@ function ensureShardRegistered(db, model, year, state) {
const fileName = `${key}.parquet`
await db.registerFileBuffer(fileName, buffer)
return fileName
} catch (err) {
// Don't let a transient failure (network blip, HF outage) poison the
// cache forever — remove the rejected entry so the next caller for
// this shard gets a fresh attempt instead of the same dead promise.
shardCache.delete(key)
throw err
}
})(),
)
}
@@ -79,9 +87,22 @@ export function useDrawDistribution({ leaid, state, model, year, groups }) {
;(byGroup[key] ??= []).push(rate)
}
// A successful query with zero matching rows (this district isn't in
// the draws shard, or none of its rows matched a known group) is not
// "ready" — there's no real data to show, so treat it like a failure
// and let the caller fall back, rather than silently claiming real
// draws while every group actually uses the fitted approximation.
const hasDraws = Object.values(byGroup).some((draws) => draws.length > 0)
if (!cancelled) {
if (hasDraws) {
setDrawsByGroup(byGroup)
setStatus('ready')
} else {
console.warn('useDrawDistribution: query succeeded but returned no usable draws for', { leaid, model, year, state })
setDrawsByGroup(null)
setStatus('error')
}
}
} catch (err) {
console.error('useDrawDistribution failed:', err)