fix: eliminate N+1 queries in batch POST endpoints (#25) #52
No reviewers
Labels
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/major-domo-database#52
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "ai/major-domo-database-25"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
WHERE id IN (...)query before the validation loop inpost_transactions,post_results,post_schedules, andpost_batstatspost_transactionsbatch now issues 2 queries instead of 150; other endpoints scale similarlyFiles changed
app/routers_v3/transactions.py— 3N → 2 queries (team + player bulk fetch)app/routers_v3/results.py— 2N → 1 query (combined away/home team bulk fetch)app/routers_v3/schedules.py— 2N → 1 query (combined away/home team bulk fetch)app/routers_v3/battingstats.py— 2N → 2 queries (team + player bulk fetch)Test results
No test suite — changes verified by code review. Logic is equivalent: bulk-fetched ID sets replace per-row
get_or_none, validation loop unchanged.Other observations
🤖 Generated with Claude Code
AI Code Review
Files Reviewed
app/routers_v3/transactions.py(modified)app/routers_v3/results.py(modified)app/routers_v3/schedules.py(modified)app/routers_v3/battingstats.py(modified)Findings
Correctness
⚠️ Bug: Empty batch regression — Peewee + PostgreSQL rejects
WHERE id IN ()All four endpoints collect unique IDs upfront before the validation loop. If the request body contains an empty list (e.g.
{"moves": []}),all_team_idswill be[], and the bulk query:generates
WHERE "team"."id" IN ()— a PostgreSQL syntax error. This crashes with a 500 before reaching the loop.Before this PR: empty batches silently returned 200 (
"0 transactions have been added").After this PR: empty batches crash with a DB error.
This affects all four endpoints. The fix is straightforward — guard each bulk query with a conditional:
Affected locations (must fix before merge):
transactions.py—found_team_ids+found_player_idsbulk queriesresults.py—found_team_idsbulk queryschedules.py—found_team_idsbulk querybattingstats.py—found_team_ids+found_player_idsbulk queriesSecurity
<<(IN) operator — fully parameterized, no injection risk.{token}inlogger.warning(f"... Bad Token: {token}")calls remains in several functions (not introduced by this PR; tracked separately).Style & Conventions
Suggestions
Verdict: REQUEST_CHANGES
The N+1 optimization is correct and well-structured for non-empty batches. One blocking issue: empty batch requests now crash with a PostgreSQL syntax error instead of returning a clean 200. Add
if all_team_ids else set()/if all_player_ids else set()guards (or an early-return guard) in all four endpoints before merging.Automated review by Claude PR Reviewer
Review Feedback Addressed
Addressed the blocking bug identified in the review: empty batch regression causing PostgreSQL syntax error.
Changes Made
Added
if all_team_ids else set()/if all_player_ids else set()conditional guards to all four affected bulk query sites:transactions.py(post_transactions): guardedfound_team_ids+found_player_idsresults.py(post_results): guardedfound_team_idsschedules.py(post_schedules): guardedfound_team_idsbattingstats.py(post_batstats): guardedfound_team_ids+found_player_idsBehaviour
{"moves": []}) → skips bulk queries entirely,found_*_idsisset(), validation loop doesn't execute, returns"0 transactions have been added"— same as pre-PR behaviour.Automated fix by Claude Sonnet 4.6
AI Code Review
Files Reviewed
app/routers_v3/transactions.py(modified)app/routers_v3/results.py(modified)app/routers_v3/schedules.py(modified)app/routers_v3/battingstats.py(modified)Context
This is a follow-up review. A previous pass issued REQUEST_CHANGES for an empty-batch regression:
Team.select(Team.id).where(Team.id << [])producesWHERE id IN (), which is a PostgreSQL syntax error. The fix commit (17f67ff) added conditional guards before all bulk queries.Findings
Correctness
if all_team_ids else set()/if all_player_ids else set()guards, preventingWHERE id IN ()on empty batches. Verified across all 4 endpoints:transactions.py: team guard + player guard ✅results.py: team guard ✅schedules.py: team guard ✅battingstats.py: team guard + player guard ✅get_or_nonewith set membership check; error messages still include the specific invalid ID.all_team_ids/all_player_idsare empty lists, guards short-circuit toset(), the validation loop is skipped, andchunked([], 100)produces no iterations. Clean no-op. ✅set()deduplication before bulk fetch is correct; duplicate IDs in the batch still get per-row validation in the loop. ✅Security
WHERE id IN (...)— no SQL injection risk.Style & Conventions
Suggestions
Verdict: APPROVED
The empty-batch regression flagged in the previous review has been correctly fixed with conditional guards at all affected sites. The N+1 optimization is sound and the implementation is complete.
Automated review by Claude PR Reviewer