[Architecture] Consolidate data access: raw SQL scattered across analyzer/jev/session, ad-hoc schema migrations in 4 modules
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start by reading app/core/db.py, app/core/db_conn.py, and the named analyzer, history, and ledger modules to map existing queries, migrations, and write paths. Then inspect validate_architecture.py and docs/architecture.md for the proposed boundaries. Done means each DB file has one versioned migration list, the historical query appears once, and get_db_connection calls outside storage are limited to db_conn.py.
Written by the indexing model from the issue text.
Description
Problem
app/core/db.py (Database, 2,228 lines) is meant to own the main DB, but other modules reach around it using db.db_path and get_db_connection directly.
Raw SQL outside the repository class
- app/core/analyzer.py:260-272 and app/core/analyzer_strategies.py:2259-2270 run the same
documents JOIN document_vectorsquery, copy-pasted. More raw access in analyzer.py:1189 and analyzer_strategies.py:2741, 2885. - app/core/jev_classifier.py:381-395 creates its own table
jev_classification_cacheinside whichever DB path it's given, and reads/writes it at 432, 460, 484 and 544. - app/core/session.py:64-90 and 417-422 query
history.dbdirectly. The first attempt uses stdlibsqlite3. - app/main.py:581 queries
sessionsdirectly infind_all_history_sessions.
Schema and migrations are ad hoc and per-module
- db.py:59-178 uses
PRAGMA user_versionplusALTER TABLE. - history.py:37-160 runs about 12 unconditional
ALTER TABLE ... ADD COLUMNstatements wrapped in try/except (history.py:70-126). - cache.py:317-327 and ledger.py:96-140 have their own
CREATE TABLEandALTER. - There is no single schema version per database file and no migration list.
Write serialization is only partly applied
Databaseroutes writes throughDBWorker.execute_write(e.g. db.py:547, 715, 740).history.pyhas 36 INSERT/UPDATE/DELETE statements that mostly run on whatever thread calls them (e.g.log_step, history.py:812).ledger.pywrites directly.- Multiple
DBWorkerinstances exist (see the composition-root issue). get_db_connectionkeeps a global per-(path, thread) cache bounded at 50 with LRU eviction that closes evicted connections (db_conn.py:72-80, 139-150), regardless of whether the owning thread is still using them.
Impact
- Schema knowledge is spread across 7+ modules, so a column rename means grepping SQL strings.
- Duplicated queries drift. For example, the two copies already differ in LEFT JOIN vs JOIN and in selected columns.
- There's no way to reason about which thread writes which DB.
Proposed approach
- Introduce per-database repository modules:
app/core/storage/main_db.py(documents, vectors, tf-idf, quarantine, jev cache),history_db.py(sessions, snapshots, step ledger) andledger_db.py. Each owns its DDL and exposes typed methods.Databasebecomes a facade overmain_db. - Add one migration runner: an ordered list of
(version, callable)per DB file, keyed offPRAGMA user_version. Replace the try/exceptALTERchains. - Move the analyzer/strategy historical-corpus query into a single repository method, for example
get_verified_documents_with_vectors(base_dir). - Define the concurrency contract in one place: either one writer per DB file (shared
DBWorkerper path) or WAL plus short-lived connections. Document it in docs/architecture.md and extendvalidate_architecture.pyto flagget_db_connection(outsideapp/core/storage/.
Acceptance criteria
grep -rn "get_db_connection(" appmatches only files under the storage layer anddb_conn.py.- Each DB file has exactly one migration list with monotonically increasing
user_version. A test opens a DB at version 0 and migrates it to head. - The duplicated historical-corpus query exists once.
- Dominant language
- Python
- Stars
- 1
- Forks
- 0
- Avg merge
- 9h 3m
- Merged PRs (30d)
- 361
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from fderuiter/sortify
-
bug ready-for-agent
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
security
Difficulty 2/5 1-3 hours Newbie friendliness 57/100
Maintainers usually reply within 1 day
-
architecture enhancement ready-for-agent
Difficulty 5/5 Over a week Newbie friendliness 35/100
fderuiter/sortify#783 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement ready-for-human
Difficulty 4/5 3-5 days Newbie friendliness 48/100
fderuiter/sortify#740 · 1 comment ·
Maintainers usually reply within 1 day
-
architecture enhancement ready-for-human
Difficulty 5/5 Over a week Newbie friendliness 25/100
fderuiter/sortify#726 · 1 comment ·
Maintainers usually reply within 1 day
All issues in fderuiter/sortify
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
MISP/misp-workbench#496 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
fossasia/visdom-dev#69 ·
Maintainers usually reply within 3 days
-
[Bug] Parameters named like a property break to_xcal()Possibly taken @atharvasalunke1267 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
collective/icalendar#2018 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day