feat: v6 — optional PostgreSQL backend for horizontal scale (tested vs Postgres 16)#65
Merged
Merged
Conversation
Roadmap v6 (owner decision: "Postgres now"). Adds an OPTIONAL Postgres backend for the cross-process state; SQLite stays the default and the fully-tested path. - Dual-backend src/core/db.py: DATABASE_URL=postgresql://... switches the whole layer to Postgres. A thin compatibility shim keeps every call site unchanged: ? -> %s placeholders, hybrid rows (row[0] AND row["col"], dict(row)), upsert() (INSERT OR REPLACE/IGNORE <-> ON CONFLICT), autoincrement_pk(). - Postgres migrations (migrations/postgres/, BIGSERIAL + to_char default); init_db picks the dir by backend. - journal uses RETURNING id on Postgres (no lastrowid); ledger/position_store/ registry/orders verified on both backends. - psycopg[binary] dependency (lazy-imported; only used when DATABASE_URL is PG) + postgres service in docker-compose under the `scale` profile. - Real integration test (tests/integration/test_postgres_backend.py, 8 tests) run against Postgres 16 — skipped when DATABASE_URL is unset (e.g. CI). PG-only lines marked pragma:no-cover (covered by that gated test). SQLite suite unchanged: 406 passed, 8 skipped, coverage 72.51% (gate 72), ruff clean, compose validates. Docs: ADR-005, README, docs/roadmap_v6.md, pendencia.v2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014htKJbgi3z1m3kzDVwXwfS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumo
v6 (decisão do dono: "Backend PostgreSQL agora"). Adiciona um backend PostgreSQL opcional para o estado cross-process, habilitando escala horizontal real (múltiplos hosts/réplicas escrevendo estado). SQLite continua o padrão e o caminho 100% testado. Tracker:
docs/roadmap_v6.md.O que muda
src/core/db.pydual-backend:DATABASE_URL=postgresql://…troca toda a camada para Postgres. Um shim fino mantém todos os call sites inalterados: placeholders?→%s, rows híbridas (row[0]erow["col"],dict(row)),upsert()(INSERT OR REPLACE/IGNORE↔ON CONFLICT),autoincrement_pk().migrations/postgres/,BIGSERIAL+ defaultto_char);init_dbescolhe o diretório por backend.RETURNING idno PG (semlastrowid); ledger / position_store / registry / orders verificados nos dois backends.psycopg[binary](lazy import; só usado quandoDATABASE_URLé PG) + serviçopostgresno compose sob o perfilscale.Testado de verdade
tests/integration/test_postgres_backend.py, 8 testes): migrations, rows híbridas, ledger, position store (upsert/replace/delete), circuit state, registry, ordens (INSERT+UPDATE), journalRETURNING. Pulado quando não háDATABASE_URL(ex.: CI).# pragma: no cover(cobertas pelo teste gated) → gate honesto para o núcleo SQLite.Como ativar
Resta (gated por ADR-005)
Leader election do loop (HA com réplica redundante) — quando "zero downtime" for requisito. Ver
docs/pendencia.v2.md.🤖 Generated with Claude Code
https://claude.ai/code/session_014htKJbgi3z1m3kzDVwXwfS
Generated by Claude Code