using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NLog; using Sony.Filtr.Contracts.Definitions; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Contracts.Entities.Genre; using Sony.Filtr.PlaylistGeneration.Data; using Sony.Filtr.Utility.Extensions; namespace Sony.Filtr.PlaylistGeneration.Caching { public class MultiplexCacheProvider : ICacheProvider { private readonly List _cacheProviders; private readonly ICacheProvider _fastCacheProvider; private readonly DbCacheProvider _dbCacheProvider; private readonly Logger _logger; public MultiplexCacheProvider(DistributedCacheProvider distributedCacheProvider, DbCacheProvider dbCacheProvider) { _cacheProviders = new List(); _cacheProviders.Add(distributedCacheProvider); _cacheProviders.Add(dbCacheProvider); _fastCacheProvider = distributedCacheProvider; _dbCacheProvider = dbCacheProvider; _logger = LogManager.GetLogger("TrackSuggestionManager2"); } public List FetchSimilarArtistsFromCache(string artistName) { foreach (var cacheProvider in _cacheProviders) { var similarArtists = cacheProvider.FetchSimilarArtistsFromCache(artistName); if (similarArtists != null && similarArtists.Any()) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheSimilarArtists(new Artist(artistName), similarArtists); return similarArtists; } } return null; } public void CacheSimilarArtists(Artist artist, List similarArtists) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheSimilarArtists(artist, similarArtists); } } public void CacheArtist(Artist artist) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheArtist(artist); } } public Artist FetchArtistFromCache(string artistName) { foreach (var cacheProvider in _cacheProviders) { var result = cacheProvider.FetchArtistFromCache(artistName); if (result != null) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheArtist(result); return result; } } return null; } public async Task> FetchArtistsFromCacheAsync(List artistNames) { List artists = new List(); var artistResult = await _fastCacheProvider.FetchArtistsFromCacheAsync(artistNames); artists.AddRange(artistResult); var missingArtists = artistNames.Except(artistResult.Select(a=> a.Name), StringComparer.InvariantCultureIgnoreCase).ToList(); if (missingArtists.Any()) { _logger.Debug("Could not find all artist tags in fastCache, doing lookup in DB for {0} artists. Some are: {1}", missingArtists.Count, string.Join(",", missingArtists.Take(5))); var dbArtistResults = await _dbCacheProvider.FetchArtistsFromCacheAsync(missingArtists.ToList()); foreach (var artist in dbArtistResults) { _fastCacheProvider.CacheArtist(artist); //Fire and forget artists.Add(artist); } } return artists; } public void CacheGenreMatch(Application application, Artist artist, IEnumerable genres) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheGenreMatch(application, artist, genres); } } public List FetchGenreMatchFromCache(Application application, Artist artistName) { foreach (var cacheProvider in _cacheProviders) { var result = cacheProvider.FetchGenreMatchFromCache(application, artistName); if (result != null && result.Any()) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheGenreMatch(application, artistName, result); return result; } } return null; } public void CacheGenreArtists(Genre genre, IEnumerable artists) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheGenreArtists(genre, artists); } } public List FetchGenreArtists(Genre genre) { foreach (var cacheProvider in _cacheProviders) { var result = cacheProvider.FetchGenreArtists(genre); if (result != null && result.Any()) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheGenreArtists(genre, result); return result; } } return null; } public string GetCacheProviderName() { return "MusicMatch.PlaylistGeneration.Caching.MultiplexCacheProvider"; } public void CacheArtistTags(string artist, List tags) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheArtistTags(artist, tags); } } public async Task> FetchArtistTagsFromCacheAsync(string artist) { foreach (var cacheProvider in _cacheProviders) { var tags = await cacheProvider.FetchArtistTagsFromCacheAsync(artist); if (tags != null) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheArtistTags(artist, tags); return tags; } } return null; } public async Task>> FetchArtistsTagsFromCacheAsync(List artists) { var artistResult = await _fastCacheProvider.FetchArtistsTagsFromCacheAsync(artists); var missingArtists = artists.Except(artistResult.Keys).ToList(); if (missingArtists.Any()) { _logger.Debug("Could not find all artist tags in fastCache, doing lookup in DB for {0} artists. Some are: {1}", missingArtists.Count, string.Join(",", missingArtists.Take(5))); var dbResults = await _dbCacheProvider.FetchArtistsTagsFromCacheAsync(missingArtists.ToList()); foreach (var dbResult in dbResults) { _fastCacheProvider.CacheArtistTags(dbResult.Key, dbResult.Value); //Fire and forget _logger.Debug("Found in DB, adding to fastCache: {0}", dbResult.Key); if (!artistResult.ContainsKey(dbResult.Key)) { artistResult.Add(dbResult.Key, dbResult.Value); } } } return artistResult; } public async Task>> FetchTopTrackForTagAsync(string tag) { foreach (var cacheProvider in _cacheProviders) { var tracks = await cacheProvider.FetchTopTrackForTagAsync(tag); if (tracks != null && tracks.Any()) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) await _fastCacheProvider.CacheTopTrackForTagAsync(tag, tracks); return tracks; } } return null; } public async Task CacheTopTrackForTagAsync(string tag, List> topTracks) { foreach (var cacheProvider in _cacheProviders) { await cacheProvider.CacheTopTrackForTagAsync(tag, topTracks); } } //public void CacheSearchTracks(string mood, string genre, List> tracks) //{ // foreach (var cacheProvider in _cacheProviders) // { // cacheProvider.CacheSearchTracks(mood, genre, tracks); // } //} //public List> FetchSearchTracks(string mood, string genre) //{ // foreach (var cacheProvider in _cacheProviders) // { // var tracks = cacheProvider.FetchSearchTracks(mood, genre); // if (tracks != null && tracks.Any()) // { // if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) // _fastCacheProvider.CacheSearchTracks(mood, genre, tracks); // return tracks; // } // } // return null; //} public async Task CacheTrackTagsAsync(Track track, List tags) { foreach (var cacheProvider in _cacheProviders) { await cacheProvider.CacheTrackTagsAsync(track, tags); } } public async Task> FetchTrackTagsFromCacheAsync(Track track) { foreach (var cacheProvider in _cacheProviders) { var tags = await cacheProvider.FetchTrackTagsFromCacheAsync(track); if (tags != null && tags.Any()) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) await _fastCacheProvider.CacheTrackTagsAsync(track, tags); return tags; } } return null; } public async Task>> FetchExtendedTopTracksForArtistsAsync(List artists, ServiceType serviceType) { //Dictionary> artistsDictionary = new Dictionary>(); var artistResult = await _fastCacheProvider.FetchExtendedTopTracksForArtistsAsync(artists, serviceType); var missingArtists = artists.Except(artistResult.Keys, StringComparer.InvariantCultureIgnoreCase).ToList(); if (missingArtists.Any()) { _logger.Debug("Could not find all artists in fastCache, doing lookup in DB for {0} artists. Some are: {1}", missingArtists.Count, string.Join(",", missingArtists.Take(5))); var dbResults = await _dbCacheProvider.FetchExtendedTopTracksForArtistsAsync(missingArtists.ToList(), serviceType); foreach (var dbResult in dbResults) { _fastCacheProvider.CacheExtendedTopTracksForArtistAsync(dbResult.Key, dbResult.Value, serviceType).FireAndForget(); artistResult.Add(dbResult.Key, dbResult.Value); } } return artistResult; } public async Task> FetchExtendedTopTracksForArtistAsync(string artistName, ServiceType serviceType) { foreach (var cacheProvider in _cacheProviders) { var topTracks = await cacheProvider.FetchExtendedTopTracksForArtistAsync(artistName, serviceType); if (topTracks != null) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) await _fastCacheProvider.CacheExtendedTopTracksForArtistAsync(artistName, topTracks, serviceType); return topTracks; } } return null; } public async Task CacheExtendedTopTracksForArtistAsync(string artistName, List tracks, ServiceType serviceType) { foreach (var cacheProvider in _cacheProviders) { await cacheProvider.CacheExtendedTopTracksForArtistAsync(artistName, tracks, serviceType); } } //public List> FetchArtistMood(string artistName) //{ // foreach (var cacheProvider in _cacheProviders) // { // var moods = cacheProvider.FetchArtistMood(artistName); // if (moods != null) // { // if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) // _fastCacheProvider.CacheArtistMood(artistName, moods); // return moods; // } // } // return null; //} //public void CacheArtistMood(string artistName, List> moods) //{ // foreach (var cacheProvider in _cacheProviders) // { // cacheProvider.CacheArtistMood(artistName, moods); // } //} public void CacheExtendedTopTracksForTag(string tag, List groupedExtendedTracks) { foreach (var cacheProvider in _cacheProviders) { cacheProvider.CacheExtendedTopTracksForTag(tag, groupedExtendedTracks); } } public List FetchExtendedTopTracksForTag(string tag) { foreach (var cacheProvider in _cacheProviders) { var tracks = cacheProvider.FetchExtendedTopTracksForTag(tag); if (tracks != null) { if (cacheProvider.GetCacheProviderName() != _fastCacheProvider.GetCacheProviderName()) _fastCacheProvider.CacheExtendedTopTracksForTag(tag, tracks); return tracks; } } return null; } } }