using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MoreLinq; using MySql.Data.MySqlClient; using NLog; using PetaPoco.Business; using Sony.Filtr.Contracts.Abstractions; using Sony.Filtr.Contracts.Definitions; using Sony.Filtr.SpotifyAnalytics; using Sony.Filtr.SpotifyAnalytics.Data; using Sony.Filtr.Utility.Extensions; using Sony.Filtr.Functional; namespace Sony.Filtr.Tasks.Tasks.Spotify.Analytics { public class CalculatePlaylistCategoryStreams { private readonly IApplicationInstanceManager _applicationInstanceManager; private readonly SpotifyAnalyticsManager _spotifyAnalyticsManager; private readonly Logger _logger; public CalculatePlaylistCategoryStreams(IApplicationInstanceManager applicationInstanceManager, SpotifyAnalyticsManager spotifyAnalyticsManager) { _applicationInstanceManager = applicationInstanceManager; _spotifyAnalyticsManager = spotifyAnalyticsManager; _logger = LogManager.GetLogger("SpotifyStreamingAggregatedReportApi"); } public async Task CalculatePlaylistCategoryStreamsAsync(DateTime date) { Func, string> createCategoryStreamsSummary = categoryStreams => { var groups = categoryStreams.GroupBy(s => new { s.Market, s.BuzzCategoryId, s.AccountId }); StringBuilder builder = new StringBuilder("Done calculating playlist category streams."); foreach (var group in groups) { builder.AppendLine($"For market:{group.Key.Market} BuzzCateogry:{group.Key.BuzzCategoryId} AccountId:{group.Key.AccountId} => LocalListStreams:{group.Sum(g => g.LocalListStreams)} TotalListStreams: {group.Sum(g => g.TotalListStreams)}"); } return builder.ToString(); }; var accounts = new List() { SpotifyAnalyticsAccount.Sony, SpotifyAnalyticsAccount.Orchard, SpotifyAnalyticsAccount.SonyMusicEntertainmentJapan, SpotifyAnalyticsAccount.SonyMusicEntertainmentJapanInternational }; var streamSums = new List<(int local, int total)>(); foreach (var account in accounts) { var playlistCategoryStreams = await CalculatePlaylistCategoryStreamsAsync((int)account, date); _logger.Info(createCategoryStreamsSummary(playlistCategoryStreams)); streamSums.Add(playlistCategoryStreams.Aggregate((local: 0, total: 0), (current, streams) => { current.local += streams.LocalListStreams; current.total += streams.TotalListStreams; return current; })); await PetaPocoRepository.Instance.ImportBulkFileLoaderAsync(playlistCategoryStreams, MySqlBulkLoaderConflictOption.Replace); } _logger.Info($"Date sum. LocalListStreams: {streamSums.Sum(tuple => tuple.local)} TotalListStreams: {streamSums.Sum(tuple => tuple.total)}"); } private async Task> CalculatePlaylistCategoryStreamsAsync(int spotifyAnalyticsAccountId, DateTime streamsDate) { var categoryStreamsForDate = new ConcurrentBag(); var applications = _applicationInstanceManager .GetApplications() .Where(a => !a.GlobalPushApplication && !a.WorkoutMarket) .DistinctBy(a => a.SpotifyRegionCode) .OrderBy(a => a.SpotifyRegionCode); Func<(int, DateTime, Sony.Filtr.Contracts.Entities.Application, List, StaticBuzzCategory), Task>> calculatePlaylistCategoryStreams = ((Func, StaticBuzzCategory, Task>)_spotifyAnalyticsManager.CalculatePlaylistCategoryStreams) .Tuple() .Timeout(TimeSpan.FromMinutes(2)) .Retry(2) .TryCatch() .OnFailure((tuple, result) => _logger.Error(result.Exception, $"Could not calculate categor streams for market {tuple.Item3.SpotifyRegionCode} and account {tuple.Item1} for {tuple.Item5} playlists and date {tuple.Item2.ToShortDateString()}")); await applications.ForEachAsync(5, async app => { var appRegions = _applicationInstanceManager.GetApplicationRegions(app.SpotifyRegionCode).OrderBy(a => a).ToList(); var sonyPlaylistsCategoryStreams = await calculatePlaylistCategoryStreams((spotifyAnalyticsAccountId, streamsDate, app, appRegions, StaticBuzzCategory.SonyMusic)); if (sonyPlaylistsCategoryStreams.IsOk) { _logger.Info($"Calculated category streams for market '{app.SpotifyRegionCode}' and account {spotifyAnalyticsAccountId} for Sony's playlists in {streamsDate.ToShortDateString()} LocalListStreams: {sonyPlaylistsCategoryStreams.Value.LocalListStreams} TotalListStreams: {sonyPlaylistsCategoryStreams.Value.TotalListStreams}"); categoryStreamsForDate.Add(sonyPlaylistsCategoryStreams.Value); } var spotifyPlaylistsCategoryStreams = await calculatePlaylistCategoryStreams((spotifyAnalyticsAccountId, streamsDate, app, appRegions, StaticBuzzCategory.Spotify)); if (spotifyPlaylistsCategoryStreams.IsOk) { _logger.Info($"Calculated category streams for market '{app.SpotifyRegionCode}' and account {spotifyAnalyticsAccountId} for Spotify's playlists in {streamsDate.ToShortDateString()} LocalListStreams: {sonyPlaylistsCategoryStreams.Value.LocalListStreams} TotalListStreams: {sonyPlaylistsCategoryStreams.Value.TotalListStreams}"); categoryStreamsForDate.Add(spotifyPlaylistsCategoryStreams.Value); } }); return categoryStreamsForDate.ToList(); } } }