- jobs: a table-backed queue in the same SQLite file. No Redis, no second process, included in the same backup. claim() is a single UPDATE...RETURNING so a job cannot run twice even with several workers. Failures back off exponentially; a missing handler fails permanently rather than retrying a bug. - metadata: Provider interface plus Open Library and Google Books (both keyless). The enricher tries providers in registration order, falls back on empty, and continues past a provider error. - migration 0004: metadata_fetch records the attempt, not just the match, so a rescan does not re-hammer a rate-limited API for an item that will never match. Errors are always retried; ok/notfound are cached for 30 days. - enrichment writes provider_ids, updates title/year, links authors through people/item_people, and downloads the cover as an asset. The cover download runs outside the transaction: a slow image host must not hold a write lock. - endpoints: queue enrichment per library, and inspect an item's matches. - web: Enrich button per library. Verified live against Open Library: "The Hobbit" matched /works/OL27482W, title and year 1937 written, a 301x500 JPEG cover downloaded and served.
16 lines
730 B
SQL
16 lines
730 B
SQL
-- 0004_metadata.sql — record which providers have been tried for an item.
|
|
--
|
|
-- provider_ids records the match that was chosen. This table records the
|
|
-- attempt, including failures, so a rescan or a restart does not re-hammer a
|
|
-- rate-limited API for an item that will never match.
|
|
|
|
CREATE TABLE metadata_fetch (
|
|
item_id INTEGER NOT NULL REFERENCES media_items(id) ON DELETE CASCADE,
|
|
provider TEXT NOT NULL,
|
|
status TEXT NOT NULL, -- ok | notfound | error
|
|
detail TEXT NOT NULL DEFAULT '',
|
|
fetched_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
|
PRIMARY KEY (item_id, provider)
|
|
);
|
|
|
|
CREATE INDEX idx_metadata_fetch_item ON metadata_fetch(item_id);
|