forked from ddrilling/AsbCloudServer
Merge branch 'dev' into feature/telemetry
# Conflicts: # AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
This commit is contained in:
commit
ea7e8cbd4b
@ -10,7 +10,7 @@ public class WellboreDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Скважина
|
/// Скважина
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WellWithTimezoneDto Well { get; set; } = null!;
|
public WellDto Well { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Идентификатор
|
/// Идентификатор
|
||||||
|
62
AsbCloudApp/Repositories/ITelemetryDataCache.cs
Normal file
62
AsbCloudApp/Repositories/ITelemetryDataCache.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Repositories
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Хранилище кеша
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDto"></typeparam>
|
||||||
|
public interface ITelemetryDataCache<TDto> where TDto : ITelemetryData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// добавить в кеш чанк записей по телеметрии
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <param name="range"></param>
|
||||||
|
void AddRange(int idTelemetry, IEnumerable<TDto> range);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// вернуть последнюю записть
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
TDto? GetLastOrDefault(int idTelemetry);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить кешированые записи
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="intervalSec"></param>
|
||||||
|
/// <param name="approxPointsCount">приблизительное кол-во возвращаемых записей после их прореживания</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IEnumerable<TDto>? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600, int approxPointsCount = 1024);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить кешированые записи
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IEnumerable<TDto>? GetOrDefault(int idTelemetry, TelemetryDataRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат телеметрии.
|
||||||
|
/// Дата первой записи телеметрии храниться отдельно и запоняется при инициализации
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
DatesRangeDto? GetOrDefaultDataDateRange(int idTelemetry);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение первой и последней записи телеметрии.
|
||||||
|
/// Первая запись телеметрии храниться отдельно и запоняется при инициализации
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry);
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace AsbCloudApp.Requests;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Параметры запроса для ствола скважины
|
|
||||||
/// </summary>
|
|
||||||
public class WellboreRequest : RequestBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Пары идентификаторов скважины и секции
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<(int idWell, int? idSection)> Ids { get; set; } = null!;
|
|
||||||
}
|
|
@ -42,7 +42,6 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="start"></param>
|
/// <param name="start"></param>
|
||||||
/// <param name="end"></param>
|
/// <param name="end"></param>
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
DatesRangeDto? GetRange(int idWell, DateTimeOffset start, DateTimeOffset end);
|
DatesRangeDto? GetRange(int idWell, DateTimeOffset start, DateTimeOffset end);
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ using System.Collections.Generic;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
|
|
||||||
namespace AsbCloudApp.Services;
|
namespace AsbCloudApp.Services;
|
||||||
|
|
||||||
@ -11,20 +10,11 @@ namespace AsbCloudApp.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWellboreService
|
public interface IWellboreService
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Получение ствола скважины
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="idWell"></param>
|
|
||||||
/// <param name="idSection"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<WellboreDto?> GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение стволов скважин
|
/// Получение стволов скважин
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
/// <param name="idsWells"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<WellboreDto>> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken);
|
Task<IEnumerable<WellboreDto>> GetWellboresAsync(IEnumerable<int> idsWells, CancellationToken cancellationToken);
|
||||||
}
|
}
|
@ -162,8 +162,8 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetRequiredService<AsbCloudDbContext>());
|
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetRequiredService<AsbCloudDbContext>());
|
||||||
|
|
||||||
services.AddSingleton(new WitsInfoService());
|
services.AddSingleton(new WitsInfoService());
|
||||||
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
services.AddSingleton<ITelemetryDataCache<TelemetryDataSaubDto>>(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
||||||
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
|
services.AddSingleton<ITelemetryDataCache<TelemetryDataSpinDto>>(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
|
||||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||||
services.AddSingleton<BackgroundWorker>();
|
services.AddSingleton<BackgroundWorker>();
|
||||||
services.AddSingleton<NotificationBackgroundWorker>();
|
services.AddSingleton<NotificationBackgroundWorker>();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
@ -18,12 +19,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
{
|
{
|
||||||
protected readonly IAsbCloudDbContext db;
|
protected readonly IAsbCloudDbContext db;
|
||||||
protected readonly ITelemetryService telemetryService;
|
protected readonly ITelemetryService telemetryService;
|
||||||
protected readonly TelemetryDataCache<TDto> telemetryDataCache;
|
protected readonly ITelemetryDataCache<TDto> telemetryDataCache;
|
||||||
|
|
||||||
public TelemetryDataBaseService(
|
public TelemetryDataBaseService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
TelemetryDataCache<TDto> telemetryDataCache)
|
ITelemetryDataCache<TDto> telemetryDataCache)
|
||||||
{
|
{
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
|
@ -11,15 +11,15 @@ using AsbCloudInfrastructure.Background;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
namespace AsbCloudInfrastructure.Services.SAUB
|
||||||
{
|
{
|
||||||
public class TelemetryDataCache<TDto>
|
public class TelemetryDataCache<TDto> : ITelemetryDataCache<TDto> where TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
|
||||||
{
|
{
|
||||||
class TelemetryDataCacheItem
|
class TelemetryDataCacheItem
|
||||||
{
|
{
|
||||||
public TDto? FirstByDate { get; init; }
|
public TDto FirstByDate { get; init; } = default!;
|
||||||
public CyclycArray<TDto> LastData { get; init; } = null!;
|
public CyclycArray<TDto> LastData { get; init; } = null!;
|
||||||
public double TimezoneHours { get; init; } = 5;
|
public double TimezoneHours { get; init; } = 5;
|
||||||
}
|
}
|
||||||
@ -48,7 +48,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
instance = new TelemetryDataCache<TDto>();
|
instance = new TelemetryDataCache<TDto>();
|
||||||
var worker = provider.GetRequiredService<BackgroundWorker>();
|
var worker = provider.GetRequiredService<BackgroundWorker>();
|
||||||
var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
|
var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
|
||||||
var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) => {
|
var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) =>
|
||||||
|
{
|
||||||
var db = provider.GetRequiredService<IAsbCloudDbContext>();
|
var db = provider.GetRequiredService<IAsbCloudDbContext>();
|
||||||
await instance.InitializeCacheFromDBAsync<TEntity>(db, onProgress, token);
|
await instance.InitializeCacheFromDBAsync<TEntity>(db, onProgress, token);
|
||||||
});
|
});
|
||||||
@ -125,7 +126,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TDto? GetLastOrDefault(int idTelemetry)
|
public virtual TDto? GetLastOrDefault(int idTelemetry)
|
||||||
{
|
{
|
||||||
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
||||||
return default;
|
return default;
|
||||||
@ -148,6 +149,19 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return new DatesRangeDto { From = from.Value, To = to };
|
return new DatesRangeDto { From = from.Value, To = to };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry)
|
||||||
|
{
|
||||||
|
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!cacheItem.LastData.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var last = cacheItem.LastData[^1];
|
||||||
|
var first = cacheItem.FirstByDate;
|
||||||
|
return (first, last);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task InitializeCacheFromDBAsync<TEntity>(IAsbCloudDbContext db, Action<string, double?> onProgress, CancellationToken token)
|
private async Task InitializeCacheFromDBAsync<TEntity>(IAsbCloudDbContext db, Action<string, double?> onProgress, CancellationToken token)
|
||||||
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
||||||
{
|
{
|
||||||
@ -215,7 +229,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var dtos = entities
|
var dtos = entities
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.Reverse()
|
.Reverse()
|
||||||
.Select(entity => {
|
.Select(entity =>
|
||||||
|
{
|
||||||
var dto = entity.Adapt<TDto>();
|
var dto = entity.Adapt<TDto>();
|
||||||
dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
|
dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
|
||||||
return dto;
|
return dto;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Exceptions;
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
@ -26,7 +27,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
ITelemetryUserService telemetryUserService,
|
ITelemetryUserService telemetryUserService,
|
||||||
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
||||||
: base(db, telemetryService, telemetryDataCache)
|
: base(db, telemetryService, telemetryDataCache)
|
||||||
{
|
{
|
||||||
this.telemetryUserService = telemetryUserService;
|
this.telemetryUserService = telemetryUserService;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
@ -11,7 +12,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public TelemetryDataSpinService(
|
public TelemetryDataSpinService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache)
|
ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache)
|
||||||
: base(db, telemetryService, telemetryDataCache)
|
: base(db, telemetryService, telemetryDataCache)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
@ -18,7 +19,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
{
|
{
|
||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
private readonly IMemoryCache memoryCache;
|
private readonly IMemoryCache memoryCache;
|
||||||
private readonly TelemetryDataCache<TelemetryDataSaubDto> dataSaubCache;
|
//TODO: методы использующие ITelemetryDataCache, скорее всего, тут не нужны
|
||||||
|
private readonly ITelemetryDataCache<TelemetryDataSaubDto> dataSaubCache;
|
||||||
private readonly ITimezoneService timezoneService;
|
private readonly ITimezoneService timezoneService;
|
||||||
|
|
||||||
public ITimezoneService TimeZoneService => timezoneService;
|
public ITimezoneService TimeZoneService => timezoneService;
|
||||||
@ -26,7 +28,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public TelemetryService(
|
public TelemetryService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
IMemoryCache memoryCache,
|
IMemoryCache memoryCache,
|
||||||
TelemetryDataCache<TelemetryDataSaubDto> dataSaubCache,
|
ITelemetryDataCache<TelemetryDataSaubDto> dataSaubCache,
|
||||||
ITimezoneService timezoneService)
|
ITimezoneService timezoneService)
|
||||||
{
|
{
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
@ -36,7 +36,7 @@ public class WellInfoService
|
|||||||
var operationsStatService = services.GetRequiredService<IOperationsStatService>();
|
var operationsStatService = services.GetRequiredService<IOperationsStatService>();
|
||||||
var processMapPlanWellDrillingRepository = services.GetRequiredService<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
|
var processMapPlanWellDrillingRepository = services.GetRequiredService<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
|
||||||
var subsystemOperationTimeService = services.GetRequiredService<ISubsystemOperationTimeService>();
|
var subsystemOperationTimeService = services.GetRequiredService<ISubsystemOperationTimeService>();
|
||||||
var telemetryDataSaubCache = services.GetRequiredService<TelemetryDataCache<TelemetryDataSaubDto>>();
|
var telemetryDataSaubCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
||||||
|
|
||||||
var wells = await wellService.GetAllAsync(token);
|
var wells = await wellService.GetAllAsync(token);
|
||||||
@ -180,16 +180,16 @@ public class WellInfoService
|
|||||||
public IEnumerable<int> IdsCompanies { get; set; } = null!;
|
public IEnumerable<int> IdsCompanies { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
|
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
|
||||||
private readonly TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
|
private readonly ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
|
||||||
private readonly IWitsRecordRepository<Record7Dto> witsRecord7Repository;
|
private readonly IWitsRecordRepository<Record7Dto> witsRecord7Repository;
|
||||||
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
|
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
|
||||||
private readonly IGtrRepository gtrRepository;
|
private readonly IGtrRepository gtrRepository;
|
||||||
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
|
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
|
||||||
|
|
||||||
public WellInfoService(
|
public WellInfoService(
|
||||||
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
|
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
|
||||||
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
|
ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
|
||||||
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
|
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
|
||||||
IWitsRecordRepository<Record1Dto> witsRecord1Repository,
|
IWitsRecordRepository<Record1Dto> witsRecord1Repository,
|
||||||
IGtrRepository gtrRepository)
|
IGtrRepository gtrRepository)
|
||||||
|
@ -11,6 +11,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudInfrastructure.Services.SAUB;
|
using AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.WellOperationService;
|
namespace AsbCloudInfrastructure.Services.WellOperationService;
|
||||||
|
|
||||||
@ -19,10 +20,10 @@ public class OperationsStatService : IOperationsStatService
|
|||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
private readonly IMemoryCache memoryCache;
|
private readonly IMemoryCache memoryCache;
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
|
||||||
public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService,
|
public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService,
|
||||||
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
||||||
{
|
{
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.memoryCache = memoryCache;
|
this.memoryCache = memoryCache;
|
||||||
|
@ -1,91 +1,134 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudInfrastructure.Services.SAUB;
|
||||||
using Mapster;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services;
|
namespace AsbCloudInfrastructure.Services;
|
||||||
|
|
||||||
public class WellboreService : IWellboreService
|
public class WellboreService : IWellboreService
|
||||||
{
|
{
|
||||||
|
const string WellboreNameFormat = "Ñòâîë {0}";
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly IWellOperationRepository wellOperationRepository;
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
|
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
|
||||||
public WellboreService(IWellService wellService, IWellOperationRepository wellOperationRepository)
|
public WellboreService(
|
||||||
|
IWellService wellService,
|
||||||
|
IWellOperationRepository wellOperationRepository,
|
||||||
|
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
||||||
{
|
{
|
||||||
this.wellService = wellService;
|
this.wellService = wellService;
|
||||||
this.wellOperationRepository = wellOperationRepository;
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
|
this.telemetryDataCache = telemetryDataCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<WellboreDto?> GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken)
|
public async Task<IEnumerable<WellboreDto>> GetWellboresAsync(IEnumerable<int> idsWells,
|
||||||
{
|
|
||||||
var request = new WellboreRequest
|
|
||||||
{
|
|
||||||
Ids = new (int, int?)[] { (idWell, idSection) },
|
|
||||||
Take = 1,
|
|
||||||
};
|
|
||||||
var data = await GetWellboresAsync(request, cancellationToken);
|
|
||||||
return data.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<WellboreDto>> GetWellboresAsync(WellboreRequest request,
|
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var wellbores = new List<WellboreDto>(request.Ids.Count());
|
var wellRequest = new WellRequest { Ids = idsWells };
|
||||||
var skip = request.Skip ?? 0;
|
var wells = await wellService.GetAsync(wellRequest, token);
|
||||||
var take = request.Take ?? 10;
|
|
||||||
|
|
||||||
var sections = wellOperationRepository.GetSectionTypes()
|
var rowSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
|
||||||
.ToDictionary(w => w.Id, w => w);
|
var groupedSections = rowSections
|
||||||
|
.Where(section => section.IdType == 1)
|
||||||
|
.GroupBy(s => s.IdWell);
|
||||||
|
|
||||||
var ids = request.Ids.GroupBy(i => i.idWell, i => i.idSection);
|
var wellbores = wells
|
||||||
|
.SelectMany(well => {
|
||||||
|
var wellSections = groupedSections.FirstOrDefault(group => group.Key == well.Id);
|
||||||
|
if (wellSections is not null)
|
||||||
|
return MakeWellboreBySections(wellSections, well);
|
||||||
|
else
|
||||||
|
return MakeWellboreDefault(well);
|
||||||
|
})
|
||||||
|
.OrderBy(w => w.Well.Id)
|
||||||
|
.ThenBy(w => w.Id);
|
||||||
|
|
||||||
var idsWells = request.Ids.Select(i => i.idWell);
|
return wellbores;
|
||||||
|
}
|
||||||
|
|
||||||
var allSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
|
private IEnumerable<WellboreDto> MakeWellboreDefault(WellDto well)
|
||||||
|
|
||||||
foreach (var id in ids)
|
|
||||||
{
|
{
|
||||||
var well = await wellService.GetOrDefaultAsync(id.Key, token);
|
var wellbore = new WellboreDto {
|
||||||
|
Id = 1,
|
||||||
|
Name = string.Format(WellboreNameFormat, 1),
|
||||||
|
Well = well,
|
||||||
|
};
|
||||||
|
//if(well.)
|
||||||
|
|
||||||
if (well is null)
|
if(well.IdTelemetry is not null)
|
||||||
continue;
|
{
|
||||||
|
var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
|
||||||
|
if (dataCache is not null)
|
||||||
|
{
|
||||||
|
wellbore.DateStart = dataCache.Value.First.DateTime;
|
||||||
|
wellbore.DepthStart = dataCache.Value.First.WellDepth!.Value;
|
||||||
|
|
||||||
var wellTimezoneOffset = TimeSpan.FromHours(well.Timezone.Hours);
|
wellbore.DateEnd = dataCache.Value.Last.DateTime;
|
||||||
|
wellbore.DepthEnd = dataCache.Value.Last.WellDepth!.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var wellFactSections = allSections
|
return new[] { wellbore };
|
||||||
.Where(section => section.IdWell == id.Key)
|
}
|
||||||
.Where(section => section.IdType == WellOperation.IdOperationTypeFact);
|
|
||||||
|
|
||||||
var idsSections = id
|
private IEnumerable<WellboreDto> MakeWellboreBySections(IEnumerable<SectionByOperationsDto> sections, WellDto well)
|
||||||
.Where(i => i.HasValue)
|
{
|
||||||
.Select(i => i!.Value);
|
var orderedSections = sections.OrderBy(s => s.DateStart);
|
||||||
|
var wellbores = new List<WellboreDto>();
|
||||||
|
int wellboreId = 1;
|
||||||
|
|
||||||
if (idsSections.Any())
|
SectionByOperationsDto? preSection = null;
|
||||||
wellFactSections = wellFactSections
|
WellboreDto? wellbore = null;
|
||||||
.Where(section => idsSections.Contains(section.IdWellSectionType));
|
|
||||||
|
|
||||||
var wellWellbores = wellFactSections.Select(section => new WellboreDto {
|
foreach (var section in orderedSections)
|
||||||
Id = section.IdWellSectionType,
|
{
|
||||||
Name = sections[section.IdWellSectionType].Caption,
|
if (wellbore is null || wellbore.DepthEnd > section.DepthStart)
|
||||||
Well = well.Adapt<WellWithTimezoneDto>(),
|
{
|
||||||
DateStart = section.DateStart.ToOffset(wellTimezoneOffset),
|
wellbore = new WellboreDto
|
||||||
DateEnd = section.DateEnd.ToOffset(wellTimezoneOffset),
|
{
|
||||||
|
Name = string.Format(WellboreNameFormat, wellboreId),
|
||||||
|
Id = wellboreId,
|
||||||
|
Well = well,
|
||||||
|
|
||||||
|
DateStart = section.DateStart,
|
||||||
|
DateEnd = section.DateEnd,
|
||||||
DepthStart = section.DepthStart,
|
DepthStart = section.DepthStart,
|
||||||
DepthEnd = section.DepthEnd,
|
DepthEnd = section.DepthEnd,
|
||||||
});
|
};
|
||||||
|
|
||||||
wellbores.AddRange(wellWellbores);
|
wellbores.Add(wellbore);
|
||||||
|
wellboreId++;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wellbore.DepthEnd = section.DepthEnd;
|
||||||
|
wellbore.DateEnd = section.DateEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wellbores
|
preSection = section;
|
||||||
.OrderBy(w => w.Well.Id).ThenBy(w => w.Id)
|
}
|
||||||
.Skip(skip).Take(take);
|
|
||||||
|
if (wellbore is not null)
|
||||||
|
{
|
||||||
|
if (well.IdTelemetry is not null)
|
||||||
|
{
|
||||||
|
var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
|
||||||
|
if (dataCache is not null)
|
||||||
|
{
|
||||||
|
wellbore.DateEnd = dataCache.Value.Last.DateTime;
|
||||||
|
wellbore.DepthEnd = dataCache.Value.Last.WellDepth!.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wellbores;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ using AsbCloudInfrastructure.Services.Subsystems;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DocumentFormat.OpenXml.InkML;
|
using DocumentFormat.OpenXml.InkML;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure
|
namespace AsbCloudInfrastructure
|
||||||
{
|
{
|
||||||
@ -29,8 +30,8 @@ namespace AsbCloudInfrastructure
|
|||||||
context.Database.EnshureCreatedAndMigrated();
|
context.Database.EnshureCreatedAndMigrated();
|
||||||
|
|
||||||
// TODO: Сделать инициализацию кеша телеметрии более явной.
|
// TODO: Сделать инициализацию кеша телеметрии более явной.
|
||||||
_ = provider.GetRequiredService<TelemetryDataCache<TelemetryDataSaubDto>>();
|
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
_ = provider.GetRequiredService<TelemetryDataCache<TelemetryDataSpinDto>>();
|
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSpinDto>>();
|
||||||
|
|
||||||
var backgroundWorker = provider.GetRequiredService<BackgroundWorker>();
|
var backgroundWorker = provider.GetRequiredService<BackgroundWorker>();
|
||||||
backgroundWorker.WorkStore.AddPeriodic<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));
|
backgroundWorker.WorkStore.AddPeriodic<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));
|
||||||
|
@ -3,14 +3,11 @@ using AsbCloudApp.Data.SAUB;
|
|||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudInfrastructure.Repository;
|
using AsbCloudInfrastructure.Services;
|
||||||
using AsbCloudInfrastructure.Services.SAUB;
|
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Org.BouncyCastle.Asn1.Ocsp;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -19,25 +16,207 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
{
|
{
|
||||||
public class WellboreServiceTest
|
public class WellboreServiceTest
|
||||||
{
|
{
|
||||||
|
private IWellService wellService;
|
||||||
|
private IWellOperationRepository wellOperationRepository;
|
||||||
|
private ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
private WellboreService wellboreService;
|
||||||
|
|
||||||
|
private WellDto well1 = new WellDto
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdState = 1,
|
||||||
|
IdTelemetry = 1,
|
||||||
|
LastTelemetryDate = DateTime.Now,
|
||||||
|
Caption = "well 1"
|
||||||
|
};
|
||||||
|
|
||||||
|
private WellDto well2 = new WellDto
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
IdState = 1,
|
||||||
|
IdTelemetry = 100,
|
||||||
|
LastTelemetryDate = DateTime.Now,
|
||||||
|
Caption = "well 2"
|
||||||
|
};
|
||||||
|
|
||||||
public WellboreServiceTest()
|
public WellboreServiceTest()
|
||||||
{
|
{
|
||||||
var wellService = Substitute.For<IWellService>();
|
wellService = Substitute.For<IWellService>();
|
||||||
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
|
||||||
.Returns(Enumerable.Empty<WellDto>());
|
|
||||||
|
|
||||||
var wellOperationRepository = Substitute.For<IWellOperationRepository>();
|
wellOperationRepository = Substitute.For<IWellOperationRepository>();
|
||||||
wellOperationRepository.GetSectionsAsync(Arg.Any<IEnumerable<int>>(), Arg.Any<CancellationToken>())
|
|
||||||
.Returns(Enumerable.Empty<SectionByOperationsDto>());
|
|
||||||
|
|
||||||
var telemetryDataCache = Substitute.For<TelemetryDataCache<TelemetryDataSaubDto>>();
|
telemetryDataCache = Substitute.For<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
telemetryDataCache.GetOrDefaultFirstLast(Arg.Any<int>());
|
|
||||||
|
wellboreService = new WellboreService(wellService, wellOperationRepository, telemetryDataCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetWellboresAsync()
|
public async Task GetWellboresAsync_returns_empty_collection()
|
||||||
{
|
{
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.False(result.Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetWellboresAsync_returns_one_bore_by_well_only()
|
||||||
|
{
|
||||||
|
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new WellDto[] { well1 });
|
||||||
|
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Single(result);
|
||||||
|
var wellbore0 = result.ElementAt(0);
|
||||||
|
Assert.Equal(well1.Caption, wellbore0.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore0.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 1", wellbore0.Name);
|
||||||
|
Assert.Equal(1, wellbore0.Id);
|
||||||
|
|
||||||
|
Assert.Equal(default, wellbore0.DateStart);
|
||||||
|
Assert.Equal(default, wellbore0.DateEnd);
|
||||||
|
Assert.Equal(default, wellbore0.DepthStart);
|
||||||
|
Assert.Equal(default, wellbore0.DepthEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetWellboresAsync_returns_two_bore_by_two_wells_only()
|
||||||
|
{
|
||||||
|
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new WellDto[] { well1, well2 });
|
||||||
|
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetWellboresAsync_returns_two_bore_by_well_with_sections()
|
||||||
|
{
|
||||||
|
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new WellDto[] { well1 });
|
||||||
|
|
||||||
|
var section0 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 01), DateEnd = new DateTime(2023, 01, 02), DepthStart = 000, DepthEnd = 100 };
|
||||||
|
var section1 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 02), DateEnd = new DateTime(2023, 01, 03), DepthStart = 100, DepthEnd = 300 };
|
||||||
|
var section2 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 03), DateEnd = new DateTime(2023, 01, 04), DepthStart = 200, DepthEnd = 210 };
|
||||||
|
var section3 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = int.MaxValue, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 03), DateEnd = new DateTime(2023, 01, 04), DepthStart = 200, DepthEnd = 220 };
|
||||||
|
var section4 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 0, DateStart = new DateTime(2023, 01, 05), DateEnd = new DateTime(2023, 01, 06), DepthStart = 150, DepthEnd = 220 };
|
||||||
|
|
||||||
|
wellOperationRepository.GetSectionsAsync(Arg.Any<IEnumerable<int>>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new SectionByOperationsDto[]{section0, section1, section2, section3, section4, });
|
||||||
|
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count());
|
||||||
|
var wellbore0 = result.ElementAt(0);
|
||||||
|
Assert.Equal(well1.Caption, wellbore0.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore0.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 1", wellbore0.Name);
|
||||||
|
Assert.Equal(1, wellbore0.Id);
|
||||||
|
|
||||||
|
Assert.Equal(section0.DateStart, wellbore0.DateStart);
|
||||||
|
Assert.Equal(section0.DepthStart, wellbore0.DepthStart);
|
||||||
|
Assert.Equal(section1.DateEnd, wellbore0.DateEnd);
|
||||||
|
Assert.Equal(section1.DepthEnd, wellbore0.DepthEnd);
|
||||||
|
|
||||||
|
var wellbore1 = result.ElementAt(1);
|
||||||
|
Assert.Equal(well1.Caption, wellbore1.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore1.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 2", wellbore1.Name);
|
||||||
|
Assert.Equal(2, wellbore1.Id);
|
||||||
|
|
||||||
|
Assert.Equal(section2.DateStart, wellbore1.DateStart);
|
||||||
|
Assert.Equal(section2.DepthStart, wellbore1.DepthStart);
|
||||||
|
Assert.Equal(section2.DateEnd, wellbore1.DateEnd);
|
||||||
|
Assert.Equal(section2.DepthEnd, wellbore1.DepthEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetWellboresAsync_returns_one_bore_by_well_with_telemetry()
|
||||||
|
{
|
||||||
|
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new WellDto[] { well1 });
|
||||||
|
|
||||||
|
var firstCacheItem = new TelemetryDataSaubDto { DateTime = new DateTime(2000, 01, 01), WellDepth = 0, };
|
||||||
|
var lastCacheItem = new TelemetryDataSaubDto { DateTime = new DateTime(2023, 01, 05), WellDepth = 321, };
|
||||||
|
|
||||||
|
telemetryDataCache.GetOrDefaultFirstLast(Arg.Any<int>())
|
||||||
|
.Returns((firstCacheItem, lastCacheItem));
|
||||||
|
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Single(result);
|
||||||
|
var wellbore0 = result.ElementAt(0);
|
||||||
|
Assert.Equal(well1.Caption, wellbore0.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore0.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 1", wellbore0.Name);
|
||||||
|
Assert.Equal(1, wellbore0.Id);
|
||||||
|
|
||||||
|
Assert.Equal(firstCacheItem.DateTime, wellbore0.DateStart);
|
||||||
|
Assert.Equal(firstCacheItem.WellDepth!.Value, wellbore0.DepthStart);
|
||||||
|
Assert.Equal(lastCacheItem.DateTime, wellbore0.DateEnd);
|
||||||
|
Assert.Equal(lastCacheItem.WellDepth!.Value, wellbore0.DepthEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetWellboresAsync_returns_two_bore_by_well_with_all()
|
||||||
|
{
|
||||||
|
wellService.GetAsync(Arg.Any<WellRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new WellDto[] { well1 });
|
||||||
|
|
||||||
|
var section0 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 01), DateEnd = new DateTime(2023, 01, 02), DepthStart = 000, DepthEnd = 100 };
|
||||||
|
var section1 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 02), DateEnd = new DateTime(2023, 01, 03), DepthStart = 100, DepthEnd = 300 };
|
||||||
|
var section2 = new SectionByOperationsDto()
|
||||||
|
{ IdWell = well1.Id, IdWellSectionType = 0, IdType = 1, DateStart = new DateTime(2023, 01, 03), DateEnd = new DateTime(2023, 01, 04), DepthStart = 200, DepthEnd = 210 };
|
||||||
|
|
||||||
|
wellOperationRepository.GetSectionsAsync(Arg.Any<IEnumerable<int>>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new SectionByOperationsDto[] { section0, section1, section2});
|
||||||
|
|
||||||
|
var firstCacheItem = new TelemetryDataSaubDto { DateTime = new DateTime(2000, 01, 01), WellDepth = 0, };
|
||||||
|
var lastCacheItem = new TelemetryDataSaubDto { DateTime = new DateTime(2023, 01, 05), WellDepth = 321, };
|
||||||
|
|
||||||
|
telemetryDataCache.GetOrDefaultFirstLast(Arg.Any<int>())
|
||||||
|
.Returns((firstCacheItem, lastCacheItem));
|
||||||
|
|
||||||
|
var result = await wellboreService.GetWellboresAsync(new[] { 1 }, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Count());
|
||||||
|
var wellbore0 = result.ElementAt(0);
|
||||||
|
Assert.Equal(well1.Caption, wellbore0.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore0.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 1", wellbore0.Name);
|
||||||
|
Assert.Equal(1, wellbore0.Id);
|
||||||
|
|
||||||
|
Assert.Equal(section0.DateStart, wellbore0.DateStart);
|
||||||
|
Assert.Equal(section0.DepthStart, wellbore0.DepthStart);
|
||||||
|
Assert.Equal(section1.DateEnd, wellbore0.DateEnd);
|
||||||
|
Assert.Equal(section1.DepthEnd, wellbore0.DepthEnd);
|
||||||
|
|
||||||
|
var wellbore1 = result.ElementAt(1);
|
||||||
|
Assert.Equal(well1.Caption, wellbore1.Well.Caption);
|
||||||
|
Assert.Equal(well1.Id, wellbore1.Well.Id);
|
||||||
|
|
||||||
|
Assert.Equal("Ствол 2", wellbore1.Name);
|
||||||
|
Assert.Equal(2, wellbore1.Id);
|
||||||
|
|
||||||
|
Assert.Equal(section2.DateStart, wellbore1.DateStart);
|
||||||
|
Assert.Equal(section2.DepthStart, wellbore1.DepthStart);
|
||||||
|
Assert.Equal(lastCacheItem.DateTime, wellbore1.DateEnd);
|
||||||
|
Assert.Equal(lastCacheItem.WellDepth!.Value, wellbore1.DepthEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ using AsbCloudApp.Services;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Org.BouncyCastle.Asn1.Ocsp;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers;
|
namespace AsbCloudWebApi.Controllers;
|
||||||
|
|
||||||
@ -27,65 +28,19 @@ public class WellboreController : ControllerBase
|
|||||||
this.wellboreService = wellboreService;
|
this.wellboreService = wellboreService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение ствола скважины
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="idWell">Id скважины</param>
|
|
||||||
/// <param name="idSection">Id типа секции скважины</param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
|
|
||||||
[HttpGet("{idWell:int}/{idSection:int}")]
|
|
||||||
[ProducesResponseType(typeof(WellboreDto), StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
||||||
public async Task<IActionResult> GetAsync(int idWell, int idSection, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var wellbore = await wellboreService.GetWellboreAsync(idWell, idSection, cancellationToken);
|
|
||||||
|
|
||||||
if (wellbore is null)
|
|
||||||
return NoContent();
|
|
||||||
|
|
||||||
return Ok(wellbore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение списка стволов скважин
|
/// Получение списка стволов скважин
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ids">Пары идентификаторов скважины и секции</param>
|
/// <param name="idsWells">Идентификаторы скважин</param>
|
||||||
/// <param name="skip">Опциональный параметр. Количество пропускаемых записей</param>
|
|
||||||
/// <param name="take">Опциональный параметр. Количество получаемых записей</param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(IEnumerable<WellboreDto>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(IEnumerable<WellboreDto>), StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> GetAllAsync([FromQuery] IEnumerable<string> ids,
|
public async Task<IActionResult> GetAllAsync([FromQuery] IEnumerable<int> idsWells,
|
||||||
int? skip,
|
|
||||||
int? take,
|
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var request = new WellboreRequest
|
var result = await wellboreService.GetWellboresAsync(idsWells, cancellationToken);
|
||||||
{
|
|
||||||
Ids = ids.Select(id => ParseId(id)),
|
|
||||||
Skip = skip,
|
|
||||||
Take = take
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(await wellboreService.GetWellboresAsync(request, cancellationToken));
|
return Ok(result);
|
||||||
}
|
|
||||||
|
|
||||||
private static (int, int?) ParseId(string id)
|
|
||||||
{
|
|
||||||
var idPair = id.Split(',');
|
|
||||||
if (!int.TryParse(idPair[0], out var idWell))
|
|
||||||
throw new ArgumentInvalidException(nameof(id), $"Не удалось получить Id скважины \"{idPair[0]}\"");
|
|
||||||
|
|
||||||
if (idPair.Length > 1)
|
|
||||||
{
|
|
||||||
if (int.TryParse(idPair[1], out int idWellSectionType))
|
|
||||||
return (idWell, idWellSectionType);
|
|
||||||
else
|
|
||||||
throw new ArgumentInvalidException(nameof(id), $"Не удалось получить Id ствола \"{idPair[1]}\"");
|
|
||||||
}
|
|
||||||
return (idWell, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
12
AsbCloudWebApi/Rest/Auth.http
Normal file
12
AsbCloudWebApi/Rest/Auth.http
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
@baseUrl = http://127.0.0.1:5000
|
||||||
|
@contentType = application/json
|
||||||
|
|
||||||
|
## Auth
|
||||||
|
POST {{baseUrl}}/auth/login
|
||||||
|
Content-Type: {{contentType}}
|
||||||
|
accept: */*
|
||||||
|
|
||||||
|
{
|
||||||
|
"login": "dev",
|
||||||
|
"password": "Rp7gsNMk"
|
||||||
|
}
|
@ -1,15 +1,13 @@
|
|||||||
@baseUrl = http://127.0.0.1:5000
|
@baseUrl = http://127.0.0.1:5000
|
||||||
@contentType = application/json
|
@contentType = application/json
|
||||||
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
|
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2OTgxMjY1MTUsImV4cCI6MTcyOTY4NDExNSwiaXNzIjoiYSIsImF1ZCI6ImEifQ.3Lq256cYtHnKlGWChPhZv2rUJPjbJEHU-18xdyJlYDE
|
||||||
|
|
||||||
@uid = 20210101_000000000
|
@idWell = 2
|
||||||
@idCluster = 1
|
|
||||||
@idWell = 1
|
|
||||||
|
|
||||||
# https://marketplace.visualstudio.com/items?itemName=humao.rest-client
|
# https://marketplace.visualstudio.com/items?itemName=humao.rest-client
|
||||||
|
|
||||||
###
|
###
|
||||||
GET {{baseUrl}}/api/well/wellbore?ids=1,2
|
GET {{baseUrl}}/api/wellbore?idsWells=1
|
||||||
Content-Type: {{contentType}}
|
Content-Type: {{contentType}}
|
||||||
accept: */*
|
accept: */*
|
||||||
Authorization: {{auth}}
|
Authorization: {{auth}}
|
||||||
|
Loading…
Reference in New Issue
Block a user