using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NLog; using Serilog.Context; using Sony.Filtr.ErrorLogging; using Sony.Filtr.Tasks; using Sony.Filtr.Tasks.Tasks; using Sony.Filtr.Tasks.Tasks.AppleMusic; using Sony.Filtr.Tasks.Tasks.Deezer; using Sony.Filtr.Tasks.Tasks.PublicApi; using Sony.Filtr.Tasks.Tasks.Spotify; using Sony.Filtr.Tasks.Tasks.Spotify.Analytics; namespace Sony.Filtr.ScheduledTask { public class ScheduledTaskRunner { private readonly ScheduledTaskManager _scheduledTaskManager; private readonly StructureMap.IContainer _container; private readonly Logger _logger; public ScheduledTaskRunner(ScheduledTaskManager scheduledTaskManager, StructureMap.IContainer container) { _scheduledTaskManager = scheduledTaskManager; _container = container; _logger = LogManager.GetLogger("ScheduledTask"); } private Dictionary CreateTaskMapping() { return new Dictionary(StringComparer.InvariantCultureIgnoreCase) { {"playlistStats", typeof(FetchPlaylistStats)}, {"playlistStatsSelected", typeof(FetchPlaylistStatsSelected)}, {"release", typeof(UpdateSpotifyReleases)}, {"importplaylists", typeof(ImportPlaylists)}, {"importBuzzPlaylists", typeof(ImportBuzzPlaylists)}, {"updateplaylistsvendorapi", typeof(UpdatePlaylistInfoWithVendorAPI) }, {"analyticsPlaylistImport", typeof(AggregatedPlaylistImportTask)}, {"analyticsPlaylistImportBackfill", typeof(AggregatedPlaylistImportTask)}, {"analyticsImport", typeof(AggregatedGeneralSpotifyImportTask)}, {"fetchpopularartists", typeof(FetchPopularArtists)}, {"importArtistFollowers", typeof(ImportArtistFollowersTask)}, {"importPopularArtistFollowers", typeof(ImportPopularArtistFollowersTask)}, {"importBuzzArtistPlaylists", typeof(ImportBuzzArtistPlaylists)}, {"importSpotifyBrowse", typeof(ImportSpotifyBrowse)}, {"deezerImportPlaylists", typeof(DeezerImportPlaylistsTask)}, {"playlistSync", typeof(PlaylistSynchronizationTask)}, {"moodagentExport", typeof(UploadMoodagentPlaylistExportTask)}, {"syncStagingDatabase", typeof(SyncStagingDatabaseTask)}, {"uploadplaylistsandusers", typeof(UploadPlaylistsAndUsers)}, {"mostPlaylistedTrack", typeof(SpotifyMostPlaylistedTrackTask)}, {"accousticDetails", typeof(SpotifyTrackAccousticDetailsTask)}, {"importSonyReleases", typeof(ImportNewSonyReleasesTask)}, {"spotifyAlbumData", typeof(SpotifyAlbumDataTask)}, {"updateplaylisttracks", typeof(UpdatePlaylistTracklistTask)}, {"adminsearchindex", typeof(AdminSearchIndexTask)}, {"indexEditorialPlaylists", typeof(IndexEditorialPlaylists)}, {"setEditorialPlaylistGenres", typeof(SetEditorialPlaylistGenres)}, {"applemusicplaylists", typeof(UpdateAppleMusicPlaylistsTask)}, {"applemusicplaylistsMostStreamed", typeof(UpdateAppleMusicPlaylistsMostStreamedTask)}, {"applemusicbuzzusers", typeof(UpdateAppleMusicBuzzUsersTask)}, {"updateAppleMusicAnalyticsAggregatedTask", typeof(UpdateAppleMusicAnalyticsAggregatedTask)}, {"updateAppleMusicSongs", typeof(UpdateAppleMusicSongsTask)}, {"exportSpotifyPlaylistTracklistHistory", typeof(ExportSpotifyPlaylistTracklistHistoryTask)}, {"exportAppleMusicPlaylistTracklistHistory", typeof(ExportAppleMusicPlaylistTracklistHistoryTask)}, {"spotifyWeeklyTopList", typeof(SpotifyWeeklyTopListTask)}, {"importBestOfTheWeek", typeof(ImportBestOfTheWeekTask)}, {"scrapeSpotifyArtistListeners", typeof(ScrapeArtistListenersTask)}, {"playlistAggregationDataImport", typeof(AggregatedPlaylistDataImportTask) }, {"newPlaylistsImport", typeof(NewPlaylistsImporter) } }; } public async Task ExecuteAsync(IEnumerable args) { Dictionary exceptions = new Dictionary(); var taskMapping = CreateTaskMapping(); foreach (var arg in args) { var key = arg.ToLower(); if (!taskMapping.ContainsKey(key)) { _logger.Debug("Argument {0} not recognized", key); continue; } var taskType = taskMapping[key]; var logId = Guid.NewGuid(); _logger.Debug($"Begin processing for argument {key} with type {taskType?.Name}. Log Id: {logId}"); _logger.Debug($"ServicePointManager.DefaultConnectionLimit: {System.Net.ServicePointManager.DefaultConnectionLimit}"); Tasks.ScheduledTask scheduledTask = null; try { scheduledTask = await _scheduledTaskManager.GetOrAddScheduledTaskAsync(key); var isThisTaskRunningNow = await _scheduledTaskManager.IsTaskCurrentlyRunById(scheduledTask); if (isThisTaskRunningNow) { _logger.Debug($"Task already running. Name: {scheduledTask.Name} with Id: {scheduledTask.Id}. Log Id: {logId}"); return; } await _scheduledTaskManager.LogTaskStartedAsync(scheduledTask, logId); using (LogContext.PushProperty("JobName", taskType.Name)) using (LogContext.PushProperty("JobId", scheduledTask.Id)) using (LogContext.PushProperty("JobAlias", scheduledTask.Name)) using (LogContext.PushProperty("JobStartTime", DateTime.Now)) { var scheduledTaskInstance = (IScheduledTask)_container.GetInstance(taskType); ScheduledTaskLog taskLog = await scheduledTaskInstance.ExecuteAsync(logId); if (taskLog != null) { await _scheduledTaskManager.LogTaskFinishedAsync(logId, taskLog); //_logger.Debug("Done processing for argument {0} with type {1}", key, taskMapping[key].GetType()); //await _scheduledTaskManager.SaveScheduledTasksInfo(taskInfo); //_logger.Debug("Done saving task info for argument {0} with type {1}", key, taskMapping[key].GetType()); } else { await _scheduledTaskManager.LogTaskFinishedAsync(logId, new ScheduledTaskLog()); } Serilog.Log.Logger.Information($"Job finished"); } } catch (Exception ex) { _logger.Error(ex, "Error occurred for argument {0} with type {1}. Continuing anyway.", key, taskType); ErrorLoggingManager.Instance.LogError(ex); await _scheduledTaskManager.LogTaskFinishedAsync(logId, new ScheduledTaskLog() { Error = true, ErrorMessage = ex.Message, Finished = DateTimeOffset.UtcNow }); exceptions.Add(key, ex); Serilog.Log.Logger.Error(ex, $"Job failed"); } await _scheduledTaskManager.LogTaskFinishedAsync(scheduledTask); } if (exceptions.Any()) { //We throw one of the exceptions afterwards so process get error code. throw exceptions.Values.First(); } _logger.Debug("Done with all actions."); } } }