Docs: the database through SeaORM
CLAUDE.md and the architecture notes described the SQL schema and migrate(), both gone: the entities are the schema, create_missing makes what is missing, and hand-written SQL has to run on SQLite and Postgres both. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
16
CLAUDE.md
16
CLAUDE.md
@@ -125,7 +125,7 @@ Non-trivial logic leaves one runnable check behind. Pure functions (`merge_polic
|
||||
subscriber. Two feeds publishing the same URL means only the first one scanned shows it.
|
||||
* **Read state lives in `entry_state`, per user, and nowhere else.** `entries` had `read`, `flagged`
|
||||
and `position` columns from before accounts; two bugs came from queries still reading them
|
||||
(retention, and the entry pruner), and `migrate()` now drops them.
|
||||
(retention, and the entry pruner), and they were dropped in 0.5.
|
||||
* **The catalogue is config.toml; the subscriptions are in the database.** A feed exists once;
|
||||
`subscriptions(user_id, feed_id)` says who wants it and with what settings. OPML children are
|
||||
derived and never written to config.
|
||||
@@ -140,10 +140,16 @@ Non-trivial logic leaves one runnable check behind. Pure functions (`merge_polic
|
||||
* `/api/settings` answering `200` does **not** mean the daemon is well — the web server is a
|
||||
different task. `ipx status` checks the control socket and the database; to see the worker
|
||||
getting through its jobs, watch for `scan complete` in the log.
|
||||
* **Every `ipx` command runs `migrate()` when it opens the database**, the healthcheck's
|
||||
`ipx status` included. A migration that rewrites a big table (`DROP COLUMN`) takes seconds on
|
||||
production, and a command run meanwhile fails with `migrating schema`. It changes nothing; wait
|
||||
for `daemon started` in the log. Copy `state.db` aside before deploying one.
|
||||
* **The database goes through SeaORM, and the entities in `src/entity.rs` are the schema.**
|
||||
`Db::open` creates any missing table or index from them (`create_missing`), on every `ipx`
|
||||
command, the healthcheck's `ipx status` included, so it must never write when nothing is
|
||||
missing: SeaORM's experimental schema sync dropped and remade an index on every open, the
|
||||
write lock that took made `ipx status` time out behind a busy daemon, and it was removed for
|
||||
it. A new column on an existing table needs its own `ALTER`; nothing adds one for you.
|
||||
* **SQL written by hand in `db.rs` has to run on SQLite and Postgres both** (issue #18): `$1`
|
||||
parameters, bound only if used; `ON CONFLICT`, not `INSERT OR IGNORE`; yes/no columns tested
|
||||
as themselves (`NOT coalesce(s.read, false)`) and written as `true`/`false`, never compared to
|
||||
1; no `rowid`, `GLOB` or `UPDATE OR IGNORE`. `Args` in `db.rs` builds the parameters.
|
||||
|
||||
## House style
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ it to a running daemon.
|
||||
|---|---|---|
|
||||
| `src/main.rs` | CLI, dispatch, scan loop, download policy | `iPXAgent.py` |
|
||||
| `src/config.rs` | TOML load/save, `General`/`Feed`/`Web`, intervals, slugs | `iPXSettings.py`, `feeds.plist` |
|
||||
| `src/db.rs` | SQLite schema, migrations, every query | `.ipxd` plists, `history.dat`, `qmcache.dat` |
|
||||
| `src/db.rs` | Every query, through SeaORM; creates missing tables | `.ipxd` plists, `history.dat`, `qmcache.dat` |
|
||||
| `src/entity.rs` | The tables, as SeaORM entities: the schema | — |
|
||||
| `src/feed.rs` | Conditional GET, RSS/Atom/OPML parsing | `FeedData.__getFeed/__getEntries` |
|
||||
| `src/download.rs` | Streaming download, naming, type sniffing, placement | `iPXDownloader.getFile` |
|
||||
| `src/torrent.rs` | librqbit session, seeding limits, stall abort | vendored BitTorrent 4.2.1 |
|
||||
@@ -65,14 +66,14 @@ entry_state user_id, feed_id, guid, read, flagged, position
|
||||
```
|
||||
|
||||
Read state is `entry_state` alone. `entries` had `read`, `flagged` and `position` columns from
|
||||
before accounts; two bugs came from queries still reading them, and `migrate()` drops them from an
|
||||
older database.
|
||||
before accounts; two bugs came from queries still reading them, and they were dropped in 0.5.
|
||||
|
||||
Schema changes: add the table or column to `SCHEMA`. `CREATE TABLE IF NOT EXISTS` leaves a table
|
||||
that already exists alone, so a new column on one also goes in `migrate()`'s `wanted` list, and a
|
||||
retired one in its `retired` list; both are checked with `PRAGMA table_info`. Columns from before
|
||||
0.3.0, the oldest version an upgrade may start from, need no entry. `Db::memory()` runs the same
|
||||
path as `Db::open`, so a migration cannot pass the tests while missing in production.
|
||||
Schema changes: the tables are the entities in `src/entity.rs`, and `Db::open` creates whatever
|
||||
table or index a database is missing from them (`db::create_missing`), with `IF NOT EXISTS`. It
|
||||
never alters a table that exists, so a new column on one needs its own `ALTER` in
|
||||
`create_missing`, or `sea-orm-migration` once there are several. `Db::memory()` builds its
|
||||
database the same way, so the tests run on the schema production gets. A database from before
|
||||
0.7 takes its last columns from the old `migrate()`, so it upgrades through a 0.7 release first.
|
||||
|
||||
## Control socket
|
||||
|
||||
|
||||
Reference in New Issue
Block a user