parent
532b954456
commit
5c27c6bf56
@ -1,7 +1,8 @@
|
|||||||
namespace Recyclarr.Cli.Pipelines.Generic;
|
namespace Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
|
||||||
public interface ILogPipelinePhase<in TContext>
|
public interface ILogPipelinePhase<in TContext>
|
||||||
|
where TContext : IPipelineContext
|
||||||
{
|
{
|
||||||
bool LogConfigPhaseAndExitIfNeeded(TContext context);
|
bool LogConfigPhaseAndExitIfNeeded(TContext context);
|
||||||
void LogPersistenceResults(TContext context);
|
void LogPersistenceResults(TContext context);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
using Recyclarr.Common;
|
||||||
|
|
||||||
|
namespace Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
|
||||||
|
public interface IPipelineContext
|
||||||
|
{
|
||||||
|
string PipelineDescription { get; }
|
||||||
|
IReadOnlyCollection<SupportedServices> SupportedServiceTypes { get; }
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
namespace Recyclarr.Cli.Pipelines.Generic;
|
namespace Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
|
||||||
public interface IPreviewPipelinePhase<in TContext>
|
public interface IPreviewPipelinePhase<in TContext>
|
||||||
|
where TContext : IPipelineContext
|
||||||
{
|
{
|
||||||
void Execute(TContext context);
|
void Execute(TContext context);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
namespace Recyclarr.Cli.Pipelines.Generic;
|
namespace Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
|
||||||
public interface ITransactionPipelinePhase<in TContext>
|
public interface ITransactionPipelinePhase<in TContext>
|
||||||
|
where TContext : IPipelineContext
|
||||||
{
|
{
|
||||||
void Execute(TContext context);
|
void Execute(TContext context);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
using Recyclarr.Cli.Pipelines.Generic;
|
||||||
using Recyclarr.Config.Models;
|
using Recyclarr.Config.Models;
|
||||||
using Recyclarr.ServarrApi.Tag;
|
using Recyclarr.ServarrApi.Tag;
|
||||||
|
|
||||||
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
||||||
|
|
||||||
public class TagApiFetchPhase(ISonarrTagApiService api, ServiceTagCache cache)
|
public class TagApiFetchPhase(ISonarrTagApiService api, ServiceTagCache cache)
|
||||||
|
: IApiFetchPipelinePhase<TagPipelineContext>
|
||||||
{
|
{
|
||||||
public async Task<IList<SonarrTag>> Execute(IServiceConfiguration config)
|
public async Task Execute(TagPipelineContext context, IServiceConfiguration config)
|
||||||
{
|
{
|
||||||
var tags = await api.GetTags(config);
|
var tags = await api.GetTags(config);
|
||||||
cache.Clear();
|
|
||||||
cache.AddTags(tags);
|
cache.AddTags(tags);
|
||||||
return tags;
|
context.ApiFetchOutput = tags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using Recyclarr.Cli.Pipelines.Generic;
|
||||||
using Recyclarr.Common.Extensions;
|
|
||||||
using Recyclarr.Config.Models;
|
using Recyclarr.Config.Models;
|
||||||
|
|
||||||
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
||||||
|
|
||||||
public class TagConfigPhase
|
public class TagConfigPhase : IConfigPipelinePhase<TagPipelineContext>
|
||||||
{
|
{
|
||||||
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification =
|
public Task Execute(TagPipelineContext context, IServiceConfiguration config)
|
||||||
"This non-static method establishes a pattern that will eventually become an interface")]
|
|
||||||
public IList<string>? Execute(SonarrConfiguration config)
|
|
||||||
{
|
{
|
||||||
return config.ReleaseProfiles
|
context.ConfigOutput = ((SonarrConfiguration) config).ReleaseProfiles
|
||||||
.SelectMany(x => x.Tags)
|
.SelectMany(x => x.Tags)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.ToListOrNull();
|
.ToList();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
using Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
|
||||||
|
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
||||||
|
|
||||||
|
public class TagLogPhase(ILogger log) : ILogPipelinePhase<TagPipelineContext>
|
||||||
|
{
|
||||||
|
public bool LogConfigPhaseAndExitIfNeeded(TagPipelineContext context)
|
||||||
|
{
|
||||||
|
if (!context.ConfigOutput.Any())
|
||||||
|
{
|
||||||
|
log.Debug("No tags to process");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogPersistenceResults(TagPipelineContext context)
|
||||||
|
{
|
||||||
|
if (context.TransactionOutput.Any())
|
||||||
|
{
|
||||||
|
log.Information("Created {Count} Tags: {Tags}",
|
||||||
|
context.TransactionOutput.Count,
|
||||||
|
context.TransactionOutput);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.Information("All tags are up to date!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,16 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using Recyclarr.Cli.Pipelines.Generic;
|
||||||
using Recyclarr.Common.Extensions;
|
using Recyclarr.Common.Extensions;
|
||||||
using Recyclarr.ServarrApi.Tag;
|
|
||||||
|
|
||||||
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
namespace Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
||||||
|
|
||||||
public class TagTransactionPhase
|
public class TagTransactionPhase : ITransactionPipelinePhase<TagPipelineContext>
|
||||||
{
|
{
|
||||||
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification =
|
public void Execute(TagPipelineContext context)
|
||||||
"This non-static method establishes a pattern that will eventually become an interface")]
|
|
||||||
public IList<string> Execute(IList<string> configTags, IList<SonarrTag> serviceTags)
|
|
||||||
{
|
{
|
||||||
// List of tags in config that do not already exist in the service. The goal is to figure out which tags need to
|
// List of tags in config that do not already exist in the service. The goal is to figure out which tags need to
|
||||||
// be created.
|
// be created.
|
||||||
return configTags
|
context.TransactionOutput = context.ConfigOutput
|
||||||
.Where(ct => serviceTags.All(st => !st.Label.EqualsIgnoreCase(ct)))
|
.Where(ct => context.ApiFetchOutput.All(st => !st.Label.EqualsIgnoreCase(ct)))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Recyclarr.Cli.Pipelines.Generic;
|
||||||
|
using Recyclarr.Common;
|
||||||
|
using Recyclarr.ServarrApi.Tag;
|
||||||
|
|
||||||
|
namespace Recyclarr.Cli.Pipelines.Tags;
|
||||||
|
|
||||||
|
[SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification =
|
||||||
|
"Context objects are similar to DTOs; for usability we want to assign not append")]
|
||||||
|
public class TagPipelineContext : IPipelineContext
|
||||||
|
{
|
||||||
|
public string PipelineDescription => "Tag Pipeline";
|
||||||
|
public IReadOnlyCollection<SupportedServices> SupportedServiceTypes { get; } = new[]
|
||||||
|
{
|
||||||
|
SupportedServices.Sonarr
|
||||||
|
};
|
||||||
|
|
||||||
|
public IList<string> ConfigOutput { get; set; } = default!;
|
||||||
|
public IList<SonarrTag> ApiFetchOutput { get; set; } = default!;
|
||||||
|
public IList<string> TransactionOutput { get; set; } = default!;
|
||||||
|
}
|
@ -1,46 +0,0 @@
|
|||||||
using Recyclarr.Cli.Console.Settings;
|
|
||||||
using Recyclarr.Cli.Pipelines.Tags.PipelinePhases;
|
|
||||||
using Recyclarr.Config.Models;
|
|
||||||
|
|
||||||
namespace Recyclarr.Cli.Pipelines.Tags;
|
|
||||||
|
|
||||||
public interface ITagPipelinePhases
|
|
||||||
{
|
|
||||||
TagConfigPhase ConfigPhase { get; }
|
|
||||||
Lazy<TagPreviewPhase> PreviewPhase { get; }
|
|
||||||
TagApiFetchPhase ApiFetchPhase { get; }
|
|
||||||
TagTransactionPhase TransactionPhase { get; }
|
|
||||||
TagApiPersistencePhase ApiPersistencePhase { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TagSyncPipeline(
|
|
||||||
ILogger log,
|
|
||||||
ITagPipelinePhases phases) : ISyncPipeline
|
|
||||||
{
|
|
||||||
public async Task Execute(ISyncSettings settings, IServiceConfiguration config)
|
|
||||||
{
|
|
||||||
if (config is not SonarrConfiguration sonarrConfig)
|
|
||||||
{
|
|
||||||
log.Debug("Skipping tag pipeline because {Instance} is not a Sonarr config", config.InstanceName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tags = phases.ConfigPhase.Execute(sonarrConfig);
|
|
||||||
if (tags is null)
|
|
||||||
{
|
|
||||||
log.Debug("No tags to process");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var serviceData = await phases.ApiFetchPhase.Execute(config);
|
|
||||||
var transactions = phases.TransactionPhase.Execute(tags, serviceData);
|
|
||||||
|
|
||||||
if (settings.Preview)
|
|
||||||
{
|
|
||||||
phases.PreviewPhase.Value.Execute(transactions.AsReadOnly());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await phases.ApiPersistencePhase.Execute(config, transactions);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue