From 627195fafedcdc0b5aeb9004415e50057db68f90 Mon Sep 17 00:00:00 2001 From: Sergey Chebotar Date: Tue, 16 May 2023 07:43:57 +0300 Subject: [PATCH] Add caching --- RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs | 1 + RhSolutions.AddIn/Properties/AssemblyInfo.cs | 4 +- RhSolutions.AddIn/RhSolutions-AddIn.dna | 2 + RhSolutions.AddIn/RhSolutions.AddIn.csproj | 1 + RhSolutions.AddIn/Services/CurrencyClient.cs | 54 ++++++++++++-------- RhSolutions.AddIn/Services/DatabaseClient.cs | 41 +++++++++------ 6 files changed, 63 insertions(+), 40 deletions(-) diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs index bf9c992..2ddff1a 100644 --- a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs +++ b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs @@ -19,6 +19,7 @@ public sealed class RhSolutionsAddIn : IExcelAddIn IServiceCollection Services = new ServiceCollection(); Services.AddHttpClient() + .AddMemoryCache() .AddSingleton((Application)ExcelDnaUtil.Application) .AddSingleton() .AddSingleton() diff --git a/RhSolutions.AddIn/Properties/AssemblyInfo.cs b/RhSolutions.AddIn/Properties/AssemblyInfo.cs index fd55a65..9005468 100644 --- a/RhSolutions.AddIn/Properties/AssemblyInfo.cs +++ b/RhSolutions.AddIn/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.3.0")] -[assembly: AssemblyFileVersion("1.6.3.0")] +[assembly: AssemblyVersion("1.6.4.0")] +[assembly: AssemblyFileVersion("1.6.4.0")] diff --git a/RhSolutions.AddIn/RhSolutions-AddIn.dna b/RhSolutions.AddIn/RhSolutions-AddIn.dna index feb0454..32a6910 100644 --- a/RhSolutions.AddIn/RhSolutions-AddIn.dna +++ b/RhSolutions.AddIn/RhSolutions-AddIn.dna @@ -3,6 +3,8 @@ + + diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj index 34dc5f4..3bf1071 100644 --- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj +++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj @@ -33,6 +33,7 @@ + diff --git a/RhSolutions.AddIn/Services/CurrencyClient.cs b/RhSolutions.AddIn/Services/CurrencyClient.cs index 4f3b922..fcc48ea 100644 --- a/RhSolutions.AddIn/Services/CurrencyClient.cs +++ b/RhSolutions.AddIn/Services/CurrencyClient.cs @@ -1,4 +1,5 @@ -using System.Net; +using Microsoft.Extensions.Caching.Memory; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Xml.Linq; @@ -7,35 +8,44 @@ namespace RhSolutions.Services; public class CurrencyClient : ICurrencyClient { - private readonly HttpClient _httpClient; + private readonly HttpClient _httpClient; + private readonly IMemoryCache _memoryCache; + private const string requestAddress = @"https://www.cbr.ru/scripts/XML_daily.asp?date_req="; public HttpStatusCode StatusCode { get; private set; } - public CurrencyClient(IServiceProvider serviceProvider) + public CurrencyClient(HttpClient httpClient, IMemoryCache memoryCache) { - _httpClient = serviceProvider.GetRequiredService(); + _httpClient = httpClient; + _memoryCache = memoryCache; } public async Task GetCurrencyCourse(DateTime date) { - string request = $"https://www.cbr.ru/scripts/XML_daily.asp?date_req={date.Date.ToString("dd/MM/yyyy")}"; - var response = await _httpClient.GetAsync(request); - - try + if (!_memoryCache.TryGetValue(date, out decimal? exchangeRate)) { - response.EnsureSuccessStatusCode(); - string xml = await response.Content.ReadAsStringAsync(); - XElement valCourses = XElement.Parse(xml); - var course = decimal.Parse(valCourses.Elements("Valute") - .Where(e => e.Element("Name").Value == "Евро") - .FirstOrDefault() - .Element("Value").Value); - return course; - } - catch - { - StatusCode = response.StatusCode; - } + string request = $"{requestAddress}{date.Date:dd/MM/yyyy}"; + HttpResponseMessage response = await _httpClient.GetAsync(request); + try + { + response.EnsureSuccessStatusCode(); + string xml = await response.Content.ReadAsStringAsync(); + XElement valCourses = XElement.Parse(xml); + exchangeRate = decimal.Parse(valCourses.Elements("Valute") + .Where(e => e.Element("Name").Value == "Евро") + .FirstOrDefault() + .Element("Value").Value); + return exchangeRate; + } + catch + { + StatusCode = response.StatusCode; + exchangeRate = null; + } - return null; + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetSlidingExpiration(TimeSpan.FromHours(1)); + _memoryCache.Set(date, exchangeRate, cacheEntryOptions); + } + return exchangeRate; } } \ No newline at end of file diff --git a/RhSolutions.AddIn/Services/DatabaseClient.cs b/RhSolutions.AddIn/Services/DatabaseClient.cs index ac3aff9..efcf607 100644 --- a/RhSolutions.AddIn/Services/DatabaseClient.cs +++ b/RhSolutions.AddIn/Services/DatabaseClient.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -7,12 +8,14 @@ namespace RhSolutions.Services; public class DatabaseClient : IDatabaseClient { - private readonly IServiceProvider serviceProvider; + private readonly HttpClient _httpClient; + private readonly IMemoryCache _memoryCache; public HttpStatusCode StatusCode { get; private set; } - public DatabaseClient(IServiceProvider provider) + public DatabaseClient(HttpClient httpClient, IMemoryCache memoryCache) { - this.serviceProvider = provider; + _httpClient = httpClient; + _memoryCache = memoryCache; } public async Task> GetProducts(string line) @@ -29,20 +32,26 @@ public class DatabaseClient : IDatabaseClient request = @"https://rh.cebotari.ru/api/search?query=" + line; } - var client = serviceProvider.GetRequiredService(); - var response = await client.GetAsync(request); + if (!_memoryCache.TryGetValue(line, out IEnumerable products)) + { + var response = await _httpClient.GetAsync(request); - try - { - response.EnsureSuccessStatusCode(); - string json = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject>(json) ?? Enumerable.Empty(); - } - catch - { - StatusCode = response.StatusCode; + try + { + response.EnsureSuccessStatusCode(); + string json = await response.Content.ReadAsStringAsync(); + products = JsonConvert.DeserializeObject>(json) ?? Enumerable.Empty(); + } + catch + { + StatusCode = response.StatusCode; + } + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetSlidingExpiration(TimeSpan.FromHours(1)); + _memoryCache.Set(line, products, cacheEntryOptions); } - return Enumerable.Empty(); + return products; } } \ No newline at end of file