public SchedulerHostedService(IEnumerable <IScheduledTask> scheduledTasks, TVMazeDBContext dbContext, TVMazeAPIService tvMazeAPIService, ILogger logger) { var referenceTime = DateTime.UtcNow; _dbContext = dbContext; _tvMazeAPIService = tvMazeAPIService; _logger = logger; foreach (var scheduledTask in scheduledTasks) { _scheduledTasks.Add(new SchedulerTaskWrapper { Schedule = CrontabSchedule.Parse(scheduledTask.Schedule), Task = scheduledTask, NextRunTime = referenceTime }); } }
/// <summary> /// Service entry point /// </summary> /// <param name="tvMazeApiService">TVMazeApi HttpClient Service</param> /// <param name="dbContext">MS SQL Db Context</param> /// <param name="cancellationToken"></param> /// <param name="logger">Logger service</param> /// <returns></returns> public async Task ExecuteAsync(TVMazeAPIService tvMazeApiService, TVMazeDBContext dbContext, CancellationToken cancellationToken, ILogger logger) { DateTime startTime = DateTime.Now; //We need to check last pack of shows, maybe we have a new ones in it bool tryFirstPack = true; _tvMazeApiService = tvMazeApiService; //HttpClient Retry Policy var maxRetryAttempts = 3; var pauseBetweenFailures = TimeSpan.FromSeconds(10); var retryPolicy = Policy .Handle <HttpRequestException>() .WaitAndRetryAsync(maxRetryAttempts, i => pauseBetweenFailures); //Select max show id into local database var maxShowId = dbContext.TVMazeShow.Select(s => s.Id).DefaultIfEmpty(0).Max(); //Calc next pageIndex for TVMazeAPI var pageIndex = (maxShowId == 0) ? 0 : (int)Math.Floor((double)maxShowId / 250) + 1; while (true) { IEnumerable <TVMazeShow> showsList = null; //need to check pack pack for new shows if (tryFirstPack && maxShowId != 0 && maxShowId < 250 * pageIndex - 1) { logger.Log(LogLevel.None, $"Pack with index={pageIndex - 1} loading started"); //Get Shows list by page index showsList = await retryPolicy.ExecuteAsync(async() => { return(await LoadShowsPack(pageIndex - 1)); }); showsList = showsList.Where(show => show.Id > maxShowId); //New shows into last pack not found - check the next pack if (!showsList.Any()) { logger.Log(LogLevel.None, $"Pack with index={pageIndex - 1} doesn't contain new shows"); tryFirstPack = false; continue; } } else { tryFirstPack = false; logger.Log(LogLevel.None, $"Pack with index={pageIndex} loading started"); //Get Shows list by page index showsList = await retryPolicy.ExecuteAsync(async() => { return(await LoadShowsPack(pageIndex)); }); //Show page request return NotFound, Nothing to synchronize if (showsList == null) { logger.Log(LogLevel.None, $"Pack with index={pageIndex} Not Found"); logger.Log(LogLevel.None, "Loading process totaly finished"); return; } } using (var personsList = new BlockingCollection <TVMazePerson>()) using (var castsList = new BlockingCollection <TVMazeCast>()) { foreach (var show in showsList) { IEnumerable <TVMazePerson> showCastsList; //Get casts for each show showCastsList = await retryPolicy.ExecuteAsync(async() => { return(await LoadShowCasts(show)); }); showCastsList.ToList().ForEach(cast => { personsList.Add(cast); castsList.Add(new TVMazeCast() { ShowId = show.Id, PersonId = cast.Id }); }); } ; //Insert downloaded data into database using (var transaction = dbContext.Database.BeginTransaction()) { try { dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + typeof(TVMazePerson).Name + " ON;"); var insertedPersonsCount = dbContext.TVMazePerson.AddNoDublicate(personsList.Distinct().ToList()); dbContext.SaveChanges(); dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + typeof(TVMazePerson).Name + " OFF;"); dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + typeof(TVMazeShow).Name + " ON;"); var insetredShowsCount = showsList.Count(); dbContext.TVMazeShow.AddRange(showsList); dbContext.SaveChanges(); dbContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT " + typeof(TVMazeShow).Name + " OFF;"); var castsForInsert = castsList.Distinct(); var insertedCastsCount = castsForInsert.Count(); dbContext.TVMazeCast.AddRange(castsForInsert); dbContext.SaveChanges(); transaction.Commit(); logger.Log(LogLevel.None, $"{insetredShowsCount} shows inserted, {insertedCastsCount} casts inserted, {insertedPersonsCount} persons inserted"); logger.Log(LogLevel.None, $"Pack with index={(tryFirstPack ? pageIndex - 1 : pageIndex)} loading finished"); } catch (Exception ex) { logger.LogError(ex, "An error occurred inserting the DB."); } } if (!tryFirstPack) { pageIndex++; } tryFirstPack = false; } } }
public TVMazeShowsController(TVMazeDBContext context) { _context = context; }