From a2b1d2e0c98bb59626bd6555e5c3898b18a046a9 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Thu, 12 Dec 2024 17:05:47 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D0=B9=20=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BE=D1=82=20=D1=81=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/DataSourceSystemController.cs | 51 ++++++++++++ .../Clients/DataSourceSystemClient.cs | 35 ++++++++ .../Interfaces/IDataSourceSystemClient.cs | 25 ++++++ .../Clients/Interfaces/ITechMessagesClient.cs | 2 +- .../Refit/IRefitDataSourceSystemClient.cs | 14 ++++ .../Refit/IRefitTechMessagesClient.cs | 2 +- .../Clients/TechMessagesClient.cs | 4 +- .../PersistenceClientFactory.cs | 14 ++++ Persistence.Client/Readme.md | 1 + ...{DrillingSystem.cs => DataSourceSystem.cs} | 8 +- Persistence.Database/Entity/TechMessage.cs | 4 +- Persistence.Database/PersistenceDbContext.cs | 2 + .../DataSourceSystemControllerTest.cs | 82 +++++++++++++++++++ .../Controllers/TechMessagesControllerTest.cs | 12 +-- Persistence.Repository/DependencyInjection.cs | 3 +- .../DataSourceSystemRepository.cs | 53 ++++++++++++ .../Repositories/TechMessagesRepository.cs | 14 ++-- ...ingSystemDto.cs => DataSourceSystemDto.cs} | 6 +- .../IDataSourceSystemRepository.cs | 22 +++++ .../Repositories/ITechMessagesRepository.cs | 2 +- 20 files changed, 328 insertions(+), 28 deletions(-) create mode 100644 Persistence.API/Controllers/DataSourceSystemController.cs create mode 100644 Persistence.Client/Clients/DataSourceSystemClient.cs create mode 100644 Persistence.Client/Clients/Interfaces/IDataSourceSystemClient.cs create mode 100644 Persistence.Client/Clients/Interfaces/Refit/IRefitDataSourceSystemClient.cs rename Persistence.Database/Entity/{DrillingSystem.cs => DataSourceSystem.cs} (63%) create mode 100644 Persistence.IntegrationTests/Controllers/DataSourceSystemControllerTest.cs create mode 100644 Persistence.Repository/Repositories/DataSourceSystemRepository.cs rename Persistence/Models/{DrillingSystemDto.cs => DataSourceSystemDto.cs} (70%) create mode 100644 Persistence/Repositories/IDataSourceSystemRepository.cs diff --git a/Persistence.API/Controllers/DataSourceSystemController.cs b/Persistence.API/Controllers/DataSourceSystemController.cs new file mode 100644 index 0000000..599c11e --- /dev/null +++ b/Persistence.API/Controllers/DataSourceSystemController.cs @@ -0,0 +1,51 @@ +using System.Net; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Persistence.Models; +using Persistence.Repositories; + +namespace Persistence.API.Controllers; + +/// +/// Работа с системами +/// +[ApiController] +[Authorize] +[Route("api/[controller]")] +public class DataSourceSystemController : ControllerBase +{ + private readonly IDataSourceSystemRepository dataSourceSystemRepository; + + public DataSourceSystemController(IDataSourceSystemRepository dataSourceSystemRepository) + { + this.dataSourceSystemRepository = dataSourceSystemRepository; + } + + /// + /// Получить системы + /// + /// + /// + [HttpGet] + public async Task> Get(CancellationToken token) + { + var result = await dataSourceSystemRepository.Get(token); + + return Ok(result); + } + + /// + /// Добавить систему + /// + /// + /// + /// + [HttpPost] + [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] + public async Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token) + { + await dataSourceSystemRepository.Add(dataSourceSystemDto, token); + + return CreatedAtAction(nameof(Add), true); + } +} diff --git a/Persistence.Client/Clients/DataSourceSystemClient.cs b/Persistence.Client/Clients/DataSourceSystemClient.cs new file mode 100644 index 0000000..fbec180 --- /dev/null +++ b/Persistence.Client/Clients/DataSourceSystemClient.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Logging; +using Persistence.Client.Clients.Base; +using Persistence.Client.Clients.Interfaces; +using Persistence.Client.Clients.Interfaces.Refit; +using Persistence.Models; + +namespace Persistence.Client.Clients; +public class DataSourceSystemClient : BaseClient, IDataSourceSystemClient +{ + private readonly IRefitDataSourceSystemClient dataSourceSystemClient; + + public DataSourceSystemClient(IRefitDataSourceSystemClient dataSourceSystemClient, ILogger logger) : base(logger) + { + this.dataSourceSystemClient = dataSourceSystemClient; + } + + public async Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token) + { + await ExecutePostResponse( + async () => await dataSourceSystemClient.Add(dataSourceSystemDto, token), token); + } + + public async Task> Get(CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await dataSourceSystemClient.Get(token), token); + + return result; + } + + public void Dispose() + { + dataSourceSystemClient.Dispose(); + } +} diff --git a/Persistence.Client/Clients/Interfaces/IDataSourceSystemClient.cs b/Persistence.Client/Clients/Interfaces/IDataSourceSystemClient.cs new file mode 100644 index 0000000..fc25412 --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/IDataSourceSystemClient.cs @@ -0,0 +1,25 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients.Interfaces; + +/// +/// Клиент для работы с системами +/// +public interface IDataSourceSystemClient : IDisposable +{ + /// + /// Получить системы + /// + /// + /// + Task> Get(CancellationToken token); + + /// + /// Добавить систему + /// + /// + /// + /// + Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token); +} diff --git a/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs b/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs index ce8a7ca..3cd0d92 100644 --- a/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs +++ b/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs @@ -54,5 +54,5 @@ public interface ITechMessagesClient : IDisposable /// /// /// - Task> GetSystems(CancellationToken token); + Task> GetSystems(CancellationToken token); } \ No newline at end of file diff --git a/Persistence.Client/Clients/Interfaces/Refit/IRefitDataSourceSystemClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitDataSourceSystemClient.cs new file mode 100644 index 0000000..ba20504 --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitDataSourceSystemClient.cs @@ -0,0 +1,14 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients.Interfaces.Refit; +public interface IRefitDataSourceSystemClient : IDisposable +{ + private const string BaseRoute = "/api/dataSourceSystem"; + + [Get($"{BaseRoute}")] + Task>> Get(CancellationToken token); + + [Post($"{BaseRoute}")] + Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token); +} diff --git a/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs index 138a0cd..6937ff7 100644 --- a/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs @@ -16,7 +16,7 @@ namespace Persistence.Client.Clients.Interfaces.Refit Task> AddRange(Guid systemId, [Body] IEnumerable dtos, CancellationToken token); [Get($"{BaseRoute}/systems")] - Task>> GetSystems(CancellationToken token); + Task>> GetSystems(CancellationToken token); [Get($"{BaseRoute}/range")] Task> GetDatesRangeAsync(CancellationToken token); diff --git a/Persistence.Client/Clients/TechMessagesClient.cs b/Persistence.Client/Clients/TechMessagesClient.cs index 7950784..d097451 100644 --- a/Persistence.Client/Clients/TechMessagesClient.cs +++ b/Persistence.Client/Clients/TechMessagesClient.cs @@ -32,9 +32,9 @@ public class TechMessagesClient : BaseClient, ITechMessagesClient return result; } - public async Task> GetSystems(CancellationToken token) + public async Task> GetSystems(CancellationToken token) { - var result = await ExecuteGetResponse>( + var result = await ExecuteGetResponse>( async () => await refitTechMessagesClient.GetSystems(token), token); return result; diff --git a/Persistence.Client/PersistenceClientFactory.cs b/Persistence.Client/PersistenceClientFactory.cs index c77ac04..5374e21 100644 --- a/Persistence.Client/PersistenceClientFactory.cs +++ b/Persistence.Client/PersistenceClientFactory.cs @@ -128,5 +128,19 @@ namespace Persistence.Client return client; } + + /// + /// Получить клиент для работы c системами + /// + /// + public IDataSourceSystemClient GetDataSourceSystemClient() + { + var logger = provider.GetRequiredService>(); + + var restClient = RestService.For(httpClient, RefitSettings); + var client = new DataSourceSystemClient(restClient, logger); + + return client; + } } } diff --git a/Persistence.Client/Readme.md b/Persistence.Client/Readme.md index e9f4024..f7c35f6 100644 --- a/Persistence.Client/Readme.md +++ b/Persistence.Client/Readme.md @@ -15,6 +15,7 @@ Persistence сервисом посредством обращения к кон - `ITimestampedSetClient` - Клиент для работы с данными с отметкой времени - `IChangeLogClient` - Клиент для работы с записями ChangeLog - `IWitsDataClient` - Клиент для работы с параметрами Wits +- `IDataSourceSystemClient` - Клиент для работы с системами ## Использование Для получения того или иного Persistence - клиента нужно diff --git a/Persistence.Database/Entity/DrillingSystem.cs b/Persistence.Database/Entity/DataSourceSystem.cs similarity index 63% rename from Persistence.Database/Entity/DrillingSystem.cs rename to Persistence.Database/Entity/DataSourceSystem.cs index 6588fb0..a0bf0c7 100644 --- a/Persistence.Database/Entity/DrillingSystem.cs +++ b/Persistence.Database/Entity/DataSourceSystem.cs @@ -3,14 +3,14 @@ using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; namespace Persistence.Database.Entity; -public class DrillingSystem +public class DataSourceSystem { - [Key, Comment("Id системы автобурения")] + [Key, Comment("Id системы")] public Guid SystemId { get; set; } - [Required, Column(TypeName = "varchar(256)"), Comment("Наименование системы автобурения")] + [Required, Column(TypeName = "varchar(256)"), Comment("Наименование системы")] public required string Name { get; set; } - [Comment("Описание системы автобурения")] + [Comment("Описание системы")] public string? Description { get; set; } } diff --git a/Persistence.Database/Entity/TechMessage.cs b/Persistence.Database/Entity/TechMessage.cs index 5c8b534..6abe718 100644 --- a/Persistence.Database/Entity/TechMessage.cs +++ b/Persistence.Database/Entity/TechMessage.cs @@ -21,8 +21,8 @@ namespace Persistence.Database.Entity [Required, Comment("Id системы, к которой относится сообщение")] public required Guid SystemId { get; set; } - [Required, ForeignKey(nameof(SystemId)), Comment("Система автобурения, к которой относится сообщение")] - public virtual required DrillingSystem System { get; set; } + [Required, ForeignKey(nameof(SystemId)), Comment("Система, к которой относится сообщение")] + public virtual required DataSourceSystem System { get; set; } [Comment("Статус события")] public int EventState { get; set; } diff --git a/Persistence.Database/PersistenceDbContext.cs b/Persistence.Database/PersistenceDbContext.cs index 849865d..6e6c8ec 100644 --- a/Persistence.Database/PersistenceDbContext.cs +++ b/Persistence.Database/PersistenceDbContext.cs @@ -21,6 +21,8 @@ public class PersistenceDbContext : DbContext public DbSet ParameterData => Set(); + public DbSet DataSourceSystem => Set(); + public PersistenceDbContext(DbContextOptions options) : base(options) { diff --git a/Persistence.IntegrationTests/Controllers/DataSourceSystemControllerTest.cs b/Persistence.IntegrationTests/Controllers/DataSourceSystemControllerTest.cs new file mode 100644 index 0000000..8638e90 --- /dev/null +++ b/Persistence.IntegrationTests/Controllers/DataSourceSystemControllerTest.cs @@ -0,0 +1,82 @@ +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client; +using Persistence.Client.Clients; +using Persistence.Client.Clients.Interfaces; +using Persistence.Database.Entity; +using Persistence.Models; +using Xunit; + +namespace Persistence.IntegrationTests.Controllers +{ + public class DataSourceSystemControllerTest : BaseIntegrationTest + { + private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey"; + private readonly IDataSourceSystemClient dataSourceSystemClient; + private readonly IMemoryCache memoryCache; + public DataSourceSystemControllerTest(WebAppFactoryFixture factory) : base(factory) + { + var scope = factory.Services.CreateScope(); + var persistenceClientFactory = scope.ServiceProvider + .GetRequiredService(); + + dataSourceSystemClient = persistenceClientFactory.GetDataSourceSystemClient(); + memoryCache = scope.ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task Get_returns_success() + { + //arrange + memoryCache.Remove(SystemCacheKey); + dbContext.CleanupDbSet(); + + //act + var response = await dataSourceSystemClient.Get(CancellationToken.None); + + //assert + Assert.NotNull(response); + Assert.Empty(response); + } + + [Fact] + public async Task Get_AfterSave_returns_success() + { + //arrange + await Add(); + + //act + var response = await dataSourceSystemClient.Get(CancellationToken.None); + + //assert + Assert.NotNull(response); + + var expectedSystemCount = 1; + var actualSystemCount = response!.Count(); + Assert.Equal(expectedSystemCount, actualSystemCount); + } + + [Fact] + public async Task Add_returns_success() + { + await Add(); + } + + private async Task Add() + { + //arrange + memoryCache.Remove(SystemCacheKey); + dbContext.CleanupDbSet(); + + var dto = new DataSourceSystemDto() + { + SystemId = Guid.NewGuid(), + Name = "Test", + Description = "Test" + }; + + //act + await dataSourceSystemClient.Add(dto, CancellationToken.None); + } + } +} diff --git a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs index 6ad95b3..4d191a6 100644 --- a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs @@ -12,7 +12,7 @@ namespace Persistence.IntegrationTests.Controllers { public class TechMessagesControllerTest : BaseIntegrationTest { - private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DrillingSystem).FullName}CacheKey"; + private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey"; private readonly ITechMessagesClient techMessagesClient; private readonly IMemoryCache memoryCache; public TechMessagesControllerTest(WebAppFactoryFixture factory) : base(factory) @@ -31,7 +31,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange memoryCache.Remove(SystemCacheKey); dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); var requestDto = new PaginationRequest() { @@ -113,7 +113,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange memoryCache.Remove(SystemCacheKey); dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); //act var response = await techMessagesClient.GetSystems(CancellationToken.None); @@ -144,7 +144,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange memoryCache.Remove(SystemCacheKey); dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); var imortantIds = new [] { 1 }; var systemIds = new [] { Guid.NewGuid() }; @@ -184,7 +184,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange memoryCache.Remove(SystemCacheKey); dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); //act var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None); @@ -246,7 +246,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange memoryCache.Remove(SystemCacheKey); dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); var dtos = new List() { diff --git a/Persistence.Repository/DependencyInjection.cs b/Persistence.Repository/DependencyInjection.cs index 7a96217..b694775 100644 --- a/Persistence.Repository/DependencyInjection.cs +++ b/Persistence.Repository/DependencyInjection.cs @@ -35,7 +35,8 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); - return services; + return services; } } diff --git a/Persistence.Repository/Repositories/DataSourceSystemRepository.cs b/Persistence.Repository/Repositories/DataSourceSystemRepository.cs new file mode 100644 index 0000000..174a1af --- /dev/null +++ b/Persistence.Repository/Repositories/DataSourceSystemRepository.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Mapster; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json.Linq; +using Persistence.Database.Entity; +using Persistence.Models; +using Persistence.Repositories; + +namespace Persistence.Repository.Repositories; +public class DataSourceSystemRepository : IDataSourceSystemRepository +{ + private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey"; + private DbContext db; + private readonly IMemoryCache memoryCache; + private const int CacheExpirationInMinutes = 60; + public DataSourceSystemRepository(DbContext db, IMemoryCache memoryCache) + { + this.db = db; + this.memoryCache = memoryCache; + } + protected virtual IQueryable GetQueryReadOnly() => db.Set(); + + public async Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token) + { + var entity = dataSourceSystemDto.Adapt(); + + await db.Set().AddAsync(entity); + await db.SaveChangesAsync(token); + + memoryCache.Remove(SystemCacheKey); + } + + public async Task> Get(CancellationToken token) + { + var systems = await memoryCache.GetOrCreateAsync(SystemCacheKey, async f => + { + f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(CacheExpirationInMinutes); + + var query = GetQueryReadOnly(); + var entities = await query.ToListAsync(token); + var dtos = entities.Select(e => e.Adapt()); + + return dtos; + }); + + return systems ?? []; + } +} diff --git a/Persistence.Repository/Repositories/TechMessagesRepository.cs b/Persistence.Repository/Repositories/TechMessagesRepository.cs index 3779892..f2fa333 100644 --- a/Persistence.Repository/Repositories/TechMessagesRepository.cs +++ b/Persistence.Repository/Repositories/TechMessagesRepository.cs @@ -12,7 +12,7 @@ namespace Persistence.Repository.Repositories { public class TechMessagesRepository : ITechMessagesRepository { - private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DrillingSystem).FullName}CacheKey"; + private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey"; private const int CacheExpirationInMinutes = 60; private readonly IMemoryCache memoryCache; private DbContext db; @@ -114,15 +114,15 @@ namespace Persistence.Repository.Repositories return dtos; } - public async Task> GetSystems(CancellationToken token) + public async Task> GetSystems(CancellationToken token) { var systems = await memoryCache.GetOrCreateAsync(SystemCacheKey, async f => { f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(CacheExpirationInMinutes); - var query = db.Set(); + var query = db.Set(); var entities = await query.ToListAsync(token); - var dtos = entities.Select(e => e.Adapt()); + var dtos = entities.Select(e => e.Adapt()); return dtos; }); @@ -156,15 +156,15 @@ namespace Persistence.Repository.Repositories if (system == null) { - system = new DrillingSystemDto() + system = new DataSourceSystemDto() { SystemId = systemId, Name = string.Empty }; - var entity = system.Adapt(); + var entity = system.Adapt(); - await db.Set().AddAsync(entity); + await db.Set().AddAsync(entity); await db.SaveChangesAsync(token); memoryCache.Remove(SystemCacheKey); diff --git a/Persistence/Models/DrillingSystemDto.cs b/Persistence/Models/DataSourceSystemDto.cs similarity index 70% rename from Persistence/Models/DrillingSystemDto.cs rename to Persistence/Models/DataSourceSystemDto.cs index c2e7abc..c4af908 100644 --- a/Persistence/Models/DrillingSystemDto.cs +++ b/Persistence/Models/DataSourceSystemDto.cs @@ -1,9 +1,9 @@ namespace Persistence.Models; /// -/// Модель системы автобурения +/// Модель системы /// -public class DrillingSystemDto +public class DataSourceSystemDto { /// /// Ключ @@ -13,7 +13,7 @@ public class DrillingSystemDto /// /// Наименование /// - public required string Name { get; set; } + public required string Name { get; set; } = string.Empty; /// /// Описание diff --git a/Persistence/Repositories/IDataSourceSystemRepository.cs b/Persistence/Repositories/IDataSourceSystemRepository.cs new file mode 100644 index 0000000..1d964eb --- /dev/null +++ b/Persistence/Repositories/IDataSourceSystemRepository.cs @@ -0,0 +1,22 @@ +using Persistence.Models; + +namespace Persistence.Repositories; + +/// +/// Интерфейс по работе с системами +/// +public interface IDataSourceSystemRepository +{ + /// + /// Добавить систему + /// + /// + /// + public Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token); + + /// + /// Получить список систем + /// + /// + public Task> Get(CancellationToken token); +} diff --git a/Persistence/Repositories/ITechMessagesRepository.cs b/Persistence/Repositories/ITechMessagesRepository.cs index c442e94..11c48fc 100644 --- a/Persistence/Repositories/ITechMessagesRepository.cs +++ b/Persistence/Repositories/ITechMessagesRepository.cs @@ -29,7 +29,7 @@ namespace Persistence.Repositories /// /// /// - Task> GetSystems(CancellationToken token); + Task> GetSystems(CancellationToken token); /// /// Получение количества сообщений по категориям и системам автобурения