Some Operation context refactor

This commit is contained in:
Mikhail Shabanov committed 2020-11-17 12:36:02 +01:00
1 parent ed52a65788
commit ec8f434f42
16 files changed
+163 -119

No files matched your search

@@ -4,23 +4,8 @@ using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public class AccountInformationPipelineContext: IDatabasePipelineContext
public class AccountInformationPipelineContextData : IDatabasePipelineContextData
{
public AccountInformationPipelineContext(
long accountId,
RealmType realmType,
RequestLanguage requestLanguage)
{
AccountId = accountId;
RealmType = realmType;
RequestLanguage = requestLanguage;
}
public long AccountId { get; }
public RealmType RealmType { get; }
public RequestLanguage RequestLanguage { get; }
public AccountInfo AccountInfo { get; set; }
public AccountInfoHistory AccountInfoHistory { get; set; }
@@ -1,28 +0,0 @@
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public class HistoryInformationPipelineContext: IDatabasePipelineContext
{
public HistoryInformationPipelineContext(
long accountId,
RealmType realmType,
RequestLanguage requestLanguage)
{
AccountId = accountId;
RealmType = realmType;
RequestLanguage = requestLanguage;
}
public long AccountId { get; }
public RealmType RealmType { get; }
public RequestLanguage RequestLanguage { get; }
public AccountInfo DbAccountInfo { get; set; }
public AccountInfoHistoryResponse Response { get; set; }
}
}
@@ -0,0 +1,13 @@
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public class HistoryInformationPipelineContextData: IDatabasePipelineContextData
{
public AccountInfo DbAccountInfo { get; set; }
public AccountInfoHistoryResponse Response { get; set; }
}
}
@@ -1,11 +0,0 @@
using WotBlitzStatisticsPro.Common.Model;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public interface IAccountPipelineContext
{
long AccountId { get; }
RealmType RealmType { get; }
RequestLanguage RequestLanguage { get; }
}
}
@@ -1,8 +1,9 @@
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public interface IDatabasePipelineContext: IAccountPipelineContext
public interface IDatabasePipelineContextData
{
AccountInfo DbAccountInfo { get; set; }
}
@@ -0,0 +1,18 @@
using WotBlitzStatisticsPro.Common.Model;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext
{
public class AccountRequest
{
public AccountRequest(long accountId, RealmType realmType, RequestLanguage requestLanguage)
{
AccountId = accountId;
RealmType = realmType;
RequestLanguage = requestLanguage;
}
public long AccountId { get; }
public RealmType RealmType { get; }
public RequestLanguage RequestLanguage { get; }
}
}
@@ -0,0 +1,11 @@
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext
{
public interface IOperationContext
{
AccountRequest Request { get; }
void AddOrReplace<TContextData>(TContextData data);
TContextData Get<TContextData>();
}
}
@@ -0,0 +1,27 @@
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext
{
public class OperationContext : IOperationContext
{
private object _contextData;
public OperationContext(AccountRequest request)
{
Request = request;
}
public AccountRequest Request { get; }
public void AddOrReplace<TContextData>(TContextData data)
{
_contextData = data;
}
public TContextData Get<TContextData>()
{
_contextData ??= default(TContextData);
return (TContextData)_contextData;
}
}
}
@@ -8,11 +8,12 @@ using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.DataAccess.Model;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class BuildAccountInfoResponseOperation : IOperation<AccountInformationPipelineContext>
public class BuildAccountInfoResponseOperation : IOperation<IOperationContext>
{
private readonly IMapper _mapper;
private readonly IDictionariesDataAccessor _dictionariesDataAccessor;
@@ -23,26 +24,28 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_dictionariesDataAccessor = dictionariesDataAccessor;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
context.Response = _mapper.Map<AccountInfo, AccountInfoResponse>(context.AccountInfo);
context.Response = _mapper.Map(context.AccountInfoHistory, context.Response);
var contextData = context.Get<AccountInformationPipelineContextData>();
var tankIds = context.Tanks.Select(t => t.TankId).ToArray();
contextData.Response = _mapper.Map<AccountInfo, AccountInfoResponse>(contextData.AccountInfo);
contextData.Response = _mapper.Map(contextData.AccountInfoHistory, contextData.Response);
var tankIds = contextData.Tanks.Select(t => t.TankId).ToArray();
var vehicles = await _dictionariesDataAccessor.GetVehicles(tankIds);
var nations = await _dictionariesDataAccessor.GetNations(context.RequestLanguage);
var tankTypes = await _dictionariesDataAccessor.GetTankTypes(context.RequestLanguage);
var nations = await _dictionariesDataAccessor.GetNations(context.Request.RequestLanguage);
var tankTypes = await _dictionariesDataAccessor.GetTankTypes(context.Request.RequestLanguage);
context.Response.Tanks = _mapper.Map<List<TankInfo>, List<TankInfoResponse>>(context.Tanks);
context.Response.Tanks.ForEach(t =>
contextData.Response.Tanks = _mapper.Map<List<TankInfo>, List<TankInfoResponse>>(contextData.Tanks);
contextData.Response.Tanks.ForEach(t =>
{
t = _mapper.Map(context.TanksHistory[t.TankId], t);
t = _mapper.Map(contextData.TanksHistory[t.TankId], t);
var vehicle = vehicles.ContainsKey(t.TankId) ? vehicles[t.TankId] : CreateStubVehicle();
t = _mapper.Map(vehicle, t,
opt =>
{
opt.Items["language"] = context.RequestLanguage;
opt.Items["language"] = context.Request.RequestLanguage;
opt.AfterMap((src, dest) =>
{
dest.TankType = tankTypes.ContainsKey(dest.TankTypeId) ? tankTypes[dest.TankTypeId] : "-";
@@ -2,12 +2,13 @@
using System.Linq;
using System.Threading.Tasks;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Calculations;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class CalculateStatisticsOperation : IOperation<AccountInformationPipelineContext>
public class CalculateStatisticsOperation : IOperation<IOperationContext>
{
private readonly IDictionariesDataAccessor _dictionariesDataAccessor;
@@ -16,12 +17,14 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_dictionariesDataAccessor = dictionariesDataAccessor;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
var tankIds = context.Tanks.Select(t => t.TankId).ToArray();
var contextData = context.Get<AccountInformationPipelineContextData>();
var tankIds = contextData.Tanks.Select(t => t.TankId).ToArray();
var tankTires = await _dictionariesDataAccessor.GetTankTires(tankIds);
foreach (var tankInfoHistory in context.TanksHistory)
foreach (var tankInfoHistory in contextData.TanksHistory)
{
if (!tankTires.ContainsKey(tankInfoHistory.Key))
{
@@ -30,8 +33,8 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
tankInfoHistory.Value.CalculateWn7(tankTires[tankInfoHistory.Key]);
}
context.AccountInfoHistory.CalculateMiddleTier(context.TanksHistory.Values.ToList(), tankTires);
context.AccountInfoHistory.CalculateWn7();
contextData.AccountInfoHistory.CalculateMiddleTier(contextData.TanksHistory.Values.ToList(), tankTires);
contextData.AccountInfoHistory.CalculateWn7();
await next.Invoke(context);
}
@@ -1,11 +1,12 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class CheckLastBattleDateOperation : IOperation<AccountInformationPipelineContext>
public class CheckLastBattleDateOperation : IOperation<IOperationContext>
{
private readonly ILogger<CheckLastBattleDateOperation> _logger;
@@ -14,14 +15,16 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_logger = logger;
}
public Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
if (context.DbAccountInfo == null ||
context.DbAccountInfo.LastBattleTime < context.AccountInfo.LastBattleTime)
var contextData = context.Get<AccountInformationPipelineContextData>();
if (contextData.DbAccountInfo == null ||
contextData.DbAccountInfo.LastBattleTime < contextData.AccountInfo.LastBattleTime)
{
return next.Invoke(context);
}
_logger.LogInformation($"Exiting without saving. Db LastBattleTime: {context.DbAccountInfo.LastBattleTime}, WG LastBattleTime: {context.AccountInfo.LastBattleTime}");
_logger.LogInformation($"Exiting without saving. Db LastBattleTime: {contextData.DbAccountInfo.LastBattleTime}, WG LastBattleTime: {contextData.AccountInfo.LastBattleTime}");
return Task.CompletedTask;
}
}
@@ -2,13 +2,14 @@
using System.Threading.Tasks;
using AutoMapper;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
using WotBlitzStatisticsPro.WgApiClient;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class GetAccountInfoOperation: IOperation<AccountInformationPipelineContext>
public class GetAccountInfoOperation: IOperation<IOperationContext>
{
private readonly IWargamingApiClient _wargamingApi;
private readonly IMapper _mapper;
@@ -21,17 +22,18 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_mapper = mapper;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
var accountInfo = await
_wargamingApi.GetPlayerAccountInfo(context.AccountId, context.RealmType, context.RequestLanguage);
_wargamingApi.GetPlayerAccountInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
// Store info to AccountInfo and in AccountInfoHistory
context.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
context.AccountInfo.Realm = context.RealmType;
var contextData = context.Get<AccountInformationPipelineContextData>();
contextData.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
contextData.AccountInfo.Realm = context.Request.RealmType;
context.AccountInfoHistory = new AccountInfoHistory(context.AccountId, context.AccountInfo.LastBattleTime);
_mapper.Map(accountInfo.Statistics.All, context.AccountInfoHistory);
contextData.AccountInfoHistory = new AccountInfoHistory(context.Request.AccountId, contextData.AccountInfo.LastBattleTime);
_mapper.Map(accountInfo.Statistics.All, contextData.AccountInfoHistory);
await next.Invoke(context);
}
@@ -3,13 +3,14 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
using WotBlitzStatisticsPro.WgApiClient;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class GetTanksInfoOperation: IOperation<AccountInformationPipelineContext>
public class GetTanksInfoOperation: IOperation<IOperationContext>
{
private readonly IWargamingTanksApiClient _wargamingApi;
private readonly IMapper _mapper;
@@ -22,22 +23,24 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_mapper = mapper;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
var tanksInfo = await
_wargamingApi.GetPlayerAccountTanksInfo(context.AccountId, context.RealmType, context.RequestLanguage);
var contextData = context.Get<AccountInformationPipelineContextData>();
context.Tanks = new List<TankInfo>();
context.TanksHistory = new Dictionary<long, TankInfoHistory>();
var tanksInfo = await
_wargamingApi.GetPlayerAccountTanksInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
contextData.Tanks = new List<TankInfo>();
contextData.TanksHistory = new Dictionary<long, TankInfoHistory>();
tanksInfo.ForEach(tank =>
{
var tankInfo = new TankInfo(tank.AccountId, tank.TankId);
_mapper.Map(tank, tankInfo);
context.Tanks.Add(tankInfo);
contextData.Tanks.Add(tankInfo);
var stat = new TankInfoHistory(tank.AccountId, tank.TankId, tank.LastBattleTime);
_mapper.Map(tank.All, stat);
context.TanksHistory[stat.TankId] = stat;
contextData.TanksHistory[stat.TankId] = stat;
});
await next.Invoke(context);
@@ -1,11 +1,12 @@
using System;
using System.Threading.Tasks;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class ReadAccountInfoFromDbOperation : IOperation<AccountInformationPipelineContext>
public class ReadAccountInfoFromDbOperation : IOperation<IOperationContext>
{
private readonly IWargamingAccountDataAccessor _accountDataAccessor;
@@ -14,9 +15,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_accountDataAccessor = accountDataAccessor;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
context.DbAccountInfo = await _accountDataAccessor.ReadAccountInfo(context.AccountId);
var contextData = context.Get<IDatabasePipelineContextData>();
contextData.DbAccountInfo = await _accountDataAccessor.ReadAccountInfo(context.Request.AccountId);
await next.Invoke(context);
}
}
@@ -4,11 +4,12 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class SaveAccountAndTanksOperation : IOperation<AccountInformationPipelineContext>
public class SaveAccountAndTanksOperation : IOperation<IOperationContext>
{
private readonly IWargamingAccountDataAccessor _accountDataAccessor;
private readonly ILogger<SaveAccountAndTanksOperation> _logger;
@@ -21,27 +22,29 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_logger = logger;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
{
await _accountDataAccessor.AddOurUpdateAccountInfo(context.AccountInfo);
await _accountDataAccessor.AddAccountInfoHistory(context.AccountInfoHistory);
var contextData = context.Get<AccountInformationPipelineContextData>();
await _accountDataAccessor.AddOurUpdateAccountInfo(contextData.AccountInfo);
await _accountDataAccessor.AddAccountInfoHistory(contextData.AccountInfoHistory);
var tanksCount = 0;
var tankIdsAsString = new StringBuilder();
foreach (var tankInfo in context.Tanks)
foreach (var tankInfo in contextData.Tanks)
{
var tankFromDb = await _accountDataAccessor.ReadTankInfo(tankInfo.AccountId, tankInfo.TankId);
if (tankFromDb == null || tankInfo.LastBattleTime > tankFromDb.LastBattleTime)
{
await _accountDataAccessor.AddOrUpdateTankInfo(tankInfo);
await _accountDataAccessor.AddTankInfoHistory(context.TanksHistory[tankInfo.TankId]);
await _accountDataAccessor.AddTankInfoHistory(contextData.TanksHistory[tankInfo.TankId]);
tanksCount++;
tankIdsAsString.Append($" {tankInfo.TankId}; ");
}
}
_logger.LogInformation($"Updated account {context.AccountInfo.AccountId} and {tanksCount} tanks: {tankIdsAsString}");
_logger.LogInformation($"Updated account {contextData.AccountInfo.AccountId} and {tanksCount} tanks: {tankIdsAsString}");
await next.Invoke(context);
}
@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
using WotBlitzStatisticsPro.Logic.Pipeline;
@@ -18,8 +19,10 @@ namespace WotBlitzStatisticsPro.Logic
public async Task<AccountInfoResponse> GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage)
{
var context = new AccountInformationPipelineContext(accountId, realm, requestLanguage);
var pipeline = new Pipeline<AccountInformationPipelineContext>(_operationFactory);
var contextData = new AccountInformationPipelineContextData();
var context = new OperationContext(new AccountRequest(accountId, realm, requestLanguage));
context.AddOrReplace(contextData);
var pipeline = new Pipeline<IOperationContext>(_operationFactory);
pipeline.AddOperation<GetAccountInfoOperation>()
.AddOperation<GetTanksInfoOperation>()
@@ -31,13 +34,15 @@ namespace WotBlitzStatisticsPro.Logic
.Invoke(context, null)
.ConfigureAwait(false);
return context.Response;
return contextData.Response;
}
public async Task<AccountInfoResponse> GatherAndSaveAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage)
{
var context = new AccountInformationPipelineContext(accountId, realm, requestLanguage);
var pipeline = new Pipeline<AccountInformationPipelineContext>(_operationFactory);
var contextData = new AccountInformationPipelineContextData();
var context = new OperationContext(new AccountRequest(accountId, realm, requestLanguage));
context.AddOrReplace(contextData);
var pipeline = new Pipeline<IOperationContext>(_operationFactory);
pipeline.AddOperation<GetAccountInfoOperation>()
.AddOperation<ReadAccountInfoFromDbOperation>()
@@ -52,29 +57,32 @@ namespace WotBlitzStatisticsPro.Logic
.Invoke(context, null)
.ConfigureAwait(false);
return context.Response;
return contextData.Response;
}
public async Task<AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate, RequestLanguage requestLanguage)
{
var context = new HistoryInformationPipelineContext(accountId, realm, requestLanguage);
var pipeline = new Pipeline<HistoryInformationPipelineContext>(_operationFactory);
//pipeline.AddOperation<ReadAccountInfoFromDbOperation>()
var contextData = new HistoryInformationPipelineContextData();
var context = new OperationContext(new AccountRequest(accountId, realm, requestLanguage));
context.AddOrReplace(contextData);
var pipeline = new Pipeline<IOperationContext>(_operationFactory);
// ToDo:
// 1. First read account info from DB operation
// 2. Read account history from DB at the startDate !Array SortedByDate! operation
// 3. Fill the OverallAccountStatistics
// PeriodAccountStatistics
// PeriodDifference
// StatisticsHistory
pipeline.AddOperation<ReadAccountInfoFromDbOperation>()
// 2. Read account history from DB at the startDate !Array SortedByDate! operation
// 3. Fill the OverallAccountStatistics
// PeriodAccountStatistics
// PeriodDifference
// StatisticsHistory
;
await pipeline.Build()
.Invoke(context, null)
.ConfigureAwait(false);
return context.Response;
return contextData.Response;
}
}
}