protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation($"Is starting."); // web server start first Thread.Yield(); var taskCancelSources = new Dictionary <Task, CancellationTokenSource> { }; stoppingToken.Register(() => { _logger.LogInformation($"Background task is stopping."); _logger.LogInformation("Stopping children background tasks."); foreach (var canlSource in taskCancelSources.Values) { canlSource.Cancel(); } }); try { async Task fetchAndUpsertLeaguesLoop(CancellationToken stoppingToken, PoeLeagueModel waitLeague = null) { stoppingToken.Register(() => { _logger.LogInformation("Stopping fetchAndUpsertLeaguesLoop task"); }); while (!stoppingToken.IsCancellationRequested) { int defaultDelayTime = 60000 * 60 * 2; // 2hr if (waitLeague == null) { await Task.Delay(defaultDelayTime, stoppingToken); } else { if (waitLeague.EndAt == null) { await Task.Delay(defaultDelayTime, stoppingToken); } else { var now = System.DateTime.UtcNow; if (waitLeague.EndAt.Value > now) { System.TimeSpan delayTimeSpan = waitLeague.EndAt.Value.Subtract(System.DateTime.UtcNow); await Task.Delay(delayTimeSpan, stoppingToken); } else { await Task.Delay(defaultDelayTime, stoppingToken); } } } await FetchAndUpsertLeagues(); } } await FetchAndUpsertLeagues(); async Task fetchAndUpsertCharactersLoop(CancellationToken stoppingToken, string targetLeagueName) { int defaultDelayTime = 60000 * 10; // 10 min stoppingToken.Register(() => { _logger.LogInformation($"Stopping {targetLeagueName} fetchAndUpsertCharactersLoop task"); }); while (!stoppingToken.IsCancellationRequested) { await FetchAndUpsertCharacters(stoppingToken, targetLeagueName); await Task.Delay(defaultDelayTime, stoppingToken); } } var tasks = new List <Task> { }; PoeLeagueModel defaultLeague = await leagueService.GetDefaultLeague(); if (defaultLeague != null) { var leagueCancelSource = new CancellationTokenSource(); Task leaguesLoop = fetchAndUpsertLeaguesLoop(leagueCancelSource.Token, defaultLeague); tasks.Add(leaguesLoop); taskCancelSources.Add(leaguesLoop, leagueCancelSource); var characterCancelSource = new CancellationTokenSource(); Task charactersLoop = fetchAndUpsertCharactersLoop(characterCancelSource.Token, defaultLeague.LeagueId); tasks.Add(charactersLoop); taskCancelSources.Add(charactersLoop, characterCancelSource); } else { _logger.LogError("Not found default league!!!"); } // you can add other leagues await Task.WhenAll(tasks.ToArray()); } catch (System.Exception e) { _logger.LogError(e.ToString()); } finally { foreach (var canlSource in taskCancelSources.Values) { canlSource.Dispose(); } } }
public async Task <ActionResult <CharacterAnalysis> > GetCharacters( [FromRoute(Name = "leagueName")] string _leagueName, [FromQuery] GetCharactersConfig config ) { config.Normalized(); string leagueName; if (_leagueName == DEFAULT_LEAGUE_NAME) { PoeLeagueModel defaultLeague = await leagueService .GetDefaultLeagueQuery() .Select(x => new PoeLeagueModel { LeagueId = x.LeagueId }) .SingleOrDefaultAsync(); if (defaultLeague != null) { leagueName = defaultLeague.LeagueId; } else { leagueName = _leagueName; } } else { leagueName = _leagueName; } var cacheKey = $"{CHARACTERS_CACHE_PREFIX}:{leagueName}:{config.GetCacheKey()}"; var encodedResult = await distributedCache.GetAsync(cacheKey); if (encodedResult != null) { var jsonStr = System.Text.Encoding.UTF8.GetString(encodedResult); var result = JsonSerializer.Deserialize <CharacterAnalysis>(jsonStr); Response.Headers.Add("Cache-Control", "public, max-age=60"); return(result); } else { var result = await leagueService.GetCharactersByAnalysis(leagueName, config); if (result.Total == 0) { return(NotFound()); } else { int expirMulti = (int)(result.Total / 1000); expirMulti = expirMulti < 1 ? 1 : expirMulti; expirMulti = expirMulti >= 2 ? 2 : expirMulti; var jsonBytes = JsonSerializer.SerializeToUtf8Bytes(result); var options = new DistributedCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromMinutes(3 * expirMulti)) .SetAbsoluteExpiration(DateTime.Now.AddHours(1 * expirMulti)); await distributedCache.SetAsync(cacheKey, jsonBytes, options); Response.Headers.Add("Cache-Control", "public, max-age=180"); return(result); } } }