The Poll fills blank Covers for every Site and both Libraries #61
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
#61 The Poll fills blank Covers for every Site and both Libraries (open)
@sulthan created 2026-08-09 23:12
Parent
Spec: #55. Originating bug: #47. Architecture and rejected alternatives:
docs/adr/0007-backend-hosts-cover-bytes.md. Domain vocabulary: CONTEXT.md.
Do not close #47 or #55 from this ticket.
What to build
Every Series that is blank today gets its Cover without anyone doing
anything — including the Series that have been permanently blank since they
were created, which is the half of #47 that a fix at creation time cannot
reach on its own.
The Poll's cover prefetch is currently guarded to a single Site. That guard
goes away: the prefetch applies to every Site and both Libraries. Nothing
about Covers is conditioned on a Bookmark's kind — the shared card template
already renders both Libraries identically — so this is a guard to remove,
not a branch to add. The lightnovelworld Series that are silently blank
today are repaired by exactly this.
A Poll fills a blank Cover and never replaces one that exists. Two
reasons, both deliberate: a Cover changing under the Reader for no visible
reason is noise, and refetching on every cycle would add a request per
Series per cycle against Sites that already bot-score the deployment's
single IP. This rule is also why no migration or backfill script is needed
anywhere in this effort — the Poll already walks every Series, so the
existing blanks heal themselves.
A failed cover fetch must never fail the chapter poll, never block it, and
never consume anything it depends on. It is retried the next time that
Series is polled; there is no separate retry queue. Failures are logged with
the Series they belong to, so a broken extractor can be told apart from an
unreachable Site.
Extend the existing poller tests rather than starting a parallel harness —
they already run a real store with a fake fetcher and assert prefetch
behaviour, including that a second poll does not refetch.
Acceptance criteria
[x] The cover prefetch runs for every Site, not one
[x] The cover prefetch runs for both Libraries
[x] A Poll fills a blank Cover
[x] A Poll never replaces a Cover that already exists
[x] A failed cover fetch does not fail or block the chapter poll for that
Series
[x] A failed cover fetch is retried on the next poll of that Series, with no
separate retry queue
[x] Failures are logged with the Series they belong to
[x] Existing poller tests are extended rather than duplicated by a new
harness
[x] Manually verified: a Series that was blank before the deploy has a Cover
after a poll cycle
[x] go test ./... is green
Blocked by
• #59 — it fills blanks using that ticket's acquisition path
Implemented on
feat/61-poll-fill-blank-covers. PR: #70Acceptance criteria ticked except the manual verify (yours).
go test ./...green.Does not close #47 or #55.
Manually verified (2026-08-10, local mock): seeded three Series with blank Covers into a local stack running this branch (asura/demonic/comix), bypassing the creation-time hook to simulate pre-deploy rows. One poll cycle later the asura Series
absolute-regressioncarried a Cover end-to-end:series.cover_address=414b18b8..., public route GET /covers/414b18b8... serves 200 image/webp 614994B, API wirecoveris the absolute content-addressed URL, and the web UI (logged in via a mocked Discord OAuth flow, driven with Playwright) renders the cover image on the card. A second due cycle left cover_address untouched (never-replace holds live). The demonic and comix rows could not be fetched from the local container (ISP DNS filter answers with the internetpositif.id block page), which exercised the graceful-degrade path: failures logged per-Series, chapter poll unaffected, retried next cycle. go test ./... was already green on the branch.