Skip to content

ADFA-4838: durable REST job engine for live content (kiwix) - #253

Merged
luisguzman-adfa merged 3 commits into
mainfrom
feat/ADFA-4838-rest-job-engine
Jul 24, 2026
Merged

luisguzman-adfa merged 3 commits into
mainfrom
feat/ADFA-4838-rest-job-engine

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

Phase 2 of ADFA-4832 (see controller/docs/ADR-4832). Replaces the per-socket, kill-on-disconnect job handling with a durable, REST-driven engine.

  • sockets/jobs.ts — module-scoped JobManager with a better-sqlite3 journal, a per-type Runner registry, structured progress (phase / percent / bytes-per-sec), cancellation that kills tracked children, and reconcileOnBoot() to resume interrupted jobs after a dashboard restart.
  • sockets/kiwix.exec.ts — kiwix runner ported from the Phase 1 socket handler: aria2 download (structured %/rate) + iiab-make-kiwix-lib index + metadata cleanup + free-space guard. aria2 flags kept in sync with the app + the socket handler.
  • routes.ts — POST /api/:type/download, GET /api/:type/jobs(/:id), POST /api/:type/jobs/:id/cancel.
  • server.ts — mounts express.json() + /api, registers the kiwix runner, calls reconcileOnBoot().
  • nginx — localhost-only /api/ proxy to :4000.
  • ADR-4832 refreshed as the accepted full-Phase-2 design of record.

Scope note: kiwix is migrated end-to-end here (the proven path, consumed by the app in ADFA-4840). maps/books already operate through the existing dashboard handlers; their runner migration lands with their active-management redesign. Packaging (TS→JS build + supervision) is ADFA-4839.

Typechecks (tsc --noEmit). Ships via the Phase 2 rootfs rebuild. Needs on-device verification.

Phase 2 of ADFA-4832. Module-scoped, persisted job engine so a content op is owned
by the dashboard process (not a socket closure) and survives a client disconnect and
a dashboard restart.

- jobs.ts: JobManager with a better-sqlite3 journal (jobs table), per-type Runner
  registry, structured progress (phase/percent/bytes-per-sec), cancellation that kills
  tracked children, and reconcileOnBoot() to resume interrupted jobs.
- kiwix.exec.ts: kiwix runner ported from the Phase 1 socket handler — aria2 download
  (structured %/rate parsing) + iiab-make-kiwix-lib index + metadata cleanup + a free-
  space guard. aria2 flags kept in sync with the app + the socket handler.
- ADR-4832 refreshed as the accepted full-Phase-2 design of record.

Typechecks (tsc --noEmit). Not wired into server.ts yet (REST routes + reconcile call
come next); no runtime behavior change until then.
- routes.ts: POST /api/:type/download, GET /api/:type/jobs(/:id), POST .../cancel.
  Stateless calls over the durable engine; clients re-attach by polling the id.
- server.ts: mount express.json() + /api router, import the kiwix runner (registers it),
  and call jobs.reconcileOnBoot() on listen so interrupted jobs resume.
- nginx: add a localhost-only /api/ proxy to :4000 (mirrors the /dashboard/ + /socket.io/
  locations).

Kiwix now works end-to-end over REST. maps/books runners and retiring the socket-owned
job paths are the next steps. Typechecks (tsc --noEmit).
Port the remaining live-content types off the Phase 1 socket handlers onto the durable
job engine, so all three run the same way.

- Generalize the job payload: items are now arbitrary (strings for kiwix ZIMs; objects
  for maps/books). RunnerContext exposes items (raw) + ids (string convenience); routes
  accept { items } or { ids }.
- maps.exec.ts: tile-extract.py extract, reusing the socket handler's box validation;
  structured progress (parses a % when the script prints one).
- books.exec.ts: Calibre-Web auth/CSRF + Gutenberg fetch + upload, per-book progress.

Deletion (maps/books) stays a separate op for now. Typechecks (tsc --noEmit).
@luisguzman-adfa
luisguzman-adfa merged commit e2e9ab4 into main Jul 24, 2026
4 checks passed
@luisguzman-adfa
luisguzman-adfa deleted the feat/ADFA-4838-rest-job-engine branch July 24, 2026 02:47
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