mirror of
https://github.com/DrMboga/WotBlitzStatisticsBlazor.git
synced 2026-10-21 02:17:20 +02:00
feat: introduced caching in the server + Added serilog
This commit is contained in:
1 parent
8c9770f8a0
commit
638489a842
25 files changed
+365
-33
No files matched your search
+21
-3
@@ -4,6 +4,7 @@ using AutoMapper;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||
using WotBlitzStatisticsPro.Logic.Model;
|
||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||
using WotBlitzStatisticsPro.WgApiClient;
|
||||
using WotBlitzStatisticsPro.WgApiClient.Model;
|
||||
@@ -15,19 +16,36 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
||||
private readonly IWargamingApiClient _wargamingApi;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly ILogger<GetAccountInfoOperation> _logger;
|
||||
private readonly StatisticsCache _cache;
|
||||
|
||||
public GetAccountInfoOperation(
|
||||
IWargamingApiClient wargamingApi,
|
||||
IMapper mapper,
|
||||
ILogger<GetAccountInfoOperation> logger)
|
||||
ILogger<GetAccountInfoOperation> logger,
|
||||
StatisticsCache cache)
|
||||
{
|
||||
_wargamingApi = wargamingApi;
|
||||
_mapper = mapper;
|
||||
_logger = logger;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
|
||||
{
|
||||
// Store info to AccountInfo and in AccountInfoHistory
|
||||
var contextData = context.Get<AccountInformationPipelineContextData>();
|
||||
|
||||
var cache = _cache.GetAccountData(context.Request.AccountId);
|
||||
if (cache != null)
|
||||
{
|
||||
contextData.AccountInfo = cache.AccountInfo;
|
||||
contextData.AccountInfoHistory = cache.AccountInfoHistory;
|
||||
_logger.LogInformation($"Account data for account {context.Request.AccountId} got from cache");
|
||||
|
||||
if (next != null) await next.Invoke(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var accountInfo = await
|
||||
_wargamingApi.GetPlayerAccountInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage, context.Request.AuthenticationToken);
|
||||
|
||||
@@ -38,14 +56,14 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
||||
return;
|
||||
}
|
||||
|
||||
// Store info to AccountInfo and in AccountInfoHistory
|
||||
var contextData = context.Get<AccountInformationPipelineContextData>();
|
||||
contextData.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
|
||||
contextData.AccountInfo.Realm = context.Request.RealmType;
|
||||
|
||||
contextData.AccountInfoHistory = new AccountInfoHistory(context.Request.AccountId, contextData.AccountInfo.LastBattleTime);
|
||||
_mapper.Map(accountInfo.Statistics?.All, contextData.AccountInfoHistory);
|
||||
|
||||
_cache.SetAccountData(context.Request.AccountId, new AccountDataCache(contextData.AccountInfo, contextData.AccountInfoHistory));
|
||||
|
||||
if (next != null) await next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -6,6 +6,7 @@ using AutoMapper;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||
using WotBlitzStatisticsPro.Logic.Model;
|
||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||
using WotBlitzStatisticsPro.WgApiClient;
|
||||
|
||||
@@ -16,21 +17,36 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
||||
private readonly IWargamingTanksApiClient _wargamingApi;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly ILogger<GetTanksInfoOperation> _logger;
|
||||
private readonly StatisticsCache _cache;
|
||||
|
||||
public GetTanksInfoOperation(
|
||||
IWargamingTanksApiClient wargamingApi,
|
||||
IMapper mapper,
|
||||
ILogger<GetTanksInfoOperation> logger)
|
||||
ILogger<GetTanksInfoOperation> logger,
|
||||
StatisticsCache cache)
|
||||
{
|
||||
_wargamingApi = wargamingApi;
|
||||
_mapper = mapper;
|
||||
_logger = logger;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
|
||||
{
|
||||
var contextData = context.Get<AccountInformationPipelineContextData>();
|
||||
|
||||
var cache = _cache.GetTanksData(context.Request.AccountId);
|
||||
if (cache != null)
|
||||
{
|
||||
contextData.Tanks = cache.TankInfo;
|
||||
contextData.TanksHistory = cache.TankInfoHistory;
|
||||
_logger.LogInformation($"Account tanks data for account {context.Request.AccountId} got from cache");
|
||||
|
||||
if (next != null) await next.Invoke(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var tanksInfo = await
|
||||
_wargamingApi.GetPlayerAccountTanksInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
|
||||
|
||||
@@ -54,6 +70,8 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
||||
contextData.TanksHistory[stat.TankId] = stat;
|
||||
});
|
||||
|
||||
_cache.SetTanksData(context.Request.AccountId, new TanksDataCache(contextData.Tanks, contextData.TanksHistory));
|
||||
|
||||
if (next != null) await next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace WotBlitzStatisticsPro.Logic
|
||||
{
|
||||
Task<AccountInfoResponse> GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage);
|
||||
|
||||
Task<AccountInfoResponse> GatherAndSaveAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage, string wargamingToken);
|
||||
Task<DateTime> GatherAndSaveAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage, string wargamingToken);
|
||||
|
||||
Task<AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate,
|
||||
RequestLanguage requestLanguage);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Logic.Model
|
||||
{
|
||||
public class AccountDataCache
|
||||
{
|
||||
public AccountDataCache(AccountInfo accountInfo, AccountInfoHistory accountInfoHistory)
|
||||
{
|
||||
AccountInfo = accountInfo;
|
||||
AccountInfoHistory = accountInfoHistory;
|
||||
}
|
||||
|
||||
public AccountInfo AccountInfo { get; }
|
||||
|
||||
public AccountInfoHistory AccountInfoHistory { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Logic.Model
|
||||
{
|
||||
public class CacheItem<T>
|
||||
{
|
||||
private const int ExpirationTimeoutInMinutes = 60;
|
||||
private DateTime? _lastRefreshed = null;
|
||||
|
||||
private T? _itemData = default(T);
|
||||
|
||||
public long AccountId { get; set; }
|
||||
|
||||
public bool IsExpired => _lastRefreshed != null &&
|
||||
(DateTime.Now - _lastRefreshed.Value).TotalMinutes > ExpirationTimeoutInMinutes;
|
||||
|
||||
public T? Data
|
||||
{
|
||||
get => _itemData;
|
||||
set
|
||||
{
|
||||
_itemData = value;
|
||||
_lastRefreshed = DateTime.Now;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Logic.Model
|
||||
{
|
||||
public class StatisticsCache
|
||||
{
|
||||
private readonly Dictionary<long, CacheItem<AccountDataCache>> _accountsCache = new();
|
||||
private readonly Dictionary<long, CacheItem<TanksDataCache>> _tanksCache = new();
|
||||
|
||||
public AccountDataCache? GetAccountData(long accountId)
|
||||
{
|
||||
if (!_accountsCache.ContainsKey(accountId) || _accountsCache[accountId].IsExpired)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _accountsCache[accountId].Data;
|
||||
}
|
||||
|
||||
public TanksDataCache? GetTanksData(long accountId)
|
||||
{
|
||||
if (!_tanksCache.ContainsKey(accountId) || _tanksCache[accountId].IsExpired)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _tanksCache[accountId].Data;
|
||||
}
|
||||
|
||||
public void SetAccountData(long accountId, AccountDataCache data)
|
||||
{
|
||||
if (!_accountsCache.ContainsKey(accountId))
|
||||
{
|
||||
_accountsCache.Add(accountId, new CacheItem<AccountDataCache>());
|
||||
ClearExpiredAccounts();
|
||||
}
|
||||
_accountsCache[accountId].Data = data;
|
||||
}
|
||||
|
||||
public void SetTanksData(long accountId, TanksDataCache data)
|
||||
{
|
||||
if (!_tanksCache.ContainsKey(accountId))
|
||||
{
|
||||
_tanksCache.Add(accountId, new CacheItem<TanksDataCache>());
|
||||
ClearExpiredTanks();
|
||||
}
|
||||
_tanksCache[accountId].Data = data;
|
||||
}
|
||||
|
||||
private void ClearExpiredAccounts()
|
||||
{
|
||||
var expired = new List<long>();
|
||||
foreach (var cacheItem in _accountsCache)
|
||||
{
|
||||
if (cacheItem.Value.IsExpired)
|
||||
{
|
||||
expired.Add(cacheItem.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var expiredKey in expired)
|
||||
{
|
||||
_accountsCache.Remove(expiredKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearExpiredTanks()
|
||||
{
|
||||
var expired = new List<long>();
|
||||
foreach (var cacheItem in _tanksCache)
|
||||
{
|
||||
if (cacheItem.Value.IsExpired)
|
||||
{
|
||||
expired.Add(cacheItem.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var expiredKey in expired)
|
||||
{
|
||||
_accountsCache.Remove(expiredKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Logic.Model
|
||||
{
|
||||
public class TanksDataCache
|
||||
{
|
||||
public TanksDataCache(List<TankInfo> tankInfo, Dictionary<long, TankInfoHistory> tankInfoHistory)
|
||||
{
|
||||
TankInfo = tankInfo;
|
||||
TankInfoHistory = tankInfoHistory;
|
||||
}
|
||||
|
||||
public List<TankInfo> TankInfo { get; }
|
||||
|
||||
public Dictionary<long, TankInfoHistory> TankInfoHistory { get; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using WotBlitzStatisticsPro.Common.Model;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||
using WotBlitzStatisticsPro.Logic.Calculations;
|
||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Logic
|
||||
@@ -58,7 +59,7 @@ namespace WotBlitzStatisticsPro.Logic
|
||||
return contextData?.Response ?? new AccountInfoResponse();
|
||||
}
|
||||
|
||||
public async Task<AccountInfoResponse> GatherAndSaveAccountInformation(
|
||||
public async Task<DateTime> GatherAndSaveAccountInformation(
|
||||
RealmType realm,
|
||||
long accountId,
|
||||
RequestLanguage requestLanguage,
|
||||
@@ -78,7 +79,6 @@ namespace WotBlitzStatisticsPro.Logic
|
||||
.AddOperation<GetTanksInfoOperation>()
|
||||
.AddOperation<CalculateStatisticsOperation>()
|
||||
.AddOperation<SaveAccountAndTanksOperation>()
|
||||
.AddOperation<BuildAccountInfoResponseOperation>()
|
||||
;
|
||||
|
||||
var firstOperation = pipeline.Build();
|
||||
@@ -95,7 +95,7 @@ namespace WotBlitzStatisticsPro.Logic
|
||||
|
||||
throw;
|
||||
}
|
||||
return contextData?.Response ?? new AccountInfoResponse();
|
||||
return contextData?.AccountInfo?.LastBattleTime.ToDateTime() ?? new DateTime(1970,1,1);
|
||||
}
|
||||
|
||||
public async Task<AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate, RequestLanguage requestLanguage)
|
||||
|
||||
@@ -7,6 +7,7 @@ using WotBlitzStatisticsPro.Common.Model;
|
||||
using WotBlitzStatisticsPro.DataAccess;
|
||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||
using WotBlitzStatisticsPro.Logic.Dictionaries;
|
||||
using WotBlitzStatisticsPro.Logic.Model;
|
||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||
using WotBlitzStatisticsPro.WgApiClient;
|
||||
|
||||
@@ -19,6 +20,7 @@ namespace WotBlitzStatisticsPro.Logic
|
||||
|
||||
public static void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<StatisticsCache>();
|
||||
ConfigureDictionariesFactory(services);
|
||||
ConfigureOperationsFactory(services);
|
||||
WotBlitzStatisticsDataAccessInstaller.ConfigureServices(services);
|
||||
|
||||
Reference in new issue
Block a user