Skip to content

[Tech debt] Factor repeated router boilerplate (DB-session lifecycle) into a shared base #161

Description

@hunter-read

What problem does this solve?

Every router package follows the same shape (__init__.py registers routes via add_api_route, core.py holds handlers, _schemas.py/_helpers.py for models/helpers — per CLAUDE.md). That consistency is good, but some boilerplate is literally duplicated across packages rather than shared:

  • The DB-session lifecycle is the biggest one: db = SessionLocal() / try: … / finally: db.close() appears in ~32 handler functions across the routers. Every handler hand-rolls open/close, which is repetitive and easy to get subtly wrong (e.g. forgetting finally, or not closing on an early return).
  • Several _helpers.py modules define near-identical _serialize(...) shapes (5 packages define a _serialize), and small schema patterns recur.

What would you like to see?

Factor the repeated boilerplate into a small shared base where it's genuinely duplicated, without flattening the per-package structure that keeps the codebase navigable.

  • DB session: replace the hand-rolled SessionLocal()/try/finally with a single shared mechanism — most idiomatically a FastAPI dependency (Depends(get_db)) that yields a session and closes it in a finally, so handlers just take db: Session = Depends(get_db) and drop the boilerplate. (This is also a prerequisite-friendly cleanup for testing.) Migrate handlers incrementally.
  • Serialization/helpers: where _serialize and similar helpers are duplicated with the same shape, consider a shared helper module — but only collapse what's actually the same; don't force-fit genuinely different serializers together.

Proposed implementation sketch

  • Add a get_db dependency (in backend/config.py or a shared deps.py) that yields SessionLocal() and closes in finally.
  • Migrate router handlers from manual db = SessionLocal() blocks to the dependency, package by package (keeps PRs reviewable).
  • Audit the duplicated _serialize/schema patterns and extract only the truly-shared ones.

Testing

  • Backend: existing endpoint tests must continue to pass unchanged (behavior-preserving refactor). Verify sessions are still closed (no leaked connections) — the dependency's finally covers this.
  • Coverage gate: touched files stay ≥80%.

Docs

  • Update the "router shape" guidance in CLAUDE.md to reflect the shared get_db dependency once adopted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpythonPull requests that update python codetech-debtRefactoring and codebase health

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions