Repository navigation
perf: friends list reads in-match and live lineup state from the active matches - #638
Merged
Merged
Conversation
…ve matches is_in_another_match and the friends subscription's player_lineup Live filter walked every friend's whole match history on each refresh. is_in_another_match now starts from the active matches (partial index widened to every active status), and a players.live_lineup computed field returns only lineup rows in Live matches so Hasura's checks run on at most one row.
…y panels Review of the first commit found three gaps: on a panel of one-off players the generic plan probed lineups through the steam_id index and re-read the whole history per active match; matches scheduled far ahead were checked for every friend; and live_lineup returned practice sessions the matches permissions hide. Lineups are now probed on their unique key, a new (status, scheduled_at) partial index serves the active statuses and the Scheduled cut-off as two ranges (additive, the old index stays), and practice is excluded. Each gap has a cost or behavior test that fails on the first commit.
Re-review found the planner prices idx_match_lineup_players_steam_id exactly like the unique key for a (match_lineup_id, steam_id) probe and breaks the tie by index age, so a REINDEX of it brought back the read-the-whole-history plan (1008 extra buffers). idx_match_lineup_players_steam_id_lineup_id already serves every steam_id lookup. The spread-history test now rebuilds every index first, and a catalog test keeps a steam_id-only index from coming back.
lukepolo
force-pushed
the
perf/friends-live-state
branch
from
October 16, 2026 16:07
30eda0f to
fc8c14e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The friends subscription is the biggest database cost on both 5stack.gg and cs.playhard.gg. For every friend, on every refresh, it walked that friend's entire match history twice: once in
is_in_another_match, and once in theplayer_lineup(where: lineup.match.status = Live)filter.is_in_another_matchnow starts from the panel's active matches and probes the friend's lineup on both columns of its unique key, so the cached generic plan can't fall back to thesteam_idindex and the friend's history. The answers are unchanged.idx_matches_active_schedule (status, scheduled_at)serves the active statuses and the near-term Scheduled matches as two index ranges, so matches scheduled further out are never read.idx_match_lineup_players_steam_id. The planner prices it exactly like the unique key for a(match_lineup_id, steam_id)probe and breaks the tie by index age, so aREINDEXof it brought the whole-history plan back (1,008 extra buffers).idx_match_lineup_players_steam_id_lineup_idalready serves everysteam_idlookup; the friends subscription reads the same 9,075 buffers without it.players.live_lineupcomputed field (get_player_live_lineup) returns only lineup rows in Live, non-practice matches. The web keeps the samewhere/limiton it, so Hasura's checks run on at most one row.test/friends-live-state.spec.tscovers:is_in_another_matchby status, by lineup and with paused tournaments (these pass on main too)live_lineupagainst the permission-filtered match join, including practice sessionssteam_id-only indexlive_lineupin web#858, which needs codegen after this deploys.player_lineupkeeps working until then.