refactor: Generalize compatibility check logic

Previously, only Sonarr had compatibility checking logic, which also
consequently meant that version information was obtained and logged for
Sonarr services. However, Radarr had no such checks because
compatibility has not yet been an issue. However, we still would like to
see version information printed when running Radarr instances.
commitlint
Robert Dailey 2 years ago
parent 934f30d71e
commit 081856e19e

@ -1,3 +1,4 @@
using System.Reactive.Linq;
using Autofac;
using CliFx.Attributes;
using JetBrains.Annotations;
@ -61,6 +62,12 @@ internal class RadarrCommand : ServiceCommand
log.Information("Processing server {Url}", FlurlLogging.SanitizeUrl(config.BaseUrl));
// There's no actual compatibility checks to perform yet. We directly access the RadarrCompatibility class,
// as opposed to a IRadarrVersionEnforcement object (like Sonarr does), simply to force the API invocation
// in Radarr to acquire and log version information.
var compatibility = scope.Resolve<RadarrCompatibility>();
await compatibility.Capabilities.LastAsync();
// ReSharper disable InvertIf
if (config.QualityDefinition != null)

@ -18,6 +18,7 @@ using TrashLib.Services.Common;
using TrashLib.Services.CustomFormat;
using TrashLib.Services.Radarr;
using TrashLib.Services.Sonarr;
using TrashLib.Services.System;
using TrashLib.Startup;
using VersionControl;
using YamlDotNet.Serialization;
@ -44,6 +45,7 @@ public static class CompositionRoot
builder.RegisterModule<RepoAutofacModule>();
builder.RegisterModule<CustomFormatAutofacModule>();
builder.RegisterModule<GuideServicesAutofacModule>();
builder.RegisterModule<SystemServiceAutofacModule>();
// Needed for Autofac.Extras.Ordering
builder.RegisterSource<OrderedRegistrationSource>();

@ -14,6 +14,8 @@ using TrashLib.Services.Sonarr;
using TrashLib.Services.Sonarr.Api;
using TrashLib.Services.Sonarr.Api.Objects;
using TrashLib.Services.Sonarr.Config;
using TrashLib.Services.System;
using TrashLib.Services.System.Dto;
using TrashLib.Startup;
namespace TrashLib.Tests.Sonarr;
@ -119,11 +121,11 @@ public class SonarrCompatibilityTest
[Test, AutoMockData]
public async Task Failure_when_release_profiles_used_with_sonarr_v4(
[Frozen] ISonarrApi api,
[Frozen] ISystemApiService api,
[Frozen(Matching.ImplementedInterfaces)] SonarrCompatibility compatibility,
SonarrVersionEnforcement enforcement)
{
api.GetVersion().Returns(new Version(4, 0));
api.GetStatus().Returns(new SystemStatus("Sonarr", "4.0"));
var config = new SonarrConfiguration
{
@ -137,11 +139,11 @@ public class SonarrCompatibilityTest
[Test, AutoMockData]
public async Task No_failure_when_release_profiles_used_with_sonarr_v3(
[Frozen] ISonarrApi api,
[Frozen] ISystemApiService api,
[Frozen(Matching.ImplementedInterfaces)] SonarrCompatibility compatibility,
SonarrVersionEnforcement enforcement)
{
api.GetVersion().Returns(new Version(3, 9));
api.GetStatus().Returns(new SystemStatus("Sonarr", "3.9"));
var config = new SonarrConfiguration
{
@ -155,11 +157,11 @@ public class SonarrCompatibilityTest
[Test, AutoMockData]
public async Task Failure_when_custom_formats_used_with_sonarr_v3(
[Frozen] ISonarrApi api,
[Frozen] ISystemApiService api,
[Frozen(Matching.ImplementedInterfaces)] SonarrCompatibility compatibility,
SonarrVersionEnforcement enforcement)
{
api.GetVersion().Returns(new Version(3, 9));
api.GetStatus().Returns(new SystemStatus("Sonarr", "3.9"));
var config = new SonarrConfiguration
{
@ -173,11 +175,11 @@ public class SonarrCompatibilityTest
[Test, AutoMockData]
public async Task No_failure_when_custom_formats_used_with_sonarr_v4(
[Frozen] ISonarrApi api,
[Frozen] ISystemApiService api,
[Frozen(Matching.ImplementedInterfaces)] SonarrCompatibility compatibility,
SonarrVersionEnforcement enforcement)
{
api.GetVersion().Returns(new Version(4, 0));
api.GetStatus().Returns(new SystemStatus("Sonarr", "4.0"));
var config = new SonarrConfiguration
{

@ -15,5 +15,6 @@ public class RadarrAutofacModule : Module
builder.RegisterType<RadarrQualityDefinitionUpdater>().As<IRadarrQualityDefinitionUpdater>();
builder.RegisterType<LocalRepoRadarrGuideService>().As<IRadarrGuideService>();
builder.RegisterType<RadarrGuideDataLister>().As<IRadarrGuideDataLister>();
builder.RegisterType<RadarrCompatibility>();
}
}

@ -0,0 +1,8 @@
namespace TrashLib.Services.Radarr;
public record RadarrCapabilities(Version Version)
{
public RadarrCapabilities() : this(new Version())
{
}
}

@ -0,0 +1,17 @@
using Serilog;
using TrashLib.Services.System;
namespace TrashLib.Services.Radarr;
public class RadarrCompatibility : ServiceCompatibility<RadarrCapabilities>
{
public RadarrCompatibility(ISystemApiService api, ILogger log)
: base(api, log)
{
}
protected override RadarrCapabilities BuildCapabilitiesObject(Version version)
{
return new RadarrCapabilities(version);
}
}

@ -10,6 +10,4 @@ public interface ISonarrApi
Task<IList<SonarrQualityDefinitionItem>> UpdateQualityDefinition(
IReadOnlyCollection<SonarrQualityDefinitionItem> newQuality);
Task<Version> GetVersion();
}

@ -14,15 +14,6 @@ public class SonarrApi : ISonarrApi
_serverInfo = serverInfo;
}
public async Task<Version> GetVersion()
{
var response = await BaseUrl()
.AppendPathSegment("system/status")
.GetJsonAsync();
return new Version(response.version);
}
public async Task<IList<SonarrTag>> GetTags()
{
return await BaseUrl()

@ -1,30 +1,19 @@
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using Serilog;
using TrashLib.Services.Sonarr.Api;
using TrashLib.Services.System;
namespace TrashLib.Services.Sonarr;
public class SonarrCompatibility : ISonarrCompatibility
public class SonarrCompatibility : ServiceCompatibility<SonarrCapabilities>, ISonarrCompatibility
{
private readonly ILogger _log;
public SonarrCompatibility(ISonarrApi api, ILogger log)
public SonarrCompatibility(ISystemApiService api, ILogger log)
: base(api, log)
{
_log = log;
Capabilities = Observable.FromAsync(async () => await api.GetVersion(), NewThreadScheduler.Default)
.Timeout(TimeSpan.FromSeconds(15))
.Select(BuildCapabilitiesObject)
.Replay(1)
.AutoConnect();
}
public IObservable<SonarrCapabilities> Capabilities { get; }
public Version MinimumVersion => new("3.0.4.1098");
private SonarrCapabilities BuildCapabilitiesObject(Version version)
protected override SonarrCapabilities BuildCapabilitiesObject(Version version)
{
_log.Debug("Sonarr Version: {Version}", version);
return new SonarrCapabilities(version)
{
SupportsNamedReleaseProfiles =

@ -0,0 +1,6 @@
namespace TrashLib.Services.System.Dto;
public record SystemStatus(
string AppName,
string Version
);

@ -0,0 +1,8 @@
using TrashLib.Services.System.Dto;
namespace TrashLib.Services.System;
public interface ISystemApiService
{
Task<SystemStatus> GetStatus();
}

@ -0,0 +1,32 @@
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using Serilog;
using TrashLib.Services.System.Dto;
namespace TrashLib.Services.System;
public abstract class ServiceCompatibility<T> where T : new()
{
private readonly ILogger _log;
protected ServiceCompatibility(ISystemApiService api, ILogger log)
{
_log = log;
Capabilities = Observable.FromAsync(async () => await api.GetStatus(), NewThreadScheduler.Default)
.Timeout(TimeSpan.FromSeconds(15))
.Do(LogServiceInfo)
.Select(x => new Version(x.Version))
.Select(BuildCapabilitiesObject)
.Replay(1)
.AutoConnect();
}
public IObservable<T> Capabilities { get; }
private void LogServiceInfo(SystemStatus status)
{
_log.Debug("{Service} Version: {Version}", status.AppName, status.Version);
}
protected abstract T BuildCapabilitiesObject(Version version);
}

@ -0,0 +1,25 @@
using Flurl;
using Flurl.Http;
using TrashLib.Config.Services;
using TrashLib.Services.System.Dto;
namespace TrashLib.Services.System;
public class SystemApiService : ISystemApiService
{
private readonly IServerInfo _serverInfo;
public SystemApiService(IServerInfo serverInfo)
{
_serverInfo = serverInfo;
}
public async Task<SystemStatus> GetStatus()
{
return await BaseUrl()
.AppendPathSegment("system/status")
.GetJsonAsync<SystemStatus>();
}
private Url BaseUrl() => _serverInfo.BuildRequest();
}

@ -0,0 +1,12 @@
using Autofac;
namespace TrashLib.Services.System;
public class SystemServiceAutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<SystemApiService>().As<ISystemApiService>();
}
}
Loading…
Cancel
Save