Skip to content

fix(api): /data/search dumps full course/prof catalog regardless of matview freshness - #187

Draft
jerryzhou196 wants to merge 1 commit into
mainfrom
fix/search-dump-stale-matview
Draft

fix(api): /data/search dumps full course/prof catalog regardless of matview freshness#187
jerryzhou196 wants to merge 1 commit into
mainfrom
fix/search-dump-stale-matview

Conversation

@jerryzhou196

Copy link
Copy Markdown
Member

Problem

/data/search returns a tiny (or empty) dump — with a 200 — when Hasura is up but the database is freshly or partially seeded, instead of the full catalog (regtest/api/dump.js expects courses.length > 7000).

Root cause

Both queries in flow/api/data/data.go INNER JOINed aggregate.course_rating / aggregate.prof_rating. Those are views over materialized views (materialized.course_rating, materialized.prof_rating), which only get refreshed by triggers on review and section_meeting writes (see refresh_course_rating / refresh_section_meeting in the init migration) — never on plain course/prof inserts.

So when the base tables are seeded but no review/section write has fired a refresh, the matviews are stale/empty and the INNER JOIN silently drops the missing rows. The handler also never checked rows.Err(), so a mid-stream pgx error would be returned as partial success too.

Fix

  • INNER JOINLEFT JOIN on aggregate.course_rating / aggregate.prof_rating so the live course/prof tables are the source of truth for which entries appear in the dump.
  • COALESCE(filled_count, 0) AS review_count so the rating count defaults to 0 when the matview has no row yet (also avoids a NULL scan into an int).
  • Check rows.Err() after each iteration loop so a streaming error surfaces as a 5xx instead of a silent truncated 200.

Rating counts can still read 0 until the matviews are refreshed, but the catalog is now complete regardless of refresh state.

Test plan

  • go build ./... / go vet ./api/data/ (passes locally)
  • Hit /data/search against a seeded-but-unrefreshed DB and confirm full courses/profs counts
  • regtest/api/dump.js still passes against a fully seeded DB

🤖 Generated with Claude Code

The search dump INNER JOINed aggregate.course_rating / aggregate.prof_rating,
which are views over materialized views (materialized.course_rating /
prof_rating). Those matviews only refresh via triggers on review and
section_meeting writes, never on plain course/prof inserts. When Hasura is up
but the DB is freshly/partially seeded, the matviews are stale or empty, so the
INNER JOIN silently drops most rows and the endpoint returns a tiny dump with a
200.

Use LEFT JOIN so the live course/prof tables are the source of truth, and
COALESCE(filled_count, 0) so rating counts default to 0 when the matview lacks a
row. Also check rows.Err() after each iteration loop so a mid-stream pgx error
surfaces as a 5xx instead of being returned as partial success.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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