Saving accounts To DB

This commit is contained in:
Mikhail Shabanov committed 2020-11-06 19:23:20 +01:00
1 parent 31b067e087
commit ddbf42e7bb
14 files changed
+372 -54

No files matched your search

@@ -6,5 +6,15 @@ namespace WotBlitzStatisticsPro.DataAccess
public interface IWargamingAccountDataAccessor public interface IWargamingAccountDataAccessor
{ {
Task<AccountInfo> ReadAccountInfo(long accountId); Task<AccountInfo> ReadAccountInfo(long accountId);
Task<TankInfo> ReadTankInfo(long accountId, long tankId);
Task AddOurUpdateAccountInfo(AccountInfo accountInfo);
Task AddAccountInfoHistory(AccountInfoHistory accountInfoHistory);
Task AddOrUpdateTankInfo(TankInfo tankInfo);
Task AddTankInfoHistory(TankInfoHistory tankInfoHistory);
} }
} }
@@ -1,16 +1,28 @@
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts using MongoDB.Bson.Serialization.Attributes;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{ {
public class AccountInfoHistory public class AccountInfoHistory
{ {
public AccountInfoHistory(long accountId, int lastBattleTime)
{
AccountInfoHistoryId = new AccountInfoHistoryKey(accountId, lastBattleTime);
}
[BsonId]
public AccountInfoHistoryKey AccountInfoHistoryId { get; set; }
///<summary> ///<summary>
/// Player account identifier /// Player account identifier
///</summary> ///</summary>
public long AccountId { get; set; } [BsonIgnore]
public long AccountId => AccountInfoHistoryId.AccountId;
///<summary> ///<summary>
/// Last battle time /// Last battle time
///</summary> ///</summary>
public int LastBattleTime { get; set; } [BsonIgnore]
public int LastBattleTime => AccountInfoHistoryId.LastBattleTime;
///<summary> ///<summary>
/// Battles count /// Battles count
@@ -0,0 +1,52 @@
using System;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{
public class AccountInfoHistoryKey : IEquatable<AccountInfoHistoryKey>
{
public AccountInfoHistoryKey()
{
}
public AccountInfoHistoryKey(long accountId, int lastBattleTime)
{
AccountId = accountId;
LastBattleTime = lastBattleTime;
}
public long AccountId { get; set; }
public int LastBattleTime { get; set; }
public bool Equals(AccountInfoHistoryKey other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return AccountId == other.AccountId && LastBattleTime == other.LastBattleTime;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((AccountInfoHistoryKey) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(AccountId, LastBattleTime);
}
public static bool operator ==(AccountInfoHistoryKey left, AccountInfoHistoryKey right)
{
return Equals(left, right);
}
public static bool operator !=(AccountInfoHistoryKey left, AccountInfoHistoryKey right)
{
return !Equals(left, right);
}
}
}
@@ -1,18 +1,34 @@
using WotBlitzStatisticsPro.Common.Model; using MongoDB.Bson.Serialization.Attributes;
using WotBlitzStatisticsPro.Common.Model;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{ {
public class TankInfo public class TankInfo
{ {
public TankInfo()
{
}
public TankInfo(long accountId, long tankId)
{
TankInfoId = new TankInfoKey(accountId, tankId);
}
[BsonId]
public TankInfoKey TankInfoId { get; set; }
///<summary> ///<summary>
/// Player account identifier /// Player account identifier
///</summary> ///</summary>
public long AccountId { get; set; } [BsonIgnore]
public long AccountId => TankInfoId.AccountId;
///<summary> ///<summary>
/// Tank identifier /// Tank identifier
///</summary> ///</summary>
public long TankId { get; set; } [BsonIgnore]
public long TankId => TankInfoId.TankId;
public int BattleLifeTimeInSeconds { get; set; } public int BattleLifeTimeInSeconds { get; set; }
@@ -1,21 +1,40 @@
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts using MongoDB.Bson.Serialization.Attributes;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{ {
public class TankInfoHistory public class TankInfoHistory
{ {
///<summary>
/// Player account identifier
///</summary>
public long AccountId { get; set; }
///<summary> public TankInfoHistory()
/// Tank identifier {
///</summary>
public long TankId { get; set; } }
public TankInfoHistory(long accountId, long tankId, int lastBattleTime)
{
TankInfoHistoryId = new TankInfoHistoryKey(accountId, tankId, lastBattleTime);
}
[BsonId]
public TankInfoHistoryKey TankInfoHistoryId { get; set; }
///<summary>
/// Player account identifier
///</summary>
[BsonIgnore]
public long AccountId => TankInfoHistoryId.AccountId;
///<summary>
/// Tank identifier
///</summary>
[BsonIgnore]
public long TankId => TankInfoHistoryId.TankId;
///<summary> ///<summary>
/// Last battle /// Last battle
///</summary> ///</summary>
public int LastBattleTime { get; set; } [BsonIgnore]
public int LastBattleTime => TankInfoHistoryId.LastBattleTime;
@@ -0,0 +1,64 @@
using System;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{
public class TankInfoHistoryKey : IEquatable<TankInfoHistoryKey>
{
public TankInfoHistoryKey()
{
}
public TankInfoHistoryKey(long accountId, long tankId, int lastBattleTime)
{
AccountId = accountId;
TankId = tankId;
LastBattleTime = lastBattleTime;
}
///<summary>
/// Player account identifier
///</summary>
public long AccountId { get; set; }
///<summary>
/// Tank identifier
///</summary>
public long TankId { get; set; }
///<summary>
/// Last battle
///</summary>
public int LastBattleTime { get; set; }
public bool Equals(TankInfoHistoryKey other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return AccountId == other.AccountId && TankId == other.TankId && LastBattleTime == other.LastBattleTime;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TankInfoHistoryKey) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(AccountId, TankId, LastBattleTime);
}
public static bool operator ==(TankInfoHistoryKey left, TankInfoHistoryKey right)
{
return Equals(left, right);
}
public static bool operator !=(TankInfoHistoryKey left, TankInfoHistoryKey right)
{
return !Equals(left, right);
}
}
}
@@ -0,0 +1,58 @@
using System;
namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts
{
public class TankInfoKey : IEquatable<TankInfoKey>
{
public TankInfoKey()
{
}
public TankInfoKey(long accountId, long tankId)
{
AccountId = accountId;
TankId = tankId;
}
///<summary>
/// Player account identifier
///</summary>
public long AccountId { get; set; }
///<summary>
/// Tank identifier
///</summary>
public long TankId { get; set; }
public bool Equals(TankInfoKey other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return AccountId == other.AccountId && TankId == other.TankId;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TankInfoKey) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(AccountId, TankId);
}
public static bool operator ==(TankInfoKey left, TankInfoKey right)
{
return Equals(left, right);
}
public static bool operator !=(TankInfoKey left, TankInfoKey right)
{
return !Equals(left, right);
}
}
}
@@ -32,36 +32,36 @@ namespace WotBlitzStatisticsPro.DataAccess
_database.GetCollection<AccountInfo>(AccountInfoCollectionName).Indexes _database.GetCollection<AccountInfo>(AccountInfoCollectionName).Indexes
.CreateMany(new[] {accountInfoRealmIndexModel, accountInfoLastBattleTimeIndexModel}); .CreateMany(new[] {accountInfoRealmIndexModel, accountInfoLastBattleTimeIndexModel});
// AccountInfoHistory AccountId+LastBattleTime //// AccountInfoHistory AccountId+LastBattleTime
var accountInfoHistoryBuilder = Builders<AccountInfoHistory>.IndexKeys; //var accountInfoHistoryBuilder = Builders<AccountInfoHistory>.IndexKeys;
var accountInfoHistoryIndexModel = new CreateIndexModel<AccountInfoHistory>( //var accountInfoHistoryIndexModel = new CreateIndexModel<AccountInfoHistory>(
accountInfoHistoryBuilder.Combine( // accountInfoHistoryBuilder.Combine(
Builders<AccountInfoHistory>.IndexKeys.Ascending(h => h.AccountId), // Builders<AccountInfoHistory>.IndexKeys.Ascending(h => h.AccountId),
Builders<AccountInfoHistory>.IndexKeys.Ascending(h => h.LastBattleTime))); // Builders<AccountInfoHistory>.IndexKeys.Ascending(h => h.LastBattleTime)));
_database.GetCollection<AccountInfoHistory>(AccountInfoHistoryCollectionName).Indexes //_database.GetCollection<AccountInfoHistory>(AccountInfoHistoryCollectionName).Indexes
.CreateOne(accountInfoHistoryIndexModel); // .CreateOne(accountInfoHistoryIndexModel);
// TankInfo AccountId+TankId, LastBattleTime //// TankInfo AccountId+TankId, LastBattleTime
var tankInfoBuilder = Builders<TankInfo>.IndexKeys; //var tankInfoBuilder = Builders<TankInfo>.IndexKeys;
var tankInfoIndexModel = new CreateIndexModel<TankInfo>( //var tankInfoIndexModel = new CreateIndexModel<TankInfo>(
tankInfoBuilder.Combine( // tankInfoBuilder.Combine(
Builders<TankInfo>.IndexKeys.Ascending(h => h.AccountId), // Builders<TankInfo>.IndexKeys.Ascending(h => h.AccountId),
Builders<TankInfo>.IndexKeys.Ascending(h => h.TankId))); // Builders<TankInfo>.IndexKeys.Ascending(h => h.TankId)));
var tankInfoLastBattleTimeIndexModel = //var tankInfoLastBattleTimeIndexModel =
new CreateIndexModel<TankInfo>(tankInfoBuilder.Ascending(t => t.LastBattleTime)); // new CreateIndexModel<TankInfo>(tankInfoBuilder.Ascending(t => t.LastBattleTime));
_database.GetCollection<TankInfo>(TankInfoCollectionName).Indexes //_database.GetCollection<TankInfo>(TankInfoCollectionName).Indexes
.CreateMany(new[] {tankInfoIndexModel, tankInfoLastBattleTimeIndexModel}); // .CreateMany(new[] {tankInfoIndexModel, tankInfoLastBattleTimeIndexModel});
// TankInfoHistory AccountId+TankId+LastBattleTime //// TankInfoHistory AccountId+TankId+LastBattleTime
var tankInfoHistoryBuilder = Builders<TankInfoHistory>.IndexKeys; //var tankInfoHistoryBuilder = Builders<TankInfoHistory>.IndexKeys;
var tankInfoHistoryIndexModel = new CreateIndexModel<TankInfoHistory>( //var tankInfoHistoryIndexModel = new CreateIndexModel<TankInfoHistory>(
tankInfoHistoryBuilder.Combine( // tankInfoHistoryBuilder.Combine(
Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.AccountId), // Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.AccountId),
Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.TankId), // Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.TankId),
Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.LastBattleTime))); // Builders<TankInfoHistory>.IndexKeys.Ascending(h => h.LastBattleTime)));
_database.GetCollection<TankInfoHistory>(TankInfoHistoryCollectionName).Indexes //_database.GetCollection<TankInfoHistory>(TankInfoHistoryCollectionName).Indexes
.CreateOne(tankInfoHistoryIndexModel); // .CreateOne(tankInfoHistoryIndexModel);
} }
public async Task<AccountInfo> ReadAccountInfo(long accountId) public async Task<AccountInfo> ReadAccountInfo(long accountId)
@@ -70,5 +70,44 @@ namespace WotBlitzStatisticsPro.DataAccess
.FindAsync(Builders<AccountInfo>.Filter.Where(a => a.AccountId == accountId)); .FindAsync(Builders<AccountInfo>.Filter.Where(a => a.AccountId == accountId));
return account.FirstOrDefault(); return account.FirstOrDefault();
} }
public async Task<TankInfo> ReadTankInfo(long accountId, long tankId)
{
var tank = await _database.GetCollection<TankInfo>(TankInfoCollectionName)
.FindAsync(Builders<TankInfo>.Filter.Where(t => t.TankInfoId == new TankInfoKey(accountId, tankId)));
return tank.FirstOrDefault();
}
public Task AddOurUpdateAccountInfo(AccountInfo accountInfo)
{
return _database.GetCollection<AccountInfo>(AccountInfoCollectionName)
.ReplaceOneAsync(
Builders<AccountInfo>.Filter.Where(a => a.AccountId == accountInfo.AccountId),
accountInfo,
new ReplaceOptions {IsUpsert = true}
);
}
public Task AddAccountInfoHistory(AccountInfoHistory accountInfoHistory)
{
return _database.GetCollection<AccountInfoHistory>(AccountInfoHistoryCollectionName)
.InsertOneAsync(accountInfoHistory);
}
public Task AddOrUpdateTankInfo(TankInfo tankInfo)
{
return _database.GetCollection<TankInfo>(TankInfoCollectionName)
.ReplaceOneAsync(
Builders<TankInfo>.Filter.Where(t => t.TankInfoId == new TankInfoKey(tankInfo.AccountId, tankInfo.TankId)),
tankInfo,
new ReplaceOptions { IsUpsert = true }
);
}
public Task AddTankInfoHistory(TankInfoHistory tankInfoHistory)
{
return _database.GetCollection<TankInfoHistory>(TankInfoHistoryCollectionName)
.InsertOneAsync(tankInfoHistory);
}
} }
} }
@@ -17,7 +17,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
public Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next) public Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
{ {
if (context.DbAccountInfo == null || if (context.DbAccountInfo == null ||
context.DbAccountInfo.LastBattleTime >= context.AccountInfo.LastBattleTime) context.DbAccountInfo.LastBattleTime < context.AccountInfo.LastBattleTime)
{ {
return next.Invoke(context); return next.Invoke(context);
} }
@@ -30,10 +30,8 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
context.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo); context.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
context.AccountInfo.Realm = context.RealmType; context.AccountInfo.Realm = context.RealmType;
context.AccountInfoHistory = context.AccountInfoHistory = new AccountInfoHistory(context.AccountId, context.AccountInfo.LastBattleTime);
_mapper.Map<WotAccountFullStatistics, AccountInfoHistory>(accountInfo.Statistics.All); _mapper.Map(accountInfo.Statistics.All, context.AccountInfoHistory);
context.AccountInfoHistory.AccountId = context.AccountId;
context.AccountInfoHistory.LastBattleTime = context.AccountInfo.LastBattleTime;
await next.Invoke(context); await next.Invoke(context);
} }
@@ -32,11 +32,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
tanksInfo.ForEach(tank => tanksInfo.ForEach(tank =>
{ {
context.Tanks.Add(_mapper.Map<WotAccountTanksStatistics, TankInfo>(tank)); var tankInfo = new TankInfo(tank.AccountId, tank.TankId);
var stat = _mapper.Map<WotAccountTanksFullStatistics, TankInfoHistory>(tank.All); _mapper.Map(tank, tankInfo);
stat.AccountId = tank.AccountId; context.Tanks.Add(tankInfo);
stat.TankId = tank.TankId; var stat = new TankInfoHistory(tank.AccountId, tank.TankId, tank.LastBattleTime);
stat.LastBattleTime = tank.LastBattleTime; _mapper.Map(tank.All, stat);
context.TanksHistory[stat.TankId] = stat; context.TanksHistory[stat.TankId] = stat;
}); });
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.Logic.Pipeline;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class SaveAccountAndTanksOperation : IOperation<AccountInformationPipelineContext>
{
private readonly IWargamingAccountDataAccessor _accountDataAccessor;
private readonly ILogger<SaveAccountAndTanksOperation> _logger;
public SaveAccountAndTanksOperation(
IWargamingAccountDataAccessor accountDataAccessor,
ILogger<SaveAccountAndTanksOperation> logger)
{
_accountDataAccessor = accountDataAccessor;
_logger = logger;
}
public async Task Invoke(AccountInformationPipelineContext context, Func<AccountInformationPipelineContext, Task> next)
{
await _accountDataAccessor.AddOurUpdateAccountInfo(context.AccountInfo);
await _accountDataAccessor.AddAccountInfoHistory(context.AccountInfoHistory);
var tanksCount = 0;
var tankIdsAsString = new StringBuilder();
foreach (var tankInfo in context.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]);
tanksCount++;
tankIdsAsString.Append($" {tankInfo.TankId}; ");
}
}
_logger.LogInformation($"Updated account {context.AccountInfo.AccountId} and {tanksCount} tanks: {tankIdsAsString}");
await next.Invoke(context);
}
}
}
@@ -43,7 +43,7 @@ namespace WotBlitzStatisticsPro.Logic
.AddOperation<CheckLastBattleDateOperation>() .AddOperation<CheckLastBattleDateOperation>()
.AddOperation<GetTanksInfoOperation>() .AddOperation<GetTanksInfoOperation>()
.AddOperation<CalculateStatisticsOperation>() .AddOperation<CalculateStatisticsOperation>()
// ToDo: add operation for save info into DB .AddOperation<SaveAccountAndTanksOperation>()
.AddOperation<BuildAccountInfoResponseOperation>() .AddOperation<BuildAccountInfoResponseOperation>()
; ;
@@ -65,6 +65,7 @@ namespace WotBlitzStatisticsPro.Logic
services.AddTransient<GetTanksInfoOperation>(); services.AddTransient<GetTanksInfoOperation>();
services.AddTransient<CalculateStatisticsOperation>(); services.AddTransient<CalculateStatisticsOperation>();
services.AddTransient<BuildAccountInfoResponseOperation>(); services.AddTransient<BuildAccountInfoResponseOperation>();
services.AddTransient<SaveAccountAndTanksOperation>();
services.AddTransient<IOperationFactory>(serviceProvider => services.AddTransient<IOperationFactory>(serviceProvider =>
new ServiceProviderOperationFactory(serviceProvider)); new ServiceProviderOperationFactory(serviceProvider));