Skip to content

Fix summary cold-cache timeouts and ranking query reads - #268

Merged
msaroufim merged 3 commits into
mainfrom
agent/summary-query-reliability
Oct 29, 2026
Merged

msaroufim merged 3 commits into
mainfrom
agent/summary-query-reliability

Conversation

@msaroufim

@msaroufim msaroufim commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

The home page's summary request was repeatedly exceeding Gunicorn's 30-second deadline after a cache-version change. Every request tried to compute 42 competitions before writing any of the 34 ended-competition cache entries, so a cold cache never recovered.

Scope submission metadata before looking up public runs and secret-test eligibility. Add a partial covering index containing the run ID used for deterministic tie-breaking, so ranking queries can use index-only scans. Disable transaction-local JIT for the short ranking queries, avoiding roughly 0.5 seconds of compilation per batch. Bound ranking work to 10 seconds per request and 3 seconds per query; save completed ended-competition results immediately and roll back timed-out queries to a savepoint so competition metadata still loads. Timed-out results are never cached as empty rankings.

Production recovery already performed: rebuilt the 34 ended-competition cache entries from the current ranking query, built the covering index concurrently, and vacuumed/analyzed runs and submissions. No submissions or ranking records were changed.

Validation:

  • 18 API and hacked-filter tests pass with local PostgreSQL 16 and isolated test databases; Ruff and diff checks pass. Regression tests compare selected/full rankings with the original SQL and exercise real PostgreSQL query cancellation followed by a successful retry.
  • Direct production SQL comparisons with Redis bypassed returned identical results for the eight active competitions, competitions 597/598, and all 42 competitions.
  • With production's default JIT setting, EXPLAIN (ANALYZE, BUFFERS) measured the new query at 0.85 seconds for the eight active competitions and 4.56 seconds for all 42. The public/secret run lookups used index-only scans with zero heap fetches. These measurements used warm PostgreSQL buffers, not a cold disk benchmark.
  • A patched in-process HTTP check against production data returned 200 with all 42 ranking lists in 0.39 seconds using Redis and 5.02 seconds with Redis disabled. Both use the final transaction-local JIT setting.
  • Live summary HTTP request recovered from 503 after 31.97 seconds to 200 in 3.95 seconds after database recovery, before this application change.

The query still scales with submissions in the selected competitions. During a timeout, the page returns competition metadata with unavailable top-user lists omitted until a later request succeeds; existing completed cache entries remain available. The use_beta diagnostic path bypasses Redis through the same bounded query implementation.

@msaroufim
msaroufim merged commit f75862b into main Oct 29, 2026
1 check passed
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