diff --git a/code/backend/Cleanuparr.Api.Tests/Features/Seeker/SeekerPreviewControllerTests.cs b/code/backend/Cleanuparr.Api.Tests/Features/Seeker/SeekerPreviewControllerTests.cs index 605f405a..c3ad26c8 100644 --- a/code/backend/Cleanuparr.Api.Tests/Features/Seeker/SeekerPreviewControllerTests.cs +++ b/code/backend/Cleanuparr.Api.Tests/Features/Seeker/SeekerPreviewControllerTests.cs @@ -377,6 +377,33 @@ public class SeekerPreviewControllerTests : IDisposable response.Excluded.ShouldHaveSingleItem().Reason.ShouldBe(SeekerExclusionReason.Resting); } + [Fact] + public async Task GetPreview_RestEndsBeforeMinCycleTime_WaitsForTheRestEnd() + { + Guid cycleId = Guid.NewGuid(); + ArrInstance radarr = AddRadarr(cycleId, minCycleTimeDays: 60, restUnitsEnabled: true); + DateTimeOffset startedAt = Now.AddDays(-2); + AddCycle(cycleId, radarr.Id, startedAt, searchedUnits: 0); + _eventsContext.SeekerHistory.Add(new SeekerHistory + { + ArrInstanceId = radarr.Id, + ExternalItemId = 1, + ItemType = InstanceType.Radarr, + CycleId = Guid.NewGuid(), + LastSearchedAt = Now.AddDays(-3), + ItemTitle = "Movie 1", + ConsecutiveMisses = 4, + }); + _eventsContext.SaveChanges(); + SetupMovies(Movie(1)); + + SeekerPreviewResponse response = Preview(await _controller.GetPreview(radarr.Id, CancellationToken.None)); + + DateTimeOffset restUntil = response.Excluded.ShouldHaveSingleItem().RestUntil.ShouldNotBeNull(); + restUntil.ShouldBeLessThan(startedAt.AddDays(60)); + response.CycleWaitingUntil.ShouldBe(restUntil); + } + [Fact] public async Task GetPreview_UnsearchedCycleWithNothingLeftOrResting_DoesNotWait() { diff --git a/code/backend/Cleanuparr.Api/Features/Seeker/Controllers/SeekerPreviewController.cs b/code/backend/Cleanuparr.Api/Features/Seeker/Controllers/SeekerPreviewController.cs index 3715569b..1d532354 100644 --- a/code/backend/Cleanuparr.Api/Features/Seeker/Controllers/SeekerPreviewController.cs +++ b/code/backend/Cleanuparr.Api/Features/Seeker/Controllers/SeekerPreviewController.cs @@ -122,7 +122,14 @@ public sealed class SeekerPreviewController : ControllerBase DateTimeOffset minCycleEnd = cycle.StartedAt.AddDays(instanceConfig.MinCycleTimeDays); if (_timeProvider.GetUtcNow() < minCycleEnd) { - waitingUntil = minCycleEnd; + // A rest ending first frees its unit for the next run. + DateTimeOffset? earliestRestUntil = evaluation.Excluded + .Where(e => e.Reason == SeekerExclusionReason.Resting) + .Select(e => e.Rest?.Until) + .Min(); + waitingUntil = earliestRestUntil is { } restUntil && restUntil < minCycleEnd + ? restUntil + : minCycleEnd; } else {