Добавить хранение названий источников данных от систем

This commit is contained in:
Roman Efremov 2024-12-12 17:05:47 +05:00
parent a28c5ac2c4
commit a2b1d2e0c9
20 changed files with 328 additions and 28 deletions

View File

@ -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;
/// <summary>
/// Работа с системами
/// </summary>
[ApiController]
[Authorize]
[Route("api/[controller]")]
public class DataSourceSystemController : ControllerBase
{
private readonly IDataSourceSystemRepository dataSourceSystemRepository;
public DataSourceSystemController(IDataSourceSystemRepository dataSourceSystemRepository)
{
this.dataSourceSystemRepository = dataSourceSystemRepository;
}
/// <summary>
/// Получить системы
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult<DataSourceSystemDto>> Get(CancellationToken token)
{
var result = await dataSourceSystemRepository.Get(token);
return Ok(result);
}
/// <summary>
/// Добавить систему
/// </summary>
/// <param name="dataSourceSystemDto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
public async Task<IActionResult> Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token)
{
await dataSourceSystemRepository.Add(dataSourceSystemDto, token);
return CreatedAtAction(nameof(Add), true);
}
}

View File

@ -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<DataSourceSystemClient> 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<IEnumerable<DataSourceSystemDto>> Get(CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<DataSourceSystemDto>>(
async () => await dataSourceSystemClient.Get(token), token);
return result;
}
public void Dispose()
{
dataSourceSystemClient.Dispose();
}
}

View File

@ -0,0 +1,25 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с системами
/// </summary>
public interface IDataSourceSystemClient : IDisposable
{
/// <summary>
/// Получить системы
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<DataSourceSystemDto>> Get(CancellationToken token);
/// <summary>
/// Добавить систему
/// </summary>
/// <param name="dataSourceSystemDto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token);
}

View File

@ -54,5 +54,5 @@ public interface ITechMessagesClient : IDisposable
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<DrillingSystemDto>> GetSystems(CancellationToken token);
Task<IEnumerable<DataSourceSystemDto>> GetSystems(CancellationToken token);
}

View File

@ -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<IApiResponse<IEnumerable<DataSourceSystemDto>>> Get(CancellationToken token);
[Post($"{BaseRoute}")]
Task<IApiResponse> Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token);
}

View File

@ -16,7 +16,7 @@ namespace Persistence.Client.Clients.Interfaces.Refit
Task<IApiResponse<int>> AddRange(Guid systemId, [Body] IEnumerable<TechMessageDto> dtos, CancellationToken token);
[Get($"{BaseRoute}/systems")]
Task<IApiResponse<IEnumerable<DrillingSystemDto>>> GetSystems(CancellationToken token);
Task<IApiResponse<IEnumerable<DataSourceSystemDto>>> GetSystems(CancellationToken token);
[Get($"{BaseRoute}/range")]
Task<IApiResponse<DatesRangeDto>> GetDatesRangeAsync(CancellationToken token);

View File

@ -32,9 +32,9 @@ public class TechMessagesClient : BaseClient, ITechMessagesClient
return result;
}
public async Task<IEnumerable<DrillingSystemDto>> GetSystems(CancellationToken token)
public async Task<IEnumerable<DataSourceSystemDto>> GetSystems(CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<DrillingSystemDto>>(
var result = await ExecuteGetResponse<IEnumerable<DataSourceSystemDto>>(
async () => await refitTechMessagesClient.GetSystems(token), token);
return result;

View File

@ -128,5 +128,19 @@ namespace Persistence.Client
return client;
}
/// <summary>
/// Получить клиент для работы c системами
/// </summary>
/// <returns></returns>
public IDataSourceSystemClient GetDataSourceSystemClient()
{
var logger = provider.GetRequiredService<ILogger<DataSourceSystemClient>>();
var restClient = RestService.For<IRefitDataSourceSystemClient>(httpClient, RefitSettings);
var client = new DataSourceSystemClient(restClient, logger);
return client;
}
}
}

View File

@ -15,6 +15,7 @@ Persistence сервисом посредством обращения к кон
- `ITimestampedSetClient` - Клиент для работы с данными с отметкой времени
- `IChangeLogClient` - Клиент для работы с записями ChangeLog
- `IWitsDataClient` - Клиент для работы с параметрами Wits
- `IDataSourceSystemClient` - Клиент для работы с системами
## Использование
Для получения того или иного Persistence - клиента нужно

View File

@ -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; }
}

View File

@ -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; }

View File

@ -21,6 +21,8 @@ public class PersistenceDbContext : DbContext
public DbSet<ParameterData> ParameterData => Set<ParameterData>();
public DbSet<DataSourceSystem> DataSourceSystem => Set<DataSourceSystem>();
public PersistenceDbContext(DbContextOptions options)
: base(options)
{

View File

@ -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<PersistenceClientFactory>();
dataSourceSystemClient = persistenceClientFactory.GetDataSourceSystemClient();
memoryCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
}
[Fact]
public async Task Get_returns_success()
{
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<DataSourceSystem>();
//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<DataSourceSystem>();
var dto = new DataSourceSystemDto()
{
SystemId = Guid.NewGuid(),
Name = "Test",
Description = "Test"
};
//act
await dataSourceSystemClient.Add(dto, CancellationToken.None);
}
}
}

View File

@ -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<TechMessage>();
dbContext.CleanupDbSet<Database.Entity.DrillingSystem>();
dbContext.CleanupDbSet<DataSourceSystem>();
var requestDto = new PaginationRequest()
{
@ -113,7 +113,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<TechMessage>();
dbContext.CleanupDbSet<Database.Entity.DrillingSystem>();
dbContext.CleanupDbSet<Database.Entity.DataSourceSystem>();
//act
var response = await techMessagesClient.GetSystems(CancellationToken.None);
@ -144,7 +144,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<TechMessage>();
dbContext.CleanupDbSet<Database.Entity.DrillingSystem>();
dbContext.CleanupDbSet<Database.Entity.DataSourceSystem>();
var imortantIds = new [] { 1 };
var systemIds = new [] { Guid.NewGuid() };
@ -184,7 +184,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<TechMessage>();
dbContext.CleanupDbSet<DrillingSystem>();
dbContext.CleanupDbSet<DataSourceSystem>();
//act
var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None);
@ -246,7 +246,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<TechMessage>();
dbContext.CleanupDbSet<DrillingSystem>();
dbContext.CleanupDbSet<DataSourceSystem>();
var dtos = new List<TechMessageDto>()
{

View File

@ -35,7 +35,8 @@ public static class DependencyInjection
services.AddTransient<ITimestampedSetRepository, TimestampedSetRepository>();
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
services.AddTransient<IParameterRepository, ParameterRepository>();
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemRepository>();
return services;
return services;
}
}

View File

@ -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<DataSourceSystem> GetQueryReadOnly() => db.Set<DataSourceSystem>();
public async Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token)
{
var entity = dataSourceSystemDto.Adapt<DataSourceSystem>();
await db.Set<DataSourceSystem>().AddAsync(entity);
await db.SaveChangesAsync(token);
memoryCache.Remove(SystemCacheKey);
}
public async Task<IEnumerable<DataSourceSystemDto>> 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<DataSourceSystemDto>());
return dtos;
});
return systems ?? [];
}
}

View File

@ -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<IEnumerable<DrillingSystemDto>> GetSystems(CancellationToken token)
public async Task<IEnumerable<DataSourceSystemDto>> GetSystems(CancellationToken token)
{
var systems = await memoryCache.GetOrCreateAsync(SystemCacheKey, async f =>
{
f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(CacheExpirationInMinutes);
var query = db.Set<Database.Entity.DrillingSystem>();
var query = db.Set<Database.Entity.DataSourceSystem>();
var entities = await query.ToListAsync(token);
var dtos = entities.Select(e => e.Adapt<Models.DrillingSystemDto>());
var dtos = entities.Select(e => e.Adapt<Models.DataSourceSystemDto>());
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<DrillingSystem>();
var entity = system.Adapt<DataSourceSystem>();
await db.Set<Database.Entity.DrillingSystem>().AddAsync(entity);
await db.Set<Database.Entity.DataSourceSystem>().AddAsync(entity);
await db.SaveChangesAsync(token);
memoryCache.Remove(SystemCacheKey);

View File

@ -1,9 +1,9 @@
namespace Persistence.Models;
/// <summary>
/// Модель системы автобурения
/// Модель системы
/// </summary>
public class DrillingSystemDto
public class DataSourceSystemDto
{
/// <summary>
/// Ключ
@ -13,7 +13,7 @@ public class DrillingSystemDto
/// <summary>
/// Наименование
/// </summary>
public required string Name { get; set; }
public required string Name { get; set; } = string.Empty;
/// <summary>
/// Описание

View File

@ -0,0 +1,22 @@
using Persistence.Models;
namespace Persistence.Repositories;
/// <summary>
/// Интерфейс по работе с системами
/// </summary>
public interface IDataSourceSystemRepository
{
/// <summary>
/// Добавить систему
/// </summary>
/// <param name="dataSourceSystemDto"></param>
/// <returns></returns>
public Task Add(DataSourceSystemDto dataSourceSystemDto, CancellationToken token);
/// <summary>
/// Получить список систем
/// </summary>
/// <returns></returns>
public Task<IEnumerable<DataSourceSystemDto>> Get(CancellationToken token);
}

View File

@ -29,7 +29,7 @@ namespace Persistence.Repositories
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<DrillingSystemDto>> GetSystems(CancellationToken token);
Task<IEnumerable<DataSourceSystemDto>> GetSystems(CancellationToken token);
/// <summary>
/// Получение количества сообщений по категориям и системам автобурения