diff --git a/Persistence.Client/Clients/Base/BaseClient.cs b/Persistence.Client/Clients/Base/BaseClient.cs new file mode 100644 index 0000000..bca6f6a --- /dev/null +++ b/Persistence.Client/Clients/Base/BaseClient.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.Logging; +using Persistence.Client.Helpers; +using Refit; + +namespace Persistence.Client.Clients.Base; +public class BaseClient +{ + private readonly ILogger logger; + + public BaseClient(ILogger logger) + { + this.logger = logger; + } + + public async Task ExecuteGetResponse(Func>> 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> 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 ExecutePostResponse(Func>> 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; + } +} diff --git a/Persistence.Client/Clients/ISetpointClient.cs b/Persistence.Client/Clients/ISetpointClient.cs deleted file mode 100644 index 0b81ffa..0000000 --- a/Persistence.Client/Clients/ISetpointClient.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Persistence.Models; -using Refit; - -namespace Persistence.Client.Clients; - -/// -/// Интерфейс клиента для работы с уставками -/// -public interface ISetpointClient -{ - private const string BaseRoute = "/api/setpoint"; - - [Get($"{BaseRoute}/current")] - Task>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); - - [Get($"{BaseRoute}/history")] - Task>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, [Query] DateTimeOffset historyMoment); - - [Get($"{BaseRoute}/log")] - Task>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); - - [Get($"{BaseRoute}/range")] - Task> GetDatesRangeAsync(CancellationToken token); - - [Get($"{BaseRoute}/part")] - Task>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); - - [Post($"{BaseRoute}/")] - Task Add(Guid setpointKey, object newValue); -} diff --git a/Persistence.Client/Clients/ITechMessagesClient.cs b/Persistence.Client/Clients/ITechMessagesClient.cs deleted file mode 100644 index 878c6cf..0000000 --- a/Persistence.Client/Clients/ITechMessagesClient.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Persistence.Models; -using Refit; - -namespace Persistence.Client.Clients -{ - /// - /// Интерфейс клиента для хранения технологических сообщений - /// - public interface ITechMessagesClient - { - private const string BaseRoute = "/api/techMessages"; - - [Get($"{BaseRoute}")] - Task>> GetPage([Query] RequestDto request, CancellationToken token); - - [Post($"{BaseRoute}")] - Task> AddRange([Body] IEnumerable dtos, CancellationToken token); - - [Get($"{BaseRoute}/systems")] - Task>> GetSystems(CancellationToken token); - - [Get($"{BaseRoute}/range")] - Task> GetDatesRangeAsync(CancellationToken token); - - [Get($"{BaseRoute}/part")] - Task>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); - - [Get($"{BaseRoute}/statistics")] - Task>> GetStatistics([Query] string autoDrillingSystem, [Query] int categoryId, CancellationToken token); - } -} diff --git a/Persistence.Client/Clients/Interfaces/ISetpointClient.cs b/Persistence.Client/Clients/Interfaces/ISetpointClient.cs new file mode 100644 index 0000000..19c5902 --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/ISetpointClient.cs @@ -0,0 +1,59 @@ +using Persistence.Models; + +namespace Persistence.Client.Clients.Interfaces; + +/// +/// Клиент для работы с уставками +/// +public interface ISetpointClient +{ + /// + /// Добавить уставку + /// + /// + /// + /// + /// + Task Add(Guid setpointKey, object newValue, CancellationToken token); + + /// + /// Получить актуальные значения уставок + /// + /// + /// + /// + Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token); + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// + /// + Task GetDatesRangeAsync(CancellationToken token); + + /// + /// Получить значения уставок за определенный момент времени + /// + /// + /// + /// + /// + Task> GetHistory(IEnumerable setpointKeys, DateTimeOffset historyMoment, CancellationToken token); + + /// + /// Получить историю изменений значений уставок + /// + /// + /// + /// + Task>> GetLog(IEnumerable setpointKeys, CancellationToken token); + + /// + /// Получить порцию записей, начиная с заданной даты + /// + /// + /// + /// + /// + Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); +} \ No newline at end of file diff --git a/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs b/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs new file mode 100644 index 0000000..8da559c --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/ITechMessagesClient.cs @@ -0,0 +1,57 @@ +using Persistence.Models; + +namespace Persistence.Client.Clients.Interfaces; + +/// +/// Клиент для работы с технологическими сообщениями +/// +public interface ITechMessagesClient +{ + /// + /// Добавить новые технологические сообщения + /// + /// + /// + /// + Task AddRange(IEnumerable dtos, CancellationToken token); + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// + /// + Task GetDatesRangeAsync(CancellationToken token); + + /// + /// Получить список технологических сообщений в виде страницы + /// + /// + /// + /// + Task> GetPage(RequestDto request, CancellationToken token); + + /// + /// Получить порцию записей, начиная с заданной даты + /// + /// + /// + /// + /// + Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); + + /// + /// Получить статистику по системам + /// + /// + /// + /// + /// + Task> GetStatistics(string autoDrillingSystem, int categoryId, CancellationToken token); + + /// + /// Получить список всех систем + /// + /// + /// + Task> GetSystems(CancellationToken token); +} \ No newline at end of file diff --git a/Persistence.Client/Clients/Interfaces/ITimeSeriesClient.cs b/Persistence.Client/Clients/Interfaces/ITimeSeriesClient.cs new file mode 100644 index 0000000..d6dd199 --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/ITimeSeriesClient.cs @@ -0,0 +1,44 @@ +using Persistence.Models; + +namespace Persistence.Client.Clients.Interfaces; + +/// +/// Клиент для работы с временными данными +/// +/// +public interface ITimeSeriesClient where TDto : class, new() +{ + /// + /// Добавление записей + /// + /// + /// + /// + Task AddRange(IEnumerable dtos, CancellationToken token); + + /// + /// Получить список объектов, удовлетворяющий диапазону дат + /// + /// + /// + /// + /// + Task> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// + /// + Task GetDatesRange(CancellationToken token); + + /// + /// Получить список объектов с прореживанием, удовлетворяющий диапазону дат + /// + /// + /// + /// + /// + /// + Task> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default); +} \ No newline at end of file diff --git a/Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs b/Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs new file mode 100644 index 0000000..ee0ca6e --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs @@ -0,0 +1,56 @@ +using Persistence.Models; + +namespace Persistence.Client.Clients.Interfaces; + +/// +/// Клиент для работы с данными с отметкой времени +/// +public interface ITimestampedSetClient +{ + /// + /// Записать новые данные + /// + /// + /// + /// + /// + Task AddRange(Guid idDiscriminator, IEnumerable sets, CancellationToken token); + + /// + /// Количество записей по указанному набору в БД. Для пагинации + /// + /// + /// + /// + Task Count(Guid idDiscriminator, CancellationToken token); + + /// + /// Получение данных с фильтрацией. Значение фильтра null - отключен + /// + /// + /// + /// + /// + /// + /// + /// + Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + + /// + /// Диапазон дат за которые есть данные + /// + /// + /// + /// + Task GetDatesRange(Guid idDiscriminator, CancellationToken token); + + /// + /// + /// + /// + /// + /// + /// + /// + Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token); +} \ No newline at end of file diff --git a/Persistence.Client/Clients/Interfaces/Refit/IRefitSetpointClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitSetpointClient.cs new file mode 100644 index 0000000..97baaba --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitSetpointClient.cs @@ -0,0 +1,30 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients.Interfaces.Refit; + +/// +/// Интерфейс клиента для работы с уставками +/// +public interface IRefitSetpointClient +{ + private const string BaseRoute = "/api/setpoint"; + + [Get($"{BaseRoute}/current")] + Task>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, CancellationToken token); + + [Get($"{BaseRoute}/history")] + Task>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, [Query] DateTimeOffset historyMoment, CancellationToken token); + + [Get($"{BaseRoute}/log")] + Task>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, CancellationToken token); + + [Get($"{BaseRoute}/range")] + Task> GetDatesRangeAsync(CancellationToken token); + + [Get($"{BaseRoute}/part")] + Task>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); + + [Post($"{BaseRoute}/")] + Task Add(Guid setpointKey, object newValue, CancellationToken token); +} diff --git a/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs new file mode 100644 index 0000000..68968a1 --- /dev/null +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitTechMessagesClient.cs @@ -0,0 +1,31 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients.Interfaces.Refit +{ + /// + /// Интерфейс клиента для хранения технологических сообщений + /// + public interface IRefitTechMessagesClient + { + private const string BaseRoute = "/api/techMessages"; + + [Get($"{BaseRoute}")] + Task>> GetPage([Query] RequestDto request, CancellationToken token); + + [Post($"{BaseRoute}")] + Task> AddRange([Body] IEnumerable dtos, CancellationToken token); + + [Get($"{BaseRoute}/systems")] + Task>> GetSystems(CancellationToken token); + + [Get($"{BaseRoute}/range")] + Task> GetDatesRangeAsync(CancellationToken token); + + [Get($"{BaseRoute}/part")] + Task>> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); + + [Get($"{BaseRoute}/statistics")] + Task>> GetStatistics([Query] string autoDrillingSystem, [Query] int categoryId, CancellationToken token); + } +} diff --git a/Persistence.Client/Clients/ITimeSeriesClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitTimeSeriesClient.cs similarity index 54% rename from Persistence.Client/Clients/ITimeSeriesClient.cs rename to Persistence.Client/Clients/Interfaces/Refit/IRefitTimeSeriesClient.cs index 8e97836..06a1266 100644 --- a/Persistence.Client/Clients/ITimeSeriesClient.cs +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitTimeSeriesClient.cs @@ -1,21 +1,21 @@ using Persistence.Models; using Refit; -namespace Persistence.Client.Clients; -public interface ITimeSeriesClient +namespace Persistence.Client.Clients.Interfaces.Refit; +public interface IRefitTimeSeriesClient where TDto : class, new() { private const string BaseRoute = "/api/dataSaub"; [Post($"{BaseRoute}")] - Task> AddRange(IEnumerable dtos); + Task> AddRange(IEnumerable dtos, CancellationToken token); [Get($"{BaseRoute}")] - Task>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd); + Task>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); [Get($"{BaseRoute}/resampled")] - Task>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024); - + Task>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default); + [Get($"{BaseRoute}/datesRange")] - Task> GetDatesRange(); + Task> GetDatesRange(CancellationToken token); } diff --git a/Persistence.Client/Clients/ITimestampedSetClient.cs b/Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedSetClient.cs similarity index 89% rename from Persistence.Client/Clients/ITimestampedSetClient.cs rename to Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedSetClient.cs index bbff603..b379725 100644 --- a/Persistence.Client/Clients/ITimestampedSetClient.cs +++ b/Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedSetClient.cs @@ -1,7 +1,7 @@ using Persistence.Models; using Refit; -namespace Persistence.Client.Clients; +namespace Persistence.Client.Clients.Interfaces.Refit; /// /// Клиент для работы с репозиторием для хранения разных наборов данных рядов. @@ -9,7 +9,7 @@ namespace Persistence.Client.Clients; /// idDiscriminator формируют клиенты и только им известно что они обозначают. /// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено. /// -public interface ITimestampedSetClient +public interface IRefitTimestampedSetClient { private const string baseUrl = "/api/TimestampedSet/{idDiscriminator}"; @@ -20,7 +20,7 @@ public interface ITimestampedSetClient /// /// [Post(baseUrl)] - Task> AddRange(Guid idDiscriminator, IEnumerable sets); + Task> AddRange(Guid idDiscriminator, IEnumerable sets, CancellationToken token); /// /// Получение данных с фильтрацией. Значение фильтра null - отключен @@ -32,7 +32,7 @@ public interface ITimestampedSetClient /// /// [Get(baseUrl)] - Task>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable? columnNames, int skip, int take); + Task>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable? columnNames, int skip, int take, CancellationToken token); /// /// Получить последние данные @@ -42,7 +42,7 @@ public interface ITimestampedSetClient /// /// [Get($"{baseUrl}/last")] - Task>> GetLast(Guid idDiscriminator, [Query] IEnumerable? columnNames, int take); + Task>> GetLast(Guid idDiscriminator, [Query] IEnumerable? columnNames, int take, CancellationToken token); /// /// Количество записей по указанному набору в БД. Для пагинации. @@ -50,7 +50,7 @@ public interface ITimestampedSetClient /// Дискриминатор (идентификатор) набора /// [Get($"{baseUrl}/count")] - Task> Count(Guid idDiscriminator); + Task> Count(Guid idDiscriminator, CancellationToken token); /// /// Диапазон дат за которые есть данные @@ -58,5 +58,5 @@ public interface ITimestampedSetClient /// Дискриминатор (идентификатор) набора /// [Get($"{baseUrl}/datesRange")] - Task> GetDatesRange(Guid idDiscriminator); + Task> GetDatesRange(Guid idDiscriminator, CancellationToken token); } diff --git a/Persistence.Client/Clients/SetpointClient.cs b/Persistence.Client/Clients/SetpointClient.cs new file mode 100644 index 0000000..91e10e2 --- /dev/null +++ b/Persistence.Client/Clients/SetpointClient.cs @@ -0,0 +1,63 @@ +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 logger) : base(logger) + { + this.refitSetpointClient = refitSetpointClient; + } + + public async Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitSetpointClient.GetCurrent(setpointKeys, token), token); + + return result; + } + + public async Task> GetHistory(IEnumerable setpointKeys, DateTimeOffset historyMoment, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitSetpointClient.GetHistory(setpointKeys, historyMoment, token), token); + + return result; + } + + public async Task>> GetLog(IEnumerable setpointKeys, CancellationToken token) + { + var result = await ExecuteGetResponse>>( + async () => await refitSetpointClient.GetLog(setpointKeys, token), token); + + return result; + } + + public async Task GetDatesRangeAsync(CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await refitSetpointClient.GetDatesRangeAsync(token), token); + + return result; + } + + public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) + { + var result = await ExecuteGetResponse>( + 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); + } +} diff --git a/Persistence.Client/Clients/TechMessagesClient.cs b/Persistence.Client/Clients/TechMessagesClient.cs new file mode 100644 index 0000000..2a7b0e0 --- /dev/null +++ b/Persistence.Client/Clients/TechMessagesClient.cs @@ -0,0 +1,65 @@ +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 TechMessagesClient : BaseClient, ITechMessagesClient +{ + private readonly IRefitTechMessagesClient refitTechMessagesClient; + + public TechMessagesClient(IRefitTechMessagesClient refitTechMessagesClient, ILogger logger) : base(logger) + { + this.refitTechMessagesClient = refitTechMessagesClient; + } + + public async Task> GetPage(RequestDto request, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTechMessagesClient.GetPage(request, token), token); + + return result; + } + + public async Task AddRange(IEnumerable dtos, CancellationToken token) + { + var result = await ExecutePostResponse( + async () => await refitTechMessagesClient.AddRange(dtos, token), token); + + return result; + } + + public async Task> GetSystems(CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTechMessagesClient.GetSystems(token), token); + + return result; + } + + public async Task GetDatesRangeAsync(CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await refitTechMessagesClient.GetDatesRangeAsync(token), token); + + return result; + } + + public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTechMessagesClient.GetPart(dateBegin, take, token), token); + + return result; + } + + public async Task> GetStatistics(string autoDrillingSystem, int categoryId, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTechMessagesClient.GetStatistics(autoDrillingSystem, categoryId, token), token); + + return result; + } +} diff --git a/Persistence.Client/Clients/TimeSeriesClient.cs b/Persistence.Client/Clients/TimeSeriesClient.cs new file mode 100644 index 0000000..0b49c81 --- /dev/null +++ b/Persistence.Client/Clients/TimeSeriesClient.cs @@ -0,0 +1,48 @@ +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 : BaseClient, ITimeSeriesClient where TDto : class, new() +{ + private readonly IRefitTimeSeriesClient timeSeriesClient; + + public TimeSeriesClient(IRefitTimeSeriesClient refitTechMessagesClient, ILogger logger) : base(logger) + { + this.timeSeriesClient = refitTechMessagesClient; + } + + public async Task AddRange(IEnumerable dtos, CancellationToken token) + { + var result = await ExecutePostResponse( + async () => await timeSeriesClient.AddRange(dtos, token), token); + + return result; + } + + public async Task> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await timeSeriesClient.Get(dateBegin, dateEnd, token), token); + + return result; + } + + public async Task> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default) + { + var result = await ExecuteGetResponse>( + async () => await timeSeriesClient.GetResampledData(dateBegin, intervalSec, approxPointsCount, token), token); + + return result; + } + + public async Task GetDatesRange(CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await timeSeriesClient.GetDatesRange(token), token); + + return result; + } +} diff --git a/Persistence.Client/Clients/TimestampedSetClient.cs b/Persistence.Client/Clients/TimestampedSetClient.cs new file mode 100644 index 0000000..2e23682 --- /dev/null +++ b/Persistence.Client/Clients/TimestampedSetClient.cs @@ -0,0 +1,56 @@ +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 logger) : base(logger) + { + this.refitTimestampedSetClient = refitTimestampedSetClient; + } + + public async Task AddRange(Guid idDiscriminator, IEnumerable sets, CancellationToken token) + { + var result = await ExecutePostResponse( + async () => await refitTimestampedSetClient.AddRange(idDiscriminator, sets, token), token); + + return result; + } + + public async Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTimestampedSetClient.Get(idDiscriminator, geTimestamp, columnNames, skip, take, token), token); + + return result; + } + + public async Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token) + { + var result = await ExecuteGetResponse>( + async () => await refitTimestampedSetClient.GetLast(idDiscriminator, columnNames, take, token), token); + + return result; + } + + public async Task Count(Guid idDiscriminator, CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await refitTimestampedSetClient.Count(idDiscriminator, token), token); + + return result; + } + + public async Task GetDatesRange(Guid idDiscriminator, CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await refitTimestampedSetClient.GetDatesRange(idDiscriminator, token), token); + + return result; + } +} diff --git a/Persistence.Client/CustomExceptions/AcceptableException.cs b/Persistence.Client/CustomExceptions/AcceptableException.cs new file mode 100644 index 0000000..0bdea54 --- /dev/null +++ b/Persistence.Client/CustomExceptions/AcceptableException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Not Acceptable (406) +/// +public class AcceptableException : Exception +{ + public AcceptableException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/BadGatewayException.cs b/Persistence.Client/CustomExceptions/BadGatewayException.cs new file mode 100644 index 0000000..2730140 --- /dev/null +++ b/Persistence.Client/CustomExceptions/BadGatewayException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Bad gateway (502) +/// +public class BadGatewayException : Exception +{ + public BadGatewayException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/ForbiddenException.cs b/Persistence.Client/CustomExceptions/ForbiddenException.cs new file mode 100644 index 0000000..bfd9e7d --- /dev/null +++ b/Persistence.Client/CustomExceptions/ForbiddenException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Forbidden (403) +/// +public class ForbiddenException : Exception +{ + public ForbiddenException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/InternalServerException.cs b/Persistence.Client/CustomExceptions/InternalServerException.cs new file mode 100644 index 0000000..6e8265b --- /dev/null +++ b/Persistence.Client/CustomExceptions/InternalServerException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Internal Server Error (500) +/// +public class InternalServerException : Exception +{ + public InternalServerException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/LockedException.cs b/Persistence.Client/CustomExceptions/LockedException.cs new file mode 100644 index 0000000..c24dca4 --- /dev/null +++ b/Persistence.Client/CustomExceptions/LockedException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Locked (423) +/// +public class LockedException : Exception +{ + public LockedException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/ServiceUnavailableException.cs b/Persistence.Client/CustomExceptions/ServiceUnavailableException.cs new file mode 100644 index 0000000..3929d42 --- /dev/null +++ b/Persistence.Client/CustomExceptions/ServiceUnavailableException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Service Unavailable Error (503) +/// +public class ServiceUnavailableException : Exception +{ + public ServiceUnavailableException(string message) + : base(message) { } +} diff --git a/Persistence.Client/CustomExceptions/TooManyRequestsException.cs b/Persistence.Client/CustomExceptions/TooManyRequestsException.cs new file mode 100644 index 0000000..d28f642 --- /dev/null +++ b/Persistence.Client/CustomExceptions/TooManyRequestsException.cs @@ -0,0 +1,10 @@ +namespace Persistence.Client.CustomExceptions; + +/// +/// Too Many Requests (429) +/// +public class TooManyRequestsException : Exception +{ + public TooManyRequestsException(string message) + : base(message) { } +} diff --git a/Persistence.Client/Helpers/ApiTokenHelper.cs b/Persistence.Client/Helpers/ApiTokenHelper.cs index 5eed66e..de163a9 100644 --- a/Persistence.Client/Helpers/ApiTokenHelper.cs +++ b/Persistence.Client/Helpers/ApiTokenHelper.cs @@ -27,6 +27,11 @@ public static class ApiTokenHelper 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) { var nameIdetifier = Guid.NewGuid().ToString(); diff --git a/Persistence.Client/Helpers/ExceptionsHelper.cs b/Persistence.Client/Helpers/ExceptionsHelper.cs new file mode 100644 index 0000000..8c349ba --- /dev/null +++ b/Persistence.Client/Helpers/ExceptionsHelper.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; +using Persistence.Client.CustomExceptions; +using Refit; + +namespace Persistence.Client.Helpers; +public static class ExceptionsHelper +{ + private static readonly Dictionary ExceptionsDictionary = new Dictionary() + { + { 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) + { + var exception = ExceptionsDictionary + .FirstOrDefault(e => e.Key == response.StatusCode).Value ?? new Exception("Неопознанная ошибка"); + + return exception; + } +} diff --git a/Persistence.Client/Persistence.Client.csproj b/Persistence.Client/Persistence.Client.csproj index d699df7..72aa381 100644 --- a/Persistence.Client/Persistence.Client.csproj +++ b/Persistence.Client/Persistence.Client.csproj @@ -18,8 +18,4 @@ - - - - diff --git a/Persistence.Client/PersistenceClientFactory.cs b/Persistence.Client/PersistenceClientFactory.cs index e84327d..26fb09d 100644 --- a/Persistence.Client/PersistenceClientFactory.cs +++ b/Persistence.Client/PersistenceClientFactory.cs @@ -1,7 +1,12 @@ using System.Text.Json; using Microsoft.Extensions.Configuration; +using Persistence.Client.Clients.Interfaces; +using Persistence.Client.Clients; using Persistence.Client.Helpers; using Refit; +using Persistence.Factories; +using Persistence.Client.Clients.Interfaces.Refit; +using Microsoft.Extensions.Logging; namespace Persistence.Client { @@ -16,17 +21,75 @@ namespace Persistence.Client PropertyNameCaseInsensitive = true }; private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); + private readonly ILogger logger; private HttpClient httpClient; - public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IConfiguration configuration) + public PersistenceClientFactory(IHttpClientFactory httpClientFactory, ILogger logger, IConfiguration configuration) { - this.httpClient = httpClientFactory.CreateClient(); + this.logger = logger; + + httpClient = httpClientFactory.CreateClient(); httpClient.Authorize(configuration); } - public T GetClient() + public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IAuthTokenFactory authTokenFactory, ILogger logger, IConfiguration configuration) { - return RestService.For(httpClient, RefitSettings); + this.logger = logger; + + httpClient = httpClientFactory.CreateClient(); + + var token = authTokenFactory.GetToken(); + httpClient.Authorize(token); + } + + /// + /// Получить клиент для работы с уставками + /// + /// + public ISetpointClient GetSetpointClient() + { + var restClient = RestService.For(httpClient, RefitSettings); + var client = new SetpointClient(restClient, logger); + + return client; + } + + /// + /// Получить клиент для работы с технологическими сообщениями + /// + /// + public ITechMessagesClient GetTechMessagesClient() + { + var restClient = RestService.For(httpClient, RefitSettings); + var client = new TechMessagesClient(restClient, logger); + + return client; + } + + /// + /// Получить клиент для работы с временными данными + /// + /// + /// + public ITimeSeriesClient GetTimeSeriesClient() + where TDto : class, new() + { + var restClient = RestService.For>(httpClient, RefitSettings); + var client = new TimeSeriesClient(restClient, logger); + + return client; + } + + /// + /// Получить клиент для работы с данными с отметкой времени + /// + /// + public ITimestampedSetClient GetTimestampedSetClient() + { + var restClient = RestService.For(httpClient, RefitSettings); + var client = new TimestampedSetClient(restClient, logger); + + return client; } } } diff --git a/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs b/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs index 2c455a0..c52b530 100644 --- a/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs @@ -1,8 +1,6 @@ -using System.Net; -using Microsoft.AspNetCore.Mvc.TagHelpers.Cache; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Persistence.Client; -using Persistence.Client.Clients; +using Persistence.Client.Clients.Interfaces; using Persistence.Database.Model; using Xunit; @@ -22,7 +20,7 @@ namespace Persistence.IntegrationTests.Controllers var persistenceClientFactory = scope.ServiceProvider .GetRequiredService(); - setpointClient = persistenceClientFactory.GetClient(); + setpointClient = persistenceClientFactory.GetSetpointClient(); } [Fact] @@ -36,12 +34,11 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await setpointClient.GetCurrent(setpointKeys); + var response = await setpointClient.GetCurrent(setpointKeys, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -51,13 +48,12 @@ namespace Persistence.IntegrationTests.Controllers var setpointKey = await Add(); //act - var response = await setpointClient.GetCurrent([setpointKey]); + var response = await setpointClient.GetCurrent([setpointKey], new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotEmpty(response.Content); - Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key); + Assert.NotNull(response); + Assert.NotEmpty(response); + Assert.Equal(setpointKey, response.FirstOrDefault()?.Key); } [Fact] @@ -72,12 +68,11 @@ namespace Persistence.IntegrationTests.Controllers var historyMoment = DateTimeOffset.UtcNow; //act - var response = await setpointClient.GetHistory(setpointKeys, historyMoment); + var response = await setpointClient.GetHistory(setpointKeys, historyMoment, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -89,13 +84,12 @@ namespace Persistence.IntegrationTests.Controllers historyMoment = historyMoment.AddDays(1); //act - var response = await setpointClient.GetHistory([setpointKey], historyMoment); + var response = await setpointClient.GetHistory([setpointKey], historyMoment, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotEmpty(response.Content); - Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key); + Assert.NotNull(response); + Assert.NotEmpty(response); + Assert.Equal(setpointKey, response.FirstOrDefault()?.Key); } [Fact] @@ -109,12 +103,11 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await setpointClient.GetLog(setpointKeys); + var response = await setpointClient.GetLog(setpointKeys, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -124,13 +117,12 @@ namespace Persistence.IntegrationTests.Controllers var setpointKey = await Add(); //act - var response = await setpointClient.GetLog([setpointKey]); + var response = await setpointClient.GetLog([setpointKey], new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotEmpty(response.Content); - Assert.Equal(setpointKey, response.Content.FirstOrDefault().Key); + Assert.NotNull(response); + Assert.NotEmpty(response); + Assert.Equal(setpointKey, response.FirstOrDefault().Key); } [Fact] @@ -143,10 +135,9 @@ namespace Persistence.IntegrationTests.Controllers var response = await setpointClient.GetDatesRangeAsync(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Equal(DateTimeOffset.MinValue, response.Content!.From); - Assert.Equal(DateTimeOffset.MaxValue, response.Content!.To); + Assert.NotNull(response); + Assert.Equal(DateTimeOffset.MinValue, response!.From); + Assert.Equal(DateTimeOffset.MaxValue, response!.To); } [Fact] @@ -165,17 +156,16 @@ namespace Persistence.IntegrationTests.Controllers var response = await setpointClient.GetDatesRangeAsync(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); + Assert.NotNull(response); - var expectedValue = part.Content! + var expectedValue = part! .FirstOrDefault()!.Created .ToString("dd.MM.yyyy-HH:mm:ss"); - var actualValueFrom = response.Content.From + var actualValueFrom = response.From .ToString("dd.MM.yyyy-HH:mm:ss"); Assert.Equal(expectedValue, actualValueFrom); - var actualValueTo = response.Content.To + var actualValueTo = response.To .ToString("dd.MM.yyyy-HH:mm:ss"); Assert.Equal(expectedValue, actualValueTo); } @@ -191,9 +181,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await setpointClient.GetPart(dateBegin, take, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -208,9 +197,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await setpointClient.GetPart(dateBegin, take, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotEmpty(response.Content); + Assert.NotNull(response); + Assert.NotEmpty(response); } [Fact] @@ -230,10 +218,7 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await setpointClient.Add(setpointKey, setpointValue); - - //assert - Assert.Equal(HttpStatusCode.Created, response.StatusCode); + await setpointClient.Add(setpointKey, setpointValue, new CancellationToken()); return setpointKey; } diff --git a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs index 1f194ad..6fdae61 100644 --- a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs @@ -1,8 +1,7 @@ -using System.Net; -using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Persistence.Client; -using Persistence.Client.Clients; +using Persistence.Client.Clients.Interfaces; using Persistence.Database.Entity; using Persistence.Models; using Xunit; @@ -20,7 +19,7 @@ namespace Persistence.IntegrationTests.Controllers var persistenceClientFactory = scope.ServiceProvider .GetRequiredService(); - techMessagesClient = persistenceClientFactory.GetClient(); + techMessagesClient = persistenceClientFactory.GetTechMessagesClient(); memoryCache = scope.ServiceProvider.GetRequiredService(); } @@ -43,11 +42,10 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content.Items); - Assert.Equal(requestDto.Skip, response.Content.Skip); - Assert.Equal(requestDto.Take, response.Content.Take); + Assert.NotNull(response); + Assert.Empty(response.Items); + Assert.Equal(requestDto.Skip, response.Skip); + Assert.Equal(requestDto.Take, response.Take); } [Fact] @@ -67,9 +65,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Equal(dtosCount, response.Content.Count); + Assert.NotNull(response); + Assert.Equal(dtosCount, response.Count); } [Fact] @@ -82,6 +79,7 @@ namespace Persistence.IntegrationTests.Controllers public async Task InsertRange_returns_BadRequest() { //arrange + var exceptionMessage = "Ошибка валидации, формата или маршрутизации запроса"; var dtos = new List() { new TechMessageDto() @@ -96,11 +94,16 @@ namespace Persistence.IntegrationTests.Controllers } }; - //act - var response = await techMessagesClient.AddRange(dtos, new CancellationToken()); - - //assert - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + try + { + //act + var response = await techMessagesClient.AddRange(dtos, new CancellationToken()); + } + catch (Exception ex) + { + //assert + Assert.Equal(exceptionMessage, ex.Message); + } } [Fact] @@ -115,9 +118,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetSystems(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -134,9 +136,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetSystems(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - string?[]? content = response.Content?.ToArray(); + Assert.NotNull(response); + string?[]? content = response?.ToArray(); Assert.Equal(systems, content); } @@ -155,9 +156,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetStatistics(autoDrillingSystem, imortantId, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -173,9 +173,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetStatistics(autoDrillingSystem, imortantId, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var categories = response.Content + Assert.NotNull(response); + var categories = response .FirstOrDefault()?.Categories .FirstOrDefault(e => e.Key == 0).Value; Assert.Equal(filteredDtos.Count(), categories); @@ -184,14 +183,18 @@ namespace Persistence.IntegrationTests.Controllers [Fact] public async Task GetDatesRange_returns_success() { + //arrange + memoryCache.Remove(SystemCacheKey); + dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); + //act var response = await techMessagesClient.GetDatesRangeAsync(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - //Assert.Equal(DateTimeOffset.MinValue, response.Content?.From); - //Assert.Equal(DateTimeOffset.MaxValue, response.Content?.To); + Assert.NotNull(response); + Assert.Equal(DateTimeOffset.MinValue, response?.From); + Assert.Equal(DateTimeOffset.MaxValue, response?.To); } [Fact] @@ -204,10 +207,9 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetDatesRangeAsync(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotNull(response.Content?.From); - Assert.NotNull(response.Content?.To); + Assert.NotNull(response); + Assert.NotNull(response?.From); + Assert.NotNull(response?.To); } [Fact] @@ -221,9 +223,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetPart(dateBegin, take, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Empty(response.Content); + Assert.NotNull(response); + Assert.Empty(response); } [Fact] @@ -238,9 +239,8 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.GetPart(dateBegin, take, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.NotEmpty(response.Content); + Assert.NotNull(response); + Assert.NotEmpty(response); } private async Task> InsertRange() @@ -279,8 +279,7 @@ namespace Persistence.IntegrationTests.Controllers var response = await techMessagesClient.AddRange(dtos, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.Created, response.StatusCode); - Assert.Equal(dtos.Count, response.Content); + Assert.Equal(dtos.Count, response); return dtos; } diff --git a/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs b/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs index 08bb11e..ca9536f 100644 --- a/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs @@ -2,7 +2,7 @@ using System.Net; using Mapster; using Microsoft.Extensions.DependencyInjection; using Persistence.Client; -using Persistence.Client.Clients; +using Persistence.Client.Clients.Interfaces; using Persistence.Database.Model; using Xunit; @@ -21,7 +21,7 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat var persistenceClientFactory = scope.ServiceProvider .GetRequiredService(); - timeSeriesClient = persistenceClientFactory.GetClient>(); + timeSeriesClient = persistenceClientFactory.GetTimeSeriesClient(); } public async Task InsertRangeSuccess(TDto dto) @@ -30,11 +30,10 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat var expected = dto.Adapt(); //act - var response = await timeSeriesClient.AddRange(new TDto[] { expected }); + var response = await timeSeriesClient.AddRange(new TDto[] { expected }, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(1, response.Content); + Assert.Equal(1, response); } public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity) @@ -46,12 +45,11 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat dbContext.SaveChanges(); - var response = await timeSeriesClient.Get(beginDate, endDate); + var response = await timeSeriesClient.Get(beginDate, endDate, new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - Assert.Single(response.Content); + Assert.NotNull(response); + Assert.Single(response); } public async Task GetDatesRangeSuccess(TEntity entity) @@ -68,13 +66,12 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat dbContext.SaveChanges(); - var response = await timeSeriesClient.GetDatesRange(); + var response = await timeSeriesClient.GetDatesRange(new CancellationToken()); //assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); + Assert.NotNull(response); - var datesRangeActual = (response.Content.To - response.Content.From).Days; + var datesRangeActual = (response.To - response.From).Days; Assert.Equal(datesRangeExpected, datesRangeActual); } @@ -98,11 +95,10 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat 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.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); + Assert.NotNull(response); var ratio = entities.Count() / approxPointsCount; if (ratio > 1) @@ -111,15 +107,11 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat .Where((_, index) => index % ratio == 0) .Count(); - Assert.Equal(expectedResampledCount, response.Content.Count()); + Assert.Equal(expectedResampledCount, response.Count()); } else { - Assert.Equal(entities.Count(), response.Content.Count()); + Assert.Equal(entities.Count(), response.Count()); } - - } - - } diff --git a/Persistence.IntegrationTests/Controllers/TimestampedSetControllerTest.cs b/Persistence.IntegrationTests/Controllers/TimestampedSetControllerTest.cs index 3fc7dff..2d52a49 100644 --- a/Persistence.IntegrationTests/Controllers/TimestampedSetControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TimestampedSetControllerTest.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Persistence.Client; -using Persistence.Client.Clients; +using Persistence.Client.Clients.Interfaces; using Persistence.Models; using Xunit; @@ -14,7 +14,7 @@ public class TimestampedSetControllerTest : BaseIntegrationTest var persistenceClientFactory = scope.ServiceProvider .GetRequiredService(); - client = persistenceClientFactory.GetClient(); + client = persistenceClientFactory.GetTimestampedSetClient(); } [Fact] @@ -25,11 +25,10 @@ public class TimestampedSetControllerTest : BaseIntegrationTest IEnumerable testSets = Generate(10, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); // act - var response = await client.AddRange(idDiscriminator, testSets); + var response = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.Equal(testSets.Count(), response.Content); + Assert.Equal(testSets.Count(), response); } [Fact] @@ -39,16 +38,14 @@ public class TimestampedSetControllerTest : BaseIntegrationTest Guid idDiscriminator = Guid.NewGuid(); int count = 10; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); // act - var response = await client.Get(idDiscriminator, null, null, 0, int.MaxValue); + var response = await client.Get(idDiscriminator, null, null, 0, int.MaxValue, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(count, items.Count()); + Assert.NotNull(response); + Assert.Equal(count, response.Count()); } [Fact] @@ -58,26 +55,24 @@ public class TimestampedSetControllerTest : BaseIntegrationTest Guid idDiscriminator = Guid.NewGuid(); int count = 10; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); string[] props = ["A"]; // 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.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(count, items.Count()); - foreach ( var item in items ) - { - Assert.Single(item.Set); - var kv = item.Set.First(); - Assert.Equal("A", kv.Key); - } - } + Assert.NotNull(response); + Assert.Equal(count, response.Count()); + foreach ( var item in response ) + { + Assert.Single(item.Set); + var kv = item.Set.First(); + Assert.Equal("A", kv.Key); + } + } - [Fact] + [Fact] public async Task Get_geDate() { // arrange @@ -86,21 +81,19 @@ public class TimestampedSetControllerTest : BaseIntegrationTest var dateMin = DateTimeOffset.Now; var dateMax = DateTimeOffset.Now.AddSeconds(count); IEnumerable testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); var tail = testSets.OrderBy(t => t.Timestamp).Skip(count / 2).Take(int.MaxValue); var geDate = tail.First().Timestamp; var tolerance = TimeSpan.FromSeconds(1); var expectedCount = tail.Count(); // act - var response = await client.Get(idDiscriminator, geDate, null, 0, int.MaxValue); + var response = await client.Get(idDiscriminator, geDate, null, 0, int.MaxValue, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(expectedCount, items.Count()); - var minDate = items.Min(t => t.Timestamp); + Assert.NotNull(response); + Assert.Equal(expectedCount, response.Count()); + var minDate = response.Min(t => t.Timestamp); Assert.Equal(geDate, geDate, tolerance); } @@ -111,21 +104,19 @@ public class TimestampedSetControllerTest : BaseIntegrationTest Guid idDiscriminator = Guid.NewGuid(); int count = 10; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); var expectedCount = count / 2; // 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.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(expectedCount, items.Count()); - } + Assert.NotNull(response); + Assert.Equal(expectedCount, response.Count()); + } - [Fact] + [Fact] public async Task Get_with_big_skip_take() { // arrange @@ -133,16 +124,14 @@ public class TimestampedSetControllerTest : BaseIntegrationTest var expectedCount = 1; int count = 10 + expectedCount; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); // 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.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(expectedCount, items.Count()); + Assert.NotNull(response); + Assert.Equal(expectedCount, response.Count()); } [Fact] @@ -152,17 +141,15 @@ public class TimestampedSetControllerTest : BaseIntegrationTest Guid idDiscriminator = Guid.NewGuid(); int count = 10; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); var expectedCount = 8; // act - var response = await client.GetLast(idDiscriminator, null, expectedCount); + var response = await client.GetLast(idDiscriminator, null, expectedCount, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var items = response.Content!; - Assert.Equal(expectedCount, items.Count()); + Assert.NotNull(response); + Assert.Equal(expectedCount, response.Count()); } [Fact] @@ -174,18 +161,16 @@ public class TimestampedSetControllerTest : BaseIntegrationTest var dateMin = DateTimeOffset.Now; var dateMax = DateTimeOffset.Now.AddSeconds(count-1); IEnumerable testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); var tolerance = TimeSpan.FromSeconds(1); // act - var response = await client.GetDatesRange(idDiscriminator); + var response = await client.GetDatesRange(idDiscriminator, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(response.Content); - var range = response.Content!; - Assert.Equal(dateMin, range.From, tolerance); - Assert.Equal(dateMax, range.To, tolerance); + Assert.NotNull(response); + Assert.Equal(dateMin, response.From, tolerance); + Assert.Equal(dateMax, response.To, tolerance); } [Fact] @@ -195,14 +180,13 @@ public class TimestampedSetControllerTest : BaseIntegrationTest Guid idDiscriminator = Guid.NewGuid(); int count = 144; IEnumerable testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7))); - var insertResponse = await client.AddRange(idDiscriminator, testSets); + var insertResponse = await client.AddRange(idDiscriminator, testSets, new CancellationToken()); // act - var response = await client.Count(idDiscriminator); + var response = await client.Count(idDiscriminator, new CancellationToken()); // assert - Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); - Assert.Equal(count, response.Content); + Assert.Equal(count, response); } private static IEnumerable Generate(int n, DateTimeOffset from) diff --git a/Persistence.IntegrationTests/WebAppFactoryFixture.cs b/Persistence.IntegrationTests/WebAppFactoryFixture.cs index 7b12362..1410b04 100644 --- a/Persistence.IntegrationTests/WebAppFactoryFixture.cs +++ b/Persistence.IntegrationTests/WebAppFactoryFixture.cs @@ -4,8 +4,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; using Persistence.API; -using Persistence.Database; using Persistence.Client; using Persistence.Database.Model; using Persistence.Database.Postgres; @@ -34,6 +34,8 @@ public class WebAppFactoryFixture : WebApplicationFactory services.AddDbContext(options => options.UseNpgsql(connectionString)); + services.AddLogging(builder => builder.AddConsole()); + services.RemoveAll(); services.AddSingleton(provider => { diff --git a/Persistence/Factories/IAuthTokenFactory.cs b/Persistence/Factories/IAuthTokenFactory.cs new file mode 100644 index 0000000..2b12095 --- /dev/null +++ b/Persistence/Factories/IAuthTokenFactory.cs @@ -0,0 +1,13 @@ +namespace Persistence.Factories; + +/// +/// Фабрика токенов аутентификации +/// +public interface IAuthTokenFactory +{ + /// + /// Получить токен + /// + /// + public string GetToken(); +}