mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 21:00:09 +00:00
Add find_missing_ebooks scheduled job
Introduce a safety-net scheduled job that scans completed audiobooks and auto-triggers ebook fetches for missing companions. Changes include: - New Prisma migration + schema field: requests.ebook_auto_retry_count (nullable) to track lifetime auto-retries. - New processor: src/lib/processors/find-missing-ebooks.processor.ts implementing the scan (limit 50), gating by ebook_auto_grab_enabled and source flags, creating ebook child requests or retrying failed ones up to a cap of 5, using transactions for race-safety and rolling back the counter if enqueue fails. - Job queue integration: add job type, payload, processor registration, and addFindMissingEbooksJob helper. - Scheduler integration: register the scheduled job (daily midnight) and trigger path. - Documentation updates: backend scheduler and ebook-sidecar docs describing behavior and limits. - Tests: add comprehensive unit tests for the processor and update scheduler tests and job-queue test helper. This implements automated recovery for missing ebook companions while keeping the retry counter processor-private and ensuring safe concurrency handling.
This commit is contained in:
@@ -24,6 +24,7 @@ export type JobType =
|
||||
| 'audible_refresh'
|
||||
| 'retry_missing_torrents'
|
||||
| 'retry_failed_imports'
|
||||
| 'find_missing_ebooks'
|
||||
| 'cleanup_seeded_torrents'
|
||||
| 'monitor_rss_feeds'
|
||||
| 'sync_reading_shelves'
|
||||
@@ -105,6 +106,10 @@ export interface RetryFailedImportsPayload extends JobPayload {
|
||||
scheduledJobId?: string;
|
||||
}
|
||||
|
||||
export interface FindMissingEbooksPayload extends JobPayload {
|
||||
scheduledJobId?: string;
|
||||
}
|
||||
|
||||
export interface CleanupSeededTorrentsPayload extends JobPayload {
|
||||
scheduledJobId?: string;
|
||||
}
|
||||
@@ -386,6 +391,12 @@ export class JobQueueService {
|
||||
return await processRetryFailedImports(payloadWithJobId);
|
||||
});
|
||||
|
||||
this.queue.process('find_missing_ebooks', 1, async (job: BullJob<FindMissingEbooksPayload>) => {
|
||||
const { processFindMissingEbooks } = await import('../processors/find-missing-ebooks.processor');
|
||||
const payloadWithJobId = await this.ensureJobRecord(job, 'find_missing_ebooks');
|
||||
return await processFindMissingEbooks(payloadWithJobId);
|
||||
});
|
||||
|
||||
this.queue.process('cleanup_seeded_torrents', 1, async (job: BullJob<CleanupSeededTorrentsPayload>) => {
|
||||
const { processCleanupSeededTorrents } = await import('../processors/cleanup-seeded-torrents.processor');
|
||||
const payloadWithJobId = await this.ensureJobRecord(job, 'cleanup_seeded_torrents');
|
||||
@@ -756,6 +767,21 @@ export class JobQueueService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add find missing ebooks job
|
||||
*/
|
||||
async addFindMissingEbooksJob(scheduledJobId?: string): Promise<string> {
|
||||
return await this.addJob(
|
||||
'find_missing_ebooks',
|
||||
{
|
||||
scheduledJobId,
|
||||
} as FindMissingEbooksPayload,
|
||||
{
|
||||
priority: 7,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cleanup seeded torrents job
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user