Skip to content

[fix] QA: not-found delay, duplicate fetches, noteworthy null-sort - #6

Closed
chondl wants to merge 3 commits into
masterfrom
qa-fixes
Closed

[fix] QA: not-found delay, duplicate fetches, noteworthy null-sort#6
chondl wants to merge 3 commits into
masterfrom
qa-fixes

Conversation

@chondl

@chondl chondl commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Track 1 · standalone bug fix. Off master (a2cea55). No dependencies; order-independent relative to the other bug fixes. Recommended slot: 4 of 5 in Track 1 (#5 → #12 → #8 → #6 → #1). No companion tests.


Three fixes from an adversarial QA pass on staging. One commit per fix, no tests on this branch. Verified against a local rig (full 2026 seed, backend on :8000).

1. Not-found page blank for 8 seconds

Symptom: any nonexistent or slow-to-load entity (/team/99999, /event/2026zzzzz, ...) showed a blank content area for 8 full seconds before the "not found" message — looks like a hung page.
Root cause: frontend/src/pagesContent/shared/notFound.tsx:14setTimeout(..., 8000). The debounce exists only to avoid flashing the not-found message before data arrives; the in-file comment describes it as "one second". The value grew 1000 → 5000 → 8000 over prior upstream commits, so 8000 is deliberate rather than a typo — but 8s is far longer than the anti-flash intent needs.
Fix: reduce to 1500ms. Enough to suppress the flash, short enough to no longer read as broken.

2. Every blob/API resource fetched twice on team pages

Symptom: on /team/*, each event/team blob was downloaded exactly twice per page load (observed on the production build, so not a StrictMode artifact).
Root cause: frontend/src/api/storage.tsx query() had no in-flight dedup. Several components request the same resource concurrently; each awaits getWithExpiry(), all miss IndexedDB (nothing is written until a fetch resolves), and all issue their own fetch.
Fix: add a module-level in-flight promise map keyed by storageKey. Concurrent callers for the same key share one fetch; the entry clears once it settles. The fetch body is extracted into fetchAndStore unchanged.

3. Noteworthy matches rank a null/placeholder match #1

Symptom: /v3/site/noteworthy_matches/2026 returned a 0/null-score, fully-DQed placeholder match (2026txmca_sf6m1) at the top of "Highest Clean Scores" (and the other lists), ahead of real high scores.
Root cause: backend/src/db/functions/noteworthy_matches.py — the lists order_by(desc(...)) without specifying null placement. CockroachDB orders NULLs first under DESC. For 2016+ the sort uses the no_foul columns; a match with no clean result on either alliance yields greatest(...) = NULL (and sum = NULL for combined), so it sorts to #1. (The value only surfaces on a NULLS-FIRST-defaulting DB, which is why it appears on staging.)
Fix: add .nullslast() to every noteworthy order_by. Null-result matches fall past the top-30 cutoff; real high-scoring matches rank first; legitimate single-alliance-DQ matches still rank by their scoring alliance.

Verification (rig, before/after): simulating staging's NULLS-FIRST ordering, 2026txmca_sf6m1/_sf9m1 ranked #1#2 above the real 964-point match; with the patched query, 2026dal_f1m1 (964) is #1 across all six lists and the placeholder is gone. yarn lint clean; backend flake8/black/isort clean.


Cross-track note (only if the blob-store stack is also taken)

Fix #2 above (storage.tsx in-flight dedup) overlaps with Track 2 PR #2 (bucket-first serving), which rewrites storage.tsx for bucket-first serving. Merging both produces one conflict in frontend/src/api/storage.tsx. Resolution: take #2's rewrite — its bucketInFlight dedup (keyed by logical path) already eliminates the double blob fetch this PR targets. If you also want this PR's query-level dedup for the API/IndexedDB path, re-wrap #2's query() in the inFlight[storageKey] pattern from this PR. If you take only Track 1, there is no conflict.

chondl added 3 commits July 9, 2026 23:46
The not-found placeholder waited 8000ms before rendering, leaving a blank
content area for 8 full seconds on any nonexistent or slow-to-load entity
(/team/99999, /event/2026zzzzz, etc.). The debounce exists only to avoid a
flash of the not-found message before data arrives; 1.5s is ample for that
while no longer looking like a hung page. (The comment already described the
intent as 'one second'; the 8000 value grew from 1000 over prior commits.)
On team pages multiple components concurrently request the same event/blob
resources. Each caller awaits getWithExpiry(), all miss IndexedDB (nothing is
written until a fetch completes), and all issue their own network fetch, so
every blob/API resource was downloaded twice per page load. Add a module-level
in-flight promise map keyed by storageKey: concurrent callers for the same key
now share one fetch, and the entry is cleared once it settles.
CockroachDB orders NULLs first under ORDER BY ... DESC, so a match whose clean
score is null on both alliances (a fully-DQed / placeholder match, e.g.
2026txmca_sf6m1) sorted to the top of every noteworthy list -- ranking a
0/null result as the highest clean score. greatest()/sum() over the no_foul
columns yields null when both alliances lack a clean result. Add .nullslast()
to every noteworthy order_by so these matches fall to the bottom (out of the
top 30) and real high-scoring matches rank first, while legitimate single-DQ
matches keep ranking by their scoring alliance.
@chondl chondl changed the title QA fixes: not-found delay, duplicate fetches, noteworthy null-sort [fix] QA: not-found delay, duplicate fetches, noteworthy null-sort Jul 10, 2026
@chondl

chondl commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

Superseded — fixes relocated to #5 (storage.tsx dedup and noteworthy null-sort); the not-found timeout change moved to #2. Branch kept.

@chondl chondl closed this Jul 10, 2026
@chondl
chondl deleted the qa-fixes branch July 19, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant