Isolate per-item Radarr failures in RecommendationPipeline.autoRequest

Matches the Go original's behavior: a lookup/addMovie failure for one
recommendation is logged and skipped rather than aborting the whole
auto-request batch.
This commit is contained in:
2026-08-12 21:18:33 +02:00
parent 62848f6ecd
commit 3c5f723d22
2 changed files with 46 additions and 2 deletions

View File

@@ -215,6 +215,46 @@ describe('RecommendationPipeline.autoRequest', () => {
await expect(pipeline.autoRequest([{ title: 'Dune', year: 2021, tmdbId: 1, reason: 'r' }])).resolves.toBeUndefined();
});
it('logs and continues when one recommendation fails, instead of aborting the rest', async () => {
const radarr = {
lookup: vi
.fn()
.mockRejectedValueOnce(new Error('radarr down'))
.mockResolvedValueOnce({
title: 'Arrival',
tmdbId: 2,
qualityProfileId: 1,
rootFolderPath: '/movies',
monitored: true,
addOptions: { searchForMovie: true },
}),
addMovie: vi.fn().mockResolvedValue(undefined),
} as unknown as RadarrClient;
const logger = { error: vi.fn() } as unknown as Logger;
const pipeline = new RecommendationPipeline(makeTracer(), logger, {
jellyfin: {} as JellyfinClient,
tmdb: {} as TmdbClient,
radarr,
tool: {} as MovieRecommenderTool,
searchTool: {} as MovieSearchTool,
minRatedMovies: 1,
maxRetry: 0,
});
await pipeline.autoRequest([
{ title: 'Dune', year: 2021, tmdbId: 1, reason: 'r1' },
{ title: 'Arrival', year: 2016, tmdbId: 2, reason: 'r2' },
]);
expect(logger.error).toHaveBeenCalledWith(
expect.objectContaining({ tmdbId: 1, title: 'Dune' }),
'Radarr auto-request failed'
);
expect(radarr.lookup).toHaveBeenCalledTimes(2);
expect(radarr.addMovie).toHaveBeenCalledTimes(1);
});
});
describe('RecommendationPipeline.searchAsync', () => {