The API returns {"models":[...]} rather than a bare array.
Added MlModelsResponse wrapper class and updated LoadModelHistory
to unwrap the list before iterating, preventing the deserialization
exception in TrainingController.
- Replace blocking urlopen with async httpx.AsyncClient
- Add await at both call sites (deck_research, deck_generate_ai)
- Uvicorn event loop no longer stalled during Perplexity API calls
- Replace SELECT * + Python-side color loop in _get_collection_for_colors()
with projected SELECT + NOT EXISTS json_each() sub-query
- Apply same pattern to _build_collection_summary(), removing card_fits_identity()
- Add partial index idx_ce_quantity on collection_entries(quantity) WHERE qty > 0
- Handle NULL and empty-string color_identity via CASE guard
- Fix colorless commander bug: old code skipped color check entirely for []
- Add scripts/bench_deckgen.py benchmark (3-5x speedup on filtered queries)
- Add tests/test_deckgen_color_filter.py with 7 regression tests
- Add @dataclass classes _TrainingState, _PPOState, _TournamentState with snapshot() method
- Wrap all state mutations in threading.Lock() for thread safety
- Replace dict bracket access with attribute access
- Remove unnecessary global declarations from pipeline functions
Previously, init_collection_db() opened a separate sqlite3.connect() call,
ran migrations, then closed that connection — entirely outside the
thread-local pool that route handlers use via _get_db_conn().
This meant:
- The migration connection and the request-serving connection were
independent objects with no ordering guarantee under concurrent startup.
- The warm-up connection was thrown away immediately, so every handler
thread still had to open its own connection on first use.
Fix:
- init_collection_db() now calls _get_db_conn() directly, so schema
creation and migrations run on the same thread-local connection that
will serve subsequent requests.
- Added _close_db_conn() helper for explicit teardown on thread exit
(e.g. FastAPI lifespan shutdown or worker thread cleanup).
- Removed the redundant standalone conn.close() that discarded the
init connection without ever making it available to route handlers.