From 614e97313eea89feaa98dfb0d5832c256f1171e2 Mon Sep 17 00:00:00 2001 From: Flaminel Date: Tue, 16 Jun 2026 23:19:58 +0300 Subject: [PATCH] passed WebhookScanTarget to ScheduleMalwareBlockerWebhookRetry instead of individual fields --- .../Features/Jobs/MalwareBlockerTests.cs | 16 +++++++++++----- .../Features/Jobs/MalwareBlocker.cs | 10 +--------- .../Services/Interfaces/IJobManagementService.cs | 12 +++++------- .../Services/JobManagementService.cs | 8 ++++---- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/code/backend/Cleanuparr.Infrastructure.Tests/Features/Jobs/MalwareBlockerTests.cs b/code/backend/Cleanuparr.Infrastructure.Tests/Features/Jobs/MalwareBlockerTests.cs index 76d4a577..2f64d61e 100644 --- a/code/backend/Cleanuparr.Infrastructure.Tests/Features/Jobs/MalwareBlockerTests.cs +++ b/code/backend/Cleanuparr.Infrastructure.Tests/Features/Jobs/MalwareBlockerTests.cs @@ -5,6 +5,7 @@ using Cleanuparr.Infrastructure.Features.Arr; using Cleanuparr.Infrastructure.Features.Arr.Interfaces; using Cleanuparr.Infrastructure.Features.DownloadClient; using Cleanuparr.Infrastructure.Features.DownloadRemover.Models; +using Cleanuparr.Infrastructure.Features.Jobs; using Cleanuparr.Infrastructure.Features.MalwareBlocker; using Cleanuparr.Infrastructure.Tests.Features.Jobs.TestHelpers; using Cleanuparr.Infrastructure.Tests.TestHelpers; @@ -417,8 +418,8 @@ public class MalwareBlockerTests : IDisposable await mockDownloadService.Received(1).BlockUnwantedFilesAsync("match-hash", Arg.Any>()); await mockDownloadService.DidNotReceive().BlockUnwantedFilesAsync("other-hash", Arg.Any>()); // Found in a client -> resolved, no retry scheduled - await _fixture.JobManagementService.DidNotReceive().ScheduleMalwareBlockerWebhookRetry( - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()); + await _fixture.JobManagementService.DidNotReceive() + .ScheduleMalwareBlockerWebhookRetry(Arg.Any()); } [Fact] @@ -468,7 +469,12 @@ public class MalwareBlockerTests : IDisposable // Assert await _fixture.JobManagementService.Received(1).ScheduleMalwareBlockerWebhookRetry( - sonarrInstance.Id, "pending-hash", 7, InstanceType.Sonarr, 1); + Arg.Is(t => + t.InstanceId == sonarrInstance.Id && + t.DownloadId == "pending-hash" && + t.ContentId == 7 && + t.Type == InstanceType.Sonarr && + t.RetryIndex == 1)); } [Fact] @@ -513,8 +519,8 @@ public class MalwareBlockerTests : IDisposable // Assert: usenet is acknowledged once seen in the queue -> no scan, no retry await mockDownloadService.DidNotReceive().BlockUnwantedFilesAsync(Arg.Any(), Arg.Any>()); - await _fixture.JobManagementService.DidNotReceive().ScheduleMalwareBlockerWebhookRetry( - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()); + await _fixture.JobManagementService.DidNotReceive() + .ScheduleMalwareBlockerWebhookRetry(Arg.Any()); } [Fact] diff --git a/code/backend/Cleanuparr.Infrastructure/Features/Jobs/MalwareBlocker.cs b/code/backend/Cleanuparr.Infrastructure/Features/Jobs/MalwareBlocker.cs index 6e0c9061..d5672336 100644 --- a/code/backend/Cleanuparr.Infrastructure/Features/Jobs/MalwareBlocker.cs +++ b/code/backend/Cleanuparr.Infrastructure/Features/Jobs/MalwareBlocker.cs @@ -139,20 +139,12 @@ public sealed class MalwareBlocker : GenericHandler if (!resolved) { - await _jobManagementService.ScheduleMalwareBlockerWebhookRetry( - target.InstanceId, target.DownloadId, target.ContentId, target.Type, target.RetryIndex); + await _jobManagementService.ScheduleMalwareBlockerWebhookRetry(target); } } protected override Task ProcessInstanceAsync(ArrInstance instance) => ScanInstanceAsync(instance); - /// - /// Iterates the instance queue and scans each download. When is set, only - /// the matching download is processed and the return value reports whether it was resolved (found and - /// scanned, a usenet record, or deliberately skipped); false means it was not yet found in any - /// download client and the webhook scan should be retried. For full scans (no target) the return - /// value is always false and ignored. - /// private async Task ScanInstanceAsync(ArrInstance instance, WebhookScanTarget? target = null) { List ignoredDownloads = ContextProvider.Get(nameof(GeneralConfig)).IgnoredDownloads; diff --git a/code/backend/Cleanuparr.Infrastructure/Services/Interfaces/IJobManagementService.cs b/code/backend/Cleanuparr.Infrastructure/Services/Interfaces/IJobManagementService.cs index 3e72d60f..f82a3394 100644 --- a/code/backend/Cleanuparr.Infrastructure/Services/Interfaces/IJobManagementService.cs +++ b/code/backend/Cleanuparr.Infrastructure/Services/Interfaces/IJobManagementService.cs @@ -1,4 +1,5 @@ using Cleanuparr.Domain.Enums; +using Cleanuparr.Infrastructure.Features.Jobs; using Cleanuparr.Infrastructure.Models; using Quartz; @@ -11,18 +12,15 @@ public interface IJobManagementService Task TriggerJobOnce(JobType jobType); /// - /// Schedules the first targeted MalwareBlocker scan for a single download received via an *arr - /// "On Grab" webhook, on the dedicated webhook JobKey (independent of the scheduled MalwareBlocker - /// job). Subsequent retries are scheduled by the handler via - /// only while the download has not been found. + /// Schedules the first targeted MalwareBlocker scan for a single download received via an *arr "On Grab" webhook. + /// Subsequent retries are scheduled by the handler via only while the download has not been found. /// Task TriggerMalwareBlockerWebhook(Guid instanceId, string downloadId, long contentId, InstanceType type); /// - /// Schedules the next targeted MalwareBlocker webhook scan after a completed attempt that did not - /// find the download, using the configured retry delays. No-op once the delays are exhausted. + /// Schedules the next targeted MalwareBlocker webhook scan after a completed attempt. /// - Task ScheduleMalwareBlockerWebhookRetry(Guid instanceId, string downloadId, long contentId, InstanceType type, int completedIndex); + Task ScheduleMalwareBlockerWebhookRetry(WebhookScanTarget target); Task> GetAllJobs(IScheduler? scheduler = null); Task GetJob(JobType jobType); diff --git a/code/backend/Cleanuparr.Infrastructure/Services/JobManagementService.cs b/code/backend/Cleanuparr.Infrastructure/Services/JobManagementService.cs index b7742f19..da752fa6 100644 --- a/code/backend/Cleanuparr.Infrastructure/Services/JobManagementService.cs +++ b/code/backend/Cleanuparr.Infrastructure/Services/JobManagementService.cs @@ -377,19 +377,19 @@ public class JobManagementService : IJobManagementService return ScheduleWebhookAttempt(instanceId, downloadId, contentId, type, attemptIndex: 0); } - public Task ScheduleMalwareBlockerWebhookRetry(Guid instanceId, string downloadId, long contentId, InstanceType type, int completedIndex) + public Task ScheduleMalwareBlockerWebhookRetry(WebhookScanTarget target) { - int nextIndex = completedIndex + 1; + int nextIndex = target.RetryIndex + 1; if (nextIndex >= Constants.MalwareBlockerWebhookRetryDelays.Count) { _logger.LogDebug( "MalwareBlocker webhook scan gave up for download {downloadId} on {type} instance {instanceId} after {attempts} attempts", - downloadId, type, instanceId, Constants.MalwareBlockerWebhookRetryDelays.Count); + target.DownloadId, target.Type, target.InstanceId, Constants.MalwareBlockerWebhookRetryDelays.Count); return Task.FromResult(false); } - return ScheduleWebhookAttempt(instanceId, downloadId, contentId, type, nextIndex); + return ScheduleWebhookAttempt(target.InstanceId, target.DownloadId, target.ContentId, target.Type, nextIndex); } private async Task ScheduleWebhookAttempt(Guid instanceId, string downloadId, long contentId, InstanceType type, int attemptIndex)