refactor: Eliminate generics for config type

pull/201/head
Robert Dailey 1 year ago
parent ea59e71b18
commit 7dec45a07a

@ -42,7 +42,7 @@ public class CacheStoragePath : ICacheStoragePath
public IFileInfo CalculatePath(string cacheObjectName)
{
return _paths.CacheDirectory
.SubDirectory(_config.ServiceName.ToLower(CultureInfo.CurrentCulture))
.SubDirectory(_config.ServiceType.ToString().ToLower(CultureInfo.CurrentCulture))
.SubDirectory(BuildUniqueServiceDir())
.File(cacheObjectName + ".json");
}

@ -1,4 +1,5 @@
using JetBrains.Annotations;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Services;
namespace Recyclarr.TrashLib.TestLibrary;
@ -6,5 +7,5 @@ namespace Recyclarr.TrashLib.TestLibrary;
[UsedImplicitly]
public class TestConfig : ServiceConfiguration
{
public override string ServiceName => "Test";
public override SupportedServices ServiceType => SupportedServices.Sonarr;
}

@ -2,6 +2,7 @@ using FluentAssertions;
using NUnit.Framework;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Config.Services;
using Recyclarr.TrashLib.Services.Radarr.Config;
using Recyclarr.TrashLib.Services.Sonarr.Config;
@ -14,17 +15,41 @@ public class ConfigRegistryTest
[Test]
public void Get_configs_by_type()
{
var configs = new[]
var configs = new IServiceConfiguration[]
{
new SonarrConfiguration {InstanceName = "one"},
new SonarrConfiguration {InstanceName = "two"}
new SonarrConfiguration {InstanceName = "two"},
new RadarrConfiguration {InstanceName = "three"}
};
var sut = new ConfigRegistry();
sut.Add(SupportedServices.Sonarr, configs[0]);
sut.Add(SupportedServices.Sonarr, configs[1]);
foreach (var c in configs)
{
sut.Add(c);
}
var result = sut.GetConfigsOfType(SupportedServices.Sonarr);
result.Should().Equal(configs.Take(2));
}
[Test]
public void Null_service_type_returns_configs_of_all_types()
{
var configs = new IServiceConfiguration[]
{
new SonarrConfiguration {InstanceName = "one"},
new SonarrConfiguration {InstanceName = "two"},
new RadarrConfiguration {InstanceName = "three"}
};
var sut = new ConfigRegistry();
foreach (var c in configs)
{
sut.Add(c);
}
var result = sut.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var result = sut.GetConfigsOfType(null);
result.Should().Equal(configs);
}
@ -33,9 +58,9 @@ public class ConfigRegistryTest
public void Get_empty_collection_when_no_configs_of_type()
{
var sut = new ConfigRegistry();
sut.Add(SupportedServices.Sonarr, new SonarrConfiguration());
sut.Add(new SonarrConfiguration());
var result = sut.GetConfigsOfType<RadarrConfiguration>(SupportedServices.Radarr);
var result = sut.GetConfigsOfType(SupportedServices.Radarr);
result.Should().BeEmpty();
}

@ -6,7 +6,6 @@ using Recyclarr.Common;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.EnvironmentVariables;
using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Services.Sonarr.Config;
using YamlDotNet.Core;
namespace Recyclarr.TrashLib.Tests.Config.Parsing;
@ -33,7 +32,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new
@ -58,7 +57,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new
@ -85,7 +84,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new
@ -112,7 +111,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new
@ -137,7 +136,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new
@ -161,7 +160,7 @@ sonarr:
var configCollection = sut.LoadFromStream(new StringReader(testYml));
var config = configCollection.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr);
var config = configCollection.GetConfigsOfType(SupportedServices.Sonarr);
config.Should().BeEquivalentTo(new[]
{
new

@ -55,7 +55,7 @@ secret_rp: 1234567
};
var parsedSecret = configLoader.LoadFromStream(new StringReader(testYml), "sonarr");
parsedSecret.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr)
parsedSecret.GetConfigsOfType(SupportedServices.Sonarr)
.Should().BeEquivalentTo(expected, o => o.Excluding(x => x.LineNumber));
}

@ -14,7 +14,6 @@ using Recyclarr.TestLibrary.AutoFixture;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Config.Yaml;
using Recyclarr.TrashLib.Services.Radarr.Config;
using Recyclarr.TrashLib.Services.Sonarr.Config;
using Recyclarr.TrashLib.TestLibrary;
@ -81,10 +80,10 @@ public class ConfigurationLoaderTest : IntegrationFixture
var loader = Resolve<IConfigurationLoader>();
var actual = loader.LoadMany(fileData.Select(x => x.Item1));
actual.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr)
actual.GetConfigsOfType(SupportedServices.Sonarr)
.Should().BeEquivalentTo(expectedSonarr);
actual.GetConfigsOfType<RadarrConfiguration>(SupportedServices.Radarr)
actual.GetConfigsOfType(SupportedServices.Radarr)
.Should().BeEquivalentTo(expectedRadarr);
}
@ -94,7 +93,7 @@ public class ConfigurationLoaderTest : IntegrationFixture
var configLoader = Resolve<ConfigurationLoader>();
var configs = configLoader.LoadFromStream(GetResourceData("Load_UsingStream_CorrectParsing.yml"), "sonarr");
configs.GetConfigsOfType<SonarrConfiguration>(SupportedServices.Sonarr)
configs.GetConfigsOfType(SupportedServices.Sonarr)
.Should().BeEquivalentTo(new List<SonarrConfiguration>
{
new()

@ -18,7 +18,7 @@ public class SonarrConfigurationValidatorTest : IntegrationFixture
var validator = Resolve<SonarrConfigurationValidator>();
var result = validator.TestValidate(config);
result.ShouldNotHaveValidationErrorFor(x => x.ServiceName);
result.ShouldNotHaveValidationErrorFor(x => x.ServiceType);
}
[Test]

@ -75,6 +75,6 @@ public class ConfigParser
throw new YamlException("Validation failed");
}
_configs.Add(_currentSection.Value, newConfig);
_configs.Add(newConfig);
}
}

@ -5,21 +5,19 @@ namespace Recyclarr.TrashLib.Config.Parsing;
public class ConfigRegistry : IConfigRegistry
{
private readonly Dictionary<SupportedServices, List<ServiceConfiguration>> _configs = new();
private readonly Dictionary<SupportedServices, List<IServiceConfiguration>> _configs = new();
public void Add(SupportedServices configType, ServiceConfiguration config)
public void Add(IServiceConfiguration config)
{
_configs.GetOrCreate(configType).Add(config);
_configs.GetOrCreate(config.ServiceType).Add(config);
}
public IReadOnlyCollection<T> GetConfigsOfType<T>(SupportedServices serviceType) where T : ServiceConfiguration
public IReadOnlyCollection<IServiceConfiguration> GetConfigsOfType(SupportedServices? serviceType)
{
if (_configs.TryGetValue(serviceType, out var configs))
{
return configs.Cast<T>().ToList();
}
return Array.Empty<T>();
return _configs
.Where(x => serviceType is null || serviceType.Value == x.Key)
.SelectMany(x => x.Value)
.ToList();
}
public bool DoesConfigExist(string name)

@ -4,6 +4,6 @@ namespace Recyclarr.TrashLib.Config.Parsing;
public interface IConfigRegistry
{
IReadOnlyCollection<T> GetConfigsOfType<T>(SupportedServices serviceType) where T : ServiceConfiguration;
IReadOnlyCollection<IServiceConfiguration> GetConfigsOfType(SupportedServices? serviceType);
bool DoesConfigExist(string name);
}

@ -2,7 +2,7 @@ namespace Recyclarr.TrashLib.Config.Services;
public interface IServiceConfiguration
{
string ServiceName { get; }
SupportedServices ServiceType { get; }
string? InstanceName { get; }
Uri BaseUrl { get; }
string ApiKey { get; }

@ -6,7 +6,7 @@ namespace Recyclarr.TrashLib.Config.Services;
public abstract class ServiceConfiguration : IServiceConfiguration
{
[YamlIgnore]
public abstract string ServiceName { get; }
public abstract SupportedServices ServiceType { get; }
// Name is set dynamically by ConfigurationLoader
[YamlIgnore]

@ -14,7 +14,6 @@ internal class ServiceConfigurationValidator : AbstractValidator<ServiceConfigur
IValidator<RadarrConfiguration> radarrValidator)
{
RuleFor(x => x.InstanceName).NotEmpty();
RuleFor(x => x.ServiceName).NotEmpty();
RuleFor(x => x.LineNumber).NotEqual(0);
RuleFor(x => x.BaseUrl).Must(x => x.Scheme is "http" or "https")
.WithMessage("Property 'base_url' is required and must be a valid URL");

@ -1,8 +1,6 @@
using Recyclarr.TrashLib.Config.Services;
namespace Recyclarr.TrashLib.Services.Processors;
public interface IServiceProcessor<T> where T : ServiceConfiguration
public interface IServiceProcessor
{
Task Process(T config, ISyncSettings settings);
Task Process(ISyncSettings settings);
}

@ -5,38 +5,41 @@ using Recyclarr.TrashLib.Services.Radarr.Config;
namespace Recyclarr.TrashLib.Services.Processors;
public class RadarrProcessor : IServiceProcessor<RadarrConfiguration>
public class RadarrProcessor : IServiceProcessor
{
private readonly ILogger _log;
private readonly ICustomFormatUpdater _cfUpdater;
private readonly IQualitySizeUpdater _qualityUpdater;
private readonly RadarrGuideService _guideService;
private readonly RadarrConfiguration _config;
public RadarrProcessor(
ILogger log,
ICustomFormatUpdater cfUpdater,
IQualitySizeUpdater qualityUpdater,
RadarrGuideService guideService)
RadarrGuideService guideService,
RadarrConfiguration config)
{
_log = log;
_cfUpdater = cfUpdater;
_qualityUpdater = qualityUpdater;
_guideService = guideService;
_config = config;
}
public async Task Process(RadarrConfiguration config, ISyncSettings settings)
public async Task Process(ISyncSettings settings)
{
var didWork = false;
if (config.QualityDefinition != null)
if (_config.QualityDefinition != null)
{
await _qualityUpdater.Process(settings.Preview, config.QualityDefinition, _guideService);
await _qualityUpdater.Process(settings.Preview, _config.QualityDefinition, _guideService);
didWork = true;
}
if (config.CustomFormats.Count > 0)
if (_config.CustomFormats.Count > 0)
{
await _cfUpdater.Process(settings.Preview, config.CustomFormats, _guideService);
await _cfUpdater.Process(settings.Preview, _config.CustomFormats, _guideService);
didWork = true;
}

@ -1,6 +1,7 @@
using Autofac;
using JetBrains.Annotations;
using Recyclarr.Common.Autofac;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Services;
namespace Recyclarr.TrashLib.Services.Processors;
@ -15,14 +16,14 @@ public class ServiceProcessorFactory
_scope = scope;
}
public LifetimeScopedValue<IServiceProcessor<T>> CreateProcessor<T>(IServiceConfiguration config)
where T : ServiceConfiguration
public LifetimeScopedValue<IServiceProcessor> CreateProcessor(
SupportedServices serviceType, IServiceConfiguration config)
{
var scope = _scope.BeginLifetimeScope(builder =>
{
builder.RegisterInstance(config).As<IServiceConfiguration>();
builder.RegisterInstance(config).As<IServiceConfiguration>().AsSelf();
});
return new LifetimeScopedValue<IServiceProcessor<T>>(scope, scope.Resolve<IServiceProcessor<T>>());
return new LifetimeScopedValue<IServiceProcessor>(scope, scope.ResolveKeyed<IServiceProcessor>(serviceType));
}
}

@ -1,6 +1,5 @@
using Autofac;
using Recyclarr.TrashLib.Services.Radarr.Config;
using Recyclarr.TrashLib.Services.Sonarr.Config;
using Recyclarr.TrashLib.Config;
namespace Recyclarr.TrashLib.Services.Processors;
@ -10,8 +9,8 @@ public class ServiceProcessorsAutofacModule : Module
{
base.Load(builder);
builder.RegisterType<ServiceProcessorFactory>();
builder.RegisterType<RadarrProcessor>().As<IServiceProcessor<RadarrConfiguration>>();
builder.RegisterType<SonarrProcessor>().As<IServiceProcessor<SonarrConfiguration>>();
builder.RegisterType<RadarrProcessor>().Keyed<IServiceProcessor>(SupportedServices.Radarr);
builder.RegisterType<SonarrProcessor>().Keyed<IServiceProcessor>(SupportedServices.Sonarr);
builder.RegisterType<ConfigCreationProcessor>().As<IConfigCreationProcessor>();
}
}

@ -7,7 +7,7 @@ using Recyclarr.TrashLib.Services.Sonarr.ReleaseProfile;
namespace Recyclarr.TrashLib.Services.Processors;
public class SonarrProcessor : IServiceProcessor<SonarrConfiguration>
public class SonarrProcessor : IServiceProcessor
{
private readonly ILogger _log;
private readonly ICustomFormatUpdater _cfUpdater;
@ -15,6 +15,7 @@ public class SonarrProcessor : IServiceProcessor<SonarrConfiguration>
private readonly SonarrGuideService _guideService;
private readonly IReleaseProfileUpdater _profileUpdater;
private readonly SonarrCapabilityEnforcer _compatibilityEnforcer;
private readonly SonarrConfiguration _config;
public SonarrProcessor(
ILogger log,
@ -22,7 +23,8 @@ public class SonarrProcessor : IServiceProcessor<SonarrConfiguration>
IQualitySizeUpdater qualityUpdater,
SonarrGuideService guideService,
IReleaseProfileUpdater profileUpdater,
SonarrCapabilityEnforcer compatibilityEnforcer)
SonarrCapabilityEnforcer compatibilityEnforcer,
SonarrConfiguration config)
{
_log = log;
_cfUpdater = cfUpdater;
@ -30,30 +32,31 @@ public class SonarrProcessor : IServiceProcessor<SonarrConfiguration>
_guideService = guideService;
_profileUpdater = profileUpdater;
_compatibilityEnforcer = compatibilityEnforcer;
_config = config;
}
public async Task Process(SonarrConfiguration config, ISyncSettings settings)
public async Task Process(ISyncSettings settings)
{
// Any compatibility failures will be thrown as exceptions
_compatibilityEnforcer.Check(config);
_compatibilityEnforcer.Check(_config);
var didWork = false;
if (config.ReleaseProfiles.Count > 0)
if (_config.ReleaseProfiles.Count > 0)
{
await _profileUpdater.Process(settings.Preview, config);
await _profileUpdater.Process(settings.Preview, _config);
didWork = true;
}
if (config.QualityDefinition != null)
if (_config.QualityDefinition != null)
{
await _qualityUpdater.Process(settings.Preview, config.QualityDefinition, _guideService);
await _qualityUpdater.Process(settings.Preview, _config.QualityDefinition, _guideService);
didWork = true;
}
if (config.CustomFormats.Count > 0)
if (_config.CustomFormats.Count > 0)
{
await _cfUpdater.Process(settings.Preview, config.CustomFormats, _guideService);
await _cfUpdater.Process(settings.Preview, _config.CustomFormats, _guideService);
didWork = true;
}

@ -6,8 +6,6 @@ using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Config.Services;
using Recyclarr.TrashLib.Http;
using Recyclarr.TrashLib.Repo.VersionControl;
using Recyclarr.TrashLib.Services.Radarr.Config;
using Recyclarr.TrashLib.Services.Sonarr.Config;
using Spectre.Console;
namespace Recyclarr.TrashLib.Services.Processors;
@ -37,7 +35,7 @@ public class SyncProcessor : ISyncProcessor
public async Task<ExitStatus> ProcessConfigs(ISyncSettings settings)
{
var failureDetected = false;
bool failureDetected;
try
{
var configs = _configLoader.LoadMany(_configFinder.GetConfigFiles(settings.Configs));
@ -48,17 +46,7 @@ public class SyncProcessor : ISyncProcessor
_log.Warning("These instances do not exist: {Instances}", invalidInstances);
}
if (settings.Service is null or SupportedServices.Radarr)
{
failureDetected |=
await ProcessService<RadarrConfiguration>(SupportedServices.Radarr, settings, configs);
}
if (settings.Service is null or SupportedServices.Sonarr)
{
failureDetected |=
await ProcessService<SonarrConfiguration>(SupportedServices.Sonarr, settings, configs);
}
failureDetected = await ProcessService(settings.Service, settings, configs);
}
catch (Exception e)
{
@ -69,11 +57,10 @@ public class SyncProcessor : ISyncProcessor
return failureDetected ? ExitStatus.Failed : ExitStatus.Succeeded;
}
private async Task<bool> ProcessService<TConfig>(
SupportedServices service, ISyncSettings settings, IConfigRegistry configs)
where TConfig : ServiceConfiguration
private async Task<bool> ProcessService(
SupportedServices? serviceType, ISyncSettings settings, IConfigRegistry configs)
{
var serviceConfigs = configs.GetConfigsOfType<TConfig>(service);
var serviceConfigs = configs.GetConfigsOfType(serviceType);
// If any config names are null, that means user specified array-style (deprecated) instances.
if (serviceConfigs.Any(x => x.InstanceName is null))
@ -98,9 +85,9 @@ public class SyncProcessor : ISyncProcessor
continue;
}
PrintProcessingHeader(service.ToString(), config);
using var processor = _factory.CreateProcessor<TConfig>(config);
await processor.Value.Process(config, settings);
PrintProcessingHeader(config.ServiceType, config);
using var processor = _factory.CreateProcessor(config.ServiceType, config);
await processor.Value.Process(settings);
}
catch (Exception e)
{
@ -131,16 +118,16 @@ public class SyncProcessor : ISyncProcessor
}
}
private void PrintProcessingHeader(string serverName, ServiceConfiguration config)
private void PrintProcessingHeader(SupportedServices serviceType, IServiceConfiguration config)
{
var instanceName = config.InstanceName ?? FlurlLogging.SanitizeUrl(config.BaseUrl);
_console.WriteLine($@"
===========================================
Processing {serverName} Server: [{instanceName}]
Processing {serviceType} Server: [{instanceName}]
===========================================
");
_log.Debug("Processing {Server} server {Name}", serverName, instanceName);
_log.Debug("Processing {Server} server {Name}", serviceType, instanceName);
}
}

@ -1,11 +1,9 @@
using JetBrains.Annotations;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Services;
namespace Recyclarr.TrashLib.Services.Radarr.Config;
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]
public class RadarrConfiguration : ServiceConfiguration
{
public override string ServiceName { get; } = SupportedServices.Radarr.ToString();
public override SupportedServices ServiceType => SupportedServices.Radarr;
}

@ -6,7 +6,7 @@ namespace Recyclarr.TrashLib.Services.Sonarr.Config;
public class SonarrConfiguration : ServiceConfiguration
{
public override string ServiceName { get; } = SupportedServices.Sonarr.ToString();
public override SupportedServices ServiceType => SupportedServices.Sonarr;
public IList<ReleaseProfileConfig> ReleaseProfiles { get; [UsedImplicitly] init; } =
Array.Empty<ReleaseProfileConfig>();

Loading…
Cancel
Save