From b5f70ac8d47182afa6e95a660bb1678f6aaac1e1 Mon Sep 17 00:00:00 2001 From: Serghei Cebotari Date: Fri, 27 Oct 2023 23:36:53 +0300 Subject: [PATCH] Implement gRPC client --- RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs | 6 +- RhSolutions.AddIn/Protos/product.proto | 17 ++++ RhSolutions.AddIn/RhSolutions.AddIn.csproj | 9 ++ RhSolutions.AddIn/Services/DatabaseClient.cs | 96 -------------------- RhSolutions.AddIn/Services/GrpcClient.cs | 13 +++ RhSolutions.AddIn/app.config | 41 +++++---- 6 files changed, 68 insertions(+), 114 deletions(-) create mode 100644 RhSolutions.AddIn/Protos/product.proto delete mode 100644 RhSolutions.AddIn/Services/DatabaseClient.cs create mode 100644 RhSolutions.AddIn/Services/GrpcClient.cs diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs index b7634a9..229265f 100644 --- a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs +++ b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs @@ -1,5 +1,6 @@ using System.Net; using ExcelDna.IntelliSense; +using Grpc.Core; #if !NET472 using System.Runtime.Versioning; #endif @@ -14,16 +15,19 @@ public sealed class RhSolutionsAddIn : IExcelAddIn public static Application Excel { get; private set; } public static ServiceProvider ServiceProvider { get; private set; } public static IAddInConfiguration Configuration { get; private set; } + public static ProductSearch.ProductSearchClient GrpcClient { get; private set; } public void AutoOpen() { IServiceCollection Services = new ServiceCollection(); + var grpcChannel = new Channel(@"rh2.cebotari.ru", ChannelCredentials.SecureSsl); + GrpcClient = new ProductSearch.ProductSearchClient(grpcChannel); Services.AddHttpClient() .AddMemoryCache() .AddSingleton((Application)ExcelDnaUtil.Application) .AddSingleton() - .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddTransient(); diff --git a/RhSolutions.AddIn/Protos/product.proto b/RhSolutions.AddIn/Protos/product.proto new file mode 100644 index 0000000..07b5de9 --- /dev/null +++ b/RhSolutions.AddIn/Protos/product.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option csharp_namespace = "RhSolutions.Services"; + +service ProductSearch { + rpc GetProduct (ProductRequest) returns (ProductReply); +} + +message ProductRequest { + string query = 1; +} + +message ProductReply { + string id = 1; + string name = 2; + double price = 3; +} \ No newline at end of file diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj index ff5db43..758f749 100644 --- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj +++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj @@ -32,6 +32,12 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -44,4 +50,7 @@ + + + \ No newline at end of file diff --git a/RhSolutions.AddIn/Services/DatabaseClient.cs b/RhSolutions.AddIn/Services/DatabaseClient.cs deleted file mode 100644 index 3036e51..0000000 --- a/RhSolutions.AddIn/Services/DatabaseClient.cs +++ /dev/null @@ -1,96 +0,0 @@ -using Microsoft.Extensions.Caching.Memory; -using Newtonsoft.Json; -using System.Web; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http.Extensions; - -namespace RhSolutions.Services; - -public class DatabaseClient : IDatabaseClient -{ - private readonly HttpClient _httpClient; - private readonly IMemoryCache _memoryCache; - public HttpStatusCode StatusCode { get; private set; } - - public DatabaseClient(HttpClient httpClient, IMemoryCache memoryCache) - { - _httpClient = httpClient; - _memoryCache = memoryCache; - } - - public async Task> GetProducts(string line) - { - if (ProductSku.TryParse(line, out var skus)) - { - ProductSku sku = skus.FirstOrDefault(); - string request = @"https://rh.cebotari.ru/api/products/" + sku.ToString(); - - if (!_memoryCache.TryGetValue(sku, out IEnumerable products)) - { - var response = await _httpClient.GetAsync(request); - - try - { - response.EnsureSuccessStatusCode(); - string json = await response.Content.ReadAsStringAsync(); - products = JsonConvert.DeserializeObject>(json) ?? Enumerable.Empty(); - } - catch - { - StatusCode = response.StatusCode; - return Enumerable.Empty(); - } - - var cacheEntryOptions = new MemoryCacheEntryOptions() - .SetSlidingExpiration(TimeSpan.FromHours(1)); - _memoryCache.Set(sku, products, cacheEntryOptions); - return products; - } - else - { - return products; - } - } - - else - { - QueryBuilder qb = new() - { - {"query", line} - }; - string request = @"https://rh.cebotari.ru/api/search" + qb.ToQueryString(); - - if (!_memoryCache.TryGetValue(line, out IEnumerable products)) - { - var response = await _httpClient.GetAsync(request); - - try - { - response.EnsureSuccessStatusCode(); - string json = await response.Content.ReadAsStringAsync(); - products = JsonConvert.DeserializeObject>(json) ?? Enumerable.Empty(); - } - catch - { - StatusCode = response.StatusCode; - return Enumerable.Empty(); - } - - var cacheEntryOptions = new MemoryCacheEntryOptions() - .SetSlidingExpiration(TimeSpan.FromHours(1)); - _memoryCache.Set(line, products, cacheEntryOptions); - if (products.Any()) - { - _memoryCache.Set(products.First(), products, cacheEntryOptions); - } - return products; - } - else - { - return products; - } - } - } -} \ No newline at end of file diff --git a/RhSolutions.AddIn/Services/GrpcClient.cs b/RhSolutions.AddIn/Services/GrpcClient.cs new file mode 100644 index 0000000..7219d11 --- /dev/null +++ b/RhSolutions.AddIn/Services/GrpcClient.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace RhSolutions.Services; + +public class GrpcClient : IDatabaseClient +{ + public async Task> GetProducts(string query) + { + var reply = await RhSolutionsAddIn.GrpcClient + .GetProductAsync(new ProductRequest() { Query = query }); + return new[] { new Product(reply.Id) { Name = reply.Name, Price = (decimal)reply.Price } }; + } +} diff --git a/RhSolutions.AddIn/app.config b/RhSolutions.AddIn/app.config index eaef242..c789b25 100644 --- a/RhSolutions.AddIn/app.config +++ b/RhSolutions.AddIn/app.config @@ -1,19 +1,26 @@  - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +