internal async Task <CachedClanWar?> TryAddCachedClanWar(string tag, DateTime serverExpiration, DateTime localExpiration, CancellationToken?cancellationToken = default) { try { using var scope = Services.CreateScope(); CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>(); CachedClanWar?clanWar = await dbContext.ClanWars.FirstOrDefaultAsync(cw => cw.Tag == tag, cancellationToken.GetValueOrDefault()).ConfigureAwait(false); if (clanWar != null) { return(clanWar); } clanWar = new CachedClanWar(tag) { LocalExpiration = localExpiration, ServerExpiration = serverExpiration }; dbContext.ClanWars.Add(clanWar); await dbContext.SaveChangesAsync(cancellationToken.GetValueOrDefault()).ConfigureAwait(false); return(clanWar); } catch (Exception) { return(null); //this is a race condition that is hard to handle } }
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); }
private async Task MonitorClanWarAsync(CachedClanWar cachedClanWar) { if (_stopRequestedTokenSource.IsCancellationRequested || _clansClient.UpdatingClanWar.TryAdd(cachedClanWar.Tag, new byte()) == false) { return; } try { CachedClanWar?fetched = await CachedClanWar.FromCurrentWarResponseAsync(cachedClanWar.Tag, _clansClient, _clansApi, _stopRequestedTokenSource.Token).ConfigureAwait(false); if (fetched.Data != null && CachedClanWar.IsNewWar(cachedClanWar, fetched)) { await _clansClient.InsertNewWarAsync(new CachedWar(fetched)).ConfigureAwait(false); cachedClanWar.Type = fetched.Data.GetWarType(); _ = Task.Run(() => _clansClient.TryAddCachedClanWar(fetched.Data.Clans.First(c => c.Key != cachedClanWar.Tag).Key, fetched.ServerExpiration, fetched.LocalExpiration)); } cachedClanWar.UpdateFrom(fetched); } finally { _clansClient.UpdatingClanWar.TryRemove(cachedClanWar.Tag, out _); } }
internal bool HasUpdated(CachedWar stored, CachedClanWar fetched) { if (stored.ServerExpiration > fetched.ServerExpiration) { return(false); } if (stored.Data == null || fetched.Data == null || ClanWar.IsSameWar(stored.Data, fetched.Data) == false) { throw new ArgumentException(); } return(HasUpdated(stored.Data, fetched.Data)); }