trader.persistence.db module¶
Engine, session factory, and schema creation for the PostgreSQL database (issue #26 — migrated off SQLite; see docs/invariants.md for why).
- exception trader.persistence.db.DatabaseError(statement, params, orig, hide_parameters=False, connection_invalidated=False, code=None, ismulti=None)[source]¶
Bases:
DBAPIErrorWraps a DB-API DatabaseError.
- Parameters:
statement (Optional[str])
params (Optional[_AnyExecuteParams])
orig (BaseException)
hide_parameters (bool)
connection_invalidated (bool)
code (Optional[str])
ismulti (Optional[bool])
- code = '4xp6'¶
- trader.persistence.db.create_db_engine(database_url)[source]¶
Build an engine for the Postgres database at database_url.
pool_pre_ping=True: unlike a SQLite file, Postgres is a real network/ socket service that can go away mid-process (a brew services restart, a dropped Unix socket). Without this, a stale pooled connection surfaces as a mystifying error mid-cycle instead of being detected and replaced before use.
No PRAGMA setup here (the pre-migration SQLite version of this function had one): journal_mode/busy_timeout have no Postgres equivalent — MVCC and its own connection-level lock manager already give concurrent readers/writers what WAL mode existed to provide — and foreign_keys=ON is unconditional on Postgres, never opt-in.
- Parameters:
database_url (str)
- Return type:
Engine
- trader.persistence.db.create_session_factory(engine)[source]¶
Build a session factory bound to engine.
- Parameters:
engine (Engine)
- Return type:
sessionmaker[Session]
- trader.persistence.db.init_db(database_url, stamp=True)[source]¶
Create every table in the (already-existing) Postgres database at database_url. Safe to run repeatedly.
Uses create_all rather than replaying migrations because the test suite builds around a hundred-plus throwaway databases and replaying history for each costs far more than it proves. The drift that would otherwise allow is caught by tests/persistence/test_migrations.py.
The new database is then stamped at head, so Alembic knows its tables already exist and a later upgrade applies only genuinely new revisions. Pass stamp=False to skip that — worth it only for a throwaway database in a tight loop, since stamping opens a second connection.
Unlike the pre-migration SQLite version, this does not create the database itself — CREATE DATABASE is a privileged, out-of-band operation (see tests/persistence/pg_testing.py for the test-suite fixture that does it), never something an app connection triggers implicitly by connecting.
- Parameters:
database_url (str)
stamp (bool)
- Return type:
Engine