diff --git a/src/Recyclarr.Gui/CompositionRoot.cs b/src/Recyclarr.Gui/CompositionRoot.cs index a17687f8..74cad10a 100644 --- a/src/Recyclarr.Gui/CompositionRoot.cs +++ b/src/Recyclarr.Gui/CompositionRoot.cs @@ -18,6 +18,6 @@ public static class CompositionRoot builder.RegisterType(); builder.Register(c => c.Resolve().CreateAppPaths()) .As() - .InstancePerLifetimeScope(); + .SingleInstance(); } } diff --git a/src/Recyclarr.TestLibrary/IntegrationFixture.cs b/src/Recyclarr.TestLibrary/IntegrationFixture.cs index d618eb35..758a5848 100644 --- a/src/Recyclarr.TestLibrary/IntegrationFixture.cs +++ b/src/Recyclarr.TestLibrary/IntegrationFixture.cs @@ -1,4 +1,5 @@ using System.IO.Abstractions; +using System.IO.Abstractions.Extensions; using System.IO.Abstractions.TestingHelpers; using Autofac; using Autofac.Features.ResolveAnything; @@ -6,7 +7,10 @@ using CliFx.Infrastructure; using Common.TestLibrary; using NSubstitute; using NUnit.Framework; +using Recyclarr.Command; +using Serilog; using Serilog.Events; +using TrashLib; using TrashLib.Startup; using VersionControl; using VersionControl.Wrappers; @@ -21,20 +25,32 @@ public abstract class IntegrationFixture : IDisposable protected IntegrationFixture() { var compRoot = new CompositionRoot(); - _container = compRoot.Setup(default, Console, LogEventLevel.Debug).Container - .BeginLifetimeScope(builder => - { - builder.RegisterSource(); - builder.RegisterInstance(Fs).As(); + _container = compRoot.Setup(builder => + { + builder.RegisterInstance(Fs).As(); + builder.RegisterInstance(new AppPaths(Fs.CurrentDirectory())).As(); + builder.RegisterInstance(Console).As(); + builder.Register(_ => CreateLogger()).As().SingleInstance(); + + RegisterMockFor(builder); + RegisterMockFor(builder); + RegisterMockFor(builder); + RegisterMockFor(builder); - RegisterMockFor(builder); - RegisterMockFor(builder); - RegisterMockFor(builder); - }); + builder.RegisterSource(); + }).Container; SetupMetadataJson(); } + private static ILogger CreateLogger() + { + return new LoggerConfiguration() + .MinimumLevel.Is(LogEventLevel.Debug) + .WriteTo.Console() + .CreateLogger(); + } + private void SetupMetadataJson() { var paths = Resolve(); diff --git a/src/Recyclarr.Tests/CompositionRootTest.cs b/src/Recyclarr.Tests/CompositionRootTest.cs index 3ed293d9..89d96ad9 100644 --- a/src/Recyclarr.Tests/CompositionRootTest.cs +++ b/src/Recyclarr.Tests/CompositionRootTest.cs @@ -1,11 +1,19 @@ using System.Collections; using System.Diagnostics.CodeAnalysis; +using System.IO.Abstractions; +using System.IO.Abstractions.Extensions; +using System.IO.Abstractions.TestingHelpers; using Autofac; using Autofac.Core; using CliFx.Infrastructure; using FluentAssertions; using NSubstitute; using NUnit.Framework; +using Recyclarr.Command; +using Serilog; +using TrashLib; +using TrashLib.Config.Services; +using TrashLib.Startup; using VersionControl; namespace Recyclarr.Tests; @@ -35,7 +43,7 @@ public class CompositionRootTest { var act = () => { - using var container = new CompositionRoot().Setup("", Substitute.For(), default).Container; + using var container = new CompositionRoot().Setup().Container; service.Instantiate(container); }; @@ -53,7 +61,7 @@ public class CompositionRootTest public ConcreteTypeEnumerator() { - _container = new CompositionRoot().Setup("", Substitute.For(), default).Container; + _container = new CompositionRoot().Setup().Container; } public IEnumerator GetEnumerator() @@ -69,12 +77,21 @@ public class CompositionRootTest } } + private static void RegisterAdditionalServices(ContainerBuilder builder) + { + var fs = new MockFileSystem(); + builder.RegisterInstance(fs).As(); + builder.RegisterInstance(new AppPaths(fs.CurrentDirectory())).As(); + builder.RegisterInstance(Substitute.For()); + builder.RegisterInstance(Substitute.For()); + builder.RegisterInstance(Substitute.For()); + builder.RegisterInstance(Substitute.For()); + } + [TestCaseSource(typeof(ConcreteTypeEnumerator))] public void Service_should_be_instantiable(Type service) { - using var container = new CompositionRoot().Setup("", Substitute.For(), default).Container; - container.Invoking(c => c.Resolve(service)) - .Should().NotThrow() - .And.NotBeNull(); + using var container = new CompositionRoot().Setup(RegisterAdditionalServices).Container; + container.Resolve(service).Should().NotBeNull(); } } diff --git a/src/Recyclarr.Tests/Config/Services/ConfigurationLoaderTest.cs b/src/Recyclarr.Tests/Config/Services/ConfigurationLoaderTest.cs index 9b9d00e4..1652e2bd 100644 --- a/src/Recyclarr.Tests/Config/Services/ConfigurationLoaderTest.cs +++ b/src/Recyclarr.Tests/Config/Services/ConfigurationLoaderTest.cs @@ -14,7 +14,6 @@ using NUnit.Framework; using Recyclarr.Config; using TestLibrary; using TestLibrary.AutoFixture; -using TestLibrary.NSubstitute; using TrashLib.Config; using TrashLib.Config.Services; using TrashLib.Services.Sonarr.Config; @@ -57,7 +56,6 @@ public class ConfigurationLoaderTest [Test, AutoMockData(typeof(ConfigurationLoaderTest), nameof(BuildContainer))] public void Load_many_iterations_of_config( [Frozen] IFileSystem fs, - [Frozen] IConfigurationProvider provider, ConfigurationLoader loader) { static StreamReader MockYaml(params object[] args) @@ -86,8 +84,6 @@ public class ConfigurationLoaderTest var actual = loader.LoadMany(fakeFiles, "sonarr").ToList(); actual.Should().BeEquivalentTo(expected); - provider.Received(3).ActiveConfiguration = - Verify.That(x => expected.Should().ContainEquivalentOf(x)); } [Test, AutoMockData(typeof(ConfigurationLoaderTest), nameof(BuildContainer))] diff --git a/src/Recyclarr.Tests/Migration/MigrationExecutorTest.cs b/src/Recyclarr.Tests/Migration/MigrationExecutorTest.cs index 19347c13..28b5c510 100644 --- a/src/Recyclarr.Tests/Migration/MigrationExecutorTest.cs +++ b/src/Recyclarr.Tests/Migration/MigrationExecutorTest.cs @@ -1,9 +1,11 @@ +using Autofac; using CliFx.Infrastructure; using FluentAssertions; using NSubstitute; using NUnit.Framework; using Recyclarr.Migration; using Recyclarr.Migration.Steps; +using TrashLib.Startup; namespace Recyclarr.Tests.Migration; @@ -14,7 +16,11 @@ public class MigrationExecutorTest [Test] public void Migration_steps_are_in_expected_order() { - var container = new CompositionRoot().Setup("", Substitute.For(), default); + var container = new CompositionRoot().Setup(builder => + { + builder.RegisterInstance(Substitute.For()); + }); + var steps = container.Resolve>(); var orderedSteps = steps.OrderBy(x => x.Order).Select(x => x.GetType()).ToList(); orderedSteps.Should().BeEquivalentTo( diff --git a/src/Recyclarr/Command/BaseCommand.cs b/src/Recyclarr/Command/BaseCommand.cs index 1df0cc84..fd7b31cd 100644 --- a/src/Recyclarr/Command/BaseCommand.cs +++ b/src/Recyclarr/Command/BaseCommand.cs @@ -1,3 +1,4 @@ +using Autofac; using CliFx; using CliFx.Attributes; using CliFx.Exceptions; @@ -5,7 +6,10 @@ using CliFx.Infrastructure; using JetBrains.Annotations; using MoreLinq.Extensions; using Recyclarr.Command.Setup; +using Recyclarr.Logging; +using Serilog; using Serilog.Events; +using TrashLib.Startup; namespace Recyclarr.Command; @@ -21,6 +25,10 @@ public abstract class BaseCommand : ICommand public static ICompositionRoot? CompositionRoot { get; set; } + protected virtual void RegisterServices(ContainerBuilder builder) + { + } + public virtual async ValueTask ExecuteAsync(IConsole console) { // Must happen first because everything can use the logger. @@ -31,7 +39,20 @@ public abstract class BaseCommand : ICommand throw new CommandException("CompositionRoot must not be null"); } - using var container = CompositionRoot.Setup(AppDataDirectory, console, logLevel); + using var container = CompositionRoot.Setup(builder => + { + builder.RegisterInstance(console).As().ExternallyOwned(); + + builder.Register(c => c.Resolve().CreateAppPaths(AppDataDirectory)) + .As() + .SingleInstance(); + + builder.Register(c => c.Resolve().Create(logLevel)) + .As() + .SingleInstance(); + + RegisterServices(builder); + }); var tasks = container.Resolve>().ToArray(); tasks.ForEach(x => x.OnStart()); diff --git a/src/Recyclarr/Command/Helpers/ActiveServiceCommandProvider.cs b/src/Recyclarr/Command/Helpers/ActiveServiceCommandProvider.cs deleted file mode 100644 index de00649e..00000000 --- a/src/Recyclarr/Command/Helpers/ActiveServiceCommandProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Recyclarr.Command.Helpers; - -public class ActiveServiceCommandProvider : IActiveServiceCommandProvider -{ - private IServiceCommand? _activeCommand; - - public IServiceCommand ActiveCommand - { - get => _activeCommand ?? - throw new InvalidOperationException("The active command has not yet been determined"); - set => _activeCommand = value; - } -} diff --git a/src/Recyclarr/Command/Helpers/CacheStoragePath.cs b/src/Recyclarr/Command/Helpers/CacheStoragePath.cs index 87d10403..54dba0e0 100644 --- a/src/Recyclarr/Command/Helpers/CacheStoragePath.cs +++ b/src/Recyclarr/Command/Helpers/CacheStoragePath.cs @@ -7,14 +7,14 @@ namespace Recyclarr.Command.Helpers; public class CacheStoragePath : ICacheStoragePath { private readonly IAppPaths _paths; - private readonly IActiveServiceCommandProvider _serviceCommandProvider; + private readonly IServiceCommand _serviceCommand; - public CacheStoragePath(IAppPaths paths, IActiveServiceCommandProvider serviceCommandProvider) + public CacheStoragePath(IAppPaths paths, IServiceCommand serviceCommand) { _paths = paths; - _serviceCommandProvider = serviceCommandProvider; + _serviceCommand = serviceCommand; } public string Path => _paths.CacheDirectory - .SubDirectory(_serviceCommandProvider.ActiveCommand.Name.ToLower()).FullName; + .SubDirectory(_serviceCommand.Name.ToLower()).FullName; } diff --git a/src/Recyclarr/Command/Helpers/IActiveServiceCommandProvider.cs b/src/Recyclarr/Command/Helpers/IActiveServiceCommandProvider.cs deleted file mode 100644 index 3b427639..00000000 --- a/src/Recyclarr/Command/Helpers/IActiveServiceCommandProvider.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Recyclarr.Command.Helpers; - -public interface IActiveServiceCommandProvider -{ - IServiceCommand ActiveCommand { get; set; } -} diff --git a/src/Recyclarr/Command/RadarrCommand.cs b/src/Recyclarr/Command/RadarrCommand.cs index 8caef3ab..f0b6851b 100644 --- a/src/Recyclarr/Command/RadarrCommand.cs +++ b/src/Recyclarr/Command/RadarrCommand.cs @@ -1,7 +1,9 @@ +using Autofac; using CliFx.Attributes; using JetBrains.Annotations; using Recyclarr.Config; using Serilog; +using TrashLib.Config.Services; using TrashLib.Extensions; using TrashLib.Services.CustomFormat; using TrashLib.Services.Radarr; @@ -30,8 +32,6 @@ internal class RadarrCommand : ServiceCommand var lister = container.Resolve(); var log = container.Resolve(); - var customFormatUpdaterFactory = container.Resolve>(); - var qualityUpdaterFactory = container.Resolve>(); var configLoader = container.Resolve>(); var guideService = container.Resolve(); @@ -49,16 +49,23 @@ internal class RadarrCommand : ServiceCommand foreach (var config in configLoader.LoadMany(Config, "radarr")) { + await using var scope = container.Container.BeginLifetimeScope(builder => + { + builder.RegisterInstance(config).As(); + }); + log.Information("Processing server {Url}", FlurlLogging.SanitizeUrl(config.BaseUrl)); if (config.QualityDefinition != null) { - await qualityUpdaterFactory().Process(Preview, config); + var updater = scope.Resolve(); + await updater.Process(Preview, config); } if (config.CustomFormats.Count > 0) { - await customFormatUpdaterFactory().Process(Preview, config.CustomFormats, guideService); + var updater = scope.Resolve(); + await updater.Process(Preview, config.CustomFormats, guideService); } } } diff --git a/src/Recyclarr/Command/ServiceCommand.cs b/src/Recyclarr/Command/ServiceCommand.cs index 39e89ccc..49a93358 100644 --- a/src/Recyclarr/Command/ServiceCommand.cs +++ b/src/Recyclarr/Command/ServiceCommand.cs @@ -1,4 +1,5 @@ using System.Text; +using Autofac; using CliFx.Attributes; using CliFx.Exceptions; using CliFx.Infrastructure; @@ -7,7 +8,6 @@ using Flurl.Http; using Flurl.Http.Configuration; using JetBrains.Annotations; using Newtonsoft.Json; -using Recyclarr.Command.Helpers; using Recyclarr.Migration; using Serilog; using TrashLib; @@ -36,6 +36,11 @@ public abstract class ServiceCommand : BaseCommand, IServiceCommand public abstract string Name { get; } + protected override void RegisterServices(ContainerBuilder builder) + { + builder.RegisterInstance(this).As(); + } + public sealed override async ValueTask ExecuteAsync(IConsole console) { try @@ -68,11 +73,8 @@ public abstract class ServiceCommand : BaseCommand, IServiceCommand var settingsProvider = container.Resolve(); var repoUpdater = container.Resolve(); var configFinder = container.Resolve(); - var commandProvider = container.Resolve(); var migration = container.Resolve(); - commandProvider.ActiveCommand = this; - // Will throw if migration is required, otherwise just a warning is issued. migration.CheckNeededMigrations(); diff --git a/src/Recyclarr/Command/SonarrCommand.cs b/src/Recyclarr/Command/SonarrCommand.cs index 62fc7b88..36620c4f 100644 --- a/src/Recyclarr/Command/SonarrCommand.cs +++ b/src/Recyclarr/Command/SonarrCommand.cs @@ -4,6 +4,7 @@ using CliFx.Exceptions; using JetBrains.Annotations; using Recyclarr.Config; using Serilog; +using TrashLib.Config.Services; using TrashLib.Extensions; using TrashLib.Services.CustomFormat; using TrashLib.Services.Sonarr; @@ -44,11 +45,8 @@ public class SonarrCommand : ServiceCommand await base.Process(container); var lister = container.Resolve(); - var profileUpdaterFactory = container.Resolve>(); - var qualityUpdaterFactory = container.Resolve>(); var configLoader = container.Resolve>(); var log = container.Resolve(); - var customFormatUpdaterFactory = container.Resolve>(); var guideService = container.Resolve(); if (ListReleaseProfiles) @@ -86,26 +84,32 @@ public class SonarrCommand : ServiceCommand foreach (var config in configLoader.LoadMany(Config, "sonarr")) { + await using var scope = container.Container.BeginLifetimeScope(builder => + { + builder.RegisterInstance(config).As(); + }); + log.Information("Processing server {Url}", FlurlLogging.SanitizeUrl(config.BaseUrl)); - var scope = container.Container.BeginLifetimeScope(); var versionEnforcement = scope.Resolve(); - await versionEnforcement.DoVersionEnforcement(config); if (config.ReleaseProfiles.Count > 0) { - await profileUpdaterFactory().Process(Preview, config); + var updater = scope.Resolve(); + await updater.Process(Preview, config); } if (!string.IsNullOrEmpty(config.QualityDefinition)) { - await qualityUpdaterFactory().Process(Preview, config); + var updater = scope.Resolve(); + await updater.Process(Preview, config); } if (config.CustomFormats.Count > 0) { - await customFormatUpdaterFactory().Process(Preview, config.CustomFormats, guideService); + var updater = scope.Resolve(); + await updater.Process(Preview, config.CustomFormats, guideService); } } } diff --git a/src/Recyclarr/CompositionRoot.cs b/src/Recyclarr/CompositionRoot.cs index 1e3953e6..2fd75783 100644 --- a/src/Recyclarr/CompositionRoot.cs +++ b/src/Recyclarr/CompositionRoot.cs @@ -4,15 +4,12 @@ using Autofac; using Autofac.Core.Activators.Reflection; using Autofac.Extras.Ordering; using CliFx; -using CliFx.Infrastructure; using Common; using Recyclarr.Command.Helpers; using Recyclarr.Command.Setup; using Recyclarr.Config; using Recyclarr.Logging; using Recyclarr.Migration; -using Serilog; -using Serilog.Events; using TrashLib; using TrashLib.Cache; using TrashLib.Config; @@ -30,18 +27,15 @@ namespace Recyclarr; public class CompositionRoot : ICompositionRoot { - public IServiceLocatorProxy Setup(string? appDataDir, IConsole console, LogEventLevel logLevel) + public IServiceLocatorProxy Setup(Action? extraRegistrations = null) { - return Setup(new ContainerBuilder(), appDataDir, console, logLevel); + return Setup(new ContainerBuilder(), extraRegistrations); } - public IServiceLocatorProxy Setup(ContainerBuilder builder, string? appDataDir, IConsole console, - LogEventLevel logLevel) + private IServiceLocatorProxy Setup(ContainerBuilder builder, Action? extraRegistrations = null) { - builder.RegisterInstance(console).As().ExternallyOwned(); - - RegisterAppPaths(builder, appDataDir); - RegisterLogger(builder, logLevel); + RegisterAppPaths(builder); + RegisterLogger(builder); builder.RegisterModule(); builder.RegisterModule(); @@ -62,29 +56,24 @@ public class CompositionRoot : ICompositionRoot ConfigurationRegistrations(builder); CommandRegistrations(builder); - builder.Register(_ => AutoMapperConfig.Setup()).InstancePerLifetimeScope(); + builder.Register(_ => AutoMapperConfig.Setup()).SingleInstance(); + + extraRegistrations?.Invoke(builder); return new ServiceLocatorProxy(builder.Build()); } - private static void RegisterLogger(ContainerBuilder builder, LogEventLevel logLevel) + private static void RegisterLogger(ContainerBuilder builder) { builder.RegisterType().As(); builder.RegisterType(); - builder.Register(c => c.Resolve().Create(logLevel)) - .As() - .InstancePerLifetimeScope(); } - private static void RegisterAppPaths(ContainerBuilder builder, string? appDataDir) + private static void RegisterAppPaths(ContainerBuilder builder) { builder.RegisterModule(); builder.RegisterType().As(); builder.RegisterType(); - - builder.Register(c => c.Resolve().CreateAppPaths(appDataDir)) - .As() - .InstancePerLifetimeScope(); } private static void ConfigurationRegistrations(ContainerBuilder builder) @@ -110,13 +99,5 @@ public class CompositionRoot : ICompositionRoot // Register all types deriving from CliFx's ICommand. These are all of our supported subcommands. builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .AssignableTo(); - - // Used to access the chosen command class. This is assigned from CliTypeActivator - // - // note: Do not allow consumers to resolve IServiceConfiguration directly; if this gets cached they end up using - // the wrong configuration when multiple instances are used. - builder.RegisterType() - .As() - .InstancePerLifetimeScope(); } } diff --git a/src/Recyclarr/Config/ConfigurationLoader.cs b/src/Recyclarr/Config/ConfigurationLoader.cs index 853e6686..265afaab 100644 --- a/src/Recyclarr/Config/ConfigurationLoader.cs +++ b/src/Recyclarr/Config/ConfigurationLoader.cs @@ -11,18 +11,15 @@ namespace Recyclarr.Config; public class ConfigurationLoader : IConfigurationLoader where T : IServiceConfiguration { - private readonly IConfigurationProvider _configProvider; private readonly IDeserializer _deserializer; private readonly IFileSystem _fileSystem; private readonly IValidator _validator; public ConfigurationLoader( - IConfigurationProvider configProvider, IFileSystem fileSystem, IYamlSerializerFactory yamlFactory, IValidator validator) { - _configProvider = configProvider; _fileSystem = fileSystem; _validator = validator; _deserializer = yamlFactory.CreateDeserializer(); @@ -82,7 +79,6 @@ public class ConfigurationLoader : IConfigurationLoader { foreach (var config in configFiles.SelectMany(file => Load(file, configSection))) { - _configProvider.ActiveConfiguration = config; yield return config; } } diff --git a/src/Recyclarr/ICompositionRoot.cs b/src/Recyclarr/ICompositionRoot.cs index fa7bcfb5..918073ed 100644 --- a/src/Recyclarr/ICompositionRoot.cs +++ b/src/Recyclarr/ICompositionRoot.cs @@ -1,13 +1,8 @@ using Autofac; -using CliFx.Infrastructure; -using Serilog.Events; namespace Recyclarr; public interface ICompositionRoot { - IServiceLocatorProxy Setup(string? appDataDir, IConsole console, LogEventLevel logLevel); - - IServiceLocatorProxy Setup(ContainerBuilder builder, string? appDataDir, IConsole console, - LogEventLevel logLevel); + IServiceLocatorProxy Setup(Action? extraRegistrations = null); } diff --git a/src/Recyclarr/Logging/LoggerFactory.cs b/src/Recyclarr/Logging/LoggerFactory.cs index a8cf71e9..88358b12 100644 --- a/src/Recyclarr/Logging/LoggerFactory.cs +++ b/src/Recyclarr/Logging/LoggerFactory.cs @@ -5,7 +5,7 @@ using TrashLib.Startup; namespace Recyclarr.Logging; -internal class LoggerFactory +public class LoggerFactory { private readonly IAppPaths _paths; diff --git a/src/TrashLib.Tests/Cache/ServiceCacheTest.cs b/src/TrashLib.Tests/Cache/ServiceCacheTest.cs index d7dfcc4a..5cef7b84 100644 --- a/src/TrashLib.Tests/Cache/ServiceCacheTest.cs +++ b/src/TrashLib.Tests/Cache/ServiceCacheTest.cs @@ -10,6 +10,7 @@ using TestLibrary.AutoFixture; using TestLibrary.NSubstitute; using TrashLib.Cache; using TrashLib.Config.Services; +using TrashLib.Services.Radarr.Config; namespace TrashLib.Tests.Cache; @@ -23,17 +24,12 @@ public class ServiceCacheTest { Filesystem = fs ?? Substitute.For(); StoragePath = Substitute.For(); - ConfigProvider = Substitute.For(); - // Set up a default for the active config's base URL. This is used to generate part of the path - ConfigProvider.ActiveConfiguration = Substitute.For(); - ConfigProvider.ActiveConfiguration.BaseUrl.Returns("http://localhost:1234"); - - Cache = new ServiceCache(Filesystem, StoragePath, ConfigProvider, Substitute.For()); + var config = new RadarrConfiguration {BaseUrl = "http://localhost:1234"}; + Cache = new ServiceCache(Filesystem, StoragePath, config, Substitute.For()); } public ServiceCache Cache { get; } - public IConfigurationProvider ConfigProvider { get; } public ICacheStoragePath StoragePath { get; } public IFileSystem Filesystem { get; } } @@ -176,15 +172,15 @@ public class ServiceCacheTest [Test, AutoMockData] public void Switching_config_and_base_url_should_yield_different_cache_paths( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, - [Frozen] IConfigurationProvider provider, + [Frozen] IServiceConfiguration config, ServiceCache sut) { - provider.ActiveConfiguration.BaseUrl.Returns("http://localhost:1234"); + config.BaseUrl.Returns("http://localhost:1234"); sut.Save(new ObjectWithAttribute {TestValue = "Foo"}); // Change the active config & base URL so we get a different path - provider.ActiveConfiguration.BaseUrl.Returns("http://localhost:5678"); + config.BaseUrl.Returns("http://localhost:5678"); sut.Save(new ObjectWithAttribute {TestValue = "Bar"}); diff --git a/src/TrashLib.Tests/CustomFormat/Processors/PersistenceProcessorTest.cs b/src/TrashLib.Tests/CustomFormat/Processors/PersistenceProcessorTest.cs index c018f15a..264b16a8 100644 --- a/src/TrashLib.Tests/CustomFormat/Processors/PersistenceProcessorTest.cs +++ b/src/TrashLib.Tests/CustomFormat/Processors/PersistenceProcessorTest.cs @@ -2,7 +2,6 @@ using System.Collections.ObjectModel; using Newtonsoft.Json.Linq; using NSubstitute; using NUnit.Framework; -using TrashLib.Config.Services; using TrashLib.Services.CustomFormat.Api; using TrashLib.Services.CustomFormat.Models; using TrashLib.Services.CustomFormat.Models.Cache; @@ -22,14 +21,13 @@ public class PersistenceProcessorTest var cfApi = Substitute.For(); var qpApi = Substitute.For(); - var configProvider = Substitute.For(); - configProvider.ActiveConfiguration = new RadarrConfiguration {DeleteOldCustomFormats = true}; + var config = new RadarrConfiguration {DeleteOldCustomFormats = true}; var guideCfs = Array.Empty(); var deletedCfsInCache = new Collection(); var profileScores = new Dictionary(); - var processor = new PersistenceProcessor(cfApi, qpApi, configProvider, () => steps); + var processor = new PersistenceProcessor(cfApi, qpApi, config, () => steps); await processor.PersistCustomFormats(guideCfs, deletedCfsInCache, profileScores); steps.JsonTransactionStep.Received().RecordDeletions(Arg.Is(deletedCfsInCache), Arg.Any>()); @@ -42,41 +40,16 @@ public class PersistenceProcessorTest var cfApi = Substitute.For(); var qpApi = Substitute.For(); - var configProvider = Substitute.For(); - configProvider.ActiveConfiguration = new RadarrConfiguration {DeleteOldCustomFormats = false}; + var config = new RadarrConfiguration {DeleteOldCustomFormats = false}; var guideCfs = Array.Empty(); var deletedCfsInCache = Array.Empty(); var profileScores = new Dictionary(); - var processor = new PersistenceProcessor(cfApi, qpApi, configProvider, () => steps); + var processor = new PersistenceProcessor(cfApi, qpApi, config, () => steps); await processor.PersistCustomFormats(guideCfs, deletedCfsInCache, profileScores); steps.JsonTransactionStep.DidNotReceive() .RecordDeletions(Arg.Any>(), Arg.Any>()); } - - [Test] - public async Task Different_active_configuration_is_properly_used() - { - var steps = Substitute.For(); - var cfApi = Substitute.For(); - var qpApi = Substitute.For(); - var configProvider = Substitute.For(); - - var guideCfs = Array.Empty(); - var deletedCfsInCache = Array.Empty(); - var profileScores = new Dictionary(); - - var processor = new PersistenceProcessor(cfApi, qpApi, configProvider, () => steps); - - configProvider.ActiveConfiguration = new RadarrConfiguration {DeleteOldCustomFormats = false}; - await processor.PersistCustomFormats(guideCfs, deletedCfsInCache, profileScores); - - configProvider.ActiveConfiguration = new RadarrConfiguration {DeleteOldCustomFormats = true}; - await processor.PersistCustomFormats(guideCfs, deletedCfsInCache, profileScores); - - steps.JsonTransactionStep.Received(1) - .RecordDeletions(Arg.Any>(), Arg.Any>()); - } } diff --git a/src/TrashLib.Tests/Sonarr/SonarrCompatibilityTest.cs b/src/TrashLib.Tests/Sonarr/SonarrCompatibilityTest.cs index bf924665..d8411486 100644 --- a/src/TrashLib.Tests/Sonarr/SonarrCompatibilityTest.cs +++ b/src/TrashLib.Tests/Sonarr/SonarrCompatibilityTest.cs @@ -168,7 +168,7 @@ public class SonarrCompatibilityTest var act = () => enforcement.DoVersionEnforcement(config); - await act.Should().ThrowAsync().WithMessage("Sonarr v3*custom format*use*v4*"); + await act.Should().ThrowAsync().WithMessage("Sonarr v3*"); } [Test, AutoMockData] diff --git a/src/TrashLib/Cache/ServiceCache.cs b/src/TrashLib/Cache/ServiceCache.cs index 478addf6..a6cba5d6 100644 --- a/src/TrashLib/Cache/ServiceCache.cs +++ b/src/TrashLib/Cache/ServiceCache.cs @@ -13,7 +13,7 @@ namespace TrashLib.Cache; public class ServiceCache : IServiceCache { private static readonly Regex AllowedObjectNameCharacters = new(@"^[\w-]+$", RegexOptions.Compiled); - private readonly IConfigurationProvider _configProvider; + private readonly IServiceConfiguration _config; private readonly IFileSystem _fs; private readonly IFNV1a _hash; private readonly ICacheStoragePath _storagePath; @@ -22,12 +22,12 @@ public class ServiceCache : IServiceCache public ServiceCache( IFileSystem fs, ICacheStoragePath storagePath, - IConfigurationProvider configProvider, + IServiceConfiguration config, ILogger log) { _fs = fs; _storagePath = storagePath; - _configProvider = configProvider; + _config = config; Log = log; _hash = FNV1aFactory.Instance.Create(FNVConfig.GetPredefinedConfig(32)); _jsonSettings = new JsonSerializerSettings @@ -84,7 +84,7 @@ public class ServiceCache : IServiceCache private string BuildServiceGuid() { - return _hash.ComputeHash(Encoding.ASCII.GetBytes(_configProvider.ActiveConfiguration.BaseUrl)) + return _hash.ComputeHash(Encoding.ASCII.GetBytes(_config.BaseUrl)) .AsHexString(); } diff --git a/src/TrashLib/Config/ConfigAutofacModule.cs b/src/TrashLib/Config/ConfigAutofacModule.cs index 85780ae4..cd951118 100644 --- a/src/TrashLib/Config/ConfigAutofacModule.cs +++ b/src/TrashLib/Config/ConfigAutofacModule.cs @@ -1,7 +1,6 @@ using System.Reflection; using Autofac; using FluentValidation; -using TrashLib.Config.Services; using TrashLib.Config.Settings; using Module = Autofac.Module; @@ -15,7 +14,6 @@ public class ConfigAutofacModule : Module .AsClosedTypesOf(typeof(IValidator<>)) .AsImplementedInterfaces(); - builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As(); } diff --git a/src/TrashLib/Config/Services/ConfigurationProvider.cs b/src/TrashLib/Config/Services/ConfigurationProvider.cs deleted file mode 100644 index aee5bba0..00000000 --- a/src/TrashLib/Config/Services/ConfigurationProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TrashLib.Config.Services; - -internal class ConfigurationProvider : IConfigurationProvider -{ - private IServiceConfiguration? _activeConfiguration; - - public IServiceConfiguration ActiveConfiguration - { - get => _activeConfiguration ?? throw new NullReferenceException("Active configuration has not been set"); - set => _activeConfiguration = value; - } -} diff --git a/src/TrashLib/Config/Services/IConfigurationProvider.cs b/src/TrashLib/Config/Services/IConfigurationProvider.cs deleted file mode 100644 index db52a1b3..00000000 --- a/src/TrashLib/Config/Services/IConfigurationProvider.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TrashLib.Config.Services; - -public interface IConfigurationProvider -{ - IServiceConfiguration ActiveConfiguration { get; set; } -} diff --git a/src/TrashLib/Config/Services/ServerInfo.cs b/src/TrashLib/Config/Services/ServerInfo.cs index d7487328..626780f3 100644 --- a/src/TrashLib/Config/Services/ServerInfo.cs +++ b/src/TrashLib/Config/Services/ServerInfo.cs @@ -5,22 +5,22 @@ namespace TrashLib.Config.Services; public class ServerInfo : IServerInfo { - private readonly IConfigurationProvider _config; + private readonly IServiceConfiguration _config; - public ServerInfo(IConfigurationProvider config) + public ServerInfo(IServiceConfiguration config) { _config = config; } public Url BuildRequest() { - var apiKey = _config.ActiveConfiguration.ApiKey; - var baseUrl = _config.ActiveConfiguration.BaseUrl; + var apiKey = _config.ApiKey; + var baseUrl = _config.BaseUrl; return baseUrl .AppendPathSegment("api/v3") .SetQueryParams(new {apikey = apiKey}); } - public string SanitizedBaseUrl => FlurlLogging.SanitizeUrl(_config.ActiveConfiguration.BaseUrl); + public string SanitizedBaseUrl => FlurlLogging.SanitizeUrl(_config.BaseUrl); } diff --git a/src/TrashLib/Services/CustomFormat/Processors/PersistenceProcessor.cs b/src/TrashLib/Services/CustomFormat/Processors/PersistenceProcessor.cs index 780fde49..fc01d65c 100644 --- a/src/TrashLib/Services/CustomFormat/Processors/PersistenceProcessor.cs +++ b/src/TrashLib/Services/CustomFormat/Processors/PersistenceProcessor.cs @@ -15,7 +15,7 @@ public interface IPersistenceProcessorSteps internal class PersistenceProcessor : IPersistenceProcessor { - private readonly IConfigurationProvider _configProvider; + private readonly IServiceConfiguration _config; private readonly ICustomFormatService _customFormatService; private readonly IQualityProfileService _qualityProfileService; private readonly Func _stepsFactory; @@ -24,13 +24,13 @@ internal class PersistenceProcessor : IPersistenceProcessor public PersistenceProcessor( ICustomFormatService customFormatService, IQualityProfileService qualityProfileService, - IConfigurationProvider configProvider, + IServiceConfiguration config, Func stepsFactory) { _customFormatService = customFormatService; _qualityProfileService = qualityProfileService; _stepsFactory = stepsFactory; - _configProvider = configProvider; + _config = config; _steps = _stepsFactory(); } @@ -60,8 +60,7 @@ internal class PersistenceProcessor : IPersistenceProcessor _steps.JsonTransactionStep.Process(guideCfs, serviceCfs); // Step 1.1: Optionally record deletions of custom formats in cache but not in the guide - var config = _configProvider.ActiveConfiguration; - if (config.DeleteOldCustomFormats) + if (_config.DeleteOldCustomFormats) { _steps.JsonTransactionStep.RecordDeletions(deletedCfsInCache, serviceCfs); }