WellMapInfoDto разделен на части.

1-я (медленная) заполняется в фоновом процессе и кешируется, 2-я при запросе из кешей телеметрии.
This commit is contained in:
ngfrolov 2023-06-29 15:54:54 +05:00
parent 968f6db348
commit 69f5639571
Signed by untrusted user who does not match committer: ng.frolov
GPG Key ID: E99907A0357B29A7
6 changed files with 125 additions and 64 deletions

View File

@ -15,7 +15,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudDb", "AsbCloudDb\As
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudWebApi.Tests", "AsbCloudWebApi.Tests\AsbCloudWebApi.Tests.csproj", "{9CF6FBB1-9AF5-45AB-A521-24F11A79B540}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalRTestClient", "SignalRTestClient\SignalRTestClient.csproj", "{E6B97963-4CEA-47B6-A0C8-625FFA9B7D69}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalRTestClient", "SignalRTestClient\SignalRTestClient.csproj", "{E6B97963-4CEA-47B6-A0C8-625FFA9B7D69}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -1,7 +1,44 @@
using System;
using AsbCloudApp.Data.SAUB;
using System;
namespace AsbCloudApp.Data
{
/// <summary>
/// Инфо о скважине для отображения на карте последними данными телеметрии
/// </summary>
public class WellMapInfoWithTelemetryStat : WellMapInfoDto
{
/// <summary>
/// Последние полученные данные от АПД
/// </summary>
public TelemetryDataSaubDto? LastDataSaub { get; set; }
/// <summary>
/// Последние полученные данные от Осцилляции
/// </summary>
public TelemetryDataSpinDto? LastDataSpin { get; set; }
/// <summary>
/// Дата полседнего получения данных от ННБ
/// </summary>
public DateTime? LastDataDdsDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от ГТИ
/// </summary>
public DateTime? LastDataGtrDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от СКПБ
/// </summary>
public DateTime? LastDataDpcsDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от станции контроля параметров цементирования (СКЦ)
/// </summary>
public DateTime? LastDataCpmsDate { get; set; }
}
/// <summary>
/// Инфо о скважине для отображения на карте
/// </summary>
@ -14,19 +51,6 @@ namespace AsbCloudApp.Data
/// </summary>
public int IdState { get; set; }
/// <summary>
/// Режим АПД:
/// 0 - "РУЧНОЙ"
/// 1 - "БУРЕНИЕ В РОТОРЕ"
/// 2 - "ПРОРАБОТКА"
/// 3 - "БУРЕНИЕ В СЛАЙДЕ"
/// 4 - "СПУСК СПО"
/// 5 - "ПОДЪЕМ СПО"
/// 6 - "ПОДЪЕМ С ПРОРАБОТКОЙ"
/// 10 - "БЛОКИРОВКА"
/// </summary>
public int IdMode { get; set; }
/// <summary>
/// Коэф-т использования автоподачи долота (суммарный ротор + слайд)
/// </summary>
@ -42,36 +66,6 @@ namespace AsbCloudApp.Data
/// </summary>
public double TorqueKUsage { get; set; }
/// <summary>
/// Состояние МСЕ
/// </summary>
public double IdStateMse { get; set; }
/// <summary>
/// Дата/время получения данных от системы АПД
/// </summary>
public DateTime LastTelemetrySaubDate { get; set; }
/// <summary>
/// Дата/время получения данных от системы осцилляции
/// </summary>
public DateTime LastTelemetrySpinDate { get; set; }
/// <summary>
/// Дата/время получения данных от ННБ
/// </summary>
public DateTime LastTelemetryDdsDate { get; set; }
/// <summary>
/// Дата/время получения данных от ГТИ
/// </summary>
public DateTime LastTelemetryGtrDate { get; set; }
/// <summary>
/// Дата/время получения данных от СКПБ
/// </summary>
public DateTime LastTelemetryDpcsDate { get; set; }
/// <summary>
/// <para>Дата начала первой фактической операции</para>
/// <para>Используется как дата начала бурения</para>

View File

@ -136,6 +136,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ILimitingParameterService, LimitingParameterService>();
services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>();
services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
services.AddTransient<WellInfoService>();
services.AddTransient<TrajectoryService>();

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Data.WITS;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
@ -18,19 +19,37 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public class WellInfoService
{
class WellMapInfoWithComanies : WellMapInfoDto
{
public int? IdTelemetry { get; set; }
public IEnumerable<int> IdsCompanies { get; set; } = null!;
}
private const string workId = "Well statistics update";
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
private readonly TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
private readonly IWitsRecordRepository<Record7Dto> witsRecord7Repository;
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
public WellInfoService(
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
IWitsRecordRepository<Record1Dto> witsRecord1Repository)
{
this.telemetryDataSaubCache = telemetryDataSaubCache;
this.telemetryDataSpinCache = telemetryDataSpinCache;
this.witsRecord7Repository = witsRecord7Repository;
this.witsRecord1Repository = witsRecord1Repository;
}
public static WorkPeriodic MakeWork()
{
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
@ -75,23 +94,22 @@ namespace AsbCloudInfrastructure.Services
WellMapInfo = activeWells.Select(well => {
var wellMapInfo = well.Adapt<WellMapInfoWithComanies>();
var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id);
var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null);
wellMapInfo.IdState = well.IdState;
double? currentDepth = null;
double? planTotalDepth = null;
DateTime lastTelemetryDate = default;
if (well.IdTelemetry.HasValue)
{
wellMapInfo.IdTelemetry = well.IdTelemetry.Value;
var lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
if(lastSaubTelemetry is not null)
{
currentDepth = lastSaubTelemetry.WellDepth;
lastTelemetryDate = lastSaubTelemetry.DateTime;
}
}
var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id);
var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null);
currentDepth ??= wellLastFactSection?.Fact?.WellDepthEnd;
var wellProcessMaps = processMaps
@ -111,9 +129,16 @@ namespace AsbCloudInfrastructure.Services
idSection ??= welllProcessMap?.IdWellSectionType;
}
double? planTotalDepth = null;
planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd;
planTotalDepth ??= wellOperationsStat?.Total.Plan?.WellDepthEnd;
wellMapInfo.FirstFactOperationDateStart = wellOperationsStat?.Total.Fact?.Start
?? wellOperationsStat?.Total.Plan?.Start;
wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End?
.AddDays(wellOperationsStat?.TvdLagDays ?? 0d);
wellMapInfo.WellDepth = new()
{
Plan = planTotalDepth,
@ -135,17 +160,51 @@ namespace AsbCloudInfrastructure.Services
var wellSubsystemStat = subsystemStat.FirstOrDefault(s => s.Well.Id == well.Id);
wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d;
wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d;
wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagDays ?? 0d;
wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id);
return wellMapInfo;
}).ToArray();
}
public static IEnumerable<WellMapInfoDto> Where(Func<WellMapInfoDto, bool> predicate)
=> WellMapInfo.Where(predicate);
public static WellMapInfoDto? FirstOrDefault(Func<WellMapInfoDto, bool> predicate)
=> WellMapInfo.FirstOrDefault(predicate);
private WellMapInfoWithTelemetryStat Convert(WellMapInfoWithComanies wellInfo)
{
var result = wellInfo.Adapt<WellMapInfoWithTelemetryStat>();
if (wellInfo.IdTelemetry.HasValue)
{
result.LastDataSaub = telemetryDataSaubCache.GetLastOrDefault(wellInfo.IdTelemetry.Value);
result.LastDataSpin = telemetryDataSpinCache.GetLastOrDefault(wellInfo.IdTelemetry.Value);
result.LastDataDdsDate = GetLastOrDefaultDdsTelemetry(wellInfo.IdTelemetry.Value);
result.LastDataGtrDate = null;
result.LastDataDpcsDate = null;
result.LastDataDpcsDate = null;
}
return result;
}
private DateTime? GetLastOrDefaultDdsTelemetry(int idTelemetry)
{
var lastDdsRecord1Date = witsRecord1Repository.GetLastOrDefault(idTelemetry)?.DateTime;
var lastDdsRecord7Date = witsRecord7Repository.GetLastOrDefault(idTelemetry)?.DateTime;
if (lastDdsRecord1Date.HasValue && lastDdsRecord7Date.HasValue)
if (lastDdsRecord1Date.Value > lastDdsRecord7Date.Value)
return lastDdsRecord1Date.Value;
else
return lastDdsRecord7Date.Value;
return lastDdsRecord1Date ?? lastDdsRecord7Date;
}
public WellMapInfoWithTelemetryStat? FirstOrDefault(Func<WellMapInfoDto, bool> predicate)
{
var first = WellMapInfo.FirstOrDefault(predicate);
if (first is WellMapInfoWithComanies wellMapInfoWithComanies)
return Convert(wellMapInfoWithComanies);
return null;
}
}
}

View File

@ -16,12 +16,12 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public class WellService : CrudCacheRepositoryBase<WellDto, Well>, IWellService
{
private readonly ITelemetryService telemetryService;
private readonly ICrudRepository<CompanyTypeDto> companyTypesService;
private readonly ITimezoneService timezoneService;
private readonly WellInfoService wellInfoService;
private readonly IWellOperationRepository wellOperationRepository;
public ITelemetryService TelemetryService => telemetryService;
@ -35,12 +35,12 @@ namespace AsbCloudInfrastructure.Services
.Include(w => w.RelationCompaniesWells)
.ThenInclude(r => r.Company);
public WellService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, ITimezoneService timezoneService)
public WellService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, ITimezoneService timezoneService, WellInfoService wellInfoService)
: base(db, memoryCache, MakeQueryWell)
{
this.telemetryService = telemetryService;
this.timezoneService = timezoneService;
this.wellInfoService = wellInfoService;
this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this);
companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
}
@ -92,13 +92,10 @@ namespace AsbCloudInfrastructure.Services
Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude,
Wells = gCluster.Select(well =>
{
var dto = WellInfoService.FirstOrDefault(w => w.Id == well.Id);
dto ??= well.Adapt<WellMapInfoDto>();
var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id);
dto ??= well.Adapt<WellMapInfoWithTelemetryStat>();
dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
if (well.IdTelemetry is not null)
dto.LastTelemetryDate = telemetryService.GetDatesRange(well.IdTelemetry.Value).To;
return dto;
}),
}),

View File

@ -0,0 +1,10 @@
@baseUrl = http://127.0.0.1:5000
@contentType = application/json
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
@idWell = 1
GET {{baseUrl}}/api/well/wellTree
Content-Type: {{contentType}}
accept: */*
Authorization: {{auth}}