Merge pull request '#577 Расширить фабрику клиентов Persistance' (#8) from ClientFactory into master

Reviewed-on: #8
This commit is contained in:
on.nemtina 2024-12-13 09:43:39 +05:00
commit 3df736fdc9
44 changed files with 1620 additions and 629 deletions

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Persistence.Models; using Persistence.Models;
using Persistence.Repositories; using Persistence.Repositories;

View File

@ -0,0 +1,62 @@
using Microsoft.Extensions.Logging;
using Persistence.Client.Helpers;
using Refit;
namespace Persistence.Client.Clients.Base;
public abstract class BaseClient
{
private readonly ILogger logger;
public BaseClient(ILogger<BaseClient> logger)
{
this.logger = logger;
}
public async Task<T> ExecuteGetResponse<T>(Func<Task<IApiResponse<T>>> getMethod, CancellationToken token)
{
var response = await getMethod.Invoke().WaitAsync(token);
if (response.IsSuccessful)
{
return response.Content;
}
var exception = response.GetPersistenceException();
logger.LogError(exception.Message);
throw exception;
}
public async Task ExecutePostResponse(Func<Task<IApiResponse>> postMethod, CancellationToken token)
{
var response = await postMethod.Invoke().WaitAsync(token);
if (response.IsSuccessful)
{
return;
}
var exception = response.GetPersistenceException();
logger.LogError(exception.Message);
throw exception;
}
public async Task<int> ExecutePostResponse(Func<Task<IApiResponse<int>>> postMethod, CancellationToken token)
{
var response = await postMethod.Invoke().WaitAsync(token);
if (response.IsSuccessful)
{
return response.Content;
}
var exception = response.GetPersistenceException();
logger.LogError(exception.Message);
throw exception;
}
}

View File

@ -0,0 +1,102 @@
using Microsoft.Extensions.Logging;
using Persistence.Client.Clients.Base;
using Persistence.Client.Clients.Interfaces;
using Persistence.Models;
using Persistence.Models.Requests;
namespace Persistence.Client.Clients;
public class ChangeLogClient : BaseClient, IChangeLogClient
{
private readonly Interfaces.Refit.IRefitChangeLogClient refitChangeLogClient;
public ChangeLogClient(Interfaces.Refit.IRefitChangeLogClient refitChangeLogClient, ILogger<ChangeLogClient> logger) : base(logger)
{
this.refitChangeLogClient = refitChangeLogClient;
}
public async Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
{
var result = await ExecuteGetResponse<int>(
async () => await refitChangeLogClient.ClearAndAddRange(idDiscriminator, dtos, token), token);
return result;
}
public async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment,
SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token)
{
var result = await ExecuteGetResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>(
async () => await refitChangeLogClient.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token), token);
return result;
}
public async Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<ChangeLogDto>>(
async () => await refitChangeLogClient.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, token), token);
return result;
}
public async Task<int> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.Add(idDiscriminator, dto, token), token);
return result;
}
public async Task<int> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.AddRange(idDiscriminator, dtos, token), token);
return result;
}
public async Task<int> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.Update(dto, token), token);
return result;
}
public async Task<int> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.UpdateRange(dtos, token), token);
return result;
}
public async Task<int> Delete(Guid id, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.Delete(id, token), token);
return result;
}
public async Task<int> DeleteRange(IEnumerable<Guid> ids, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitChangeLogClient.DeleteRange(ids, token), token);
return result;
}
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto?>(
async () => await refitChangeLogClient.GetDatesRange(idDiscriminator, token), token);
return result;
}
public void Dispose()
{
refitChangeLogClient.Dispose();
}
}

View File

@ -1,106 +0,0 @@
using Persistence.Models;
using Persistence.Models.Requests;
using Refit;
namespace Persistence.Client.Clients;
/// <summary>
/// Интерфейс для тестирования API, предназначенного для работы с записями ChangeLod
/// </summary>
public interface IChangeLogClient
{
private const string BaseRoute = "/api/ChangeLog";
/// <summary>
/// Импорт с заменой: удаление старых строк и добавление новых
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param>
/// <returns></returns>
[Post($"{BaseRoute}/replace/{{idDiscriminator}}")]
Task<IApiResponse<int>> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos);
/// <summary>
/// Получение актуальных данных на определенную дату (с пагинацией)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="moment"></param>
/// <param name="filterRequest">параметры запроса фильтрации</param>
/// <param name="paginationRequest">параметры запроса пагинации</param>
/// <returns></returns>
[Get($"{BaseRoute}/moment/{{idDiscriminator}}")]
Task<IApiResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>> GetByDate(
Guid idDiscriminator,
DateTimeOffset moment,
[Query] SectionPartRequest filterRequest,
[Query] PaginationRequest paginationRequest);
/// <summary>
/// Получение исторических данных за определенный период времени
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dateBegin"></param>
/// <param name="dateEnd"></param>
/// <returns></returns>
[Get($"{BaseRoute}/history/{{idDiscriminator}}")]
Task<IApiResponse<IEnumerable<ChangeLogDto>>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd);
/// <summary>
/// Добавить одну запись
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dto"></param>
/// <returns></returns>
[Post($"{BaseRoute}/{{idDiscriminator}}")]
Task<IApiResponse<int>> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto);
/// <summary>
/// Добавить несколько записей
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param>
/// <returns></returns>
[Post($"{BaseRoute}/range/{{idDiscriminator}}")]
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos);
/// <summary>
/// Обновить одну запись
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[Put($"{BaseRoute}")]
Task<IApiResponse<int>> Update(DataWithWellDepthAndSectionDto dto);
/// <summary>
/// Обновить несколько записей
/// </summary>
/// <param name="dtos"></param>
/// <returns></returns>
[Put($"{BaseRoute}/range")]
Task<IApiResponse<int>> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos);
/// <summary>
/// Удалить одну запись
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[Delete($"{BaseRoute}")]
Task<IApiResponse<int>> Delete(Guid id);
/// <summary>
/// Удалить несколько записей
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
[Delete($"{BaseRoute}/range")]
Task<IApiResponse<int>> DeleteRange([Body] IEnumerable<Guid> ids);
/// <summary>
/// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <returns></returns>
[Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator);
}

View File

@ -1,21 +0,0 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients;
public interface ITimeSeriesClient<TDto>
where TDto : class, new()
{
private const string BaseRoute = "/api/dataSaub";
[Post($"{BaseRoute}")]
Task<IApiResponse<int>> AddRange(IEnumerable<TDto> dtos);
[Get($"{BaseRoute}")]
Task<IApiResponse<IEnumerable<TDto>>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd);
[Get($"{BaseRoute}/resampled")]
Task<IApiResponse<IEnumerable<TDto>>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024);
[Get($"{BaseRoute}/datesRange")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange();
}

View File

@ -1,62 +0,0 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients;
/// <summary>
/// Клиент для работы с репозиторием для хранения разных наборов данных рядов.
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
/// </summary>
public interface ITimestampedSetClient
{
private const string baseUrl = "/api/TimestampedSet/{idDiscriminator}";
/// <summary>
/// Добавление новых данных
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="sets"></param>
/// <returns></returns>
[Post(baseUrl)]
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets);
/// <summary>
/// Получение данных с фильтрацией. Значение фильтра null - отключен
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="geTimestamp">Фильтр позднее даты</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <returns></returns>
[Get(baseUrl)]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable<string>? columnNames, int skip, int take);
/// <summary>
/// Получить последние данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="take"></param>
/// <returns></returns>
[Get($"{baseUrl}/last")]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> GetLast(Guid idDiscriminator, [Query] IEnumerable<string>? columnNames, int take);
/// <summary>
/// Количество записей по указанному набору в БД. Для пагинации.
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <returns></returns>
[Get($"{baseUrl}/count")]
Task<IApiResponse<int>> Count(Guid idDiscriminator);
/// <summary>
/// Диапазон дат за которые есть данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <returns></returns>
[Get($"{baseUrl}/datesRange")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator);
}

View File

@ -0,0 +1,98 @@
using Persistence.Models;
using Persistence.Models.Requests;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с записями ChangeLog
/// </summary>
public interface IChangeLogClient : IDisposable
{
/// <summary>
/// Добавить одну запись
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token);
/// <summary>
/// Добавить несколько записей
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
/// <summary>
/// Импорт с заменой: удаление старых строк и добавление новых
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
/// <summary>
/// Удалить одну запись
/// </summary>
/// <param name="id"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> Delete(Guid id, CancellationToken token);
/// <summary>
/// Удалить несколько записей
/// </summary>
/// <param name="ids"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> DeleteRange(IEnumerable<Guid> ids, CancellationToken token);
/// <summary>
/// Получение актуальных данных на определенную дату (с пагинацией)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="moment"></param>
/// <param name="filterRequest"></param>
/// <param name="paginationRequest"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
/// <summary>
/// Получение исторических данных за определенный период времени
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dateBegin"></param>
/// <param name="dateEnd"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
/// <summary>
/// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token);
/// <summary>
/// Обновить одну запись
/// </summary>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
/// <summary>
/// Обновить несколько записей
/// </summary>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
}

View File

@ -0,0 +1,59 @@
using Persistence.Models;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с уставками
/// </summary>
public interface ISetpointClient : IDisposable
{
/// <summary>
/// Добавить уставку
/// </summary>
/// <param name="setpointKey"></param>
/// <param name="newValue"></param>
/// <param name="token"></param>
/// <returns></returns>
Task Add(Guid setpointKey, object newValue, CancellationToken token);
/// <summary>
/// Получить актуальные значения уставок
/// </summary>
/// <param name="setpointKeys"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<SetpointValueDto>> GetCurrent(IEnumerable<Guid> setpointKeys, CancellationToken token);
/// <summary>
/// Получить диапазон дат, для которых есть данные в репозитории
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token);
/// <summary>
/// Получить значения уставок за определенный момент времени
/// </summary>
/// <param name="setpointKeys"></param>
/// <param name="historyMoment"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<SetpointValueDto>> GetHistory(IEnumerable<Guid> setpointKeys, DateTimeOffset historyMoment, CancellationToken token);
/// <summary>
/// Получить историю изменений значений уставок
/// </summary>
/// <param name="setpointKeys"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLog(IEnumerable<Guid> setpointKeys, CancellationToken token);
/// <summary>
/// Получить порцию записей, начиная с заданной даты
/// </summary>
/// <param name="dateBegin"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<SetpointLogDto>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token);
}

View File

@ -0,0 +1,58 @@
using Persistence.Models;
using Persistence.Models.Requests;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с технологическими сообщениями
/// </summary>
public interface ITechMessagesClient : IDisposable
{
/// <summary>
/// Добавить новые технологические сообщения
/// </summary>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddRange(IEnumerable<TechMessageDto> dtos, CancellationToken token);
/// <summary>
/// Получить диапазон дат, для которых есть данные в репозитории
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token);
/// <summary>
/// Получить список технологических сообщений в виде страницы
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<PaginationContainer<TechMessageDto>> GetPage(PaginationRequest request, CancellationToken token);
/// <summary>
/// Получить порцию записей, начиная с заданной даты
/// </summary>
/// <param name="dateBegin"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TechMessageDto>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token);
/// <summary>
/// Получить статистику по системам
/// </summary>
/// <param name="autoDrillingSystem"></param>
/// <param name="categoryId"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<MessagesStatisticDto>> GetStatistics(string autoDrillingSystem, int categoryId, CancellationToken token);
/// <summary>
/// Получить список всех систем
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<string>> GetSystems(CancellationToken token);
}

View File

@ -0,0 +1,44 @@
using Persistence.Models;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с временными данными
/// </summary>
/// <typeparam name="TDto"></typeparam>
public interface ITimeSeriesClient<TDto> : IDisposable where TDto : class, new()
{
/// <summary>
/// Добавление записей
/// </summary>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token);
/// <summary>
/// Получить список объектов, удовлетворяющий диапазону дат
/// </summary>
/// <param name="dateBegin"></param>
/// <param name="dateEnd"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TDto>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
/// <summary>
/// Получить диапазон дат, для которых есть данные в репозитории
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRange(CancellationToken token);
/// <summary>
/// Получить список объектов с прореживанием, удовлетворяющий диапазону дат
/// </summary>
/// <param name="dateBegin"></param>
/// <param name="intervalSec"></param>
/// <param name="approxPointsCount"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TDto>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default);
}

View File

@ -0,0 +1,59 @@
using Persistence.Models;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с репозиторием для хранения разных наборов данных рядов.
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
/// </summary>
public interface ITimestampedSetClient : IDisposable
{
/// <summary>
/// Записать новые данные
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="sets"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token);
/// <summary>
/// Количество записей по указанному набору в БД. Для пагинации
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> Count(Guid idDiscriminator, CancellationToken token);
/// <summary>
/// Получение данных с фильтрацией. Значение фильтра null - отключен
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="geTimestamp"></param>
/// <param name="columnNames"></param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
/// <summary>
/// Диапазон дат за которые есть данные
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token);
/// <summary>
///
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="columnNames"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token);
}

View File

@ -0,0 +1,47 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients.Interfaces;
/// <summary>
/// Клиент для работы с параметрами Wits
/// </summary>
public interface IWitsDataClient : IDisposable
{
/// <summary>
/// Получить набор параметров (Wits) для построения графика
/// </summary>
/// <param name="discriminatorId"></param>
/// <param name="dateFrom"></param>
/// <param name="dateTo"></param>
/// <param name="approxPointsCount"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<WitsDataDto>> GetValuesForGraph(Guid discriminatorId, [Query] DateTimeOffset dateFrom, [Query] DateTimeOffset dateTo, [Query] int approxPointsCount, CancellationToken token);
/// <summary>
/// Сохранить набор параметров (Wits)
/// </summary>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token);
/// <summary>
/// Получить порцию записей, начиная с заданной даты
/// </summary>
/// <param name="discriminatorId"></param>
/// <param name="dateBegin"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<WitsDataDto>> GetPart(Guid discriminatorId, [Query] DateTimeOffset dateBegin, [Query] int take = 24 * 60 * 60, CancellationToken token = default);
/// <summary>
/// Получить диапазон дат, для которых есть данные в репозитории
/// </summary>
/// <param name="discriminatorId"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto> GetDatesRangeAsync(Guid discriminatorId, CancellationToken token);
}

View File

@ -0,0 +1,46 @@
using Persistence.Models;
using Persistence.Models.Requests;
using Refit;
namespace Persistence.Client.Clients.Interfaces.Refit;
public interface IRefitChangeLogClient : IDisposable
{
private const string BaseRoute = "/api/ChangeLog";
[Post($"{BaseRoute}/replace/{{idDiscriminator}}")]
Task<IApiResponse<int>> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
[Get($"{BaseRoute}/moment/{{idDiscriminator}}")]
Task<IApiResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>> GetByDate(
Guid idDiscriminator,
DateTimeOffset moment,
[Query] SectionPartRequest filterRequest,
[Query] PaginationRequest paginationRequest,
CancellationToken token);
[Get($"{BaseRoute}/history/{{idDiscriminator}}")]
Task<IApiResponse<IEnumerable<ChangeLogDto>>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
[Post($"{BaseRoute}/{{idDiscriminator}}")]
Task<IApiResponse<int>> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token);
[Post($"{BaseRoute}/range/{{idDiscriminator}}")]
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
[Put($"{BaseRoute}")]
Task<IApiResponse<int>> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
[Put($"{BaseRoute}/range")]
Task<IApiResponse<int>> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
[Delete($"{BaseRoute}")]
Task<IApiResponse<int>> Delete(Guid id, CancellationToken token);
[Delete($"{BaseRoute}/range")]
Task<IApiResponse<int>> DeleteRange([Body] IEnumerable<Guid> ids, CancellationToken token);
[Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator, CancellationToken token);
}

View File

@ -1,23 +1,20 @@
using Persistence.Models; using Persistence.Models;
using Refit; using Refit;
namespace Persistence.Client.Clients; namespace Persistence.Client.Clients.Interfaces.Refit;
/// <summary> public interface IRefitSetpointClient : IDisposable
/// Интерфейс клиента для работы с уставками
/// </summary>
public interface ISetpointClient
{ {
private const string BaseRoute = "/api/setpoint"; private const string BaseRoute = "/api/setpoint";
[Get($"{BaseRoute}/current")] [Get($"{BaseRoute}/current")]
Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys); Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys, CancellationToken token);
[Get($"{BaseRoute}/history")] [Get($"{BaseRoute}/history")]
Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys, [Query] DateTimeOffset historyMoment); Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys, [Query] DateTimeOffset historyMoment, CancellationToken token);
[Get($"{BaseRoute}/log")] [Get($"{BaseRoute}/log")]
Task<IApiResponse<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys); Task<IApiResponse<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys, CancellationToken token);
[Get($"{BaseRoute}/range")] [Get($"{BaseRoute}/range")]
Task<IApiResponse<DatesRangeDto>> GetDatesRangeAsync(CancellationToken token); Task<IApiResponse<DatesRangeDto>> GetDatesRangeAsync(CancellationToken token);
@ -26,5 +23,5 @@ public interface ISetpointClient
Task<IApiResponse<IEnumerable<SetpointLogDto>>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); Task<IApiResponse<IEnumerable<SetpointLogDto>>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token);
[Post($"{BaseRoute}/")] [Post($"{BaseRoute}/")]
Task<IApiResponse> Add(Guid setpointKey, object newValue); Task<IApiResponse> Add(Guid setpointKey, object newValue, CancellationToken token);
} }

View File

@ -2,12 +2,9 @@
using Persistence.Models.Requests; using Persistence.Models.Requests;
using Refit; using Refit;
namespace Persistence.Client.Clients namespace Persistence.Client.Clients.Interfaces.Refit
{ {
/// <summary> public interface IRefitTechMessagesClient : IDisposable
/// Интерфейс клиента для хранения технологических сообщений
/// </summary>
public interface ITechMessagesClient
{ {
private const string BaseRoute = "/api/techMessages"; private const string BaseRoute = "/api/techMessages";

View File

@ -0,0 +1,21 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients.Interfaces.Refit;
public interface IRefitTimeSeriesClient<TDto> : IDisposable
where TDto : class, new()
{
private const string BaseRoute = "/api/dataSaub";
[Post($"{BaseRoute}")]
Task<IApiResponse<int>> AddRange(IEnumerable<TDto> dtos, CancellationToken token);
[Get($"{BaseRoute}")]
Task<IApiResponse<IEnumerable<TDto>>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
[Get($"{BaseRoute}/resampled")]
Task<IApiResponse<IEnumerable<TDto>>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default);
[Get($"{BaseRoute}/datesRange")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(CancellationToken token);
}

View File

@ -0,0 +1,24 @@
using Persistence.Models;
using Refit;
namespace Persistence.Client.Clients.Interfaces.Refit;
public interface IRefitTimestampedSetClient : IDisposable
{
private const string baseUrl = "/api/TimestampedSet/{idDiscriminator}";
[Post(baseUrl)]
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token);
[Get(baseUrl)]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
[Get($"{baseUrl}/last")]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> GetLast(Guid idDiscriminator, [Query] IEnumerable<string>? columnNames, int take, CancellationToken token);
[Get($"{baseUrl}/count")]
Task<IApiResponse<int>> Count(Guid idDiscriminator, CancellationToken token);
[Get($"{baseUrl}/datesRange")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator, CancellationToken token);
}

View File

@ -1,8 +1,9 @@
using Persistence.Models; using Microsoft.AspNetCore.Mvc;
using Persistence.Models;
using Refit; using Refit;
namespace Persistence.Client.Clients; namespace Persistence.Client.Clients.Interfaces.Refit;
public interface IWitsDataClient public interface IRefitWitsDataClient : IDisposable
{ {
private const string BaseRoute = "/api/witsData"; private const string BaseRoute = "/api/witsData";

View File

@ -0,0 +1,68 @@
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 SetpointClient : BaseClient, ISetpointClient
{
private readonly IRefitSetpointClient refitSetpointClient;
public SetpointClient(IRefitSetpointClient refitSetpointClient, ILogger<SetpointClient> logger) : base(logger)
{
this.refitSetpointClient = refitSetpointClient;
}
public async Task<IEnumerable<SetpointValueDto>> GetCurrent(IEnumerable<Guid> setpointKeys, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<SetpointValueDto>>(
async () => await refitSetpointClient.GetCurrent(setpointKeys, token), token);
return result;
}
public async Task<IEnumerable<SetpointValueDto>> GetHistory(IEnumerable<Guid> setpointKeys, DateTimeOffset historyMoment, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<SetpointValueDto>>(
async () => await refitSetpointClient.GetHistory(setpointKeys, historyMoment, token), token);
return result;
}
public async Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLog(IEnumerable<Guid> setpointKeys, CancellationToken token)
{
var result = await ExecuteGetResponse<Dictionary<Guid, IEnumerable<SetpointLogDto>>>(
async () => await refitSetpointClient.GetLog(setpointKeys, token), token);
return result;
}
public async Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto>(
async () => await refitSetpointClient.GetDatesRangeAsync(token), token);
return result;
}
public async Task<IEnumerable<SetpointLogDto>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<SetpointLogDto>>(
async () => await refitSetpointClient.GetPart(dateBegin, take, token), token);
return result;
}
public async Task Add(Guid setpointKey, object newValue, CancellationToken token)
{
await ExecutePostResponse(
async () => await refitSetpointClient.Add(setpointKey, newValue, token), token);
}
public void Dispose()
{
refitSetpointClient.Dispose();
}
}

View File

@ -0,0 +1,71 @@
using Microsoft.Extensions.Logging;
using Persistence.Client.Clients.Base;
using Persistence.Client.Clients.Interfaces;
using Persistence.Client.Clients.Interfaces.Refit;
using Persistence.Models;
using Persistence.Models.Requests;
namespace Persistence.Client.Clients;
public class TechMessagesClient : BaseClient, ITechMessagesClient
{
private readonly IRefitTechMessagesClient refitTechMessagesClient;
public TechMessagesClient(IRefitTechMessagesClient refitTechMessagesClient, ILogger<TechMessagesClient> logger) : base(logger)
{
this.refitTechMessagesClient = refitTechMessagesClient;
}
public async Task<PaginationContainer<TechMessageDto>> GetPage(PaginationRequest request, CancellationToken token)
{
var result = await ExecuteGetResponse<PaginationContainer<TechMessageDto>>(
async () => await refitTechMessagesClient.GetPage(request, token), token);
return result;
}
public async Task<int> AddRange(IEnumerable<TechMessageDto> dtos, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitTechMessagesClient.AddRange(dtos, token), token);
return result;
}
public async Task<IEnumerable<string>> GetSystems(CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<string>>(
async () => await refitTechMessagesClient.GetSystems(token), token);
return result;
}
public async Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto>(
async () => await refitTechMessagesClient.GetDatesRangeAsync(token), token);
return result;
}
public async Task<IEnumerable<TechMessageDto>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<TechMessageDto>>(
async () => await refitTechMessagesClient.GetPart(dateBegin, take, token), token);
return result;
}
public async Task<IEnumerable<MessagesStatisticDto>> GetStatistics(string autoDrillingSystem, int categoryId, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<MessagesStatisticDto>>(
async () => await refitTechMessagesClient.GetStatistics(autoDrillingSystem, categoryId, token), token);
return result;
}
public void Dispose()
{
refitTechMessagesClient.Dispose();
}
}

View File

@ -0,0 +1,53 @@
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 TimeSeriesClient<TDto> : BaseClient, ITimeSeriesClient<TDto> where TDto : class, new()
{
private readonly IRefitTimeSeriesClient<TDto> timeSeriesClient;
public TimeSeriesClient(IRefitTimeSeriesClient<TDto> refitTechMessagesClient, ILogger<TimeSeriesClient<TDto>> logger) : base(logger)
{
this.timeSeriesClient = refitTechMessagesClient;
}
public async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await timeSeriesClient.AddRange(dtos, token), token);
return result;
}
public async Task<IEnumerable<TDto>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<TDto>>(
async () => await timeSeriesClient.Get(dateBegin, dateEnd, token), token);
return result;
}
public async Task<IEnumerable<TDto>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default)
{
var result = await ExecuteGetResponse<IEnumerable<TDto>>(
async () => await timeSeriesClient.GetResampledData(dateBegin, intervalSec, approxPointsCount, token), token);
return result;
}
public async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto?>(
async () => await timeSeriesClient.GetDatesRange(token), token);
return result;
}
public void Dispose()
{
timeSeriesClient.Dispose();
}
}

View File

@ -0,0 +1,61 @@
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 TimestampedSetClient : BaseClient, ITimestampedSetClient
{
private readonly IRefitTimestampedSetClient refitTimestampedSetClient;
public TimestampedSetClient(IRefitTimestampedSetClient refitTimestampedSetClient, ILogger<TimestampedSetClient> logger) : base(logger)
{
this.refitTimestampedSetClient = refitTimestampedSetClient;
}
public async Task<int> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitTimestampedSetClient.AddRange(idDiscriminator, sets, token), token);
return result;
}
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<TimestampedSetDto>>(
async () => await refitTimestampedSetClient.Get(idDiscriminator, geTimestamp, columnNames, skip, take, token), token);
return result;
}
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<TimestampedSetDto>>(
async () => await refitTimestampedSetClient.GetLast(idDiscriminator, columnNames, take, token), token);
return result;
}
public async Task<int> Count(Guid idDiscriminator, CancellationToken token)
{
var result = await ExecuteGetResponse<int>(
async () => await refitTimestampedSetClient.Count(idDiscriminator, token), token);
return result;
}
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto?>(
async () => await refitTimestampedSetClient.GetDatesRange(idDiscriminator, token), token);
return result;
}
public void Dispose()
{
refitTimestampedSetClient.Dispose();
}
}

View File

@ -0,0 +1,53 @@
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 WitsDataClient : BaseClient, IWitsDataClient
{
private readonly IRefitWitsDataClient refitWitsDataClient;
public WitsDataClient(IRefitWitsDataClient refitWitsDataClient, ILogger<WitsDataClient> logger) : base(logger)
{
this.refitWitsDataClient = refitWitsDataClient;
}
public async Task<int> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token)
{
var result = await ExecutePostResponse(
async () => await refitWitsDataClient.AddRange(dtos, token), token);
return result;
}
public async Task<DatesRangeDto> GetDatesRangeAsync(Guid discriminatorId, CancellationToken token)
{
var result = await ExecuteGetResponse<DatesRangeDto>(
async () => await refitWitsDataClient.GetDatesRangeAsync(discriminatorId, token), token);
return result;
}
public async Task<IEnumerable<WitsDataDto>> GetPart(Guid discriminatorId, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default)
{
var result = await ExecuteGetResponse<IEnumerable<WitsDataDto>>(
async () => await refitWitsDataClient.GetPart(discriminatorId, dateBegin, take, token), token);
return result;
}
public async Task<IEnumerable<WitsDataDto>> GetValuesForGraph(Guid discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo, int approxPointsCount, CancellationToken token)
{
var result = await ExecuteGetResponse<IEnumerable<WitsDataDto>>(
async () => await refitWitsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointsCount, token), token);
return result;
}
public void Dispose()
{
refitWitsDataClient.Dispose();
}
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Not Acceptable (406)
/// </summary>
public class AcceptableException : Exception
{
public AcceptableException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Bad gateway (502)
/// </summary>
public class BadGatewayException : Exception
{
public BadGatewayException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Forbidden (403)
/// </summary>
public class ForbiddenException : Exception
{
public ForbiddenException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Internal Server Error (500)
/// </summary>
public class InternalServerException : Exception
{
public InternalServerException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Locked (423)
/// </summary>
public class LockedException : Exception
{
public LockedException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Service Unavailable Error (503)
/// </summary>
public class ServiceUnavailableException : Exception
{
public ServiceUnavailableException(string message)
: base(message) { }
}

View File

@ -0,0 +1,10 @@
namespace Persistence.Client.CustomExceptions;
/// <summary>
/// Too Many Requests (429)
/// </summary>
public class TooManyRequestsException : Exception
{
public TooManyRequestsException(string message)
: base(message) { }
}

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Persistence.Models.Configurations; using Persistence.Models.Configurations;
using RestSharp; using RestSharp;
@ -27,6 +27,11 @@ public static class ApiTokenHelper
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
} }
public static void Authorize(this HttpClient httpClient, string jwtToken)
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
}
private static string CreateDefaultJwtToken(this AuthUser authUser) private static string CreateDefaultJwtToken(this AuthUser authUser)
{ {
var nameIdetifier = Guid.NewGuid().ToString(); var nameIdetifier = Guid.NewGuid().ToString();
@ -36,7 +41,8 @@ public static class ApiTokenHelper
new("client_id", authUser.ClientId), new("client_id", authUser.ClientId),
new("username", authUser.Username), new("username", authUser.Username),
new("password", authUser.Password), new("password", authUser.Password),
new("grant_type", authUser.GrantType) new("grant_type", authUser.GrantType),
new(ClaimTypes.NameIdentifier.ToString(), Guid.NewGuid().ToString())
}; };
var tokenDescriptor = new SecurityTokenDescriptor var tokenDescriptor = new SecurityTokenDescriptor

View File

@ -0,0 +1,35 @@
using System.ComponentModel.DataAnnotations;
using Persistence.Client.CustomExceptions;
using Refit;
namespace Persistence.Client.Helpers;
public static class ExceptionsHelper
{
private static readonly Dictionary<System.Net.HttpStatusCode, Exception> ExceptionsDictionary = new Dictionary<System.Net.HttpStatusCode, Exception>()
{
{ System.Net.HttpStatusCode.BadRequest, new ValidationException("Ошибка валидации, формата или маршрутизации запроса") },
{ System.Net.HttpStatusCode.Unauthorized, new UnauthorizedAccessException("Ошибка авторизации, клиент должен аутентифицировать себя, чтобы получить запрошенный ответ") },
{ System.Net.HttpStatusCode.Forbidden, new ForbiddenException("Клиент известен серверу, но он неавторизован") },
{ System.Net.HttpStatusCode.NotFound, new EntryPointNotFoundException("Сервер не может найти запрошенный ресурс") },
{ System.Net.HttpStatusCode.MethodNotAllowed, new MethodAccessException("Обращение запрещено") },
{ System.Net.HttpStatusCode.NotAcceptable, new AcceptableException("После выполнения согласования контента не найдено содержимого, соответствующего заданным критериям") },
{ System.Net.HttpStatusCode.RequestTimeout, new TimeoutException("Время ожидания истекло") },
{ System.Net.HttpStatusCode.Locked, new LockedException("Запрашиваемый ресурс заблокирован") },
{ System.Net.HttpStatusCode.TooManyRequests, new TooManyRequestsException("Пользователь отправил слишком много запросов в определённый промежуток времени") },
{ System.Net.HttpStatusCode.InternalServerError, new InternalServerException("На сервере произошла ошибка, в результате которой он не может успешно обработать запрос") },
{ System.Net.HttpStatusCode.NotImplemented, new NotImplementedException("Метод запроса не поддерживается сервером") },
{ System.Net.HttpStatusCode.BadGateway, new BadGatewayException("В процессе обработки запроса полуен недопустимый ответ от целевого сервера") },
{ System.Net.HttpStatusCode.ServiceUnavailable, new ServiceUnavailableException("В процессе обработки запроса полуен недопустимый ответ от целевого сервера") },
{ System.Net.HttpStatusCode.GatewayTimeout, new TimeoutException("Время ожидания целевого сервера истекло") }
};
public static Exception GetPersistenceException(this IApiResponse response)
{
ExceptionsDictionary
.TryGetValue(response.StatusCode, out var exception);
var result = exception ?? new Exception("Неопознанная ошибка");
return result;
}
}

View File

@ -1,9 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<!--Генерация NuGet пакета при сборке-->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<!--Наименование-->
<Title>Persistence.Client</Title>
<!--Версия пакета-->
<VersionPrefix>1.0.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</VersionPrefix>
<!--Версия сборки-->
<AssemblyVersion>1.0.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</AssemblyVersion>
<!--Id пакета-->
<PackageId>Persistence.Client</PackageId>
<!--Автор-->
<Authors>Digital Drilling</Authors>
<!--Компания-->
<Company>Digital Drilling</Company>
<!--Описание-->
<Description>Пакет для получения клиентов для работы с Persistence сервисом</Description>
<!--Url репозитория-->
<RepositoryUrl>https://git.ddrilling.ru/on.nemtina/persistence.git</RepositoryUrl>
<!--тип репозитория-->
<RepositoryType>git</RepositoryType>
<!--Символы отладки-->
<IncludeSymbols>true</IncludeSymbols>
<!--Формат пакета с символами-->
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<!--Путь к пакету-->
<PackageOutputPath>C:\Projects\Nuget</PackageOutputPath>
<!--Readme-->
<PackageReadmeFile>Readme.md</PackageReadmeFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -11,6 +43,10 @@
<AssemblyVersion>1.0.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</AssemblyVersion> <AssemblyVersion>1.0.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="Readme.md" Pack="true" PackagePath="\"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" />
<PackageReference Include="Refit" Version="8.0.0" /> <PackageReference Include="Refit" Version="8.0.0" />
@ -22,4 +58,5 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Persistence\Persistence.csproj" /> <ProjectReference Include="..\Persistence\Persistence.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,6 +1,12 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Persistence.Client.Clients.Interfaces;
using Persistence.Client.Clients;
using Persistence.Client.Helpers; using Persistence.Client.Helpers;
using Refit; using Refit;
using Persistence.Factories;
using Persistence.Client.Clients.Interfaces.Refit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json; using System.Text.Json;
namespace Persistence.Client namespace Persistence.Client
@ -16,17 +22,111 @@ namespace Persistence.Client
PropertyNameCaseInsensitive = true PropertyNameCaseInsensitive = true
}; };
private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions));
private readonly HttpClient httpClient; private readonly IServiceProvider provider;
public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IConfiguration configuration) private HttpClient httpClient;
public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IServiceProvider provider, IConfiguration configuration)
{ {
this.httpClient = httpClientFactory.CreateClient(); this.provider = provider;
httpClient = httpClientFactory.CreateClient();
httpClient.Authorize(configuration); httpClient.Authorize(configuration);
} }
public T GetClient<T>() public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IAuthTokenFactory authTokenFactory, IServiceProvider provider, IConfiguration configuration)
{ {
return RestService.For<T>(httpClient, RefitSettings); this.provider = provider;
httpClient = httpClientFactory.CreateClient();
var token = authTokenFactory.GetToken();
httpClient.Authorize(token);
}
/// <summary>
/// Получить клиент для работы с уставками
/// </summary>
/// <returns></returns>
public ISetpointClient GetSetpointClient()
{
var logger = provider.GetRequiredService<ILogger<SetpointClient>>();
var restClient = RestService.For<IRefitSetpointClient>(httpClient, RefitSettings);
var client = new SetpointClient(restClient, logger);
return client;
}
/// <summary>
/// Получить клиент для работы с технологическими сообщениями
/// </summary>
/// <returns></returns>
public ITechMessagesClient GetTechMessagesClient()
{
var logger = provider.GetRequiredService<ILogger<TechMessagesClient>>();
var restClient = RestService.For<IRefitTechMessagesClient>(httpClient, RefitSettings);
var client = new TechMessagesClient(restClient, logger);
return client;
}
/// <summary>
/// Получить клиент для работы с временными данными
/// </summary>
/// <typeparam name="TDto"></typeparam>
/// <returns></returns>
public ITimeSeriesClient<TDto> GetTimeSeriesClient<TDto>()
where TDto : class, new()
{
var logger = provider.GetRequiredService<ILogger<TimeSeriesClient<TDto>>>();
var restClient = RestService.For<IRefitTimeSeriesClient<TDto>>(httpClient, RefitSettings);
var client = new TimeSeriesClient<TDto>(restClient, logger);
return client;
}
/// <summary>
/// Получить клиент для работы с данными с отметкой времени
/// </summary>
/// <returns></returns>
public ITimestampedSetClient GetTimestampedSetClient()
{
var logger = provider.GetRequiredService<ILogger<TimestampedSetClient>>();
var restClient = RestService.For<IRefitTimestampedSetClient>(httpClient, RefitSettings);
var client = new TimestampedSetClient(restClient, logger);
return client;
}
/// <summary>
/// Получить клиент для работы с записями ChangeLog
/// </summary>
/// <returns></returns>
public IChangeLogClient GetChangeLogClient()
{
var logger = provider.GetRequiredService<ILogger<ChangeLogClient>>();
var restClient = RestService.For<IRefitChangeLogClient>(httpClient, RefitSettings);
var client = new ChangeLogClient(restClient, logger);
return client;
}
/// <summary>
/// Получить клиент для работы c параметрами Wits
/// </summary>
/// <returns></returns>
public IWitsDataClient GetWitsDataClient()
{
var logger = provider.GetRequiredService<ILogger<WitsDataClient>>();
var restClient = RestService.For<IRefitWitsDataClient>(httpClient, RefitSettings);
var client = new WitsDataClient(restClient, logger);
return client;
} }
} }
} }

View File

@ -0,0 +1,47 @@
# Persistence Client Nuget Readme
## Краткое описание Persistence сервиса
Persistence сервис отвечает за работу с хранимыми данными
в рамках совокупности различных систем.
## Описание пакета
Данный пакет предоставляет возможность взаимодействия с
Persistence сервисом посредством обращения к конкретному
клиенту, ответсвенному за работу с одной из областей сервиса.
## Список предоставляемых клиентов
- `ISetpointClient` - Клиент для работы с уставками
- `ITechMessagesClient` - Клиент для работы с технологическими сообщениями
- `ITimeSeriesClient` - Клиент для работы с временными данными
- `ITimestampedSetClient` - Клиент для работы с данными с отметкой времени
- `IChangeLogClient` - Клиент для работы с записями ChangeLog
- `IWitsDataClient` - Клиент для работы с параметрами Wits
## Использование
Для получения того или иного Persistence - клиента нужно
обращаться к фабрике Persistence клиентов - `PersistenceClientFactory`. Для этого требуется:
1. Добавить в проект фабрику HTTP - клиентов `IHttpClientFactory`.
<br>Она должна предоставлять HTTP - клиента через метод `GetClient()`.
>В том случае, если фабрика клиентов предоставляет не авторизованного клиента -
необходимо добавить в проект фабрику токенов аутентификации `IAuthTokenFactory` с методом `GetToken()`,
возвращающем токен в виде строки (без префикса `Bearer`).
2. Добавить логирование `ILoger`
3. Внедрить зависимость в проект `services.AddSingleton<PersistenceClientFactory>();` - пример.
4. Обратиться к фабрике Persistence - клиентов и получить требуемого клиента.
## xunit тестирование
При написании интеграционных тестов с ипользованием Persistence - клиентов
Http - клиент не обязан быть авторизован через передачу токена в `PersistenceClientFactory`.
Для осуществления тестовой авторизации достаточно добавить в `appsettings.Tests.json` :
```json
"NeedUseKeyCloak": false,
"AuthUser": {
"username": "myuser",
"password": 12345,
"clientId": "webapi",
"grantType": "password"
},
"KeycloakGetTokenUrl": "http://192.168.0.10:8321/realms/Persistence/protocol/openid-connect/token"
```
При этом возможна авторизация через `KeyCloak`.

View File

@ -1,12 +1,12 @@
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients.Interfaces;
using Persistence.Database.Entity;
using Persistence.Database.Model; using Persistence.Database.Model;
using Persistence.Models; using Persistence.Models;
using Persistence.Models.Requests; using Persistence.Models.Requests;
using System.Net;
using Xunit; using Xunit;
namespace Persistence.IntegrationTests.Controllers; namespace Persistence.IntegrationTests.Controllers;
@ -20,7 +20,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
client = persistenceClientFactory.GetClient<IChangeLogClient>(); client = persistenceClientFactory.GetChangeLogClient();
} }
[Fact] [Fact]
@ -33,11 +33,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dtos = Generate(2); var dtos = Generate(2);
// act // act
var result = await client.ClearAndAddRange(idDiscriminator, dtos); var result = await client.ClearAndAddRange(idDiscriminator, dtos, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(2, result);
Assert.Equal(2, result.Content);
} }
[Fact] [Fact]
@ -50,11 +49,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dtos = createdResult.Item2.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>()); var dtos = createdResult.Item2.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>());
// act // act
var result = await client.ClearAndAddRange(idDiscriminator, dtos); var result = await client.ClearAndAddRange(idDiscriminator, dtos, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(insertedCount*2, result);
Assert.Equal(insertedCount * 2, result.Content);
} }
[Fact] [Fact]
@ -67,11 +65,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dto = dtos.FirstOrDefault()!; var dto = dtos.FirstOrDefault()!;
// act // act
var result = await client.Add(idDiscriminator, dto); var result = await client.Add(idDiscriminator, dto, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result);
Assert.Equal(count, result.Content);
} }
[Fact] [Fact]
@ -83,11 +80,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dtos = Generate(count); var dtos = Generate(count);
// act // act
var result = await client.AddRange(idDiscriminator, dtos); var result = await client.AddRange(idDiscriminator, dtos, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result);
Assert.Equal(count, result.Content);
} }
[Fact] [Fact]
@ -99,8 +95,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var idDiscriminator = Guid.NewGuid(); var idDiscriminator = Guid.NewGuid();
var dtos = Generate(1); var dtos = Generate(1);
var dto = dtos.FirstOrDefault()!; var dto = dtos.FirstOrDefault()!;
var result = await client.Add(idDiscriminator, dto); var result = await client.Add(idDiscriminator, dto, new CancellationToken());
Assert.Equal(HttpStatusCode.Created, result.StatusCode);
var entity = dbContext.ChangeLog var entity = dbContext.ChangeLog
.Where(x => x.IdDiscriminator == idDiscriminator) .Where(x => x.IdDiscriminator == idDiscriminator)
@ -109,26 +104,22 @@ public class ChangeLogControllerTest : BaseIntegrationTest
dto.DepthEnd += 10; dto.DepthEnd += 10;
// act // act
result = await client.Update(dto); result = await client.Update(dto, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(2, result);
Assert.Equal(2, result.Content);
var dateBegin = DateTimeOffset.UtcNow.AddDays(-1); var dateBegin = DateTimeOffset.UtcNow.AddDays(-1);
var dateEnd = DateTimeOffset.UtcNow.AddDays(1); var dateEnd = DateTimeOffset.UtcNow.AddDays(1);
var changeLogResult = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); var changeLogResult = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, new CancellationToken());
Assert.Equal(HttpStatusCode.OK, changeLogResult.StatusCode); Assert.NotNull(changeLogResult);
Assert.NotNull(changeLogResult.Content);
var changeLogDtos = changeLogResult.Content; var obsoleteDto = changeLogResult
var obsoleteDto = changeLogDtos
.Where(e => e.Obsolete.HasValue) .Where(e => e.Obsolete.HasValue)
.FirstOrDefault(); .FirstOrDefault();
var activeDto = changeLogDtos var activeDto = changeLogResult
.Where(e => !e.Obsolete.HasValue) .Where(e => !e.Obsolete.HasValue)
.FirstOrDefault(); .FirstOrDefault();
@ -162,11 +153,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
}).ToArray(); }).ToArray();
// act // act
var result = await client.UpdateRange(dtos); var result = await client.UpdateRange(dtos, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(count * 2, result);
Assert.Equal(count * 2, result.Content);
} }
[Fact] [Fact]
@ -180,11 +170,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
dbContext.SaveChanges(); dbContext.SaveChanges();
// act // act
var result = await client.Delete(entity.Id); var result = await client.Delete(entity.Id, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(1, result);
Assert.Equal(1, result.Content);
} }
[Fact] [Fact]
@ -199,11 +188,10 @@ public class ChangeLogControllerTest : BaseIntegrationTest
// act // act
var ids = entities.Select(e => e.Id); var ids = entities.Select(e => e.Id);
var result = await client.DeleteRange(ids); var result = await client.DeleteRange(ids, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(count, result);
Assert.Equal(count, result.Content);
} }
[Fact] [Fact]
@ -215,21 +203,20 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var entities = changeLogItems.Item2.OrderBy(e => e.Creation); var entities = changeLogItems.Item2.OrderBy(e => e.Creation);
// act // act
var result = await client.GetDatesRange(idDiscriminator); var result = await client.GetDatesRange(idDiscriminator, new CancellationToken());
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result);
Assert.NotNull(result.Content);
var minDate = entities.First().Creation; var minDate = entities.First().Creation;
var maxDate = entities.Last().Creation; var maxDate = entities.Last().Creation;
var expectedMinDate = minDate.ToUniversalTime().ToString(); var expectedMinDate = minDate.ToUniversalTime().ToString();
var actualMinDate = result.Content.From.ToUniversalTime().ToString(); var actualMinDate = result.From.ToUniversalTime().ToString();
Assert.Equal(expectedMinDate, actualMinDate); Assert.Equal(expectedMinDate, actualMinDate);
var expectedMaxDate = maxDate.ToUniversalTime().ToString(); var expectedMaxDate = maxDate.ToUniversalTime().ToString();
var actualMaxDate = result.Content.To.ToUniversalTime().ToString(); var actualMaxDate = result.To.ToUniversalTime().ToString();
Assert.Equal(expectedMaxDate, actualMaxDate); Assert.Equal(expectedMaxDate, actualMaxDate);
} }
@ -250,7 +237,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var ids = entities.Select(e => e.Id); var ids = entities.Select(e => e.Id);
var idsToDelete = ids.Skip(2); var idsToDelete = ids.Skip(2);
var deletedCount = await client.DeleteRange(idsToDelete); var deletedCount = await client.DeleteRange(idsToDelete, new CancellationToken());
var filterRequest = new SectionPartRequest() var filterRequest = new SectionPartRequest()
{ {
@ -266,16 +253,15 @@ public class ChangeLogControllerTest : BaseIntegrationTest
}; };
var moment = DateTimeOffset.UtcNow.AddDays(16); var moment = DateTimeOffset.UtcNow.AddDays(16);
var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest); var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, new CancellationToken());
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result);
Assert.NotNull(result.Content);
var restEntities = entities.Where(e => !idsToDelete.Contains(e.Id)); var restEntities = entities.Where(e => !idsToDelete.Contains(e.Id));
Assert.Equal(restEntities.Count(), result.Content.Count); Assert.Equal(restEntities.Count(), result.Count);
var actualIds = restEntities.Select(e => e.Id); var actualIds = restEntities.Select(e => e.Id);
var expectedIds = result.Content.Items.Select(e => e.Id); var expectedIds = result.Items.Select(e => e.Id);
Assert.Equivalent(expectedIds, actualIds); Assert.Equivalent(expectedIds, actualIds);
} }
@ -305,17 +291,16 @@ public class ChangeLogControllerTest : BaseIntegrationTest
entity.DepthEnd += 10; entity.DepthEnd += 10;
} }
var dtos = entities.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>()).ToArray(); var dtos = entities.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>()).ToArray();
await client.UpdateRange(dtos); await client.UpdateRange(dtos, new CancellationToken());
//act //act
var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter); var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter);
var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter); var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter);
var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result);
Assert.NotNull(result.Content); Assert.Equal(changeLogCount, result.Count());
Assert.Equal(changeLogCount, result.Content.Count());
} }

View File

@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients.Interfaces;
using Persistence.Database.Model; using Persistence.Database.Model;
using System.Net; using System.Net;
using Xunit; using Xunit;
@ -21,7 +21,7 @@ namespace Persistence.IntegrationTests.Controllers
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
setpointClient = persistenceClientFactory.GetClient<ISetpointClient>(); setpointClient = persistenceClientFactory.GetSetpointClient();
} }
[Fact] [Fact]
@ -35,12 +35,11 @@ namespace Persistence.IntegrationTests.Controllers
}; };
//act //act
var response = await setpointClient.GetCurrent(setpointKeys); var response = await setpointClient.GetCurrent(setpointKeys, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -50,13 +49,12 @@ namespace Persistence.IntegrationTests.Controllers
var setpointKey = await Add(); var setpointKey = await Add();
//act //act
var response = await setpointClient.GetCurrent([setpointKey]); var response = await setpointClient.GetCurrent([setpointKey], new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content); Assert.Equal(setpointKey, response.FirstOrDefault()?.Key);
Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key);
} }
[Fact] [Fact]
@ -71,12 +69,11 @@ namespace Persistence.IntegrationTests.Controllers
var historyMoment = DateTimeOffset.UtcNow; var historyMoment = DateTimeOffset.UtcNow;
//act //act
var response = await setpointClient.GetHistory(setpointKeys, historyMoment); var response = await setpointClient.GetHistory(setpointKeys, historyMoment, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -88,13 +85,12 @@ namespace Persistence.IntegrationTests.Controllers
historyMoment = historyMoment.AddDays(1); historyMoment = historyMoment.AddDays(1);
//act //act
var response = await setpointClient.GetHistory([setpointKey], historyMoment); var response = await setpointClient.GetHistory([setpointKey], historyMoment, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content); Assert.Equal(setpointKey, response.FirstOrDefault()?.Key);
Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key);
} }
[Fact] [Fact]
@ -108,12 +104,11 @@ namespace Persistence.IntegrationTests.Controllers
}; };
//act //act
var response = await setpointClient.GetLog(setpointKeys); var response = await setpointClient.GetLog(setpointKeys, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -123,13 +118,12 @@ namespace Persistence.IntegrationTests.Controllers
var setpointKey = await Add(); var setpointKey = await Add();
//act //act
var response = await setpointClient.GetLog([setpointKey]); var response = await setpointClient.GetLog([setpointKey], new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content); Assert.Equal(setpointKey, response.FirstOrDefault().Key);
Assert.Equal(setpointKey, response.Content.FirstOrDefault().Key);
} }
[Fact] [Fact]
@ -142,10 +136,9 @@ namespace Persistence.IntegrationTests.Controllers
var response = await setpointClient.GetDatesRangeAsync(CancellationToken.None); var response = await setpointClient.GetDatesRangeAsync(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(DateTimeOffset.MinValue, response!.From);
Assert.Equal(DateTimeOffset.MinValue, response.Content!.From); Assert.Equal(DateTimeOffset.MaxValue, response!.To);
Assert.Equal(DateTimeOffset.MaxValue, response.Content!.To);
} }
[Fact] [Fact]
@ -164,17 +157,16 @@ namespace Persistence.IntegrationTests.Controllers
var response = await setpointClient.GetDatesRangeAsync(CancellationToken.None); var response = await setpointClient.GetDatesRangeAsync(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content);
var expectedValue = part.Content! var expectedValue = part!
.FirstOrDefault()!.Created .FirstOrDefault()!.Created
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
var actualValueFrom = response.Content.From var actualValueFrom = response.From
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
Assert.Equal(expectedValue, actualValueFrom); Assert.Equal(expectedValue, actualValueFrom);
var actualValueTo = response.Content.To var actualValueTo = response.To
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
Assert.Equal(expectedValue, actualValueTo); Assert.Equal(expectedValue, actualValueTo);
} }
@ -190,9 +182,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await setpointClient.GetPart(dateBegin, take, CancellationToken.None); var response = await setpointClient.GetPart(dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -207,9 +198,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await setpointClient.GetPart(dateBegin, take, CancellationToken.None); var response = await setpointClient.GetPart(dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content);
} }
[Fact] [Fact]
@ -229,10 +219,7 @@ namespace Persistence.IntegrationTests.Controllers
}; };
//act //act
var response = await setpointClient.Add(setpointKey, setpointValue); await setpointClient.Add(setpointKey, setpointValue, new CancellationToken());
//assert
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
return setpointKey; return setpointKey;
} }

View File

@ -1,7 +1,7 @@
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients.Interfaces;
using Persistence.Database.Entity; using Persistence.Database.Entity;
using Persistence.Models; using Persistence.Models;
using Persistence.Models.Requests; using Persistence.Models.Requests;
@ -21,7 +21,7 @@ namespace Persistence.IntegrationTests.Controllers
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
techMessagesClient = persistenceClientFactory.GetClient<ITechMessagesClient>(); techMessagesClient = persistenceClientFactory.GetTechMessagesClient();
memoryCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>(); memoryCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
} }
@ -44,11 +44,10 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetPage(requestDto, CancellationToken.None); var response = await techMessagesClient.GetPage(requestDto, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response.Items);
Assert.Empty(response.Content.Items); Assert.Equal(requestDto.Skip, response.Skip);
Assert.Equal(requestDto.Skip, response.Content.Skip); Assert.Equal(requestDto.Take, response.Take);
Assert.Equal(requestDto.Take, response.Content.Take);
} }
[Fact] [Fact]
@ -68,9 +67,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetPage(requestDto, CancellationToken.None); var response = await techMessagesClient.GetPage(requestDto, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(dtosCount, response.Count);
Assert.Equal(dtosCount, response.Content.Count);
} }
[Fact] [Fact]
@ -83,9 +81,10 @@ namespace Persistence.IntegrationTests.Controllers
public async Task InsertRange_returns_BadRequest() public async Task InsertRange_returns_BadRequest()
{ {
//arrange //arrange
const string exceptionMessage = "Ошибка валидации, формата или маршрутизации запроса";
var dtos = new List<TechMessageDto>() var dtos = new List<TechMessageDto>()
{ {
new() new TechMessageDto()
{ {
EventId = Guid.NewGuid(), EventId = Guid.NewGuid(),
CategoryId = -1, // < 0 CategoryId = -1, // < 0
@ -97,11 +96,16 @@ namespace Persistence.IntegrationTests.Controllers
} }
}; };
try
{
//act //act
var response = await techMessagesClient.AddRange(dtos, CancellationToken.None); var response = await techMessagesClient.AddRange(dtos, new CancellationToken());
}
catch (Exception ex)
{
//assert //assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Equal(exceptionMessage, ex.Message);
}
} }
[Fact] [Fact]
@ -116,9 +120,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetSystems(CancellationToken.None); var response = await techMessagesClient.GetSystems(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -135,9 +138,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetSystems(CancellationToken.None); var response = await techMessagesClient.GetSystems(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); string?[]? content = response?.ToArray();
string?[]? content = response.Content?.ToArray();
Assert.Equal(systems, content); Assert.Equal(systems, content);
} }
@ -156,9 +158,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetStatistics(autoDrillingSystem, importantId, CancellationToken.None); var response = await techMessagesClient.GetStatistics(autoDrillingSystem, importantId, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -174,9 +175,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetStatistics(autoDrillingSystem, importantId, CancellationToken.None); var response = await techMessagesClient.GetStatistics(autoDrillingSystem, importantId, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); var categories = response
var categories = response.Content
.FirstOrDefault()?.Categories .FirstOrDefault()?.Categories
.FirstOrDefault(e => e.Key == 0).Value; .FirstOrDefault(e => e.Key == 0).Value;
Assert.Equal(filteredDtos.Count(), categories); Assert.Equal(filteredDtos.Count(), categories);
@ -185,14 +185,18 @@ namespace Persistence.IntegrationTests.Controllers
[Fact] [Fact]
public async Task GetDatesRange_returns_success() public async Task GetDatesRange_returns_success()
{ {
//arrange
memoryCache.Remove(SystemCacheKey);
dbContext.CleanupDbSet<TechMessage>();
dbContext.CleanupDbSet<DrillingSystem>();
//act //act
var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None); var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(DateTimeOffset.MinValue, response?.From);
//Assert.Equal(DateTimeOffset.MinValue, response.Content?.From); Assert.Equal(DateTimeOffset.MaxValue, response?.To);
//Assert.Equal(DateTimeOffset.MaxValue, response.Content?.To);
} }
[Fact] [Fact]
@ -205,10 +209,9 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None); var response = await techMessagesClient.GetDatesRangeAsync(CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotNull(response?.From);
Assert.NotNull(response.Content?.From); Assert.NotNull(response?.To);
Assert.NotNull(response.Content?.To);
} }
[Fact] [Fact]
@ -222,9 +225,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetPart(dateBegin, take, CancellationToken.None); var response = await techMessagesClient.GetPart(dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -239,9 +241,8 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.GetPart(dateBegin, take, CancellationToken.None); var response = await techMessagesClient.GetPart(dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content);
} }
private async Task<IEnumerable<TechMessageDto>> InsertRange() private async Task<IEnumerable<TechMessageDto>> InsertRange()
@ -280,8 +281,7 @@ namespace Persistence.IntegrationTests.Controllers
var response = await techMessagesClient.AddRange(dtos, CancellationToken.None); var response = await techMessagesClient.AddRange(dtos, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Equal(dtos.Count, response);
Assert.Equal(dtos.Count, response.Content);
return dtos; return dtos;
} }

View File

@ -1,7 +1,7 @@
using Mapster; using Mapster;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients.Interfaces;
using Persistence.Database.Model; using Persistence.Database.Model;
using System.Net; using System.Net;
using Xunit; using Xunit;
@ -22,7 +22,7 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
timeSeriesClient = persistenceClientFactory.GetClient<ITimeSeriesClient<TDto>>(); timeSeriesClient = persistenceClientFactory.GetTimeSeriesClient<TDto>();
} }
public async Task InsertRangeSuccess(TDto dto) public async Task InsertRangeSuccess(TDto dto)
@ -31,11 +31,10 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
var expected = dto.Adapt<TDto>(); var expected = dto.Adapt<TDto>();
//act //act
var response = await timeSeriesClient.AddRange([expected]); var response = await timeSeriesClient.AddRange(new TDto[] { expected }, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(1, response);
Assert.Equal(1, response.Content);
} }
public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity) public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity)
@ -47,12 +46,11 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
dbContext.SaveChanges(); dbContext.SaveChanges();
var response = await timeSeriesClient.Get(beginDate, endDate); var response = await timeSeriesClient.Get(beginDate, endDate, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Single(response);
Assert.Single(response.Content);
} }
public async Task GetDatesRangeSuccess(TEntity entity) public async Task GetDatesRangeSuccess(TEntity entity)
@ -69,13 +67,12 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
dbContext.SaveChanges(); dbContext.SaveChanges();
var response = await timeSeriesClient.GetDatesRange(); var response = await timeSeriesClient.GetDatesRange(new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content);
var datesRangeActual = (response.Content.To - response.Content.From).Days; var datesRangeActual = (response.To - response.From).Days;
Assert.Equal(datesRangeExpected, datesRangeActual); Assert.Equal(datesRangeExpected, datesRangeActual);
} }
@ -99,11 +96,10 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
dbContext.SaveChanges(); dbContext.SaveChanges();
var response = await timeSeriesClient.GetResampledData(entity.Date.AddMinutes(-1), differenceBetweenStartAndEndDays * 24 * 60 * 60 + 60, approxPointsCount); var response = await timeSeriesClient.GetResampledData(entity.Date.AddMinutes(-1), differenceBetweenStartAndEndDays * 24 * 60 * 60 + 60, approxPointsCount, new CancellationToken());
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content);
var ratio = entities.Count / approxPointsCount; var ratio = entities.Count / approxPointsCount;
if (ratio > 1) if (ratio > 1)
@ -112,15 +108,11 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
.Where((_, index) => index % ratio == 0) .Where((_, index) => index % ratio == 0)
.Count(); .Count();
Assert.Equal(expectedResampledCount, response.Content.Count()); Assert.Equal(expectedResampledCount, response.Count());
} }
else else
{ {
Assert.Equal(entities.Count, response.Content.Count()); Assert.Equal(entities.Count(), response.Count());
} }
} }
} }

View File

@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients.Interfaces;
using Persistence.Models; using Persistence.Models;
using Xunit; using Xunit;
@ -14,7 +14,7 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
client = persistenceClientFactory.GetClient<ITimestampedSetClient>(); client = persistenceClientFactory.GetTimestampedSetClient();
} }
[Fact] [Fact]
@ -25,11 +25,10 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
IEnumerable<TimestampedSetDto> testSets = Generate(10, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(10, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
// act // act
var response = await client.AddRange(idDiscriminator, testSets); var response = await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.Equal(testSets.Count(), response);
Assert.Equal(testSets.Count(), response.Content);
} }
[Fact] [Fact]
@ -39,16 +38,14 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
Guid idDiscriminator = Guid.NewGuid(); Guid idDiscriminator = Guid.NewGuid();
int count = 10; int count = 10;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
// act // act
var response = await client.Get(idDiscriminator, null, null, 0, int.MaxValue); var response = await client.Get(idDiscriminator, null, null, 0, int.MaxValue, CancellationToken.None);
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(count, response.Count());
var items = response.Content!;
Assert.Equal(count, items.Count());
} }
[Fact] [Fact]
@ -58,18 +55,16 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
Guid idDiscriminator = Guid.NewGuid(); Guid idDiscriminator = Guid.NewGuid();
int count = 10; int count = 10;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
string[] props = ["A"]; string[] props = ["A"];
// act // act
var response = await client.Get(idDiscriminator, null, props, 0, int.MaxValue); var response = await client.Get(idDiscriminator, null, props, 0, int.MaxValue, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(count, response.Count());
var items = response.Content!; foreach (var item in response)
Assert.Equal(count, items.Count());
foreach (var item in items)
{ {
Assert.Single(item.Set); Assert.Single(item.Set);
var kv = item.Set.First(); var kv = item.Set.First();
@ -86,21 +81,19 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
var dateMin = DateTimeOffset.Now; var dateMin = DateTimeOffset.Now;
var dateMax = DateTimeOffset.Now.AddSeconds(count); var dateMax = DateTimeOffset.Now.AddSeconds(count);
IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7)));
var insertResponse = await client.AddRange(idDiscriminator, testSets); var insertResponse = await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
var tail = testSets.OrderBy(t => t.Timestamp).Skip(count / 2).Take(int.MaxValue); var tail = testSets.OrderBy(t => t.Timestamp).Skip(count / 2).Take(int.MaxValue);
var geDate = tail.First().Timestamp; var geDate = tail.First().Timestamp;
var tolerance = TimeSpan.FromSeconds(1); var tolerance = TimeSpan.FromSeconds(1);
var expectedCount = tail.Count(); var expectedCount = tail.Count();
// act // act
var response = await client.Get(idDiscriminator, geDate, null, 0, int.MaxValue); var response = await client.Get(idDiscriminator, geDate, null, 0, int.MaxValue, CancellationToken.None);
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(expectedCount, response.Count());
var items = response.Content!; var minDate = response.Min(t => t.Timestamp);
Assert.Equal(expectedCount, items.Count());
var minDate = items.Min(t => t.Timestamp);
Assert.Equal(geDate, geDate, tolerance); Assert.Equal(geDate, geDate, tolerance);
} }
@ -111,17 +104,15 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
Guid idDiscriminator = Guid.NewGuid(); Guid idDiscriminator = Guid.NewGuid();
int count = 10; int count = 10;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
var expectedCount = count / 2; var expectedCount = count / 2;
// act // act
var response = await client.Get(idDiscriminator, null, null, 2, expectedCount); var response = await client.Get(idDiscriminator, null, null, 2, expectedCount, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(expectedCount, response.Count());
var items = response.Content!;
Assert.Equal(expectedCount, items.Count());
} }
@ -133,16 +124,14 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
var expectedCount = 1; var expectedCount = 1;
int count = 10 + expectedCount; int count = 10 + expectedCount;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
// act // act
var response = await client.Get(idDiscriminator, null, null, count - expectedCount, count); var response = await client.Get(idDiscriminator, null, null, count - expectedCount, count, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(expectedCount, response.Count());
var items = response.Content!;
Assert.Equal(expectedCount, items.Count());
} }
[Fact] [Fact]
@ -152,17 +141,15 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
Guid idDiscriminator = Guid.NewGuid(); Guid idDiscriminator = Guid.NewGuid();
int count = 10; int count = 10;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
var expectedCount = 8; var expectedCount = 8;
// act // act
var response = await client.GetLast(idDiscriminator, null, expectedCount); var response = await client.GetLast(idDiscriminator, null, expectedCount, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(expectedCount, response.Count());
var items = response.Content!;
Assert.Equal(expectedCount, items.Count());
} }
[Fact] [Fact]
@ -174,18 +161,16 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
var dateMin = DateTimeOffset.Now; var dateMin = DateTimeOffset.Now;
var dateMax = DateTimeOffset.Now.AddSeconds(count - 1); var dateMax = DateTimeOffset.Now.AddSeconds(count - 1);
IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
var tolerance = TimeSpan.FromSeconds(1); var tolerance = TimeSpan.FromSeconds(1);
// act // act
var response = await client.GetDatesRange(idDiscriminator); var response = await client.GetDatesRange(idDiscriminator, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(dateMin, response.From, tolerance);
var range = response.Content!; Assert.Equal(dateMax, response.To, tolerance);
Assert.Equal(dateMin, range.From, tolerance);
Assert.Equal(dateMax, range.To, tolerance);
} }
[Fact] [Fact]
@ -195,14 +180,13 @@ public class TimestampedSetControllerTest : BaseIntegrationTest
Guid idDiscriminator = Guid.NewGuid(); Guid idDiscriminator = Guid.NewGuid();
int count = 144; int count = 144;
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
await client.AddRange(idDiscriminator, testSets); await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
// act // act
var response = await client.Count(idDiscriminator); var response = await client.Count(idDiscriminator, new CancellationToken());
// assert // assert
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.Equal(count, response);
Assert.Equal(count, response.Content);
} }
private static IEnumerable<TimestampedSetDto> Generate(int n, DateTimeOffset from) private static IEnumerable<TimestampedSetDto> Generate(int n, DateTimeOffset from)

View File

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Persistence.Client; using Persistence.Client;
using Persistence.Client.Clients; using Persistence.Client.Clients;
using Persistence.Client.Clients.Interfaces;
using Persistence.Database.Entity; using Persistence.Database.Entity;
using Persistence.Models; using Persistence.Models;
using System.Net; using System.Net;
@ -17,7 +18,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
var persistenceClientFactory = scope.ServiceProvider var persistenceClientFactory = scope.ServiceProvider
.GetRequiredService<PersistenceClientFactory>(); .GetRequiredService<PersistenceClientFactory>();
witsDataClient = persistenceClientFactory.GetClient<IWitsDataClient>(); witsDataClient = persistenceClientFactory.GetWitsDataClient();
} }
[Fact] [Fact]
@ -32,8 +33,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetDatesRangeAsync(discriminatorId, CancellationToken.None); var response = await witsDataClient.GetDatesRangeAsync(discriminatorId, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content);
} }
[Fact] [Fact]
@ -50,9 +50,8 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetPart(discriminatorId, dateBegin, take, CancellationToken.None); var response = await witsDataClient.GetPart(discriminatorId, dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -80,9 +79,8 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, CancellationToken.None); var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Empty(response);
Assert.Empty(response.Content);
} }
[Fact] [Fact]
@ -98,14 +96,13 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetDatesRangeAsync(discriminatorId, CancellationToken.None); var response = await witsDataClient.GetDatesRangeAsync(discriminatorId, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content);
var expectedDateFrom = dtos var expectedDateFrom = dtos
.Select(e => e.Timestamped) .Select(e => e.Timestamped)
.Min() .Min()
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
var actualDateFrom = response.Content.From.DateTime var actualDateFrom = response.From.DateTime
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
Assert.Equal(expectedDateFrom, actualDateFrom); Assert.Equal(expectedDateFrom, actualDateFrom);
@ -113,7 +110,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
.Select(e => e.Timestamped) .Select(e => e.Timestamped)
.Max() .Max()
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
var actualDateTo = response.Content.To.DateTime var actualDateTo = response.To.DateTime
.ToString("dd.MM.yyyy-HH:mm:ss"); .ToString("dd.MM.yyyy-HH:mm:ss");
Assert.Equal(expectedDateTo, actualDateTo); Assert.Equal(expectedDateTo, actualDateTo);
} }
@ -133,13 +130,12 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetPart(discriminatorId, dateBegin, take, CancellationToken.None); var response = await witsDataClient.GetPart(discriminatorId, dateBegin, take, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.NotEmpty(response);
Assert.NotEmpty(response.Content); Assert.Equal(take, response.Count());
Assert.Equal(take, response.Content.Count());
var expectedDto = dtos.FirstOrDefault(); var expectedDto = dtos.FirstOrDefault();
var actualDto = response.Content.FirstOrDefault(); var actualDto = response.FirstOrDefault();
Assert.Equal(expectedDto?.DiscriminatorId, actualDto?.DiscriminatorId); Assert.Equal(expectedDto?.DiscriminatorId, actualDto?.DiscriminatorId);
var expectedValueDto = expectedDto?.Values.FirstOrDefault(); var expectedValueDto = expectedDto?.Values.FirstOrDefault();
@ -164,15 +160,15 @@ public class WitsDataControllerTest : BaseIntegrationTest
var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, CancellationToken.None); var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, CancellationToken.None);
//assert //assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response);
Assert.NotNull(response.Content); Assert.Equal(approxPointCount, response.Count());
Assert.Equal(approxPointCount, response.Content.Count());
} }
[Fact] [Fact]
public async Task AddRange_returns_BadRequest() public async Task AddRange_returns_BadRequest()
{ {
//arrange //arrange
const string exceptionMessage = "Ошибка валидации, формата или маршрутизации запроса";
var dtos = new List<WitsDataDto>() var dtos = new List<WitsDataDto>()
{ {
new WitsDataDto() new WitsDataDto()
@ -191,11 +187,16 @@ public class WitsDataControllerTest : BaseIntegrationTest
} }
}; };
try
{
//act //act
var response = await witsDataClient.AddRange(dtos, CancellationToken.None); var response = await witsDataClient.AddRange(dtos, CancellationToken.None);
}
catch (Exception ex)
{
//assert //assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Equal(exceptionMessage, ex.Message);
}
} }
private async Task<IEnumerable<WitsDataDto>> AddRange(int countToCreate = 10) private async Task<IEnumerable<WitsDataDto>> AddRange(int countToCreate = 10)
@ -227,8 +228,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
//assert //assert
var count = dtos.SelectMany(e => e.Values).Count(); var count = dtos.SelectMany(e => e.Values).Count();
Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Equal(count, response);
Assert.Equal(count, response.Content);
return dtos; return dtos;
} }

View File

@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Persistence.API; using Persistence.API;
using Persistence.Client; using Persistence.Client;
using Persistence.Database.Model; using Persistence.Database.Model;
@ -34,6 +35,8 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
services.AddDbContext<PersistencePostgresContext>(options => services.AddDbContext<PersistencePostgresContext>(options =>
options.UseNpgsql(connectionString)); options.UseNpgsql(connectionString));
services.AddLogging(builder => builder.AddConsole());
services.RemoveAll<IHttpClientFactory>(); services.RemoveAll<IHttpClientFactory>();
services.AddSingleton<IHttpClientFactory>(provider => services.AddSingleton<IHttpClientFactory>(provider =>
{ {

View File

@ -1,4 +1,4 @@
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Persistence.Database.Entity; using Persistence.Database.Entity;

View File

@ -0,0 +1,13 @@
namespace Persistence.Factories;
/// <summary>
/// Фабрика токенов аутентификации
/// </summary>
public interface IAuthTokenFactory
{
/// <summary>
/// Получить токен
/// </summary>
/// <returns></returns>
public string GetToken();
}