Selector/Selector.CLI/Services/LocalWatcherService.cs

184 lines
7.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Selector.Cache;
using Selector.CLI.Consumer;
namespace Selector.CLI
{
class LocalWatcherService : IHostedService
{
private const string ConfigInstanceKey = "localconfig";
private readonly ILogger<LocalWatcherService> Logger;
private readonly RootOptions Config;
private readonly IWatcherFactory WatcherFactory;
private readonly IWatcherCollectionFactory WatcherCollectionFactory;
private readonly IRefreshTokenFactoryProvider SpotifyFactory;
private readonly IServiceProvider ServiceProvider;
private Dictionary<string, IWatcherCollection> Watchers { get; set; } = new();
public LocalWatcherService(
IWatcherFactory watcherFactory,
IWatcherCollectionFactory watcherCollectionFactory,
IRefreshTokenFactoryProvider spotifyFactory,
IServiceProvider serviceProvider,
ILogger<LocalWatcherService> logger,
IOptions<RootOptions> config
) {
Logger = logger;
Config = config.Value;
WatcherFactory = watcherFactory;
WatcherCollectionFactory = watcherCollectionFactory;
SpotifyFactory = spotifyFactory;
ServiceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
Logger.LogInformation("Starting local watcher service...");
var watcherIndices = await InitInstances();
Logger.LogInformation("Starting {count} affected watcher collection(s)...", watcherIndices.Count());
StartWatcherCollections(watcherIndices);
}
private async Task<IEnumerable<string>> InitInstances()
{
var indices = new HashSet<string>();
foreach (var watcherOption in Config.WatcherOptions.Instances)
{
var logMsg = new StringBuilder();
if (!string.IsNullOrWhiteSpace(watcherOption.Name))
{
logMsg.Append($"Creating [{watcherOption.Name}] watcher [{watcherOption.Type}]");
}
else
{
logMsg.Append($"Creating new [{watcherOption.Type}] watcher");
}
if (!string.IsNullOrWhiteSpace(watcherOption.PlaylistUri)) logMsg.Append($" [{ watcherOption.PlaylistUri}]");
Logger.LogInformation(logMsg.ToString());
var watcherCollectionIdx = watcherOption.WatcherCollection ?? ConfigInstanceKey;
indices.Add(watcherCollectionIdx);
if (!Watchers.ContainsKey(watcherCollectionIdx))
Watchers[watcherCollectionIdx] = WatcherCollectionFactory.Get();
var watcherCollection = Watchers[watcherCollectionIdx];
Logger.LogDebug("Getting Spotify factory");
var spotifyFactory = await SpotifyFactory.GetFactory(watcherOption.RefreshKey);
IWatcher watcher = null;
switch(watcherOption.Type)
{
case WatcherType.Player:
watcher = await WatcherFactory.Get<PlayerWatcher>(spotifyFactory, id: watcherOption.Name, pollPeriod: watcherOption.PollPeriod);
break;
case WatcherType.Playlist:
var playlistWatcher = await WatcherFactory.Get<PlaylistWatcher>(spotifyFactory, id: watcherOption.Name, pollPeriod: watcherOption.PollPeriod) as PlaylistWatcher;
playlistWatcher.config = new() { PlaylistId = watcherOption.PlaylistUri };
watcher = playlistWatcher;
break;
}
List<IConsumer> consumers = new();
if (watcherOption.Consumers is not null)
{
foreach (var consumer in watcherOption.Consumers)
{
switch (consumer)
{
case Consumers.AudioFeatures:
consumers.Add(await ServiceProvider.GetService<AudioFeatureInjectorFactory>().Get(spotifyFactory));
break;
case Consumers.AudioFeaturesCache:
consumers.Add(await ServiceProvider.GetService<CachingAudioFeatureInjectorFactory>().Get(spotifyFactory));
break;
case Consumers.CacheWriter:
consumers.Add(await ServiceProvider.GetService<CacheWriterFactory>().Get());
break;
case Consumers.Publisher:
consumers.Add(await ServiceProvider.GetService<PublisherFactory>().Get());
break;
case Consumers.PlayCounter:
if (!string.IsNullOrWhiteSpace(watcherOption.LastFmUsername))
{
consumers.Add(await ServiceProvider.GetService<PlayCounterFactory>().Get(creds: new() { Username = watcherOption.LastFmUsername }));
}
else
{
Logger.LogError("No Last.fm username provided, skipping play counter");
}
break;
case Consumers.MappingPersister:
consumers.Add(await ServiceProvider.GetService<MappingPersisterFactory>().Get());
break;
}
}
}
watcherCollection.Add(watcher, consumers);
}
return indices;
}
private void StartWatcherCollections(IEnumerable<string> indices)
{
foreach (var index in indices)
{
try
{
Logger.LogInformation("Starting watcher collection [{index}]", index);
Watchers[index].Start();
}
catch (KeyNotFoundException)
{
Logger.LogError("Unable to retrieve watcher collection [{index}] when starting", index);
}
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
Logger.LogInformation("Shutting down");
foreach((var key, var watcher) in Watchers)
{
Logger.LogInformation("Stopping watcher collection [{key}]", key);
watcher.Stop();
}
return Task.CompletedTask;
}
}
}