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
                });
            }
        }
Beispiel #2
0
        /// <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;
                    }
            }
        }
Beispiel #3
0
 public TVMazeShowsController(TVMazeDBContext context)
 {
     _context = context;
 }