Skip to content

feat(orm): validate connection config at DatabaseManager construction time#196

Open
tmgbedu wants to merge 1 commit into
mainfrom
task/db-boot-validation-1232
Open

feat(orm): validate connection config at DatabaseManager construction time#196
tmgbedu wants to merge 1 commit into
mainfrom
task/db-boot-validation-1232

Conversation

@tmgbedu

@tmgbedu tmgbedu commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to backlog task #1223 / PR #194, per the reviewer's recommendation on that PR (task #1231).

PR #194 hardened ConnectionFactory.build_url()/make() so a bad connection config fails with a friendly DriverNotFound instead of a raw KeyError/ValueError -- but only at the point of first connection/engine-creation (e.g. db:migrate, or the app's first query), since that's when factory code first runs.

This PR moves that failure earlier: DatabaseManager now validates every configured connection up front, in __init__. Since DatabaseProvider.register() constructs the DatabaseManager during app boot, a misconfigured connection now raises immediately when the Application is constructed, not lazily on first DB use.

Validated per connection (skipped entirely if the connection supplies an explicit url, mirroring build_url()'s own passthrough):

  • driver key must be present -> DriverNotFound if missing
  • driver value must be one of ConnectionFactory.DRIVER_URLS -> DriverNotFound if unsupported (reuses the exception + supported-driver list from PR fix(orm): harden ConnectionFactory against bad port and unknown driver #194, doesn't reinvent)
  • for non-sqlite drivers, a port that's present but not int-castable (e.g. "not-a-port") -> ValueError. A missing/empty port is not an error since ConnectionFactory already defaults it per-driver.

Test plan

  • uv run pytest fastapi_startkit/tests/masoniteorm/config/test_manager.py -v -- new TestDatabaseManagerBootTimeValidation class: happy path (sqlite/mysql/postgres all construct fine), missing driver key, unsupported driver, non-numeric port, missing port is not an error, explicit url bypass, and an end-to-end Application boot repro -- all passing
  • Updated test_connection_raises_for_missing_driver in test_model_attributes.py to assert the failure now happens at DatabaseManager(...) construction rather than at first .connection() call
  • Full suite: uv run pytest --ignore=tests/masoniteorm/postgres from fastapi_startkit/ -- 1988 passed, 7 skipped, no regressions
  • Coverage: 81.25% (threshold 80%)
  • Manually verified: a valid config still runs db:migrate end-to-end unchanged; a bad config (unsupported driver) now raises DriverNotFound at Application(...) construction, before db:migrate or any query ever runs
  • ruff check / ruff format --check clean

Per the current merge freeze, this PR is intentionally left open/unmerged.

… time

PR #194 hardened ConnectionFactory.build_url()/make() so a bad connection
config fails with a friendly DriverNotFound instead of a raw KeyError, but
only at the point of first connection/engine-creation (e.g. db:migrate or
the first query) since that is when factory code first runs.

DatabaseManager now validates every configured connection up front, in
__init__, so DatabaseProvider.register() (which builds the DatabaseManager
during app boot) surfaces a bad config immediately:
- a connection missing its 'driver' key, or with an unsupported driver,
  raises DriverNotFound, reusing PR #194's exception and driver list
- a non-numeric 'port' on a non-sqlite driver raises ValueError
- a missing/empty port is left alone (ConnectionFactory already defaults
  it per-driver) and an explicit 'url' bypasses these checks entirely,
  mirroring build_url()'s own passthrough

Updates test_connection_raises_for_missing_driver to assert the failure now
happens at DatabaseManager construction rather than at first .connection()
call, and adds a boot-time validation test class covering the happy path,
each failure mode, and an end-to-end Application-boot repro.
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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