Skip to content

refactor(server): extract MetadataDB into lib/metadata_db.py (R3) - #830

Merged
byrongamatos merged 1 commit into
mainfrom
refactor/r3-metadata-db
Jul 10, 2026
Merged

refactor(server): extract MetadataDB into lib/metadata_db.py (R3)#830
byrongamatos merged 1 commit into
mainfrom
refactor/r3-metadata-db

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

First step of R3 (kill the core monoliths). Move-only, backend-only, zero behaviour change.

What moves

MetadataDB (4,018 lines) and the query helpers it owns — keyset paging cursors, the tuning grouping key (_tuning_group_key_sql), smart-arrangement naming (_ensure_smart_names / _arr_smart_sort_key), tag normalisation, the startup DB-restore swap (_apply_pending_db_restore / _sqlite_file_integrity_ok) — leave server.py for a new flat lib/metadata_db.py.

server.py: 14,037 → 9,705 lines.

lib/ needs no infra change: it is already COPY lib/ in the Dockerfile, bind-mounted in docker-compose.yml, and on PYTHONPATH=/app/lib:/app.

The one non-verbatim change

MetadataDB.__init__ takes config_dir explicitly instead of reading the module-level CONFIG_DIR:

meta_db = MetadataDB(CONFIG_DIR)

That is the seam that lets the class leave server.py, and it means lib/metadata_db.py performs no IO at import — Principle V, and the reason this file belongs in lib/ rather than a future root-level appstate.py.

Everything else is byte-identical. Mechanically verified two ways:

  • each of the 7 moved blocks appears verbatim in the new module;
  • server.py reconstructs exactly from origin/main minus the six cut ranges, minus the now-dead import contextlib, plus the import-back block and the constructor call site.

What deliberately does not move

The meta_db singleton stays in server.py, so server.meta_db (282 refs) and server.app (67 refs) resolve unchanged, no route moves, and none of the 114 monkeypatch.setattr(server, …) targets is affected. Logging still goes through the feedBack.server logger, so log filters and caplog assertions resolve to the same logger object.

Tests

tests/test_settings_export_library_db.py imports _apply_pending_db_restore from metadata_db — the test moves with its subject. Four call sites; no other test changed.

Verification

  • pyflakes (the Python analogue of the strict no-undef gate): lib/metadata_db.py clean — zero undefined names, zero unused imports. server.py gains no new undefined name. Exactly one import (contextlib) went dead with the move and was removed.
  • pytest2341 passed, 4 skipped.
  • node --test1030 passed.
  • npm run lint — 0 errors.
  • Boot smoke: uvicorn server:app with a seeded DLC_DIR and the three migrated plugins symlinked — /api/version and /api/library answer, and stems/studio/editor all register as script_type=module with their src/main.js module graphs serving 200 over the R0 route.
  • Codex preflight: 0 findings.

Pre-existing issues found, deliberately not fixed here

  • server.py:1014logger.exception(...) inside TuningProviderRegistry.get_merged()'s except handler, but logger is never defined (the module logger is log). A raising tuning provider turns a swallowed error into a NameError. Present on main; own follow-up PR.
  • _KEYSET_ROW_IDX is defined and never read. Moved verbatim rather than deleted.

Register

docs/size-exemptions.md ratcheted: server.py 14,037 → 9,705. lib/metadata_db.py (4,373) added to Planned, NOT exempt — the class is a monolith in its own right and wants a per-table split once the router train lands.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a dedicated metadata database layer supporting library browsing, search, playlists, favorites, enrichment, progression, and user statistics.
    • Added reliable database snapshot restoration with integrity checks and cleanup.
    • Added cursor-based pagination and improved grouped-work and smart-arrangement handling.
  • Bug Fixes

    • Improved database initialization by using the configured data directory explicitly, avoiding unnecessary import-time file access.
    • Preserved existing routes and behavior while centralizing metadata operations.

Move-only. The library metadata cache -- the `MetadataDB` class (4,018 lines)
plus the query helpers it owns (keyset paging cursors, the tuning grouping key,
smart-arrangement naming, tag normalisation, the startup DB-restore swap) --
moves out of server.py into a flat `lib/` module. Every moved block is
byte-identical to its server.py original; server.py is exactly origin/main
minus the six cut ranges, minus the now-dead `import contextlib`, plus the
import-back block and the constructor call site.

server.py: 14,037 -> 9,705 lines.

The one non-verbatim change is the seam that lets the class leave server.py:
`MetadataDB.__init__` now takes `config_dir` explicitly instead of reading the
module-level CONFIG_DIR, so `lib/metadata_db.py` does no IO at import
(Principle V). The `meta_db` singleton stays in server.py, so `server.meta_db`
(282 refs) and `server.app` (67 refs) resolve unchanged and no route moves.
None of the 114 `monkeypatch.setattr(server, ...)` targets moved.

Logging still goes through the `feedBack.server` logger, so log filters and
caplog assertions resolve to the same logger object.

`tests/test_settings_export_library_db.py` imports `_apply_pending_db_restore`
from metadata_db (the test moves with its subject); no other test changed.

Verified: pyflakes clean on the new module (zero undefined names, zero unused
imports) and no new undefined name in server.py; pytest 2341 passed;
node --test 1030 passed; eslint 0 errors; uvicorn boot smoke serves
/api/version, /api/library, and all three migrated plugins' src/ module graphs
(stems, studio, editor -> 200).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 77390968-87b8-421f-b299-3a22a19a797c

📥 Commits

Reviewing files that changed from the base of the PR and between e134f5c and 27164ec.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • docs/size-exemptions.md
  • lib/metadata_db.py
  • lib/scan_worker.py
  • server.py
  • tests/test_settings_api.py
  • tests/test_settings_export_library_db.py

📝 Walkthrough

Walkthrough

MetadataDB is extracted from server.py into lib/metadata_db.py, including schema management, metadata services, enrichment, grouping, and library queries. Server initialization, restore tests, documentation, and size tracking are updated for the new module and explicit config_dir constructor.

Changes

Metadata database implementation

Layer / File(s) Summary
MetadataDB foundation and schema
lib/metadata_db.py
Adds SQLite initialization, migrations, restoration handling, normalization helpers, and cursor pagination utilities.
Metadata domain services
lib/metadata_db.py
Adds favorites, personal metadata, progression, practice statistics, playlists, wishlist, and library-cache operations.
Enrichment and library query engine
lib/metadata_db.py
Adds enrichment lifecycle handling, filter construction, chart grouping, work-display maintenance, and library query APIs.
Server wiring and restore tests
server.py, lib/scan_worker.py, tests/test_settings_api.py, tests/test_settings_export_library_db.py, CHANGELOG.md, docs/size-exemptions.md
Updates imports and MetadataDB(CONFIG_DIR) construction, removes duplicated helpers, adjusts smart arrangement selection, redirects restore tests, and documents the extraction.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: extracting MetadataDB from server.py into lib/metadata_db.py.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/r3-metadata-db

Comment @coderabbitai help to get the list of available commands.

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