From f79c7111fea39eca8ff5d768e5c79b32b1c652c6 Mon Sep 17 00:00:00 2001 From: andy Date: Sun, 19 Dec 2021 13:44:22 +0000 Subject: [PATCH] added event bus, proxying cache events to event bus before proxying those to signalr --- Selector.CLI/Program.cs | 2 + Selector.Cache/Consumer/PlayCounterCaching.cs | 6 +- Selector.Cache/Key.cs | 68 ++++++++++++++----- Selector.Cache/Services/PlayCountPuller.cs | 6 +- Selector.Model/Events/UserEventBus.cs | 50 ++++++++++++++ .../Extensions/ServiceExtensions.cs | 15 ++-- Selector.Web/Extensions/ServiceExtensions.cs | 12 ++-- ...xyService.cs => CacheEventProxyService.cs} | 33 +++++---- Selector.Web/Services/CacheHubProxy.cs | 38 ----------- .../CacheMappings/ICacheEventMapping.cs | 13 ++++ .../CacheMappings/NowPlayingCacheMapping.cs | 52 ++++++++++++++ Selector.Web/Services/EventHubProxy.cs | 26 +++++++ .../EventMappings/IEventHubMapping.cs | 15 ++++ .../EventMappings/NowPlayingHubMapping.cs | 40 +++++++++++ .../Services/Mappings/ICacheHubMapping.cs | 16 ----- .../Services/Mappings/NowPlayingMapping.cs | 46 ------------- .../Mappings/NowPlayingMappingFactory.cs | 38 ----------- Selector.Web/Services/Mappings/UserMapping.cs | 37 ---------- Selector.Web/Startup.cs | 2 + Selector/Events/IEventBus.cs | 13 ++++ 20 files changed, 305 insertions(+), 223 deletions(-) create mode 100644 Selector.Model/Events/UserEventBus.cs rename Selector.Web/Services/{CacheHubProxyService.cs => CacheEventProxyService.cs} (51%) delete mode 100644 Selector.Web/Services/CacheHubProxy.cs create mode 100644 Selector.Web/Services/CacheMappings/ICacheEventMapping.cs create mode 100644 Selector.Web/Services/CacheMappings/NowPlayingCacheMapping.cs create mode 100644 Selector.Web/Services/EventHubProxy.cs create mode 100644 Selector.Web/Services/EventMappings/IEventHubMapping.cs create mode 100644 Selector.Web/Services/EventMappings/NowPlayingHubMapping.cs delete mode 100644 Selector.Web/Services/Mappings/ICacheHubMapping.cs delete mode 100644 Selector.Web/Services/Mappings/NowPlayingMapping.cs delete mode 100644 Selector.Web/Services/Mappings/NowPlayingMappingFactory.cs delete mode 100644 Selector.Web/Services/Mappings/UserMapping.cs create mode 100644 Selector/Events/IEventBus.cs diff --git a/Selector.CLI/Program.cs b/Selector.CLI/Program.cs index 01d4c8f..8253cf6 100644 --- a/Selector.CLI/Program.cs +++ b/Selector.CLI/Program.cs @@ -13,6 +13,7 @@ using Selector.Cache; using Selector.Cache.Extensions; using IF.Lastfm.Core.Api; +using Selector.Model.Extensions; namespace Selector.CLI { @@ -101,6 +102,7 @@ namespace Selector.CLI Console.WriteLine("> Configuring..."); // CONFIG var config = ConfigureOptions(context, services); + services.AddHttpClient(); Console.WriteLine("> Adding Services..."); // SERVICES diff --git a/Selector.Cache/Consumer/PlayCounterCaching.cs b/Selector.Cache/Consumer/PlayCounterCaching.cs index 3b85ee5..4303551 100644 --- a/Selector.Cache/Consumer/PlayCounterCaching.cs +++ b/Selector.Cache/Consumer/PlayCounterCaching.cs @@ -56,9 +56,9 @@ namespace Selector.Cache var tasks = new Task[] { - Db.StringSetAsync(Key.TrackPlayCount(track.Name, track.Artists[0].Name), e.Track, expiry: CacheExpiry), - Db.StringSetAsync(Key.AlbumPlayCount(track.Album.Name, track.Album.Artists[0].Name), e.Album, expiry: CacheExpiry), - Db.StringSetAsync(Key.ArtistPlayCount(track.Artists[0].Name), e.Artist, expiry: CacheExpiry), + Db.StringSetAsync(Key.TrackPlayCount(e.Username, track.Name, track.Artists[0].Name), e.Track, expiry: CacheExpiry), + Db.StringSetAsync(Key.AlbumPlayCount(e.Username, track.Album.Name, track.Album.Artists[0].Name), e.Album, expiry: CacheExpiry), + Db.StringSetAsync(Key.ArtistPlayCount(e.Username, track.Artists[0].Name), e.Artist, expiry: CacheExpiry), Db.StringSetAsync(Key.UserPlayCount(e.Username), e.User, expiry: CacheExpiry), }; diff --git a/Selector.Cache/Key.cs b/Selector.Cache/Key.cs index 9788571..63e3f58 100644 --- a/Selector.Cache/Key.cs +++ b/Selector.Cache/Key.cs @@ -1,40 +1,72 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace Selector.Cache { public class Key { - public const string CurrentlyPlayingName = "CurrentlyPlaying"; + public const char MajorSep = ':'; + public const char MinorSep = '.'; - public const string TrackName = "Track"; - public const string AlbumName = "Album"; - public const string ArtistName = "Artist"; - public const string UserName = "User"; + public const string All = "*"; + public const string CurrentlyPlayingName = "CURRENTLY_PLAYING"; - public const string AudioFeatureName = "AudioFeature"; - public const string PlayCountName = "PlayCount"; + public const string TrackName = "TRACK"; + public const string AlbumName = "ALBUM"; + public const string ArtistName = "ARTIST"; + public const string UserName = "USER"; - public const string WorkerName = "Worker"; - public const string WatcherName = "Watcher"; - public const string ReservedName = "Reserved"; + public const string AudioFeatureName = "AUDIO_FEATURE"; + public const string PlayCountName = "PLAY_COUNT"; + + public const string SpotifyName = "SPOTIFY"; + public const string LastfmName = "LASTFM"; + + public const string WatcherName = "WATCHER"; /// /// Current playback for a user /// /// User's database Id (Guid) /// - public static string CurrentlyPlaying(string user) => Namespace(user, CurrentlyPlayingName); - public static string AudioFeature(string trackId) => Namespace(TrackName, trackId, AudioFeatureName); + public static string CurrentlyPlaying(string user) => MajorNamespace(MinorNamespace(UserName, CurrentlyPlayingName), user); + public static readonly string AllCurrentlyPlaying = CurrentlyPlaying(All); - public static string TrackPlayCount(string name, string artist) => Namespace(TrackName, artist, name, PlayCountName); - public static string AlbumPlayCount(string name, string artist) => Namespace(AlbumName, artist, name, PlayCountName); - public static string ArtistPlayCount(string name) => Namespace(ArtistName, name, PlayCountName); - public static string UserPlayCount(string username) => Namespace(UserName, username, PlayCountName); + public static string AudioFeature(string trackId) => MajorNamespace(MinorNamespace(TrackName, AudioFeatureName), trackId); + public static readonly string AllAudioFeatures = AudioFeature(All); - public static string WatcherReserved(int id) => Namespace(WatcherName, id.ToString(), ReservedName); + public static string TrackPlayCount(string username, string name, string artist) => MajorNamespace(MinorNamespace(TrackName, PlayCountName), artist, name, username); + public static string AlbumPlayCount(string username, string name, string artist) => MajorNamespace(MinorNamespace(AlbumName, PlayCountName), artist, name, username); + public static string ArtistPlayCount(string username, string name) => MajorNamespace(MinorNamespace(ArtistName, PlayCountName), name, username); + public static string UserPlayCount(string username) => MajorNamespace(MinorNamespace(UserName, PlayCountName), username); - public static string Namespace(params string[] args) => string.Join(":", args); + public static string UserSpotify(string username) => MajorNamespace(MinorNamespace(UserName, SpotifyName), username); + public static readonly string AllUserSpotify = UserSpotify(All); + public static string UserLastfm(string username) => MajorNamespace(MinorNamespace(UserName, LastfmName), username); + public static readonly string AllUserLastfm = UserLastfm(All); + + public static string Watcher(int id) => MajorNamespace(WatcherName, id.ToString()); + public static readonly string AllWatcher = MajorNamespace(WatcherName, All); + + public static string MajorNamespace(params string[] args) => Namespace(MajorSep, args); + public static string MinorNamespace(params string[] args) => Namespace(MinorSep, args); + public static string Namespace(char separator, params string[] args) => string.Join(separator, args); + + public static string[] UnMajorNamespace(string arg) => UnNamespace(arg, MajorSep); + public static string[] UnMinorNamespace(string arg) => UnNamespace(arg, MinorSep); + public static string[] UnNamespace(string key, params char[] args) => key.Split(args); + + public static string Param(string key) => UnMajorNamespace(key).Skip(1).First(); + public static (string, string) ParamPair(string key) { + var split = UnMajorNamespace(key); + return (split[1], split[2]); + } + public static (string, string, string) ParamTriplet(string key) + { + var split = UnMajorNamespace(key); + return (split[1], split[2], split[3]); + } } } diff --git a/Selector.Cache/Services/PlayCountPuller.cs b/Selector.Cache/Services/PlayCountPuller.cs index 49c98a3..f4dfd3a 100644 --- a/Selector.Cache/Services/PlayCountPuller.cs +++ b/Selector.Cache/Services/PlayCountPuller.cs @@ -45,9 +45,9 @@ namespace Selector.Cache { if (string.IsNullOrWhiteSpace(username)) throw new ArgumentNullException("No username provided"); - var trackCache = Cache?.StringGetAsync(Key.TrackPlayCount(track, artist)); - var albumCache = Cache?.StringGetAsync(Key.AlbumPlayCount(album, albumArtist)); - var artistCache = Cache?.StringGetAsync(Key.ArtistPlayCount(artist)); + var trackCache = Cache?.StringGetAsync(Key.TrackPlayCount(username, track, artist)); + var albumCache = Cache?.StringGetAsync(Key.AlbumPlayCount(username, album, albumArtist)); + var artistCache = Cache?.StringGetAsync(Key.ArtistPlayCount(username, artist)); var userCache = Cache?.StringGetAsync(Key.UserPlayCount(username)); var cacheTasks = new Task[] { trackCache, albumCache, artistCache, userCache }; diff --git a/Selector.Model/Events/UserEventBus.cs b/Selector.Model/Events/UserEventBus.cs new file mode 100644 index 0000000..07f198a --- /dev/null +++ b/Selector.Model/Events/UserEventBus.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Selector.Events; + +namespace Selector.Model.Events +{ + public class UserEventBus: IEventBus + { + private readonly ILogger Logger; + + public event EventHandler UserChange; + public event EventHandler SpotifyLinkChange; + public event EventHandler LastfmCredChange; + + public event EventHandler<(string, CurrentlyPlayingDTO)> CurrentlyPlaying; + + public UserEventBus(ILogger logger) + { + Logger = logger; + } + + public void OnUserChange(object sender, ApplicationUser args) + { + Logger.LogTrace("Firing user event [{usernamne}]", args?.UserName); + UserChange?.Invoke(sender, args); + } + + public void OnSpotifyLinkChange(object sender, ApplicationUser args) + { + Logger.LogTrace("Firing user Spotify event [{usernamne}]", args?.UserName); + SpotifyLinkChange?.Invoke(sender, args); + } + + public void OnLastfmCredChange(object sender, ApplicationUser args) + { + Logger.LogTrace("Firing user Last.fm event [{usernamne}]", args?.UserName); + LastfmCredChange?.Invoke(sender, args); + } + + public void OnCurrentlyPlayingChange(object sender, string userId, CurrentlyPlayingDTO args) + { + Logger.LogTrace("Firing currently playing event [{usernamne}/{userId}]", args?.Username, userId); + CurrentlyPlaying?.Invoke(sender, (userId, args)); + } + } +} diff --git a/Selector.Model/Extensions/ServiceExtensions.cs b/Selector.Model/Extensions/ServiceExtensions.cs index f26a5b1..3dba790 100644 --- a/Selector.Model/Extensions/ServiceExtensions.cs +++ b/Selector.Model/Extensions/ServiceExtensions.cs @@ -1,17 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; +using Selector.Events; using Selector.Model.Authorisation; +using Selector.Model.Events; namespace Selector.Model.Extensions { public static class ServiceExtensions { + public static void AddModelEventBus(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(sp => sp.GetService()); + } + public static void AddAuthorisationHandlers(this IServiceCollection services) { services.AddAuthorization(options => diff --git a/Selector.Web/Extensions/ServiceExtensions.cs b/Selector.Web/Extensions/ServiceExtensions.cs index 3d6d308..4228a73 100644 --- a/Selector.Web/Extensions/ServiceExtensions.cs +++ b/Selector.Web/Extensions/ServiceExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Selector.Web.Service; +using Selector.Web.Hubs; namespace Selector.Web.Extensions { @@ -7,11 +8,14 @@ namespace Selector.Web.Extensions { public static void AddCacheHubProxy(this IServiceCollection services) { - services.AddSingleton(); - services.AddHostedService(); + services.AddScoped(); + services.AddHostedService(); - services.AddTransient(); - services.AddScoped(); + services.AddTransient(); + services.AddTransient(); + + services.AddScoped, NowPlayingHubMapping>(); + services.AddScoped(); } } } diff --git a/Selector.Web/Services/CacheHubProxyService.cs b/Selector.Web/Services/CacheEventProxyService.cs similarity index 51% rename from Selector.Web/Services/CacheHubProxyService.cs rename to Selector.Web/Services/CacheEventProxyService.cs index 9d13c86..77418ce 100644 --- a/Selector.Web/Services/CacheHubProxyService.cs +++ b/Selector.Web/Services/CacheEventProxyService.cs @@ -8,33 +8,38 @@ using Microsoft.Extensions.Logging; namespace Selector.Web.Service { - public class CacheHubProxyService: IHostedService + public class CacheEventProxyService: IHostedService { - private readonly ILogger Logger; - private readonly CacheHubProxy Proxy; + private readonly ILogger Logger; private readonly IServiceScopeFactory ScopeFactory; - public CacheHubProxyService( - ILogger logger, - CacheHubProxy proxy, + private readonly IEnumerable CacheEvents; + + public CacheEventProxyService( + ILogger logger, + IEnumerable mappings, IServiceScopeFactory scopeFactory ) { Logger = logger; - Proxy = proxy; ScopeFactory = scopeFactory; + + CacheEvents = mappings; } public Task StartAsync(CancellationToken cancellationToken) { - Logger.LogInformation("Starting cache hub proxy"); + Logger.LogInformation("Starting cache event proxy"); - using(var scope = ScopeFactory.CreateScope()) - { - foreach(var mapping in scope.ServiceProvider.GetServices()) - { - mapping.FormAll(); - } + foreach (var mapping in CacheEvents) + { + mapping.ConstructMapping(); + } + + using (var scope = ScopeFactory.CreateScope()) + { + var hubProxy = scope.ServiceProvider.GetRequiredService(); + hubProxy.FormMappings(); } return Task.CompletedTask; diff --git a/Selector.Web/Services/CacheHubProxy.cs b/Selector.Web/Services/CacheHubProxy.cs deleted file mode 100644 index 4eccf99..0000000 --- a/Selector.Web/Services/CacheHubProxy.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.AspNetCore.SignalR; - -using StackExchange.Redis; -using Selector.Web.Hubs; - -namespace Selector.Web.Service -{ - public class CacheHubProxy - { - private readonly ILogger Logger; - private readonly ISubscriber Subscriber; - private readonly IServiceProvider Services; - - public CacheHubProxy(ILogger logger, - ISubscriber subscriber, - IServiceProvider services - ) - { - Logger = logger; - Subscriber = subscriber; - Services = services; - } - - public void FormMapping(ICacheHubMapping mapping) where THub: Hub where T: class - { - var context = Services.GetService>(); - mapping.ConstructMapping(Subscriber, context); - } - } -} \ No newline at end of file diff --git a/Selector.Web/Services/CacheMappings/ICacheEventMapping.cs b/Selector.Web/Services/CacheMappings/ICacheEventMapping.cs new file mode 100644 index 0000000..ceb7bf2 --- /dev/null +++ b/Selector.Web/Services/CacheMappings/ICacheEventMapping.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.SignalR; +using StackExchange.Redis; + +namespace Selector.Web.Service +{ + public interface ICacheEventMapping + { + public Task ConstructMapping(); + } +} \ No newline at end of file diff --git a/Selector.Web/Services/CacheMappings/NowPlayingCacheMapping.cs b/Selector.Web/Services/CacheMappings/NowPlayingCacheMapping.cs new file mode 100644 index 0000000..15e1bad --- /dev/null +++ b/Selector.Web/Services/CacheMappings/NowPlayingCacheMapping.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; + +using StackExchange.Redis; + +using Selector.Web.Hubs; +using Selector.Cache; +using Selector.Model.Events; + +namespace Selector.Web.Service +{ + public class NowPlayingCacheMapping : ICacheEventMapping + { + private readonly ILogger Logger; + private readonly ISubscriber Subscriber; + private readonly UserEventBus UserEvent; + + public NowPlayingCacheMapping(ILogger logger, + ISubscriber subscriber, + UserEventBus userEvent) + { + Logger = logger; + Subscriber = subscriber; + UserEvent = userEvent; + } + + public async Task ConstructMapping() + { + Logger.LogDebug("Forming now playing event mapping between cache and event bus"); + + (await Subscriber.SubscribeAsync(Key.AllCurrentlyPlaying)).OnMessage(message => { + + try{ + var userId = Key.Param(message.Channel); + + var deserialised = JsonSerializer.Deserialize(message.Message); + Logger.LogDebug("Received new currently playing [{username}]", deserialised.Username); + + UserEvent.OnCurrentlyPlayingChange(this, userId, deserialised); + } + catch(Exception e) + { + Logger.LogError(e, $"Error parsing new currently playing [{message}]"); + } + }); + } + } +} \ No newline at end of file diff --git a/Selector.Web/Services/EventHubProxy.cs b/Selector.Web/Services/EventHubProxy.cs new file mode 100644 index 0000000..a3e3023 --- /dev/null +++ b/Selector.Web/Services/EventHubProxy.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Logging; + +namespace Selector.Web.Service +{ + public class EventHubProxy + { + private readonly ILogger Logger; + + private readonly NowPlayingHubMapping NowPlayingMapping; + + public EventHubProxy(ILogger logger, + NowPlayingHubMapping nowPlayingMapping + ) + { + Logger = logger; + NowPlayingMapping = nowPlayingMapping; + } + + public void FormMappings() + { + Logger.LogDebug("Forming event mappings between event bus and SignalR hubs"); + + NowPlayingMapping.ConstructMapping(); + } + } +} \ No newline at end of file diff --git a/Selector.Web/Services/EventMappings/IEventHubMapping.cs b/Selector.Web/Services/EventMappings/IEventHubMapping.cs new file mode 100644 index 0000000..637a016 --- /dev/null +++ b/Selector.Web/Services/EventMappings/IEventHubMapping.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; + +using StackExchange.Redis; + +namespace Selector.Web.Service +{ + public interface IEventHubMapping + where THub : Hub + where T : class + { + public Task ConstructMapping(); + // public Task RemoveMapping(); + } +} diff --git a/Selector.Web/Services/EventMappings/NowPlayingHubMapping.cs b/Selector.Web/Services/EventMappings/NowPlayingHubMapping.cs new file mode 100644 index 0000000..5ffa657 --- /dev/null +++ b/Selector.Web/Services/EventMappings/NowPlayingHubMapping.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; + +using Selector.Web.Hubs; +using Selector.Model.Events; + +namespace Selector.Web.Service +{ + public class NowPlayingHubMapping: IEventHubMapping + { + private readonly ILogger Logger; + private readonly UserEventBus UserEvent; + private readonly IHubContext Hub; + + public NowPlayingHubMapping(ILogger logger, + UserEventBus userEvent, + IHubContext hub) + { + Logger = logger; + UserEvent = userEvent; + Hub = hub; + } + + public Task ConstructMapping() + { + Logger.LogDebug("Forming now playing event mapping between event bus and SignalR hub"); + + UserEvent.CurrentlyPlaying += async (o, args) => + { + (string id, CurrentlyPlayingDTO e) = args; + Logger.LogDebug("Passing now playing event to SignalR hub [{userId}]", id); + + await Hub.Clients.User(id).OnNewPlaying(e); + }; + + return Task.CompletedTask; + } + } +} diff --git a/Selector.Web/Services/Mappings/ICacheHubMapping.cs b/Selector.Web/Services/Mappings/ICacheHubMapping.cs deleted file mode 100644 index 7505aa6..0000000 --- a/Selector.Web/Services/Mappings/ICacheHubMapping.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.SignalR; -using StackExchange.Redis; - -namespace Selector.Web.Service -{ - public interface ICacheHubMapping - where THub : Hub - where T : class - { - public Task ConstructMapping(ISubscriber subscriber, IHubContext hub); - // public Task RemoveMapping(ISubscriber subscriber, THub hub); - } -} \ No newline at end of file diff --git a/Selector.Web/Services/Mappings/NowPlayingMapping.cs b/Selector.Web/Services/Mappings/NowPlayingMapping.cs deleted file mode 100644 index 9eb8830..0000000 --- a/Selector.Web/Services/Mappings/NowPlayingMapping.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Text.Json; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.SignalR; -using Microsoft.Extensions.Logging; - -using StackExchange.Redis; - -using Selector.Web.Hubs; -using Selector.Cache; - -namespace Selector.Web.Service -{ - public class NowPlayingMapping : ICacheHubMapping - { - private readonly ILogger Logger; - private readonly string UserId; - private readonly string Username; - - public NowPlayingMapping(ILogger logger, string userId, string username) - { - Logger = logger; - UserId = userId; - Username = username; - } - - public async Task ConstructMapping(ISubscriber subscriber, IHubContext hub) - { - var key = Key.CurrentlyPlaying(UserId); - (await subscriber.SubscribeAsync(key)).OnMessage(async message => { - - try{ - var trimmedMessage = message.ToString().Substring(key.Length + 1); - var deserialised = JsonSerializer.Deserialize(trimmedMessage); - Logger.LogDebug($"Received new currently playing [{deserialised.Username}] [{deserialised.Username}]"); - await hub.Clients.User(UserId).OnNewPlaying(deserialised); - } - catch(Exception e) - { - Logger.LogError(e, $"Error parsing new currently playing [{message}]"); - } - }); - } - } -} \ No newline at end of file diff --git a/Selector.Web/Services/Mappings/NowPlayingMappingFactory.cs b/Selector.Web/Services/Mappings/NowPlayingMappingFactory.cs deleted file mode 100644 index 305d504..0000000 --- a/Selector.Web/Services/Mappings/NowPlayingMappingFactory.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using Microsoft.AspNetCore.SignalR; -using Microsoft.Extensions.Logging; - -using Selector.Web.Hubs; - -namespace Selector.Web.Service -{ - public interface IUserMappingFactory - where TMap : ICacheHubMapping - where THub : Hub - where T : class - { - public TMap Get(string userId, string username); - } - - public interface INowPlayingMappingFactory: IUserMappingFactory - { } - - public class NowPlayingMappingFactory : INowPlayingMappingFactory { - - private readonly ILoggerFactory LoggerFactory; - - public NowPlayingMappingFactory(ILoggerFactory loggerFactory) - { - LoggerFactory = loggerFactory; - } - - public NowPlayingMapping Get(string userId, string username) - { - return new NowPlayingMapping( - LoggerFactory?.CreateLogger(), - userId, - username - ); - } - } -} diff --git a/Selector.Web/Services/Mappings/UserMapping.cs b/Selector.Web/Services/Mappings/UserMapping.cs deleted file mode 100644 index 18d49e7..0000000 --- a/Selector.Web/Services/Mappings/UserMapping.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Linq; - -using Selector.Model; - -namespace Selector.Web.Service -{ - public interface IUserMapping { - public void FormAll(); - } - - public class NowPlayingUserMapping: IUserMapping - { - private readonly ApplicationDbContext Db; - private readonly CacheHubProxy Proxy; - private readonly INowPlayingMappingFactory NowPlayingMappingFactory; - - public NowPlayingUserMapping( - ApplicationDbContext db, - CacheHubProxy proxy, - INowPlayingMappingFactory nowPlayingMappingFactory - ) - { - Db = db; - Proxy = proxy; - NowPlayingMappingFactory = nowPlayingMappingFactory; - } - - public void FormAll() - { - foreach(var user in Db.Users) - { - Proxy.FormMapping(NowPlayingMappingFactory.Get(user.Id, user.UserName)); - } - } - } -} \ No newline at end of file diff --git a/Selector.Web/Startup.cs b/Selector.Web/Startup.cs index c129f86..4e57ff1 100644 --- a/Selector.Web/Startup.cs +++ b/Selector.Web/Startup.cs @@ -48,6 +48,7 @@ namespace Selector.Web services.AddRazorPages().AddRazorRuntimeCompilation(); services.AddControllers(); services.AddSignalR(o => o.EnableDetailedErrors = true); + services.AddHttpClient(); services.AddDbContext(options => options.UseNpgsql(Configuration.GetConnectionString("Default")) @@ -92,6 +93,7 @@ namespace Selector.Web }); services.AddAuthorisationHandlers(); + services.AddModelEventBus(); if (config.RedisOptions.Enabled) services.AddRedisServices(config.RedisOptions.ConnectionString); diff --git a/Selector/Events/IEventBus.cs b/Selector/Events/IEventBus.cs new file mode 100644 index 0000000..cd8a75d --- /dev/null +++ b/Selector/Events/IEventBus.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Selector.Events +{ + public interface IEventBus + { + + } +}