diff --git a/code/Executable/DependencyInjection/QuartzDI.cs b/code/Executable/DependencyInjection/QuartzDI.cs index 31b1ea40..afa18d91 100644 --- a/code/Executable/DependencyInjection/QuartzDI.cs +++ b/code/Executable/DependencyInjection/QuartzDI.cs @@ -1,10 +1,11 @@ -using Common.Configuration; +using Common.Configuration; using Common.Configuration.ContentBlocker; using Common.Configuration.DownloadCleaner; using Common.Configuration.General; using Common.Configuration.QueueCleaner; using Common.Helpers; using Executable.Jobs; +using Infrastructure.Configuration; using Infrastructure.Verticals.ContentBlocker; using Infrastructure.Verticals.DownloadCleaner; using Infrastructure.Verticals.Jobs; @@ -20,16 +21,27 @@ public static class QuartzDI services .AddQuartz(q => { - TriggersConfig? config = configuration - .GetRequiredSection(TriggersConfig.SectionName) - .Get(); + // We'll configure triggers from a dedicated JSON file + var triggerConfigTask = services + .BuildServiceProvider() + .GetRequiredService() + .GetConfigurationAsync("triggers.json"); + + triggerConfigTask.Wait(); + TriggersConfig? config = triggerConfigTask.Result; if (config is null) { - throw new NullReferenceException("triggers configuration is null"); + // Create a default if it doesn't exist + config = new TriggersConfig + { + ContentBlocker = "0 */30 * ? * *", // Every 30 minutes + QueueCleaner = "0 */15 * ? * *", // Every 15 minutes + DownloadCleaner = "0 */20 * ? * *" // Every 20 minutes + }; } - q.AddJobs(configuration, config); + q.AddJobs(services.BuildServiceProvider(), config); }) .AddQuartzHostedService(opt => { @@ -38,19 +50,22 @@ public static class QuartzDI private static void AddJobs( this IServiceCollectionQuartzConfigurator q, - IConfiguration configuration, + IServiceProvider serviceProvider, TriggersConfig triggersConfig ) { - ContentBlockerConfig? contentBlockerConfig = configuration - .GetRequiredSection(ContentBlockerConfig.SectionName) - .Get(); + var configManager = serviceProvider.GetRequiredService(); + + // Get configurations from JSON files + var contentBlockerConfigTask = configManager.GetContentBlockerConfigAsync(); + contentBlockerConfigTask.Wait(); + ContentBlockerConfig? contentBlockerConfig = contentBlockerConfigTask.Result; q.AddJob(contentBlockerConfig, triggersConfig.ContentBlocker); - QueueCleanerConfig? queueCleanerConfig = configuration - .GetRequiredSection(QueueCleanerConfig.SectionName) - .Get(); + var queueCleanerConfigTask = configManager.GetQueueCleanerConfigAsync(); + queueCleanerConfigTask.Wait(); + QueueCleanerConfig? queueCleanerConfig = queueCleanerConfigTask.Result; if (contentBlockerConfig?.Enabled is true && queueCleanerConfig is { Enabled: true, RunSequentially: true }) { @@ -62,9 +77,9 @@ public static class QuartzDI q.AddJob(queueCleanerConfig, triggersConfig.QueueCleaner); } - DownloadCleanerConfig? downloadCleanerConfig = configuration - .GetRequiredSection(DownloadCleanerConfig.SectionName) - .Get(); + var downloadCleanerConfigTask = configManager.GetDownloadCleanerConfigAsync(); + downloadCleanerConfigTask.Wait(); + DownloadCleanerConfig? downloadCleanerConfig = downloadCleanerConfigTask.Result; q.AddJob(downloadCleanerConfig, triggersConfig.DownloadCleaner); } diff --git a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs b/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs index 56ce043e..be2b8bcd 100644 --- a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs +++ b/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Text.RegularExpressions; using Common.Configuration.Arr; using Common.Configuration.ContentBlocker; @@ -6,6 +6,7 @@ using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr; using Domain.Models.Arr.Queue; +using Infrastructure.Configuration; using Infrastructure.Helpers; using Infrastructure.Providers; using Infrastructure.Verticals.Arr; @@ -18,7 +19,6 @@ using Infrastructure.Verticals.Notifications; using MassTransit; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using LogContext = Serilog.Context.LogContext; namespace Infrastructure.Verticals.ContentBlocker; @@ -28,14 +28,11 @@ public sealed class ContentBlocker : GenericHandler private readonly ContentBlockerConfig _config; private readonly BlocklistProvider _blocklistProvider; private readonly IgnoredDownloadsProvider _ignoredDownloadsProvider; + private readonly IConfigurationManager _configManager; public ContentBlocker( ILogger logger, - IOptions config, - IOptions downloadClientConfig, - IOptions sonarrConfig, - IOptions radarrConfig, - IOptions lidarrConfig, + IConfigurationManager configManager, IMemoryCache cache, IBus messageBus, ArrClientFactory arrClientFactory, @@ -45,19 +42,38 @@ public sealed class ContentBlocker : GenericHandler INotificationPublisher notifier, IgnoredDownloadsProvider ignoredDownloadsProvider ) : base( - logger, downloadClientConfig, - sonarrConfig, radarrConfig, lidarrConfig, - cache, messageBus, arrClientFactory, arrArrQueueIterator, downloadServiceFactory, - notifier + logger, cache, messageBus, + arrClientFactory, arrArrQueueIterator, + downloadServiceFactory, notifier ) { - _config = config.Value; + _configManager = configManager; _blocklistProvider = blocklistProvider; _ignoredDownloadsProvider = ignoredDownloadsProvider; + + // Initialize the configuration + var configTask = _configManager.GetContentBlockerConfigAsync(); + configTask.Wait(); + _config = configTask.Result ?? new ContentBlockerConfig(); + + // Initialize base class configs + InitializeConfigs().Wait(); } + private async Task InitializeConfigs() + { + // Get configurations from the configuration manager + _downloadClientConfig = await _configManager.GetDownloadClientConfigAsync() ?? new DownloadClientConfig(); + _sonarrConfig = await _configManager.GetSonarrConfigAsync() ?? new SonarrConfig(); + _radarrConfig = await _configManager.GetRadarrConfigAsync() ?? new RadarrConfig(); + _lidarrConfig = await _configManager.GetLidarrConfigAsync() ?? new LidarrConfig(); + } + public override async Task ExecuteAsync() { + // Refresh configurations before executing + await InitializeConfigs(); + if (_downloadClientConfig.DownloadClient is Common.Enums.DownloadClient.None or Common.Enums.DownloadClient.Disabled) { _logger.LogWarning("download client is not set"); diff --git a/code/Infrastructure/Verticals/DownloadCleaner/DownloadCleaner.cs b/code/Infrastructure/Verticals/DownloadCleaner/DownloadCleaner.cs index c06a5e3e..cadf641c 100644 --- a/code/Infrastructure/Verticals/DownloadCleaner/DownloadCleaner.cs +++ b/code/Infrastructure/Verticals/DownloadCleaner/DownloadCleaner.cs @@ -3,6 +3,7 @@ using Common.Configuration.DownloadCleaner; using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr.Queue; +using Infrastructure.Configuration; using Infrastructure.Providers; using Infrastructure.Verticals.Arr; using Infrastructure.Verticals.Arr.Interfaces; @@ -12,7 +13,6 @@ using Infrastructure.Verticals.Notifications; using MassTransit; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using LogContext = Serilog.Context.LogContext; namespace Infrastructure.Verticals.DownloadCleaner; @@ -22,16 +22,13 @@ public sealed class DownloadCleaner : GenericHandler private readonly DownloadCleanerConfig _config; private readonly IgnoredDownloadsProvider _ignoredDownloadsProvider; private readonly HashSet _excludedHashes = []; + private readonly IConfigurationManager _configManager; private static bool _hardLinkCategoryCreated; public DownloadCleaner( ILogger logger, - IOptions config, - IOptions downloadClientConfig, - IOptions sonarrConfig, - IOptions radarrConfig, - IOptions lidarrConfig, + IConfigurationManager configManager, IMemoryCache cache, IBus messageBus, ArrClientFactory arrClientFactory, @@ -40,19 +37,41 @@ public sealed class DownloadCleaner : GenericHandler INotificationPublisher notifier, IgnoredDownloadsProvider ignoredDownloadsProvider ) : base( - logger, downloadClientConfig, - sonarrConfig, radarrConfig, lidarrConfig, - cache, messageBus, arrClientFactory, arrArrQueueIterator, downloadServiceFactory, + logger, cache, messageBus, + arrClientFactory, arrArrQueueIterator, downloadServiceFactory, notifier ) { - _config = config.Value; - _config.Validate(); + _configManager = configManager; _ignoredDownloadsProvider = ignoredDownloadsProvider; + + // Initialize the configuration + var configTask = _configManager.GetDownloadCleanerConfigAsync(); + configTask.Wait(); + _config = configTask.Result ?? new DownloadCleanerConfig(); + if (_config != null) + { + _config.Validate(); + } + + // Initialize base class configs + InitializeConfigs().Wait(); + } + + private async Task InitializeConfigs() + { + // Get configurations from the configuration manager + _downloadClientConfig = await _configManager.GetDownloadClientConfigAsync() ?? new DownloadClientConfig(); + _sonarrConfig = await _configManager.GetSonarrConfigAsync() ?? new SonarrConfig(); + _radarrConfig = await _configManager.GetRadarrConfigAsync() ?? new RadarrConfig(); + _lidarrConfig = await _configManager.GetLidarrConfigAsync() ?? new LidarrConfig(); } public override async Task ExecuteAsync() { + // Refresh configurations before executing + await InitializeConfigs(); + if (_downloadClientConfig.DownloadClient is Common.Enums.DownloadClient.None or Common.Enums.DownloadClient.Disabled) { _logger.LogWarning("download client is not set"); diff --git a/code/Infrastructure/Verticals/Jobs/GenericHandler.cs b/code/Infrastructure/Verticals/Jobs/GenericHandler.cs index 7a21f46f..2c183ca6 100644 --- a/code/Infrastructure/Verticals/Jobs/GenericHandler.cs +++ b/code/Infrastructure/Verticals/Jobs/GenericHandler.cs @@ -3,6 +3,7 @@ using Common.Configuration.DownloadClient; using Domain.Enums; using Domain.Models.Arr; using Domain.Models.Arr.Queue; +using Infrastructure.Configuration; using Infrastructure.Verticals.Arr; using Infrastructure.Verticals.DownloadClient; using Infrastructure.Verticals.DownloadRemover.Models; @@ -10,17 +11,16 @@ using Infrastructure.Verticals.Notifications; using MassTransit; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Infrastructure.Verticals.Jobs; public abstract class GenericHandler : IHandler, IDisposable { protected readonly ILogger _logger; - protected readonly DownloadClientConfig _downloadClientConfig; - protected readonly SonarrConfig _sonarrConfig; - protected readonly RadarrConfig _radarrConfig; - protected readonly LidarrConfig _lidarrConfig; + protected DownloadClientConfig _downloadClientConfig = new(); + protected SonarrConfig _sonarrConfig = new(); + protected RadarrConfig _radarrConfig = new(); + protected LidarrConfig _lidarrConfig = new(); protected readonly IMemoryCache _cache; protected readonly IBus _messageBus; protected readonly ArrClientFactory _arrClientFactory; @@ -30,10 +30,6 @@ public abstract class GenericHandler : IHandler, IDisposable protected GenericHandler( ILogger logger, - IOptions downloadClientConfig, - IOptions sonarrConfig, - IOptions radarrConfig, - IOptions lidarrConfig, IMemoryCache cache, IBus messageBus, ArrClientFactory arrClientFactory, @@ -43,10 +39,6 @@ public abstract class GenericHandler : IHandler, IDisposable ) { _logger = logger; - _downloadClientConfig = downloadClientConfig.Value; - _sonarrConfig = sonarrConfig.Value; - _radarrConfig = radarrConfig.Value; - _lidarrConfig = lidarrConfig.Value; _cache = cache; _messageBus = messageBus; _arrClientFactory = arrClientFactory; diff --git a/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs b/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs index 6e98081c..faf92a79 100644 --- a/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs +++ b/code/Infrastructure/Verticals/QueueCleaner/QueueCleaner.cs @@ -4,6 +4,7 @@ using Common.Configuration.QueueCleaner; using Domain.Enums; using Domain.Models.Arr; using Domain.Models.Arr.Queue; +using Infrastructure.Configuration; using Infrastructure.Helpers; using Infrastructure.Providers; using Infrastructure.Verticals.Arr; @@ -16,7 +17,6 @@ using Infrastructure.Verticals.Notifications; using MassTransit; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using LogContext = Serilog.Context.LogContext; namespace Infrastructure.Verticals.QueueCleaner; @@ -25,15 +25,12 @@ public sealed class QueueCleaner : GenericHandler { private readonly QueueCleanerConfig _config; private readonly IMemoryCache _cache; + private readonly IConfigurationManager _configManager; private readonly IgnoredDownloadsProvider _ignoredDownloadsProvider; public QueueCleaner( ILogger logger, - IOptions config, - IOptions downloadClientConfig, - IOptions sonarrConfig, - IOptions radarrConfig, - IOptions lidarrConfig, + IConfigurationManager configManager, IMemoryCache cache, IBus messageBus, ArrClientFactory arrClientFactory, @@ -42,16 +39,35 @@ public sealed class QueueCleaner : GenericHandler INotificationPublisher notifier, IgnoredDownloadsProvider ignoredDownloadsProvider ) : base( - logger, downloadClientConfig, - sonarrConfig, radarrConfig, lidarrConfig, - cache, messageBus, arrClientFactory, arrArrQueueIterator, downloadServiceFactory, + logger, cache, messageBus, + arrClientFactory, arrArrQueueIterator, downloadServiceFactory, notifier ) { - _config = config.Value; - _config.Validate(); + _configManager = configManager; _cache = cache; _ignoredDownloadsProvider = ignoredDownloadsProvider; + + // Initialize the configuration + var configTask = _configManager.GetQueueCleanerConfigAsync(); + configTask.Wait(); + _config = configTask.Result ?? new QueueCleanerConfig(); + if (_config != null) + { + _config.Validate(); + } + + // Initialize base class configs + InitializeConfigs().Wait(); + } + + private async Task InitializeConfigs() + { + // Get configurations from the configuration manager + _downloadClientConfig = await _configManager.GetDownloadClientConfigAsync() ?? new DownloadClientConfig(); + _sonarrConfig = await _configManager.GetSonarrConfigAsync() ?? new SonarrConfig(); + _radarrConfig = await _configManager.GetRadarrConfigAsync() ?? new RadarrConfig(); + _lidarrConfig = await _configManager.GetLidarrConfigAsync() ?? new LidarrConfig(); } protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config)