You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Blocked by #279. Implement this only after the interactive core/enrichment split from #279 is available and stable.
Problem
CSV imports currently persist books and queue opted-in Open Library enrichment, but the normal enrichment path is a scheduled sweep that runs every five minutes.
Relevant code:
server/services/library-transfer.service.ts
server/services/book-enrichment.service.ts
server/repositories/book-enrichment.repository.ts
tasks/books/enrich-imported.ts
app/pages/library/index.vue
nuxt.config.ts
The existing worker is durable and includes claims, leases, retries, ISBN locking, additive metadata updates, and cleanup. The library page polls pending status every five seconds. However, a newly completed CSV upload may remain visibly incomplete until the next scheduled sweep starts, and the client-side update currently patches only coverPath and enrichment status rather than tags and richer metadata.
Dependency
This issue depends on #279 because the CSV path should reuse the same separation introduced there between:
persisting a minimum viable core book;
optional cover/metadata/tag enrichment;
user-visible pending and terminal enrichment states;
idempotent patching of enriched data into the UI.
Do not duplicate a second incompatible enrichment model inside the CSV import workflow.
Goal
After a CSV upload has persisted its core book records, start enrichment promptly and show progress/results in the UI without making the five-minute cron sweep the primary happy path.
Retain the durable job table and scheduled sweep as recovery for disconnects, failures, retries, and interrupted processing.
Proposed flow
Validate and persist the CSV import as it does today.
Create or update durable enrichment jobs for eligible imported records.
Return the import result once core persistence is complete; do not wait for all Open Library covers/tags.
Apply cover, suggested/system tags, description, and other enriched fields to visible records as they become available.
Leave unfinished jobs eligible for retry and for the existing scheduled sweep.
The foreground request should identify the imported batch rather than accepting arbitrary book IDs, and the service must verify that the requesting user owns the batch/jobs it processes.
The upload request itself should not remain open until the whole batch is enriched. Large imports need a quick import result followed by separately observable enrichment progress.
UI requirements
Show a clear post-import summary immediately after core persistence.
Books waiting for enrichment must show a spinner/skeleton for their covers rather than the terminal no-cover placeholder.
Cover, tags, description, and other returned metadata should update without a full reload.
Show useful terminal states for no_cover, not_found, and failed.
Progress should survive navigation to/from the library page.
The UI should communicate that the import succeeded even if optional enrichment is still running or later fails.
Cloudflare and reliability considerations
Do not rely solely on ctx.waitUntil(); its post-response extension is limited to 30 seconds.
Keep the immediate happy path attached to a client request.
Preserve durable jobs so client disconnects do not lose work.
Keep the five-minute scheduled task as a recovery sweep, not the expected start mechanism.
Maintain bounded batch size and concurrency to respect Open Library pacing and Cloudflare/D1/R2 limits.
Claims, leases, retries, and ISBN locks must remain safe under overlap between a foreground processor and the scheduled sweep.
Processing remains at-least-once, so metadata and cover application must be idempotent.
Cloudflare preview deployments intentionally omit cron triggers; the immediate foreground path should still work there.
Extend the enrichment update contract beyond only coverPath and status. It should provide enough data to patch visible books consistently, including as applicable:
user book ID and canonical book ID;
cover path;
enrichment status;
suggested/system tags;
description;
publication metadata changed by enrichment;
terminal error/outcome suitable for user-facing state.
Avoid repeatedly returning unchanged large fields if a compact versioned patch or updated-at cursor can provide the same result.
Concurrency and integrity
Foreground processing and cron recovery must be able to race safely.
Multiple imported records sharing an ISBN must not download/store duplicate covers unnecessarily.
Existing manual/user metadata must not be overwritten.
Removed or changed imported books must cause their jobs/claims to cancel safely.
Downloaded but unreferenced covers must be cleaned up.
A completed/no-cover/not-found job must not return to an infinite pending state.
Retry backoff must remain bounded and observable.
Observability
Record structured timings and counts for:
time from import completion to foreground enrichment start;
Important
Blocked by #279. Implement this only after the interactive core/enrichment split from #279 is available and stable.
Problem
CSV imports currently persist books and queue opted-in Open Library enrichment, but the normal enrichment path is a scheduled sweep that runs every five minutes.
Relevant code:
server/services/library-transfer.service.tsserver/services/book-enrichment.service.tsserver/repositories/book-enrichment.repository.tstasks/books/enrich-imported.tsapp/pages/library/index.vuenuxt.config.tsThe existing worker is durable and includes claims, leases, retries, ISBN locking, additive metadata updates, and cleanup. The library page polls pending status every five seconds. However, a newly completed CSV upload may remain visibly incomplete until the next scheduled sweep starts, and the client-side update currently patches only
coverPathand enrichment status rather than tags and richer metadata.Dependency
This issue depends on #279 because the CSV path should reuse the same separation introduced there between:
Do not duplicate a second incompatible enrichment model inside the CSV import workflow.
Goal
After a CSV upload has persisted its core book records, start enrichment promptly and show progress/results in the UI without making the five-minute cron sweep the primary happy path.
Retain the durable job table and scheduled sweep as recovery for disconnects, failures, retries, and interrupted processing.
Proposed flow
The foreground request should identify the imported batch rather than accepting arbitrary book IDs, and the service must verify that the requesting user owns the batch/jobs it processes.
Transport
Prefer the transport established by #279:
The upload request itself should not remain open until the whole batch is enriched. Large imports need a quick import result followed by separately observable enrichment progress.
UI requirements
no_cover,not_found, andfailed.Cloudflare and reliability considerations
ctx.waitUntil(); its post-response extension is limited to 30 seconds.References:
Data returned to the client
Extend the enrichment update contract beyond only
coverPathand status. It should provide enough data to patch visible books consistently, including as applicable:Avoid repeatedly returning unchanged large fields if a compact versioned patch or updated-at cursor can provide the same result.
Concurrency and integrity
Observability
Record structured timings and counts for:
This should make it possible to confirm that normal imports begin enrichment immediately while the scheduled sweep is functioning only as recovery.
Acceptance criteria
Non-goals