Add download cleaner and dry run (#58)

This commit is contained in:
Marius Nechifor
2025-02-16 03:09:07 +02:00
parent 19b3675701
commit 596a5aed8d
86 changed files with 2503 additions and 409 deletions
+27 -10
View File
@@ -1,3 +1,4 @@
using Common.Attributes;
using Common.Configuration.Arr;
using Common.Configuration.Logging;
using Common.Configuration.QueueCleaner;
@@ -5,6 +6,8 @@ using Common.Helpers;
using Domain.Enums;
using Domain.Models.Arr;
using Domain.Models.Arr.Queue;
using Infrastructure.Interceptors;
using Infrastructure.Verticals.Arr.Interfaces;
using Infrastructure.Verticals.ItemStriker;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -12,24 +15,30 @@ using Newtonsoft.Json;
namespace Infrastructure.Verticals.Arr;
public abstract class ArrClient
public abstract class ArrClient : InterceptedService, IArrClient, IDryRunService
{
protected readonly ILogger<ArrClient> _logger;
protected readonly HttpClient _httpClient;
protected readonly LoggingConfig _loggingConfig;
protected readonly QueueCleanerConfig _queueCleanerConfig;
protected readonly Striker _striker;
protected readonly IStriker _striker;
/// <summary>
/// Constructor to be used by interceptors.
/// </summary>
protected ArrClient()
{
}
protected ArrClient(
ILogger<ArrClient> logger,
IHttpClientFactory httpClientFactory,
IOptions<LoggingConfig> loggingConfig,
IOptions<QueueCleanerConfig> queueCleanerConfig,
Striker striker
IStriker striker
)
{
_logger = logger;
_striker = striker;
_httpClient = httpClientFactory.CreateClient(Constants.HttpClientWithRetryName);
_loggingConfig = loggingConfig.Value;
_queueCleanerConfig = queueCleanerConfig.Value;
@@ -110,16 +119,14 @@ public abstract class ArrClient
public virtual async Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient)
{
Uri uri = new(arrInstance.Url, GetQueueDeleteUrlPath(record.Id, removeFromClient));
using HttpRequestMessage request = new(HttpMethod.Delete, uri);
SetApiKey(request, arrInstance.ApiKey);
using HttpResponseMessage response = await _httpClient.SendAsync(request);
try
{
response.EnsureSuccessStatusCode();
using HttpRequestMessage request = new(HttpMethod.Delete, uri);
SetApiKey(request, arrInstance.ApiKey);
using var _ = await ((ArrClient)Proxy).SendRequestAsync(request);
_logger.LogInformation(
removeFromClient
? "queue item deleted | {url} | {title}"
@@ -157,6 +164,16 @@ public abstract class ArrClient
request.Headers.Add("x-api-key", apiKey);
}
[DryRunSafeguard]
protected virtual async Task<HttpResponseMessage> SendRequestAsync(HttpRequestMessage request)
{
HttpResponseMessage response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return response;
}
private bool HasIgnoredPatterns(QueueRecord record)
{
if (_queueCleanerConfig.ImportFailedIgnorePatterns?.Count is null or 0)
@@ -1,6 +1,7 @@
using Common.Configuration;
using Common.Configuration.Arr;
using Domain.Models.Arr.Queue;
using Infrastructure.Verticals.Arr.Interfaces;
using Microsoft.Extensions.Logging;
namespace Infrastructure.Verticals.Arr;
@@ -14,7 +15,7 @@ public sealed class ArrQueueIterator
_logger = logger;
}
public async Task Iterate(ArrClient arrClient, ArrInstance arrInstance, Func<IReadOnlyList<QueueRecord>, Task> action)
public async Task Iterate(IArrClient arrClient, ArrInstance arrInstance, Func<IReadOnlyList<QueueRecord>, Task> action)
{
const ushort maxPage = 100;
ushort page = 1;
@@ -0,0 +1,19 @@
using Common.Configuration.Arr;
using Domain.Enums;
using Domain.Models.Arr;
using Domain.Models.Arr.Queue;
namespace Infrastructure.Verticals.Arr.Interfaces;
public interface IArrClient
{
Task<QueueListResponse> GetQueueItemsAsync(ArrInstance arrInstance, int page);
Task<bool> ShouldRemoveFromQueue(InstanceType instanceType, QueueRecord record, bool isPrivateDownload);
Task DeleteQueueItemAsync(ArrInstance arrInstance, QueueRecord record, bool removeFromClient);
Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<SearchItem>? items);
bool IsRecordValid(QueueRecord record);
}
@@ -0,0 +1,5 @@
namespace Infrastructure.Verticals.Arr.Interfaces;
public interface ILidarrClient : IArrClient
{
}
@@ -0,0 +1,5 @@
namespace Infrastructure.Verticals.Arr.Interfaces;
public interface IRadarrClient : IArrClient
{
}
@@ -0,0 +1,5 @@
namespace Infrastructure.Verticals.Arr.Interfaces;
public interface ISonarrClient : IArrClient
{
}
@@ -5,6 +5,7 @@ using Common.Configuration.QueueCleaner;
using Domain.Models.Arr;
using Domain.Models.Arr.Queue;
using Domain.Models.Lidarr;
using Infrastructure.Verticals.Arr.Interfaces;
using Infrastructure.Verticals.ItemStriker;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -12,14 +13,19 @@ using Newtonsoft.Json;
namespace Infrastructure.Verticals.Arr;
public sealed class LidarrClient : ArrClient
public class LidarrClient : ArrClient, ILidarrClient
{
/// <inheritdoc/>
public LidarrClient()
{
}
public LidarrClient(
ILogger<LidarrClient> logger,
IHttpClientFactory httpClientFactory,
IOptions<LoggingConfig> loggingConfig,
IOptions<QueueCleanerConfig> queueCleanerConfig,
Striker striker
IStriker striker
) : base(logger, httpClientFactory, loggingConfig, queueCleanerConfig, striker)
{
}
@@ -54,13 +60,12 @@ public sealed class LidarrClient : ArrClient
);
SetApiKey(request, arrInstance.ApiKey);
using var response = await _httpClient.SendAsync(request);
string? logContext = await ComputeCommandLogContextAsync(arrInstance, command);
try
{
response.EnsureSuccessStatusCode();
using var _ = await ((LidarrClient)Proxy).SendRequestAsync(request);
_logger.LogInformation("{log}", GetSearchLog(arrInstance.Url, command, true, logContext));
}
catch
@@ -5,6 +5,7 @@ using Common.Configuration.QueueCleaner;
using Domain.Models.Arr;
using Domain.Models.Arr.Queue;
using Domain.Models.Radarr;
using Infrastructure.Verticals.Arr.Interfaces;
using Infrastructure.Verticals.ItemStriker;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -12,14 +13,19 @@ using Newtonsoft.Json;
namespace Infrastructure.Verticals.Arr;
public sealed class RadarrClient : ArrClient
public class RadarrClient : ArrClient, IRadarrClient
{
/// <inheritdoc/>
public RadarrClient()
{
}
public RadarrClient(
ILogger<ArrClient> logger,
IHttpClientFactory httpClientFactory,
IOptions<LoggingConfig> loggingConfig,
IOptions<QueueCleanerConfig> queueCleanerConfig,
Striker striker
IStriker striker
) : base(logger, httpClientFactory, loggingConfig, queueCleanerConfig, striker)
{
}
@@ -62,12 +68,11 @@ public sealed class RadarrClient : ArrClient
);
SetApiKey(request, arrInstance.ApiKey);
using HttpResponseMessage response = await _httpClient.SendAsync(request);
string? logContext = await ComputeCommandLogContextAsync(arrInstance, command);
try
{
response.EnsureSuccessStatusCode();
using var _ = await ((RadarrClient)Proxy).SendRequestAsync(request);
_logger.LogInformation("{log}", GetSearchLog(arrInstance.Url, command, true, logContext));
}
@@ -5,6 +5,7 @@ using Common.Configuration.QueueCleaner;
using Domain.Models.Arr;
using Domain.Models.Arr.Queue;
using Domain.Models.Sonarr;
using Infrastructure.Verticals.Arr.Interfaces;
using Infrastructure.Verticals.ItemStriker;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -13,14 +14,19 @@ using Series = Domain.Models.Sonarr.Series;
namespace Infrastructure.Verticals.Arr;
public sealed class SonarrClient : ArrClient
public class SonarrClient : ArrClient, ISonarrClient
{
/// <inheritdoc/>
public SonarrClient()
{
}
public SonarrClient(
ILogger<SonarrClient> logger,
IHttpClientFactory httpClientFactory,
IOptions<LoggingConfig> loggingConfig,
IOptions<QueueCleanerConfig> queueCleanerConfig,
Striker striker
IStriker striker
) : base(logger, httpClientFactory, loggingConfig, queueCleanerConfig, striker)
{
}
@@ -58,13 +64,12 @@ public sealed class SonarrClient : ArrClient
);
SetApiKey(request, arrInstance.ApiKey);
using HttpResponseMessage response = await _httpClient.SendAsync(request);
string? logContext = await ComputeCommandLogContextAsync(arrInstance, command, command.SearchType);
try
{
response.EnsureSuccessStatusCode();
using var _ = await ((SonarrClient)Proxy).SendRequestAsync(request);
_logger.LogInformation("{log}", GetSearchLog(command.SearchType, arrInstance.Url, command, true, logContext));
}
catch