From a44e2b4235617770c460470f41cbe1f57a9a8b9e Mon Sep 17 00:00:00 2001 From: rays Date: Mon, 5 Oct 2026 23:50:15 +0000 Subject: [PATCH] Bring the docs up to what changed: reload, corrections, flags, durability An audit after 0.10.1 found the docs behind the code. architecture.md named no reload command (#120) and still said a changed title was picked up, false since #96 until #141; it now says what a scan writes again, and what the Directory page's endpoint sends (#142). cli.md lacked add's --list and --category, and that add, rm and import tell a running daemon to read the catalogue again. users.md did not mention Currently Listening or its search (#127). configuration.md says that ipx no longer waits for the disk on each write, on SQLite or Postgres (#135, #140), and what that can lose. Co-Authored-By: Claude Opus 5.5 --- docs/architecture.md | 14 +++++++++----- docs/cli.md | 6 +++++- docs/configuration.md | 6 ++++++ docs/users.md | 4 ++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 60ffe0b..2924a00 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -38,7 +38,9 @@ build needs node and `npm ci` run once. re-derived into the database each scan, never written to config.toml. A Patreon creator link (a token, no `show=`) with more than one show is treated the same way, before any fetch: its shows come from Patreon's web API and each becomes a derived feed. -4. Record entries. A changed title or description flips the item back to unread. +4. Record entries: the new ones, and those the feed now gives a different title, text, artwork, + length or number, compared with what is stored for the items it lists (#141). A corrected item + keeps its read state. 5. Record enclosures. `enclosures.url` is `UNIQUE`, which is the dedupe key and subsumes the original's `history.dat` pickle: a reaped file keeps its row so it is never fetched twice. 6. Apply the merged policy (see [users.md](users.md)) and mark anything rejected as `skipped` with @@ -90,13 +92,15 @@ printf '{"cmd":"fetch","force":true}\n' | socat - UNIX-CONNECT:$XDG_RUNTIME_DIR/ ``` **Commands** — `fetch` (optional `feed`, `force`), `reap` (optional `dry_run`), `download` -(`enclosure`), `status`. +(`enclosure`), `status`, `reload` (read the catalogue and settings again from the database, which +`ipx add`, `rm` and `import` send after changing them in a process of their own; answered with +`status`). **Events** — `feed_start`, `feed_skip`, `feed_done`, `feed_error`, `progress`, `download_done`, `download_error`, `torrent_deferred`, `reaped`, `reap_done`, `scan_done`, `status`, `error`. `scan_done`, `reap_done` and `status` are terminal: a client that asked for work stops reading -there. Commands run one at a time, in the order they arrive, except `status`: the socket answers it -straight away, so the Docker healthcheck is never left waiting behind a scan or a download, and +there. Commands run one at a time, in the order they arrive, except `status` and `reload`: the +socket answers them straight away, so the Docker healthcheck is never left waiting behind a scan or a download, and answers only the client that asked, since `status` would end any other client's session. Progress carries the enclosure id, without which a UI cannot tell one download from another and @@ -128,7 +132,7 @@ else a `401`. A feed's items and files (its entries, `download-latest`, `/api/en | `POST /api/enclosures/{id}/download`, `DELETE /api/enclosures/{id}` | `?force=true` overrides the shared-file warning | | `POST /api/fetch` | | | `GET /api/opml`, `POST /api/opml` | export your subscriptions; subscribe to every feed in an OPML | -| `GET /api/directory/{id}` | a listed feed's description and latest twenty items, for its page before you subscribe: title, link, date, length and text, never a file or its address, and only for a feed the directory lists | +| `GET /api/directory/{id}` | a listed feed's description, why its last check failed when it did (in words, never its error, which can name its address), and latest twenty items, for its page before you subscribe: title, link, date, length and text, never a file or its address, and only for a feed the directory lists | | `GET /api/popular`, `GET /api/directory`, `POST /api/popular/{id}` | the ten most subscribed feeds, and every listable feed A to Z, with an OPML's feeds in place of the OPML and everyone counted (id, title, art, count, whether it is yours, the feed's iTunes category, whether it carries audio or video; never a URL, never a private feed); subscribe by id | | `GET /api/settings`, `PATCH /api/settings` | admin-only to write | | `GET /api/users`, `POST /api/users`, `PATCH /api/users/{id}`, `DELETE /api/users/{id}` | admin-only; the only admin cannot be demoted or removed | diff --git a/docs/cli.md b/docs/cli.md index 6efaf37..3f692ab 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -13,13 +13,17 @@ processes must never download the same thing. `--local` forces the work to happe | `ipx list` | Subscriptions and their state | | `ipx status` | Counts: feeds, pending, downloaded | | `ipx fetch [FEED] [--force]` | Scan everything, or one feed. `--force` ignores the TTL | -| `ipx add [--folder X] [--keywords a,b]` | Subscribe; the id comes from the feed title | +| `ipx add [--folder X] [--keywords a,b] [--list] [--category C]` | Subscribe; the id comes from the feed title. `--list` puts it in the Directory for anyone to subscribe to instead, and keeps it there when its last subscriber leaves; `--category` files it under one of the Directory's categories. Run for a feed already in the catalogue, these list it or set its category | | `ipx rm ` | Unsubscribe; downloads and history are kept | | `ipx import ` / `ipx export ` | Move subscriptions in or out. Import subscribes the first admin, as the shared web token does; in the web UI it subscribes whoever is signed in | | `ipx reap [--dry-run]` | Run retention now | | `ipx user ` | Accounts for the web UI | | `ipx daemon [--web ADDR]` | Scheduler, control socket and web UI | +`add`, `rm` and `import` change the catalogue in a process of their own. With a daemon running they +then tell it to read the catalogue again; without that it kept its own copy and wrote it back at +its next change, undoing them. If it does not answer they say so: restart it. + ## Accounts Passwords are read from **stdin**, so they miss the shell history and any `ps` listing. diff --git a/docs/configuration.md b/docs/configuration.md index 3a8a07f..b250c38 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -27,6 +27,12 @@ config.toml's default location is `$XDG_CONFIG_HOME/ipx/config.toml` Postgres database instead. Back SQLite up by copying `state.db` while the daemon is stopped, or with `sqlite3 state.db .backup`; back Postgres up with `pg_dump`. +ipx does not wait for the disk to confirm each write: SQLite syncs at checkpoints +(`synchronous=NORMAL`), and ipx's own Postgres sessions set `synchronous_commit=off`, which leaves +other databases on the server as they are. Waiting made a scan take most of a second a feed. A +crash of ipx loses nothing; a power cut, or a crash of the Postgres server, can lose the last moment +of changes, a read mark or a saved position, and never corrupts the database. + ## `[general]` ```toml diff --git a/docs/users.md b/docs/users.md index bd1e09a..c973eba 100644 --- a/docs/users.md +++ b/docs/users.md @@ -87,6 +87,10 @@ Patreon or Supercast, which put the key in the path, and any feed inside an OPML itself. Those are someone's paid subscriptions, and listing them would let anyone here read what they pay for. +**Currently Listening**, under the Directory, is every episode you started and have not finished, +across all your feeds, with how much is left. A click picks one up where you left off. The search +box looks through it, as it does a feed's items, and through the Directory by name. + An admin can do the same from **Settings → Manage users…**: add someone (with a password, or none for someone the proxy signs in), tick or untick Admin, or remove an account. Removing one takes its subscriptions and read state with it; downloaded files stay. The only admin cannot be demoted or