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
@@ -24,7 +24,7 @@ type Mutation {
|
|||||||
"Updates the necessary dictionaries in database.\n\n\n**Returns:**\nInformation about what was updated."
|
"Updates the necessary dictionaries in database.\n\n\n**Returns:**\nInformation about what was updated."
|
||||||
updateDictionaries("Determines what dictionaries should be updated." updateDictionariesRequest: UpdateDictionariesRequestInput!): [UpdateDictionariesResponseItem!]!
|
updateDictionaries("Determines what dictionaries should be updated." updateDictionariesRequest: UpdateDictionariesRequestInput!): [UpdateDictionariesResponseItem!]!
|
||||||
"Gathers all account information"
|
"Gathers all account information"
|
||||||
gatherAccountInformation("Account region" realmType: RealmType! "AccountId" accountId: Long! "Request language" requestLanguage: RequestLanguage!): AccountInfoResponse!
|
gatherAccountInformation("Account region" realmType: RealmType! "AccountId" accountId: Long! "Request language" requestLanguage: RequestLanguage!): DateTime!
|
||||||
"This method accepts GitHub oauth code, and returns JWT token with GutHub user as claim"
|
"This method accepts GitHub oauth code, and returns JWT token with GutHub user as claim"
|
||||||
gitHubAuthenticate("OAuth code can be generated by this URL https:\/\/github.com\/login\/oauth\/authorize?client_id={yourClientId}" oauthCode: String!): String!
|
gitHubAuthenticate("OAuth code can be generated by this URL https:\/\/github.com\/login\/oauth\/authorize?client_id={yourClientId}" oauthCode: String!): String!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using HotChocolate;
|
using HotChocolate;
|
||||||
using HotChocolate.AspNetCore.Authorization;
|
using HotChocolate.AspNetCore.Authorization;
|
||||||
using HotChocolate.Types;
|
using HotChocolate.Types;
|
||||||
@@ -43,7 +44,7 @@ namespace WotBlitzStatisticsPro.GraphQl.Mutation
|
|||||||
/// <param name="requestLanguage">Request language</param>
|
/// <param name="requestLanguage">Request language</param>
|
||||||
/// <param name="wgToken">Wargaming authentication token</param>
|
/// <param name="wgToken">Wargaming authentication token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<AccountInfoResponse> GatherAccountInformation(
|
public Task<DateTime> GatherAccountInformation(
|
||||||
RealmType realmType,
|
RealmType realmType,
|
||||||
long accountId,
|
long accountId,
|
||||||
RequestLanguage requestLanguage,
|
RequestLanguage requestLanguage,
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace WotBlitzStatisticsPro.GraphQl
|
namespace WotBlitzStatisticsPro.GraphQl
|
||||||
{
|
{
|
||||||
@@ -7,12 +11,36 @@ namespace WotBlitzStatisticsPro.GraphQl
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
CreateHostBuilder(args).Build().Run();
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json")
|
||||||
|
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.ReadFrom.Configuration(configuration)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.Information("Starting web host");
|
||||||
|
CreateHostBuilder(args).Build().Run();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Fatal(ex, "Host terminated unexpectedly");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Log.CloseAndFlush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
Host.CreateDefaultBuilder(args)
|
Host.CreateDefaultBuilder(args)
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
.UseSerilog()
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
{
|
{
|
||||||
webBuilder.UseStartup<Startup>();
|
webBuilder.UseStartup<Startup>();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using HotChocolate.Types;
|
using HotChocolate.Types;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.Common.Model;
|
using WotBlitzStatisticsPro.Common.Model;
|
||||||
using WotBlitzStatisticsPro.Logic;
|
using WotBlitzStatisticsPro.Logic;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Serilog;
|
||||||
using WotBlitzStatisticsPro.Common;
|
using WotBlitzStatisticsPro.Common;
|
||||||
using WotBlitzStatisticsPro.Common.Model;
|
using WotBlitzStatisticsPro.Common.Model;
|
||||||
using WotBlitzStatisticsPro.GraphQl.GitHubOauth;
|
using WotBlitzStatisticsPro.GraphQl.GitHubOauth;
|
||||||
@@ -37,7 +38,10 @@ namespace WotBlitzStatisticsPro.GraphQl
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
var wgApiConfig = new WargamingApiSettings();
|
//services.AddLogging(loggingBuilder =>
|
||||||
|
// loggingBuilder.AddSerilog(dispose: true));
|
||||||
|
|
||||||
|
var wgApiConfig = new WargamingApiSettings();
|
||||||
Configuration.GetSection("WargamingApi").Bind(wgApiConfig);
|
Configuration.GetSection("WargamingApi").Bind(wgApiConfig);
|
||||||
|
|
||||||
var mongoConfig = new MongoSettings();
|
var mongoConfig = new MongoSettings();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.10.0" />
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.10.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Serilog": {
|
||||||
|
"Using": [ "Serilog.Sinks.Console" ],
|
||||||
|
"MinimumLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"Override": {
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"System": "Warning"
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
"WriteTo": [
|
||||||
|
{ "Name": "Console" }
|
||||||
|
],
|
||||||
|
"Enrich": [ "FromLogContext" ]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"Serilog": {
|
||||||
|
"Using": [ "Serilog.Sinks.Console" ],
|
||||||
|
"MinimumLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Override": {
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"System": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WriteTo": [
|
||||||
|
{ "Name": "Console" }
|
||||||
|
],
|
||||||
|
"Enrich": [ "FromLogContext" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,9 +14,30 @@
|
|||||||
"Mongo": {
|
"Mongo": {
|
||||||
"ConnectionString": "*",
|
"ConnectionString": "*",
|
||||||
"DatabaseName": "*"
|
"DatabaseName": "*"
|
||||||
},
|
},
|
||||||
"GitHubOAuth": {
|
"GitHubOAuth": {
|
||||||
"ClientId": "YourClientId",
|
"ClientId": "YourClientId",
|
||||||
"ClientSecret": "YourSecret"
|
"ClientSecret": "YourSecret"
|
||||||
}
|
},
|
||||||
}
|
"Serilog": {
|
||||||
|
"Using": [ "Serilog.Sinks.Console" ],
|
||||||
|
"MinimumLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Override": {
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"System": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WriteTo": [
|
||||||
|
{
|
||||||
|
"Name": "Console",
|
||||||
|
"Args": {
|
||||||
|
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
|
||||||
|
"outputTemplate": "{Timestamp:HH:mm:ss.fff} [{Level:u3}] {Message:lj} |{SourceContext}|{NewLine}{Exception}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Enrich": [ "FromLogContext" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-3
@@ -4,6 +4,7 @@ using AutoMapper;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Model;
|
||||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||||
using WotBlitzStatisticsPro.WgApiClient;
|
using WotBlitzStatisticsPro.WgApiClient;
|
||||||
using WotBlitzStatisticsPro.WgApiClient.Model;
|
using WotBlitzStatisticsPro.WgApiClient.Model;
|
||||||
@@ -15,19 +16,36 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
|||||||
private readonly IWargamingApiClient _wargamingApi;
|
private readonly IWargamingApiClient _wargamingApi;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly ILogger<GetAccountInfoOperation> _logger;
|
private readonly ILogger<GetAccountInfoOperation> _logger;
|
||||||
|
private readonly StatisticsCache _cache;
|
||||||
|
|
||||||
public GetAccountInfoOperation(
|
public GetAccountInfoOperation(
|
||||||
IWargamingApiClient wargamingApi,
|
IWargamingApiClient wargamingApi,
|
||||||
IMapper mapper,
|
IMapper mapper,
|
||||||
ILogger<GetAccountInfoOperation> logger)
|
ILogger<GetAccountInfoOperation> logger,
|
||||||
|
StatisticsCache cache)
|
||||||
{
|
{
|
||||||
_wargamingApi = wargamingApi;
|
_wargamingApi = wargamingApi;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
|
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
|
var accountInfo = await
|
||||||
_wargamingApi.GetPlayerAccountInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage, context.Request.AuthenticationToken);
|
_wargamingApi.GetPlayerAccountInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage, context.Request.AuthenticationToken);
|
||||||
|
|
||||||
@@ -38,14 +56,14 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store info to AccountInfo and in AccountInfoHistory
|
|
||||||
var contextData = context.Get<AccountInformationPipelineContextData>();
|
|
||||||
contextData.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
|
contextData.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
|
||||||
contextData.AccountInfo.Realm = context.Request.RealmType;
|
contextData.AccountInfo.Realm = context.Request.RealmType;
|
||||||
|
|
||||||
contextData.AccountInfoHistory = new AccountInfoHistory(context.Request.AccountId, contextData.AccountInfo.LastBattleTime);
|
contextData.AccountInfoHistory = new AccountInfoHistory(context.Request.AccountId, contextData.AccountInfo.LastBattleTime);
|
||||||
_mapper.Map(accountInfo.Statistics?.All, contextData.AccountInfoHistory);
|
_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);
|
if (next != null) await next.Invoke(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -6,6 +6,7 @@ using AutoMapper;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Model;
|
||||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||||
using WotBlitzStatisticsPro.WgApiClient;
|
using WotBlitzStatisticsPro.WgApiClient;
|
||||||
|
|
||||||
@@ -16,21 +17,36 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
|
|||||||
private readonly IWargamingTanksApiClient _wargamingApi;
|
private readonly IWargamingTanksApiClient _wargamingApi;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly ILogger<GetTanksInfoOperation> _logger;
|
private readonly ILogger<GetTanksInfoOperation> _logger;
|
||||||
|
private readonly StatisticsCache _cache;
|
||||||
|
|
||||||
public GetTanksInfoOperation(
|
public GetTanksInfoOperation(
|
||||||
IWargamingTanksApiClient wargamingApi,
|
IWargamingTanksApiClient wargamingApi,
|
||||||
IMapper mapper,
|
IMapper mapper,
|
||||||
ILogger<GetTanksInfoOperation> logger)
|
ILogger<GetTanksInfoOperation> logger,
|
||||||
|
StatisticsCache cache)
|
||||||
{
|
{
|
||||||
_wargamingApi = wargamingApi;
|
_wargamingApi = wargamingApi;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
|
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
|
||||||
{
|
{
|
||||||
var contextData = context.Get<AccountInformationPipelineContextData>();
|
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
|
var tanksInfo = await
|
||||||
_wargamingApi.GetPlayerAccountTanksInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
|
_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;
|
contextData.TanksHistory[stat.TankId] = stat;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_cache.SetTanksData(context.Request.AccountId, new TanksDataCache(contextData.Tanks, contextData.TanksHistory));
|
||||||
|
|
||||||
if (next != null) await next.Invoke(context);
|
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> 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,
|
Task<AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate,
|
||||||
RequestLanguage requestLanguage);
|
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;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Calculations;
|
||||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||||
|
|
||||||
namespace WotBlitzStatisticsPro.Logic
|
namespace WotBlitzStatisticsPro.Logic
|
||||||
@@ -58,7 +59,7 @@ namespace WotBlitzStatisticsPro.Logic
|
|||||||
return contextData?.Response ?? new AccountInfoResponse();
|
return contextData?.Response ?? new AccountInfoResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AccountInfoResponse> GatherAndSaveAccountInformation(
|
public async Task<DateTime> GatherAndSaveAccountInformation(
|
||||||
RealmType realm,
|
RealmType realm,
|
||||||
long accountId,
|
long accountId,
|
||||||
RequestLanguage requestLanguage,
|
RequestLanguage requestLanguage,
|
||||||
@@ -78,7 +79,6 @@ namespace WotBlitzStatisticsPro.Logic
|
|||||||
.AddOperation<GetTanksInfoOperation>()
|
.AddOperation<GetTanksInfoOperation>()
|
||||||
.AddOperation<CalculateStatisticsOperation>()
|
.AddOperation<CalculateStatisticsOperation>()
|
||||||
.AddOperation<SaveAccountAndTanksOperation>()
|
.AddOperation<SaveAccountAndTanksOperation>()
|
||||||
.AddOperation<BuildAccountInfoResponseOperation>()
|
|
||||||
;
|
;
|
||||||
|
|
||||||
var firstOperation = pipeline.Build();
|
var firstOperation = pipeline.Build();
|
||||||
@@ -95,7 +95,7 @@ namespace WotBlitzStatisticsPro.Logic
|
|||||||
|
|
||||||
throw;
|
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)
|
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.DataAccess;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||||
using WotBlitzStatisticsPro.Logic.Dictionaries;
|
using WotBlitzStatisticsPro.Logic.Dictionaries;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Model;
|
||||||
using WotBlitzStatisticsPro.Logic.Pipeline;
|
using WotBlitzStatisticsPro.Logic.Pipeline;
|
||||||
using WotBlitzStatisticsPro.WgApiClient;
|
using WotBlitzStatisticsPro.WgApiClient;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ namespace WotBlitzStatisticsPro.Logic
|
|||||||
|
|
||||||
public static void ConfigureServices(IServiceCollection services)
|
public static void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddSingleton<StatisticsCache>();
|
||||||
ConfigureDictionariesFactory(services);
|
ConfigureDictionariesFactory(services);
|
||||||
ConfigureOperationsFactory(services);
|
ConfigureOperationsFactory(services);
|
||||||
WotBlitzStatisticsDataAccessInstaller.ConfigureServices(services);
|
WotBlitzStatisticsDataAccessInstaller.ConfigureServices(services);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using WotBlitzStatisticsPro.Common.Model;
|
|||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Model;
|
||||||
|
|
||||||
namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
||||||
{
|
{
|
||||||
@@ -17,16 +18,19 @@ namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
|||||||
{
|
{
|
||||||
private GetAccountInfoOperation _operation;
|
private GetAccountInfoOperation _operation;
|
||||||
private AccountInformationPipelineContextData _contextData;
|
private AccountInformationPipelineContextData _contextData;
|
||||||
|
private StatisticsCache _cache;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
InitAutoMapper();
|
InitAutoMapper();
|
||||||
InitWgApiClient();
|
InitWgApiClient();
|
||||||
|
_cache = new StatisticsCache();
|
||||||
_operation = new GetAccountInfoOperation(
|
_operation = new GetAccountInfoOperation(
|
||||||
WargamingApiClient,
|
WargamingApiClient,
|
||||||
Mapper,
|
Mapper,
|
||||||
(new Mock<ILogger<GetAccountInfoOperation>>()).Object);
|
(new Mock<ILogger<GetAccountInfoOperation>>()).Object,
|
||||||
|
_cache);
|
||||||
|
|
||||||
_contextData = new AccountInformationPipelineContextData();
|
_contextData = new AccountInformationPipelineContextData();
|
||||||
}
|
}
|
||||||
@@ -51,6 +55,21 @@ namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
|||||||
var expectedAccountInfoHistory =
|
var expectedAccountInfoHistory =
|
||||||
await File.ReadAllTextAsync(GetFixturePath("MappedAccountHistory.json"));
|
await File.ReadAllTextAsync(GetFixturePath("MappedAccountHistory.json"));
|
||||||
accountInfoHistorySerialized.Should().Be(expectedAccountInfoHistory);
|
accountInfoHistorySerialized.Should().Be(expectedAccountInfoHistory);
|
||||||
|
|
||||||
|
// ToDo: Check cache
|
||||||
|
Assert.Fail("Implement test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ShouldGetAndSaveAccountInfoInformationIfCacheExpired()
|
||||||
|
{
|
||||||
|
Assert.Fail("Implement test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ShouldReadDataFromCacheIfItIsNotEmpty()
|
||||||
|
{
|
||||||
|
Assert.Fail("Implement test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ using NUnit.Framework;
|
|||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
|
||||||
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations;
|
||||||
|
using WotBlitzStatisticsPro.Logic.Model;
|
||||||
|
|
||||||
namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
||||||
{
|
{
|
||||||
@@ -16,16 +17,21 @@ namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
|||||||
{
|
{
|
||||||
private GetTanksInfoOperation _operation;
|
private GetTanksInfoOperation _operation;
|
||||||
private AccountInformationPipelineContextData _contextData;
|
private AccountInformationPipelineContextData _contextData;
|
||||||
|
private StatisticsCache _cache;
|
||||||
|
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
InitAutoMapper();
|
InitAutoMapper();
|
||||||
InitWgApiClient();
|
InitWgApiClient();
|
||||||
|
_cache = new StatisticsCache();
|
||||||
|
|
||||||
_operation = new GetTanksInfoOperation(
|
_operation = new GetTanksInfoOperation(
|
||||||
WargamingTanksApiClient,
|
WargamingTanksApiClient,
|
||||||
Mapper,
|
Mapper,
|
||||||
(new Mock<ILogger<GetTanksInfoOperation>>()).Object);
|
(new Mock<ILogger<GetTanksInfoOperation>>()).Object,
|
||||||
|
_cache);
|
||||||
|
|
||||||
_contextData = new AccountInformationPipelineContextData();
|
_contextData = new AccountInformationPipelineContextData();
|
||||||
}
|
}
|
||||||
@@ -50,6 +56,21 @@ namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
|||||||
var expectedTanksHistory =
|
var expectedTanksHistory =
|
||||||
await File.ReadAllTextAsync(GetFixturePath("MappedTanksHistory.json"));
|
await File.ReadAllTextAsync(GetFixturePath("MappedTanksHistory.json"));
|
||||||
tanksHistorySerialized.Should().Be(expectedTanksHistory);
|
tanksHistorySerialized.Should().Be(expectedTanksHistory);
|
||||||
|
|
||||||
|
// ToDo: Check cache
|
||||||
|
Assert.Fail("Implement test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ShouldGetAndSaveTankInfoInformationIfCacheExpired()
|
||||||
|
{
|
||||||
|
Assert.Fail("Implement test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ShouldReadDataFromCacheIfItIsNotEmpty()
|
||||||
|
{
|
||||||
|
Assert.Fail("Implement test");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Net.Http;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Moq.Protected;
|
using Moq.Protected;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -97,7 +98,10 @@ namespace WotBlitzStatisticsPro.Tests.OperationStepsTests
|
|||||||
ItExpr.IsAny<CancellationToken>())
|
ItExpr.IsAny<CancellationToken>())
|
||||||
.ReturnsAsync(tanksInfoResponse);
|
.ReturnsAsync(tanksInfoResponse);
|
||||||
|
|
||||||
var client = new WargamingApiClient(new HttpClient(handlerMock.Object), settingsMock.Object);
|
var client = new WargamingApiClient(
|
||||||
|
new HttpClient(handlerMock.Object),
|
||||||
|
settingsMock.Object,
|
||||||
|
(new Mock<ILogger<WagramingApiClientBase>>()).Object);
|
||||||
WargamingApiClient = client;
|
WargamingApiClient = client;
|
||||||
WargamingTanksApiClient = client;
|
WargamingTanksApiClient = client;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Net.Http;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.Common;
|
using WotBlitzStatisticsPro.Common;
|
||||||
using WotBlitzStatisticsPro.Common.Model;
|
using WotBlitzStatisticsPro.Common.Model;
|
||||||
|
|
||||||
@@ -19,14 +20,17 @@ namespace WotBlitzStatisticsPro.WgApiClient
|
|||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly IWargamingApiSettings _wargamingApiSettings;
|
private readonly IWargamingApiSettings _wargamingApiSettings;
|
||||||
|
private readonly ILogger<WagramingApiClientBase> _logger;
|
||||||
|
|
||||||
public WagramingApiClientBase(
|
public WagramingApiClientBase(
|
||||||
HttpClient httpClient,
|
HttpClient httpClient,
|
||||||
IWargamingApiSettings wargamingApiSettings)
|
IWargamingApiSettings wargamingApiSettings,
|
||||||
|
ILogger<WagramingApiClientBase> logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_wargamingApiSettings = wargamingApiSettings;
|
_wargamingApiSettings = wargamingApiSettings;
|
||||||
_blitzApiUrls[RealmType.Eu] = "https://api.wotblitz.eu/wotb/";
|
_logger = logger;
|
||||||
|
_blitzApiUrls[RealmType.Eu] = "https://api.wotblitz.eu/wotb/";
|
||||||
_blitzApiUrls[RealmType.Ru] = "https://api.wotblitz.ru/wotb/";
|
_blitzApiUrls[RealmType.Ru] = "https://api.wotblitz.ru/wotb/";
|
||||||
_blitzApiUrls[RealmType.Na] = "https://api.wotblitz.com/wotb/";
|
_blitzApiUrls[RealmType.Na] = "https://api.wotblitz.com/wotb/";
|
||||||
_blitzApiUrls[RealmType.Asia] = "https://api.wotblitz.asia/wotb/";
|
_blitzApiUrls[RealmType.Asia] = "https://api.wotblitz.asia/wotb/";
|
||||||
@@ -53,6 +57,9 @@ namespace WotBlitzStatisticsPro.WgApiClient
|
|||||||
var responseString = await response.Content.ReadAsStringAsync();
|
var responseString = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
var responseBody = JsonConvert.DeserializeObject<ResponseBody<T>>(responseString);
|
var responseBody = JsonConvert.DeserializeObject<ResponseBody<T>>(responseString);
|
||||||
|
|
||||||
|
_logger.LogInformation($"HTTP GET {uri} - {responseBody.Status}");
|
||||||
|
|
||||||
switch (responseBody.Status)
|
switch (responseBody.Status)
|
||||||
{
|
{
|
||||||
case "ok":
|
case "ok":
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.Common;
|
using WotBlitzStatisticsPro.Common;
|
||||||
using WotBlitzStatisticsPro.Common.Model;
|
using WotBlitzStatisticsPro.Common.Model;
|
||||||
using WotBlitzStatisticsPro.WgApiClient.Model;
|
using WotBlitzStatisticsPro.WgApiClient.Model;
|
||||||
@@ -10,7 +11,10 @@ namespace WotBlitzStatisticsPro.WgApiClient
|
|||||||
public class WargamingAchievementsApiClient: WagramingApiClientBase,
|
public class WargamingAchievementsApiClient: WagramingApiClientBase,
|
||||||
IWargamingAchievementsApiClient
|
IWargamingAchievementsApiClient
|
||||||
{
|
{
|
||||||
public WargamingAchievementsApiClient(HttpClient httpClient, IWargamingApiSettings wargamingApiSettings) : base(httpClient, wargamingApiSettings)
|
public WargamingAchievementsApiClient(
|
||||||
|
HttpClient httpClient,
|
||||||
|
IWargamingApiSettings wargamingApiSettings,
|
||||||
|
ILogger<WagramingApiClientBase> logger) : base(httpClient, wargamingApiSettings, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WotBlitzStatisticsPro.Common;
|
using WotBlitzStatisticsPro.Common;
|
||||||
using WotBlitzStatisticsPro.Common.Model;
|
using WotBlitzStatisticsPro.Common.Model;
|
||||||
using WotBlitzStatisticsPro.WgApiClient.Model;
|
using WotBlitzStatisticsPro.WgApiClient.Model;
|
||||||
@@ -15,7 +16,8 @@ namespace WotBlitzStatisticsPro.WgApiClient
|
|||||||
{
|
{
|
||||||
public WargamingApiClient(
|
public WargamingApiClient(
|
||||||
HttpClient httpClient,
|
HttpClient httpClient,
|
||||||
IWargamingApiSettings wargamingApiSettings) : base(httpClient, wargamingApiSettings)
|
IWargamingApiSettings wargamingApiSettings,
|
||||||
|
ILogger<WagramingApiClientBase> logger) : base(httpClient, wargamingApiSettings, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user