public async Task <CachedWar?> GetActiveClanWarOrDefaultAsync(string tag, CancellationToken?cancellationToken = default) { string formattedTag = Clash.FormatTag(tag); using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); List <CachedWar> cache = await dbContext.Wars .AsNoTracking() .Where(i => (i.ClanTag == formattedTag || i.OpponentTag == formattedTag)) .OrderByDescending(w => w.PreparationStartTime) .ToListAsync(cancellationToken.GetValueOrDefault(_stopRequestedTokenSource.Token)) .ConfigureAwait(false); if (cache.Count == 0) { return(null); } return(cache.FirstOrDefault(c => c.State == WarState.InWar && c.EndTime > DateTime.UtcNow) ?? cache.FirstOrDefault(c => c.State == WarState.Preparation && c.EndTime > DateTime.UtcNow) ?? cache.First()); }
private async Task <CachedClan> PrepareNewCachedClanAsync(string formattedTag, bool downloadWars, bool downloadCwl, bool downloadMembers, CacheContext dbContext) { CachedClan cachedClan = new CachedClan(formattedTag) { DownloadCurrentWar = downloadWars, DownloadCwl = downloadCwl, DownloadMembers = downloadMembers }; dbContext.Clans.Add(cachedClan); CachedClanWar cachedClanWar = await dbContext.ClanWars .Where(w => w.Tag == formattedTag) .FirstOrDefaultAsync(_stopRequestedTokenSource.Token) .ConfigureAwait(false); if (cachedClanWar == null) { cachedClanWar = new CachedClanWar(formattedTag); dbContext.ClanWars.Add(cachedClanWar); } dbContext.Groups.Add(new CachedClanWarLeagueGroup(formattedTag)); dbContext.WarLogs.Add(new CachedClanWarLog(formattedTag)); return(cachedClan); }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); int id = int.MinValue; while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { if (!_clansClient.DownloadMembers) { await Task.Delay(Configuration.DelayBetweenTasks); continue; } using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); List <CachedClan> cachedClans = await dbContext.Clans .OrderBy(c => c.Id) .Where(c => c.Id > id && c.DownloadMembers) .Take(Configuration.ConcurrentClanDownloads) .AsNoTracking() .ToListAsync(_stopRequestedTokenSource.Token) .ConfigureAwait(false); id = cachedClans.Count < Configuration.ConcurrentClanDownloads ? int.MinValue : cachedClans.Max(c => c.Id); foreach (CachedClan cachedClan in cachedClans) { await MonitorMembersAsync(cachedClan); } await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _playersClientBase.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); while (cancellationToken.IsCancellationRequested == false && _stopRequestedTokenSource.IsCancellationRequested == false) { using var scope = Services.CreateScope(); using CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); List <CachedPlayer> cachedPlayers = await dbContext.Players .Where(v => v.Download && v.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && v.LocalExpiration < DateTime.UtcNow) .OrderBy(v => v.ServerExpiration) .Take(Configuration.ConcurrentPlayerDownloads) .ToListAsync(_stopRequestedTokenSource.Token) .ConfigureAwait(false); List <Task> tasks = new(); for (int i = 0; i < cachedPlayers.Count; i++) { tasks.Add(UpdatePlayerAsync(cachedPlayers[i])); } await Task.WhenAll(tasks).ConfigureAwait(false); await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _playersClientBase.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { if (_clansClient.DownloadCurrentWars == false) { await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); continue; } using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); //List<string> clanWarWithLogStatus = await dbContext.ClanWarWithLogStatus // .Where(w => // w.IsWarLogPublic == true && // w.DownloadCurrentWar && // w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && // w.LocalExpiration < DateTime.UtcNow) // .OrderBy(w => w.ServerExpiration) // .Take(100) // .Select(l => l.Tag ) // .ToListAsync() // .ConfigureAwait(false); List <CachedClanWar> cachedClanWars = await( from cw in dbContext.ClanWars join c in dbContext.Clans on cw.Tag equals c.Tag into cw_c_join from c2 in cw_c_join.DefaultIfEmpty() where c2.IsWarLogPublic == true && c2.DownloadCurrentWar == true && cw.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && cw.LocalExpiration < DateTime.UtcNow orderby cw.ServerExpiration select cw) .Take(Configuration.ConcurrentClanWarDownloads) .ToListAsync(); List <Task> tasks = new(); foreach (CachedClanWar cachedClanWar in cachedClanWars) { tasks.Add(MonitorClanWarAsync(cachedClanWar)); } await Task.WhenAll(tasks).ConfigureAwait(false); await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { if (_clansClient.DownloadWarLog == false) { await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); continue; } using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); //var clanWarLogsWithLogStatus = await dbContext.ClanWarLogWithLogStatus // .Where(w => // w.IsWarLogPublic && // w.DownloadCurrentWar && // w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && // w.LocalExpiration < DateTime.UtcNow) // .OrderBy(w => w.ServerExpiration) // .Take(1000) // .Select(l => l.Tag) // .ToListAsync() // .ConfigureAwait(false); List <CachedClanWarLog> cachedLogs = await( from l in dbContext.WarLogs join c in dbContext.Clans on l.Tag equals c.Tag where c.IsWarLogPublic == true && c.DownloadCurrentWar && l.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && l.LocalExpiration < DateTime.UtcNow orderby l.ServerExpiration select l) .Take(Configuration.ConcurrentWarLogDownloads) .ToListAsync() .ConfigureAwait(false); List <Task> tasks = new(); foreach (CachedClanWarLog cachedLog in cachedLogs) { tasks.Add(MonitorLogAsync(cachedLog)); } await Task.WhenAll(tasks).ConfigureAwait(false); await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); //for (int i = 0; i < clanWarLogsWithLogStatus.Count; i++) // await MonitorLogAsync(clanWarLogsWithLogStatus[i]); await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); List <CachedClan> cachedClans = await dbContext.Clans .Where(w => w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && w.LocalExpiration < DateTime.UtcNow) .OrderBy(w => w.ServerExpiration) .Take(Configuration.ConcurrentClanDownloads) .ToListAsync(_stopRequestedTokenSource.Token) .ConfigureAwait(false); List <Task> tasks = new(); foreach (CachedClan cachedClan in cachedClans) { tasks.Add(MonitorClanAsync(cachedClan)); } await Task.WhenAll(tasks).ConfigureAwait(false); await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); if (_deletedUnmonitoredPlayers < DateTime.UtcNow.AddMinutes(-10)) { _deletedUnmonitoredPlayers = DateTime.UtcNow; tasks = new List <Task> { DeleteUnmonitoredPlayersNotInAClan(), DeletePlayersInClansNotMonitored() }; await Task.WhenAll(tasks); } await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { if (_clansClient.DownloadCurrentWars == false && _clansClient.DownloadCwl == false) { await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); continue; } using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); var wars = await dbContext.Wars .Where(w => w.IsFinal == false && w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && w.LocalExpiration < DateTime.UtcNow //&& //w.State < WarState.WarEnded && //todo is there an index on state? //w.EndTime.AddDays(8) > DateTime.UtcNow //todo does this require a new column and a new index? //todo w.StartTime < DateTime.UtcNow.AddHours(-1)) //todo preparation start time < now ) .OrderBy(w => w.ServerExpiration) .ToListAsync() .ConfigureAwait(false); for (int i = 0; i < wars.Count; i++) { await MonitorWarAsync(wars[i]).ConfigureAwait(false); } await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
private async Task MonitorWarAsync(CachedWar cached) { if (_stopRequestedTokenSource.IsCancellationRequested || _clansClient.UpdatingWar.TryAdd(cached, new byte()) == false) { return; } try { using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); List <CachedClanWar>?cachedClanWars = null; if (cached.WarTag == null) { cachedClanWars = await dbContext.ClanWars .AsNoTracking() .Where(c => cached.ClanTags.Contains(c.Tag)) .OrderByDescending(c => c.ServerExpiration) .ToListAsync(_stopRequestedTokenSource.Token) .ConfigureAwait(false); if (cachedClanWars.Count == 2 && cachedClanWars.All(c => c.PreparationStartTime > cached.PreparationStartTime) || cached.EndTime.AddDays(8) < DateTime.UtcNow) { cached.IsFinal = true; return; } CachedClanWar?cachedClanWar = cachedClanWars .OrderByDescending(c => c.ServerExpiration) .FirstOrDefault(c => c.PreparationStartTime == cached.PreparationStartTime); if (cached.Data != null && cachedClanWar?.Data != null && _clansClient.HasUpdated(cached, cachedClanWar)) { _clansClient.OnClanWarUpdated(cached.Data, cachedClanWar.Data); } if (cachedClanWar != null) { cached.UpdateFrom(cachedClanWar); } } else { CachedWar?fetched = await CachedWar .FromClanWarLeagueWarResponseAsync( cached.WarTag, cached.Season.Value, _clansClient, _clansApi, _stopRequestedTokenSource.Token) .ConfigureAwait(false); if (cached.Data != null && fetched.Data != null && cached.Season == fetched.Season && _clansClient.HasUpdated(cached, fetched)) { _clansClient.OnClanWarUpdated(cached.Data, fetched.Data); } cached.UpdateFrom(fetched); } cached.IsFinal = cached.State == WarState.WarEnded; SendWarAnnouncements(cached, cachedClanWars); } finally { _clansClient.UpdatingWar.TryRemove(cached, out _); } }
public async Task RunAsync(CancellationToken cancellationToken) { try { if (_isRunning) { return; } _isRunning = true; _stopRequestedTokenSource = new CancellationTokenSource(); _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information)); int id = int.MinValue; while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false) { if (_clansClient.DownloadCwl == false) { await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); continue; } using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); //var cachedWarLogs = await dbContext.ClanWarLeagueGroupWithStatus // .Where(w => // w.DownloadCwl == true && // w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && // w.LocalExpiration < DateTime.UtcNow) // .OrderBy(w => w.ServerExpiration) // .Take(10) // .ToListAsync() // .ConfigureAwait(false); List <CachedClanWarLeagueGroup> cachedGroup = await( from g in dbContext.Groups join c in dbContext.Clans on g.Tag equals c.Tag where c.DownloadCwl && g.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && g.LocalExpiration <DateTime.UtcNow && g.Id> id orderby g.Id select g) .Take(Configuration.ConcurrentCwlDownloads) .ToListAsync() .ConfigureAwait(false); id = cachedGroup.Count == Configuration.ConcurrentClanDownloads ? cachedGroup.Max(g => g.Id) : int.MinValue; List <Task> tasks = new(); foreach (CachedClanWarLeagueGroup group in cachedGroup) { tasks.Add(MonitorCwlAsync(group, dbContext)); } await Task.WhenAll(tasks).ConfigureAwait(false); await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false); await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false); } _isRunning = false; } catch (Exception e) { _isRunning = false; if (_stopRequestedTokenSource.IsCancellationRequested) { return; } _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e)); if (cancellationToken.IsCancellationRequested == false) { _ = RunAsync(cancellationToken); } } }
private async Task MonitorCwlAsync(CachedClanWarLeagueGroup cached, CacheContext dbContext) { if (_stopRequestedTokenSource.IsCancellationRequested || _updatingGroup.TryAdd(cached.Tag, new byte()) == false) { return; } try { CachedClanWarLeagueGroup?fetched = await CachedClanWarLeagueGroup .FromClanWarLeagueGroupResponseAsync(cached.Tag, _clansClient, _clansApi, _stopRequestedTokenSource.Token) .ConfigureAwait(false); if (fetched.Data != null && _clansClient.HasUpdated(cached, fetched)) { _clansClient.OnClanWarLeagueGroupUpdated(cached.Data, fetched.Data); } cached.UpdateFrom(fetched); List <Task> tasks = new List <Task>(); HashSet <string> downloadWarTags = new HashSet <string>(); if (cached.Data == null || cached.Season.Value.Month < DateTime.Now.Month) { return; } try { foreach (var round in cached.Data.Rounds) { foreach (string warTag in round.WarTags.Where(w => w != "#0")) { if (_updatingWarTags.TryAdd(warTag, new byte())) { downloadWarTags.Add(warTag); tasks.Add(ReturnNewWarOrDefaultAsync(cached.Tag, cached.Season.Value, warTag)); } } } await Task.WhenAll(tasks).ConfigureAwait(false); foreach (Task <CachedWar?> cachedWarTask in tasks) { if (cachedWarTask.IsCompletedSuccessfully && cachedWarTask.Result is CachedWar cachedWar && cachedWar.Data != null) { dbContext.Wars.Add(cachedWar); _clansClient.OnClanWarAdded(cachedWar.Data); } } } finally { foreach (string warTag in downloadWarTags) { _updatingWarTags.TryRemove(warTag, out _); } } } catch (Exception e) { _clansClient.OnLog(this, new LogEventArgs(nameof(MonitorCwlAsync), LogLevel.Debug, $"Error updating group:{cached.Tag};\n{e.Message};\n{e.InnerException?.Message}")); } finally { _updatingGroup.TryRemove(cached.Tag, out _); } }