fix: replace 467 manual db.close() calls with middleware (#30) #33
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-merged
ai-pr-opened
ai-reviewed
ai-reviewing
ai-reviewing
ai-working
bug
enhancement
evolution
performance
phase-0
phase-1a
phase-1b
phase-1c
phase-1d
security
tech-debt
todo
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-database#33
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "ai/paper-dynasty-database#30"
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
db_session_middlewaretoapp/main.pythat opens the DB connection at the start of every HTTP request and closes it in atry/finallyblock — guaranteeing connections are always released, even on uncaught exceptionsdb.close()calls from 30 router files inapp/routers_v2/What was fixed
Every endpoint manually called
db.close()before eachraise HTTPException(...)and before eachreturn. Any code path that threw an unexpected exception would leak the connection. With 486 call sites, the pattern was also extremely brittle to maintain.The middleware approach is the standard Peewee + FastAPI pattern:
db.connect(reuse_if_open=True)is safe for both SQLite andPooledPostgresqlDatabase(which returns the connection to the pool onclose()).Files changed
app/main.py— addedfrom .db_engine import dbimport + middlewareapp/routers_v2/*.py— removeddb.close()from 30 files (467 calls)Other observations
Some router files now have
dbas an unused import (e.g.admin.py,awards.py,current.py,rarity.py,rewards.pyand a few others) where the only use wasdb.close(). These are harmless but could be cleaned up in a follow-up.AI Code Review
Files Reviewed
app/main.py(modified — addeddbimport + middleware)app/routers_v2/*.py— 30 router files (modified,db.close()removed)Findings
Correctness
Requestis already imported on line 1 ofmain.py(from fastapi import FastAPI, Request), so the new middleware signature compiles without changes.db.connect(reuse_if_open=True)is the documented safe pattern for bothSqliteDatabaseandPooledPostgresqlDatabase. With the pool (autoconnect=Trueindb_engine.py),close()returns the connection to the pool rather than destroying it — correct behaviour for prod.try/finallyblock guarantees the connection is released even when an endpoint raises an unhandled exception, which is exactly the bug being fixed.if not db.is_closed(): db.close()guard prevents a double-close on code paths where an endpoint may have already closed. Defensive and safe.+db.close()line in the diff is thefinallyblock in the middleware itself — not a missed removal.StreamingResponseorBackgroundTaskspatterns exist in the routers, so there is no risk of thefinallyblock releasing the connection before response body generation completes.db.atomic()inplayers.py(put_players) is unaffected — Peewee atomic context managers work correctly with a pre-opened connection.Security
Style & Conventions
main.pyis a minor cosmetic improvement.dbimports: Several router files (admin.py,awards.py,current.py,rarity.py,rewards.py, and others) now importdbbut never use it — the only use wasdb.close(). The PR body already flags these for follow-up cleanup. Harmless.Suggestions
dbimport from the router files. A simplegrep -rn "^from \.\.db_engine import db" app/routers_v2/after merge will identify the exact list.Verdict: APPROVED ✓
Correct implementation of the standard Peewee + FastAPI connection-management pattern. Eliminates a real connection-leak bug across all 467 unguarded call sites. The middleware is the right architectural fix and is safe for both the SQLite (dev) and
PooledPostgresqlDatabase(prod) backends. Ready to merge.Automated review by Claude PR Reviewer
AI Code Review
Files Reviewed
app/main.py(modified — middleware added, imports reformatted)app/routers_v2/*.py— all 30 router files (puredb.close()removals)app/db_engine.py(read for context, not modified)Findings
Correctness
db.connect(reuse_if_open=True)is safe for bothSqliteDatabaseandPooledPostgresqlDatabase— for the pool,close()returns the connection to the pool rather than destroying it.finallyblock correctly guards against connection leaks on uncaught exceptions, which the prior 467 manualdb.close()calls could not guarantee.Requestis already imported inmain.py(used byget_docs), so no missing import.db.close()calls — no logic was altered.db_engine.pycallsdb.close()at module level (line 1067) after table creation at startup. This pre-existing behaviour is unaffected; the middleware correctly handles per-request lifecycle after that.players.py, the old code calleddb.close()mid-function before afor x in card_vals:loop and then continued executing — a latent bug. The removal is strictly correct.get_scouting_dfsinteams.pyis a non-async helper; removingdb.close()from it is correct since connection lifecycle is now owned by the middleware at the request boundary.Security
Style & Conventions
main.pyreformatted from compressed one-liners to one-per-line style — clean improvement, no concerns.dbimport (e.g.admin.py,awards.py,current.py,rarity.py,rewards.py) wheredbwas only used fordb.close(). These are harmless but should be removed in a follow-up to keep linting clean.Suggestions
dbimport from router files where the only previous use wasdb.close(). Agreppass will identify them quickly.Verdict: APPROVED
Clean, correct refactor. The middleware pattern is the standard Peewee + FastAPI approach and strictly improves connection safety over 467 scattered
db.close()calls. No security issues, no broken edge cases, no logic changes in the routers. Safe to merge.Automated review by Claude PR Reviewer
AI Code Review
Files Reviewed
app/main.py(modified — middleware added)app/routers_v2/*.py(30 files —db.close()removals only)Findings
Correctness
db.connect(reuse_if_open=True)intry,db.close()infinallywith anis_closed()guard.db.close()lines removed across 30 router files, 0 other logic changes in any router.db.close()is the middleware'sfinallyblock — expected.dbis properly exported fromdb_engine.py(bothSqliteDatabaseandPooledPostgresqlDatabasepaths).include_router()calls is valid — Starlette processes middleware at request time, not definition time.Security
Style & Conventions
main.py(one-per-line routers) is an improvement to readability.Suggestions
dbimports after merge (files wheredbwas only used fordb.close()):admin.py,awards.py,cardsets.py,current.py,events.py,gamerewards.py,gauntletruns.py,notifications.py,packtypes.py,paperdex.py,rarity.py,results.py,rewards.py,scouting.py,stratgame.py. PR author already flagged this for follow-up — no blocker.Verdict: APPROVED ✓
Clean, correct mechanical refactor. The middleware pattern eliminates the connection-leak risk and removes 467 brittle call sites. Safe for both SQLite (dev) and
PooledPostgresqlDatabase(prod). The unused-import cleanup can follow in a separate PR.Automated review by Claude PR Reviewer
46b9aa27betobcdbf2add1