Repository navigation
Add from LibriVox: admin search, the librivox.fetch Bridge job and its match - #378
Merged
Merged
Conversation
The console's Add from LibriVox needs the community metadata database's LibriVox works and the exact recording a LibriVox project is. The client gains lookup?librivox_id= (asked alone) and works/search's source and lang filters; the Service gains LibrivoxSearch, LibrivoxWork (a work's LibriVox recordings only, never a first-recording guess) and LibrivoxRecordingOf (a lookup without a recording is not found). All three work in mirror mode through pkg/query, tested over a real artifact. Part of LibriVox L6 (v2.7.0 row 14).
An admin adds a LibriVox recording to a books library; the Bridge downloads and places it, and the placed book is recorded as that recording so /meta answers it with no console match. - bridge: the librivox.fetch kind (internal, writes, a books library, server-built strict params, deduped per library and project), so a Bridge that runs it reports the librivox feature; its result and codes; the open fetches of a set of projects. - catalog: FoldLibrivoxFetch records a done fetch's book in book_matches (accepted, set by the requesting admin), replacing a stale row at that path and never another path's, only when the result agrees with the job and names an indexed book; RecordingBooks finds a recording on this server by its exact, non-empty recording id. - api: GET /admin/librivox/search, GET /admin/librivox/work and POST /admin/librivox/fetch (admin only, 404 metadata_off, 409 in_library), the fold from OnEnded, the done job named by its book in notifications. - The scanner already skips .audiosilo/librivox.json; a test holds it. Part of LibriVox L6 (v2.7.0 row 14).
A new Library section finds LibriVox works in the community metadata database, lists a work's recordings (readers, length, sections, project, its LibriVox page) and adds one to a books library through the Bridge's librivox.fetch job, following the job until it lands. A recording already on the server links to its book instead of offering Add. Add is off, with a note, until a paired Bridge that runs librivox.fetch has reported; an offline Bridge still takes the job. With community metadata off the page says so and links to Metadata settings. The Bridge job list names the project, the bell names a finished fetch, and in_library refusals have their own words, in every console language. Part of LibriVox L6 (v2.7.0 row 14).
…g it A recording row now names a parked fetch's reason (a read-only library, a full disk) instead of the bare state, and keeps following the last job it queued or saw after the work stops naming it (the work lists only open jobs), so a failed fetch's reason no longer vanishes on the next refresh. The Portuguese strings say "o Bridge" like the rest of the console. Part of LibriVox L6 (v2.7.0 row 14).
The work route's lookup of open librivox.fetch jobs walked every fetch ever kept, ended ones too, and sorted them in a temp b-tree: nothing prunes this kind, so the set grows by one row per book added. An open job never has a finished_at, so asking for that lets idx_bridge_jobs_kind_finished reach only the open rows. The project ids are bound as one JSON list, as the package's other IN reads are. Part of LibriVox L6 (v2.7.0 row 14).
LibrivoxFetchCode, LibrivoxFetchCodes and the six code constants had no
caller outside their own test: the work route sends a job as {id, state},
so the server never states a fetch's code and the console reads it from
the job itself. A second copy of the code list with no reader could only
drift from the one that is shown.
Part of LibriVox L6 (v2.7.0 row 14).
Three places restated a rule the code already had a name for: - the three LibriVox routes wrote the metadata service's 502 by hand instead of through writeLookupFailed; - LibrivoxWork decided what a LibriVox recording is, and which page link is kept, beside librivoxOf, which /meta already uses for both; - the fold admitted "." through bridgeBookPath and then refused it by hand, which is cleanLibPath; RecordingBooks filtered an empty recording in SQL after returning early for one. No answer changes. Part of LibriVox L6 (v2.7.0 row 14).
A match applied is one of the changes the chapter check, the upcoming pass and the cover colours wake for, and every other match write reaches them through EditBook. The fold wrote the book's match without telling them, and the Bridge's rescan had already woken them before the match existed, so a book added from LibriVox waited for the next unrelated change (or the daily pass) before its work was looked at. Part of LibriVox L6 (v2.7.0 row 14).
The work query asked again every 3 s while any recording had an open job. Each ask is an uncached request to the metadata service (through one of its four work-fetch slots) plus the job and match reads, and it never stopped for a job queued behind an offline Bridge or parked on a full disk. The work document does not change while a job runs: each row already follows its own job by id and asks for the work again when it ends, and Add asks for it too. The search keeps its answers fresh for a minute, so a refocus or a retyped query does not ask the metadata service again, and Add seeds the new job after invalidating the job lists (its key sits under theirs), so the answer it just got is not refetched at once. Part of LibriVox L6 (v2.7.0 row 14).
The page restated things the console already has: the small external link (ExternalTextLink), a person's id and name (MetaPersonRef), the Bridge settings link's own label (its copy in six locales goes; es, fr, it and pt now read as the rest of the console does) and the 3 s open-job interval (JOBS_POLL_OPEN_MS). Smaller forms of the same behaviour: a row's busy flag is a boolean (each row owns its hook), the Add block is read off the Bridge note instead of being derived twice, the row's status is early returns instead of a three-deep ternary, the search text lives in the search card, and the client's search method no longer takes a language and limit nothing passes. Part of LibriVox L6 (v2.7.0 row 14).
The Bridge counts every regular file in the placed folder outside .audiosilo/, so the cover is in files and bytes too, not only the sections. Part of LibriVox L6 (v2.7.0 row 14).
OpenLibrivoxFetches was the one read of the open jobs that did not expire lapsed leases first (Job, List, OpenJob and Blocker all do). A fetch whose lease ran out on its last attempt, the Bridge having died, stayed claimed in the table until something else expired it, so the work route went on listing it as the recording's open job and the console kept Add off. Part of LibriVox L6 (v2.7.0 row 14).
book_matches is keyed by library and path, with no index by work or recording, so the work route scanned the whole table once per LibriVox recording of the work. WorkRecordingBooks reads the work's matched books once, grouped by recording; RecordingBooks (the fetch route's check) goes through it, so the rule lives in one query. in_library is still an empty list for a recording with no book. Part of LibriVox L6 (v2.7.0 row 14).
Four ways a recording's row lost track of its fetch: - The server records a done fetch's book just after the job reads done. A poll landing between the two asked the work once, was told the book is not in the library, and never asked again, so Add came back after a successful add. A done job now asks once more two seconds later. - A failed ask for the work again (after an Add, or when a job ends) replaced the whole card with the error. Every row unmounted and forgot the job it followed, so after Retry a failed fetch no longer said why. The rows stay while there is an earlier answer to show. - A followed job that is gone (its library deleted) answered 404, but the last good answer stayed as the job's state: the row read Queued or Running for ever, Add stayed off and the 404 was polled every 3 s. A 404 now drops the job, stops the poll and asks the work again. - Rows invalidated the work by the id in its answer, while the query is keyed by the id asked for. A retired work id answers with its new one, so neither ask reached the query. Part of LibriVox L6 (v2.7.0 row 14).
A fetch parked on a read-only library read in the bell as "The job is waiting for you (not_writable)", while the LibriVox page and the Bridge's job list both word the code. The bell now uses the same words for a librivox.fetch's known park codes; another kind's job with the same code reads as before. Part of LibriVox L6 (v2.7.0 row 14).
The link under "Adding a book needs a paired Bridge" took the shared default label, which in Spanish, French, Italian and Portuguese says "de la Bridge" where this page's notes say "un Bridge": a note and the link beside it disagreed in one sentence. The page's own label, worded like its notes, is back. Part of LibriVox L6 (v2.7.0 row 14).
…x recording
The Community metadata card told a book with no ASIN or ISBN that it was
"matched to its store listing", which is wrong for a book added from
LibriVox: its recording has no store listing. The card now reads the
book's /meta answer (already fetched for the Story card), whose recording
carries a librivox block only for a LibriVox recording, and says "Matched
to its LibriVox recording" when that is the recorded match. Retail matches
keep the store listing line; until /meta answers the line stays neutral
("Matched ...") rather than guess. In all six console languages.
Part of LibriVox L6 (v2.7.0 row 14).
KodeStar
added a commit
to KodeStar/audiosilo-frontend
that referenced
this pull request
Nov 13, 2026
…292) LibriVox L6-2 (v2.7.0 row 14, LIBRIVOX-PLAN.md "L6"), the player side of Add from LibriVox. What: - A books library's Books mode gets a "..." menu with "Find on LibriVox" (admins only). It opens `/find-librivox?connection=&library=`, a Library-tab page beside Find shows. - Search LibriVox works (community metadata, never librivox.org), open a work, see its LibriVox recordings (reader, length, sections, project link). "Add to <library>" queues the server's `librivox.fetch` Bridge job. The row follows the job by id (steps, sections, park and failure reasons), offers Cancel, then "In your library" with Open. Library lists are re-read when a book lands. - Gate `librivoxAccess`: admin + the `bridge` flag + `bridge.features` has `librivox` + `metadata`. Older servers and non-admins never see the menu, and a pasted URL sends no request. Offline state follows the app's offline rule. - Wire mirrored by hand: the three `/admin/librivox` routes, `GET /admin/bridge/jobs/{id}`, error codes `metadata_off`, `in_library`, `not_book_library`. Additive; no change for older servers. - Six locales; CONVENTIONS and STYLEGUIDE entries. Tests: gating, client shapes and error codes, hooks against a fake client (polling, Add, Cancel), the page's states (RNTL), the menu, the route tree. Reviews: /simplify + /code-review high (Fable 5.2) on the whole branch, fixes applied. Verified live (web export under the server's /web CSP, server + paired Bridge from the paired branches, live meta, Chrome at 1440 and 390 px): menu opens the page; Johnny Crow's Garden added and followed to "In your library", Open lands on the book, the book shows in Books mode; Cancel mid-download on a 23-section project leaves no staging folder and offers Add again; a listener, metadata off and a stopped Bridge all hide the menu and send no admin request; no console errors or CSP violations on the page. Needs a device run: the native "..." dropdown, the library Select popover (only shown with two or more books libraries, so not seen live), the LibriVox link on iOS and Android. Pairs with KodeStar/audiosilo-server#378 (routes, job, fold, console) and KodeStar/audiosilo-bridge#68 (librivox.fetch).
KodeStar
added a commit
to KodeStar/audiosilo-docs
that referenced
this pull request
Nov 13, 2026
…ots (#303) Docs for LibriVox L6 (v2.7.0 row 14): Add from LibriVox in the console and the player, run by the Bridge. - New User Guide page `admin/librivox` ("Add free books from LibriVox"): what is needed (admin, community metadata on, a paired Bridge with the library mapped writable), console and player steps, what lands on disk, the book arriving matched, cancel and resume, failure reasons, Clear community matches. - New Developer Docs page `bridge/librivox`: the gate, the three `/admin/librivox` routes, the `librivox.fetch` job (params, progress, result, failure codes), the identity rule (a `book_matches` row from the fold, never a first-recording fallback), archive.org-only fetching, placement, staging and resume, `.audiosilo/librivox.json`. - Updated: features, running a Bridge, Bridge jobs, console tour, books, browsing, FAQ, API reference and index, Bridge pairing/jobs, configuration, attachments, scanner, data model, web UI, notifications, player library/routes/state, the cross-repo contract, the documentation mapping table. Also adds `audible.sync` and `audible.import` where two kind lists had missed them. - Screenshots: `admin/librivox.png` and `web-player/find-librivox.png`, captured from the real UI with live community metadata. Pairs with KodeStar/audiosilo-server#378, KodeStar/audiosilo-bridge#68, KodeStar/audiosilo-frontend#292.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LibriVox L6-1 (v2.7.0 row 14, LIBRIVOX-PLAN.md "L6").
What:
internal/meta:lookup?librivox_id=and source-filtered work search (source=librivox), both also through the mirror's fallback transport.GET /admin/librivox/search,GET /admin/librivox/work,POST /admin/librivox/fetch. The fetch resolves the LibriVox project to its exact(work_id, recording_id)with meta's lookup at queue time and queues alibrivox.fetchjob (books library, writable on the Bridge, one open job per project and library). 409in_library/kind_unavailable/not_book_library, 404metadata_off.catalog.FoldLibrivoxFetch(fromOnEnded): a done fetch records abook_matchesrow (accepted, set by the requesting admin) at the placed path, so/metaanswers the new book as its recording with no console match. Never from a first-recording fallback. It replaces only a stale row at that same path.librivoxfeature. No module, no new/serverflag; additive wire.Tests: allowed and denied cases on all three routes (listener, API key, bridge/cast/feed tokens, no token,
?token=), metadata off, in_library, dedupe, lapsed leases, stale-row overwrite, another path untouched, the fold's identity checks; console tests.Reviews: /simplify + /code-review high (Fable 5.2) on the whole branch, fixes applied.
Verified live (scratch server + a real paired Bridge from KodeStar/audiosilo-bridge
feat/librivox-l6+ live meta + Chrome): project 192 added in ~3 s,/metamatched withlibrivox.id192 and no hand match, Health matched, In library + 409 on a second add,kill -9of the Bridge mid-download resumed without re-fetching finished sections, a listener gets 403 and metadata off gives 404 on all three routes.Not verified live: the
exists/disk_full/archive_unavailable/ cancel paths (Bridge tests only), mirror mode (tests only).Pairs with KodeStar/audiosilo-bridge (librivox.fetch), the player (KodeStar/audiosilo-frontend, L6-2) and the docs (KodeStar/audiosilo-docs).