Files
routstr-core/migrations
9qeklajc 250864b45d Support PostgreSQL for the application database
SQLite stores every INTEGER as 64-bit, so a set of portability defects stayed
invisible until the application database ran on PostgreSQL:

- Monetary columns hold millisatoshis but mapped to INT4, capping a key balance
  at 2_147_483_647 msats (~0.0215 BTC); asyncpg rejects anything larger. Unix
  timestamp columns had the same width, so long-dated expiries and the 2038
  boundary would overflow. Both are widened to BIGINT by a migration that is a
  no-op on SQLite, where the width does not exist.
- Secret.nsec_state was a bare Python Enum, which makes PostgreSQL demand a
  native `nsecstate` type that the migration never created, so every read or
  write of the secrets singleton failed and took node bootstrap with it. It is
  now a non-native enum, rendering VARCHAR on both backends.
- Model-path persistence imported the SQLite-only INSERT .. ON CONFLICT
  construct, which does not compile against PostgreSQL. The upsert is now built
  for the dialect bound to the session.
- The Alembic version-clear recovery path built a sync engine from the async
  URL, which left postgresql+asyncpg intact and raised MissingGreenlet. It now
  runs through the configured async driver.
- The WAL PRAGMA is gated on the bound dialect rather than a DATABASE_URL
  prefix. SQLite-only Cashu wallet maintenance stays scoped to
  .wallet/*.sqlite3 and the log-derived analytics index is untouched.
- PostgreSQL migration failures and unknown revisions now fail closed instead
  of stamping head. PostgreSQL rolls back DDL transactionally, so stamping
  after an error can mark migrations applied that never committed. Existing
  SQLite recovery behaviour is unchanged.

Adds asyncpg and two test suites: dialect-portability invariants that run in the
normal suite, and an opt-in integration suite covering the full Alembic chain
plus the billing, reservation, refund, invoice and payout paths against a real
server, enabled by ROUTSTR_TEST_POSTGRES_URL and skipped without it.
2026-09-30 13:20:02 +00:00
..
2025-08-23 17:01:28 -03:00
2025-08-09 13:50:05 -03:00