using database id for cache key, fixes #17

This commit is contained in:
andy 2021-11-05 18:41:45 +00:00
parent 0d74257b89
commit 6e05647676
13 changed files with 65 additions and 39 deletions

View File

@ -101,7 +101,7 @@ namespace Selector.CLI
switch(watcherOption.Type) switch(watcherOption.Type)
{ {
case WatcherType.Player: case WatcherType.Player:
watcher = await WatcherFactory.Get<PlayerWatcher>(spotifyFactory, watcherOption.PollPeriod); watcher = await WatcherFactory.Get<PlayerWatcher>(spotifyFactory, id: watcherOption.Name, pollPeriod: watcherOption.PollPeriod);
break; break;
case WatcherType.Playlist: case WatcherType.Playlist:
throw new NotImplementedException("Playlist watchers not implemented"); throw new NotImplementedException("Playlist watchers not implemented");

View File

@ -41,11 +41,11 @@ namespace Selector.Cache
{ {
var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e); var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e);
Logger.LogTrace($"Caching current for [{e.Username}]"); Logger.LogTrace($"Caching current for [{e.Id}/{e.SpotifyUsername}]");
var resp = await Db.StringSetAsync(Key.CurrentlyPlaying(e.Username), payload); var resp = await Db.StringSetAsync(Key.CurrentlyPlaying(e.Id), payload);
Logger.LogDebug($"Cached current for [{e.Username}], {(resp ? "value set" : "value NOT set")}"); Logger.LogDebug($"Cached current for [{e.Id}/{e.SpotifyUsername}], {(resp ? "value set" : "value NOT set")}");
} }

View File

@ -41,12 +41,12 @@ namespace Selector.Cache
{ {
var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e); var payload = JsonSerializer.Serialize((CurrentlyPlayingDTO) e);
Logger.LogTrace($"Publishing current for [{e.Username}]"); Logger.LogTrace($"Publishing current for [{e.Id}/{e.SpotifyUsername}]");
// TODO: currently using spotify username for cache key, use db username // TODO: currently using spotify username for cache key, use db username
var receivers = await Subscriber.PublishAsync(Key.CurrentlyPlaying(e.Username), payload); var receivers = await Subscriber.PublishAsync(Key.CurrentlyPlaying(e.Id), payload);
Logger.LogDebug($"Published current for [{e.Username}], {receivers} receivers"); Logger.LogDebug($"Published current for [{e.Id}/{e.SpotifyUsername}], {receivers} receivers");
} }
public void Subscribe(IWatcher watch = null) public void Subscribe(IWatcher watch = null)

View File

@ -18,7 +18,7 @@ namespace Selector.Cache {
return new() return new()
{ {
Context = e.Current, Context = e.Current,
Username = e.Username, Username = e.SpotifyUsername,
Track = track Track = track
}; };
} }
@ -27,7 +27,7 @@ namespace Selector.Cache {
return new() return new()
{ {
Context = e.Current, Context = e.Current,
Username = e.Username, Username = e.SpotifyUsername,
Episode = episode Episode = episode
}; };
} }

View File

@ -7,14 +7,28 @@ namespace Selector.Cache
public class Key public class Key
{ {
public const string CurrentlyPlayingName = "CurrentlyPlaying"; public const string CurrentlyPlayingName = "CurrentlyPlaying";
public const string TrackName = "Track"; public const string TrackName = "Track";
public const string AlbumName = "Album";
public const string ArtistName = "Artist";
public const string AudioFeatureName = "AudioFeature"; public const string AudioFeatureName = "AudioFeature";
public const string PlayCountName = "PlayCount";
public const string WorkerName = "Worker"; public const string WorkerName = "Worker";
public static string CurrentlyPlaying(string user) => Namespace(new[] { user, CurrentlyPlayingName }); /// <summary>
public static string AudioFeature(string trackId) => Namespace(new[] { TrackName, trackId, AudioFeatureName }); /// Current playback for a user
/// </summary>
/// <param name="user">User's database Id (Guid)</param>
/// <returns></returns>
public static string CurrentlyPlaying(string user) => Namespace(user, CurrentlyPlayingName);
public static string AudioFeature(string trackId) => Namespace(TrackName, trackId, AudioFeatureName);
public static string Namespace(string[] args) => string.Join(":", args); 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 Namespace(params string[] args) => string.Join(":", args);
} }
} }

View File

@ -22,9 +22,11 @@ namespace Selector.Model
public class ApplicationUserDTO public class ApplicationUserDTO
{ {
public string Id { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string PhoneNumber { get; set; } public string PhoneNumber { get; set; }
public bool LockoutEnabled { get; set; }
public bool SpotifyIsLinked { get; set; } public bool SpotifyIsLinked { get; set; }
public DateTime SpotifyLastRefresh { get; set; } public DateTime SpotifyLastRefresh { get; set; }
@ -35,9 +37,11 @@ namespace Selector.Model
public string LastFmUsername { get; set; } public string LastFmUsername { get; set; }
public static explicit operator ApplicationUserDTO(ApplicationUser user) => new() { public static explicit operator ApplicationUserDTO(ApplicationUser user) => new() {
Id = user.Id,
UserName = user.UserName, UserName = user.UserName,
Email = user.Email, Email = user.Email,
PhoneNumber = user.PhoneNumber, PhoneNumber = user.PhoneNumber,
LockoutEnabled = user.LockoutEnabled,
SpotifyIsLinked = user.SpotifyIsLinked, SpotifyIsLinked = user.SpotifyIsLinked,
SpotifyLastRefresh = user.SpotifyLastRefresh, SpotifyLastRefresh = user.SpotifyLastRefresh,

View File

@ -27,7 +27,7 @@ namespace Selector.Web.Service
public async Task ConstructMapping(ISubscriber subscriber, IHubContext<NowPlayingHub, INowPlayingHubClient> hub) public async Task ConstructMapping(ISubscriber subscriber, IHubContext<NowPlayingHub, INowPlayingHubClient> hub)
{ {
var key = Key.CurrentlyPlaying(Username); var key = Key.CurrentlyPlaying(UserId);
(await subscriber.SubscribeAsync(key)).OnMessage(async message => { (await subscriber.SubscribeAsync(key)).OnMessage(async message => {
try{ try{

View File

@ -79,12 +79,12 @@ namespace Selector
} }
else else
{ {
Logger.LogDebug($"Track info error [{e.Username}] [{trackInfo.Result.Status}]"); Logger.LogDebug($"Track info error [{e.Id}/{e.SpotifyUsername}] [{trackInfo.Result.Status}]");
} }
} }
else else
{ {
Logger.LogError(trackInfo.Exception, $"Track info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); Logger.LogError(trackInfo.Exception, $"Track info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]");
} }
if (albumInfo.IsCompletedSuccessfully) if (albumInfo.IsCompletedSuccessfully)
@ -95,12 +95,12 @@ namespace Selector
} }
else else
{ {
Logger.LogDebug($"Album info error [{e.Username}] [{albumInfo.Result.Status}]"); Logger.LogDebug($"Album info error [{e.Id}/{e.SpotifyUsername}] [{albumInfo.Result.Status}]");
} }
} }
else else
{ {
Logger.LogError(albumInfo.Exception, $"Album info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); Logger.LogError(albumInfo.Exception, $"Album info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]");
} }
//TODO: Add artist count //TODO: Add artist count
@ -113,15 +113,15 @@ namespace Selector
} }
else else
{ {
Logger.LogDebug($"User info error [{e.Username}] [{userInfo.Result.Status}]"); Logger.LogDebug($"User info error [{e.Id}/{e.SpotifyUsername}] [{userInfo.Result.Status}]");
} }
} }
else else
{ {
Logger.LogError(userInfo.Exception, $"User info task faulted, [{e.Username}] [{e.Current.DisplayString()}]"); Logger.LogError(userInfo.Exception, $"User info task faulted, [{e.Id}/{e.SpotifyUsername}] [{e.Current.DisplayString()}]");
} }
Logger.LogDebug($"Adding Last.fm data [{Credentials.Username}/{e.Username}] [{track.DisplayString()}], track: {trackCount}, album: {albumCount}, artist: {artistCount}, user: {userCount}"); Logger.LogDebug($"Adding Last.fm data [{e.Id}/{e.SpotifyUsername}/{Credentials.Username}] [{track.DisplayString()}], track: {trackCount}, album: {albumCount}, artist: {artistCount}, user: {userCount}");
OnNewPlayCount(new() OnNewPlayCount(new()
{ {

View File

@ -13,7 +13,8 @@ namespace Selector
public abstract class BaseWatcher: IWatcher public abstract class BaseWatcher: IWatcher
{ {
protected readonly ILogger<BaseWatcher> Logger; protected readonly ILogger<BaseWatcher> Logger;
public string Username { get; set; } public string Id { get; set; }
public string SpotifyUsername { get; set; }
public BaseWatcher(ILogger<BaseWatcher> logger = null) public BaseWatcher(ILogger<BaseWatcher> logger = null)
{ {

View File

@ -9,17 +9,23 @@ namespace Selector
/// <summary> /// <summary>
/// Spotify Username /// Spotify Username
/// </summary> /// </summary>
public string Username { get; set; } public string SpotifyUsername { get; set; }
/// <summary>
/// String Id for watcher, used to hold user Db Id
/// </summary>
/// <value></value>
public string Id { get; set; }
PlayerTimeline Timeline { get; set; } PlayerTimeline Timeline { get; set; }
public static ListeningChangeEventArgs From(CurrentlyPlayingContext previous, CurrentlyPlayingContext current, PlayerTimeline timeline, string username = null) public static ListeningChangeEventArgs From(CurrentlyPlayingContext previous, CurrentlyPlayingContext current, PlayerTimeline timeline, string id = null, string username = null)
{ {
return new ListeningChangeEventArgs() return new ListeningChangeEventArgs()
{ {
Previous = previous, Previous = previous,
Current = current, Current = current,
Timeline = timeline, Timeline = timeline,
Username = username Id = id,
SpotifyUsername = username
}; };
} }
} }

View File

@ -7,7 +7,7 @@ namespace Selector
{ {
public interface IWatcherFactory public interface IWatcherFactory
{ {
public Task<IWatcher> Get<T>(ISpotifyConfigFactory spotifyFactory, int pollPeriod) public Task<IWatcher> Get<T>(ISpotifyConfigFactory spotifyFactory, string id, int pollPeriod)
where T : class, IWatcher; where T : class, IWatcher;
} }
} }

View File

@ -74,14 +74,14 @@ namespace Selector
&& (Live.Item is FullTrack || Live.Item is FullEpisode)) && (Live.Item is FullTrack || Live.Item is FullEpisode))
{ {
Logger.LogDebug($"Playback started: {Live.DisplayString()}"); Logger.LogDebug($"Playback started: {Live.DisplayString()}");
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// STOPPED PLAYBACK // STOPPED PLAYBACK
else if((previous.Item is FullTrack || previous.Item is FullEpisode) else if((previous.Item is FullTrack || previous.Item is FullEpisode)
&& Live is null) && Live is null)
{ {
Logger.LogDebug($"Playback stopped: {previous.DisplayString()}"); Logger.LogDebug($"Playback stopped: {previous.DisplayString()}");
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// CONTINUING PLAYBACK // CONTINUING PLAYBACK
else { else {
@ -92,17 +92,17 @@ namespace Selector
{ {
if(!eq.IsEqual(previousTrack, currentTrack)) { if(!eq.IsEqual(previousTrack, currentTrack)) {
Logger.LogDebug($"Track changed: {previousTrack.DisplayString()} -> {currentTrack.DisplayString()}"); Logger.LogDebug($"Track changed: {previousTrack.DisplayString()} -> {currentTrack.DisplayString()}");
OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) { if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) {
Logger.LogDebug($"Album changed: {previousTrack.Album.DisplayString()} -> {currentTrack.Album.DisplayString()}"); Logger.LogDebug($"Album changed: {previousTrack.Album.DisplayString()} -> {currentTrack.Album.DisplayString()}");
OnAlbumChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnAlbumChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) { if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) {
Logger.LogDebug($"Artist changed: {previousTrack.Artists.DisplayString()} -> {currentTrack.Artists.DisplayString()}"); Logger.LogDebug($"Artist changed: {previousTrack.Artists.DisplayString()} -> {currentTrack.Artists.DisplayString()}");
OnArtistChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnArtistChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
} }
// CHANGED CONTENT // CHANGED CONTENT
@ -110,8 +110,8 @@ namespace Selector
|| (previous.Item is FullEpisode && Live.Item is FullTrack)) || (previous.Item is FullEpisode && Live.Item is FullTrack))
{ {
Logger.LogDebug($"Media type changed: {previous.Item}, {previous.Item}"); Logger.LogDebug($"Media type changed: {previous.Item}, {previous.Item}");
OnContentChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnContentChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// PODCASTS // PODCASTS
else if(previous.Item is FullEpisode previousEp else if(previous.Item is FullEpisode previousEp
@ -119,7 +119,7 @@ namespace Selector
{ {
if(!eq.IsEqual(previousEp, currentEp)) { if(!eq.IsEqual(previousEp, currentEp)) {
Logger.LogDebug($"Podcast changed: {previousEp.DisplayString()} -> {currentEp.DisplayString()}"); Logger.LogDebug($"Podcast changed: {previousEp.DisplayString()} -> {currentEp.DisplayString()}");
OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnItemChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
} }
else { else {
@ -129,25 +129,25 @@ namespace Selector
// CONTEXT // CONTEXT
if(!eq.IsEqual(previous.Context, Live.Context)) { if(!eq.IsEqual(previous.Context, Live.Context)) {
Logger.LogDebug($"Context changed: {previous.Context.DisplayString()} -> {Live.Context.DisplayString()}"); Logger.LogDebug($"Context changed: {previous.Context.DisplayString()} -> {Live.Context.DisplayString()}");
OnContextChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnContextChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// DEVICE // DEVICE
if(!eq.IsEqual(previous?.Device, Live?.Device)) { if(!eq.IsEqual(previous?.Device, Live?.Device)) {
Logger.LogDebug($"Device changed: {previous?.Device.DisplayString()} -> {Live?.Device.DisplayString()}"); Logger.LogDebug($"Device changed: {previous?.Device.DisplayString()} -> {Live?.Device.DisplayString()}");
OnDeviceChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnDeviceChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// IS PLAYING // IS PLAYING
if(previous.IsPlaying != Live.IsPlaying) { if(previous.IsPlaying != Live.IsPlaying) {
Logger.LogDebug($"Playing state changed: {previous.IsPlaying} -> {Live.IsPlaying}"); Logger.LogDebug($"Playing state changed: {previous.IsPlaying} -> {Live.IsPlaying}");
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnPlayingChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
// VOLUME // VOLUME
if(previous.Device.VolumePercent != Live.Device.VolumePercent) { if(previous.Device.VolumePercent != Live.Device.VolumePercent) {
Logger.LogDebug($"Volume changed: {previous.Device.VolumePercent}% -> {Live.Device.VolumePercent}%"); Logger.LogDebug($"Volume changed: {previous.Device.VolumePercent}% -> {Live.Device.VolumePercent}%");
OnVolumeChange(ListeningChangeEventArgs.From(previous, Live, Past, Username)); OnVolumeChange(ListeningChangeEventArgs.From(previous, Live, Past, id: Id, username: SpotifyUsername));
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace Selector
Equal = equal; Equal = equal;
} }
public async Task<IWatcher> Get<T>(ISpotifyConfigFactory spotifyFactory, int pollPeriod = 3000) public async Task<IWatcher> Get<T>(ISpotifyConfigFactory spotifyFactory, string id = null, int pollPeriod = 3000)
where T : class, IWatcher where T : class, IWatcher
{ {
if(typeof(T).IsAssignableFrom(typeof(PlayerWatcher))) if(typeof(T).IsAssignableFrom(typeof(PlayerWatcher)))
@ -35,7 +35,8 @@ namespace Selector
LoggerFactory?.CreateLogger<PlayerWatcher>() ?? NullLogger<PlayerWatcher>.Instance, LoggerFactory?.CreateLogger<PlayerWatcher>() ?? NullLogger<PlayerWatcher>.Instance,
pollPeriod: pollPeriod pollPeriod: pollPeriod
) { ) {
Username = user.DisplayName SpotifyUsername = user.DisplayName,
Id = id
}; };
} }
//else if (typeof(T).IsAssignableFrom(typeof(PlaylistWatcher))) //else if (typeof(T).IsAssignableFrom(typeof(PlaylistWatcher)))