Правки по результатам PR + добавление backgroundWorker для старта работы сервиса DataSaubStatDrillingQuality

This commit is contained in:
Olga Nemt 2024-10-08 11:23:25 +05:00
parent 1f2bf13a83
commit 619244c66d
12 changed files with 188 additions and 167 deletions

View File

@ -16,4 +16,19 @@ public interface IDataSaubStatDto
/// Дата и время окончания /// Дата и время окончания
/// </summary> /// </summary>
public DateTimeOffset DateEnd { get; set; } public DateTimeOffset DateEnd { get; set; }
/// <summary>
/// Глубина забоя по стволу начальная
/// </summary>
public double DepthStart { get; set; }
/// <summary>
/// Глубина забоя по стволу конечная
/// </summary>
public double DepthEnd { get; set; }
/// <summary>
/// Ключ телеметрии
/// </summary>
public int IdTelemetry { get; set; }
} }

View File

@ -0,0 +1,23 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services;
/// <summary>
/// Сервис записи данных в таблицу t_data_saub_stat_drilling_quality, которая используется для построения РТК-отчета
/// </summary>
public interface IDataSaubStatDrillingQualityService
{
/// <summary>
/// Расчет статистики DataSaubStat
/// </summary>
/// <param name="lastDaysFilter">
/// Количество дней за которые должны были приходить данные, чтобы телеметрия попала в обработку.
/// </param>
/// <param name="onProgressCallback"></param>
/// <param name="token"></param>
/// <returns></returns>
Task CreateStatAsync(int lastDaysFilter, Action<string, double?> onProgressCallback, CancellationToken token);
}

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace AsbCloudApp.Services; namespace AsbCloudApp.Services;
/// <summary> /// <summary>
/// Сервис записи данных в таблицу DataSaubStat, которая используется для построения РТК-отчета /// Сервис записи данных в таблицу t_data_saub_stat, которая используется для построения РТК-отчета
/// </summary> /// </summary>
public interface IDataSaubStatService public interface IDataSaubStatService
{ {

View File

@ -1,22 +1,13 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DetectOperations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background.PeriodicWorks; namespace AsbCloudInfrastructure.Background.PeriodicWorks;
/// <summary> /// <summary>
/// задача по добавлению данных в таблицу DataSaubStat, которая используется для построения РТК-отчета /// задача по добавлению данных в таблицу t_data_saub_stat, которая используется для построения РТК-отчета
/// </summary> /// </summary>
internal class WorkDataSaubStat : Work internal class WorkDataSaubStat : Work
{ {
@ -31,7 +22,7 @@ internal class WorkDataSaubStat : Work
{ {
var dataSaubStatService = services.GetRequiredService<IDataSaubStatService>(); var dataSaubStatService = services.GetRequiredService<IDataSaubStatService>();
if (dataSaubStatService != null ) if (dataSaubStatService != null)
await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token); await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token);
} }

View File

@ -0,0 +1,30 @@
using AsbCloudApp.Services;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background.PeriodicWorks;
/// <summary>
/// задача по добавлению данных в таблицу t_data_saub_stat_drilling_quality,
/// которая используется для построения страницы "Качество"
/// </summary>
internal class WorkDataSaubStatDrillingQuality : Work
{
private int Gap = 60;
public WorkDataSaubStatDrillingQuality() : base("Generate DataSaubStatDrillingQuality entries and save them into Db")
{
Timeout = TimeSpan.FromMinutes(10);
}
protected override async Task Action(string id, IServiceProvider services, Action<string, double?> onProgressCallback, CancellationToken token)
{
var dataSaubStatService = services.GetRequiredService<IDataSaubStatDrillingQualityService>();
if (dataSaubStatService != null)
await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token);
}
}

View File

@ -15,6 +15,7 @@ using AsbCloudApp.Services;
using AsbCloudApp.Services.DailyReport; using AsbCloudApp.Services.DailyReport;
using AsbCloudApp.Services.Notifications; using AsbCloudApp.Services.Notifications;
using AsbCloudApp.Services.ProcessMaps.WellDrilling; using AsbCloudApp.Services.ProcessMaps.WellDrilling;
using AsbCloudApp.Services.WellReport;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance; using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance;
using AsbCloudDb.Model.Manuals; using AsbCloudDb.Model.Manuals;
@ -41,14 +42,13 @@ using AsbCloudInfrastructure.Services.Trajectory.Parser;
using AsbCloudInfrastructure.Services.WellOperations.Factories; using AsbCloudInfrastructure.Services.WellOperations.Factories;
using AsbCloudInfrastructure.Services.WellOperationService; using AsbCloudInfrastructure.Services.WellOperationService;
using AsbCloudInfrastructure.Services.WellOperationService.WellOperationService; using AsbCloudInfrastructure.Services.WellOperationService.WellOperationService;
using AsbCloudInfrastructure.Services.WellReport;
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
using AsbCloudApp.Services.WellReport;
using AsbCloudInfrastructure.Services.WellReport;
namespace AsbCloudInfrastructure; namespace AsbCloudInfrastructure;
@ -318,10 +318,10 @@ public static class DependencyInjection
services.AddTransient<WellInfoService>(); services.AddTransient<WellInfoService>();
services.AddTransient<IHelpPageService, HelpPageService>(); services.AddTransient<IHelpPageService, HelpPageService>();
services.AddTransient<IScheduleReportService, ScheduleReportService>(); services.AddTransient<IScheduleReportService, ScheduleReportService>();
services.AddTransient<IDataSaubStatRepository<DataSaubStatDto>, DataSaubStatRepository>(); services.AddTransient<IDataSaubStatRepository<DataSaubStatDto>, DataSaubStatRepository<DataSaubStat, DataSaubStatDto>>();
services.AddTransient<IDataSaubStatRepository<DataSaubStatDrillingQualityDto>, DataSaubStatDrillingQualityRepository>(); services.AddTransient<IDataSaubStatRepository<DataSaubStatDrillingQualityDto>, DataSaubStatRepository<DataSaubStatDrillingQuality, DataSaubStatDrillingQualityDto>>();
services.AddTransient<IDataSaubStatService, DataSaubStatService>(); services.AddTransient<IDataSaubStatService, DataSaubStatService>();
services.AddTransient<IDataSaubStatService, DataSaubStatDrillingQualityService>(); services.AddTransient<IDataSaubStatDrillingQualityService, DataSaubStatDrillingQualityService>();
services.AddTransient<IWellOperationService, WellOperationService>(); services.AddTransient<IWellOperationService, WellOperationService>();
services.AddTransient< services.AddTransient<
@ -397,10 +397,10 @@ public static class DependencyInjection
ProcessMapPlanBaseRepository<ProcessMapPlanStaticMeasurementOutput, ProcessMapPlanStaticMeasurementOutputDto>>(); ProcessMapPlanBaseRepository<ProcessMapPlanStaticMeasurementOutput, ProcessMapPlanStaticMeasurementOutputDto>>();
services.AddTransient< services.AddTransient<
IChangeLogRepository<ProcessMapPlanSubsystemsDto, ProcessMapPlanBaseRequestWithWell>, IChangeLogRepository<ProcessMapPlanSubsystemsDto, ProcessMapPlanBaseRequestWithWell>,
ProcessMapPlanBaseRepository<ProcessMapPlanSubsystems, ProcessMapPlanSubsystemsDto>>(); ProcessMapPlanBaseRepository<ProcessMapPlanSubsystems, ProcessMapPlanSubsystemsDto>>();
services.AddTransient<IProcessMapReportDrillingService, ProcessMapReportDrillingService>(); services.AddTransient<IProcessMapReportDrillingService, ProcessMapReportDrillingService>();
services.AddTransient<TrajectoryService>(); services.AddTransient<TrajectoryService>();
@ -475,7 +475,7 @@ public static class DependencyInjection
services.AddTransient<ITrajectoryNnbRepository, TrajectoryNnbRepository>(); services.AddTransient<ITrajectoryNnbRepository, TrajectoryNnbRepository>();
services.AddTransient<ITrajectoryRepository<TrajectoryGeoPlanDto>, TrajectoryEditableRepository<TrajectoryPlan, TrajectoryGeoPlanDto>>(); services.AddTransient<ITrajectoryRepository<TrajectoryGeoPlanDto>, TrajectoryEditableRepository<TrajectoryPlan, TrajectoryGeoPlanDto>>();
services.AddTransient<ITrajectoryRepository<TrajectoryGeoFactDto>, TrajectoryEditableRepository<TrajectoryFact, TrajectoryGeoFactDto>>(); services.AddTransient<ITrajectoryRepository<TrajectoryGeoFactDto>, TrajectoryEditableRepository<TrajectoryFact, TrajectoryGeoFactDto>>();
services.AddTransient<IFaqRepository, FaqRepository>(); services.AddTransient<IFaqRepository, FaqRepository>();
services.AddTransient<ISlipsStatService, SlipsStatService>(); services.AddTransient<ISlipsStatService, SlipsStatService>();
services.AddTransient<IWellContactService, WellContactService>(); services.AddTransient<IWellContactService, WellContactService>();
services.AddTransient<ICrudRepository<WellSectionTypeDto>, CrudCacheRepositoryBase<WellSectionTypeDto, services.AddTransient<ICrudRepository<WellSectionTypeDto>, CrudCacheRepositoryBase<WellSectionTypeDto,
@ -569,7 +569,7 @@ public static class DependencyInjection
services.AddTransient<ProcessMapPlanStaticMeasurementOutputExportService>(); services.AddTransient<ProcessMapPlanStaticMeasurementOutputExportService>();
services.AddTransient<ProcessMapPlanSubsystemsExportService>(); services.AddTransient<ProcessMapPlanSubsystemsExportService>();
services.AddTransient<WellOperationParserFactory>(); services.AddTransient<WellOperationParserFactory>();
services.AddTransient<WellOperationExportServiceFactory>(); services.AddTransient<WellOperationExportServiceFactory>();
services.AddTransient<IWellReportService, WellReportService>(); services.AddTransient<IWellReportService, WellReportService>();

View File

@ -1,111 +0,0 @@
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository;
public class DataSaubStatAbstractRepository<TEntity, TDto> : IDataSaubStatRepository<TDto>
where TDto : AsbCloudApp.Data.IDataSaubStatDto
where TEntity : class, AsbCloudDb.Model.IDataSaubStat
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
public DataSaubStatAbstractRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService)
{
db = dbContext;
this.telemetryService = telemetryService;
}
public async Task<IEnumerable<TDto>> GetLastsAsync(int[] idTelemetries, CancellationToken token)
{
var timeZoneOffsets = idTelemetries
.Distinct()
.ToDictionary(idTelemetry => idTelemetry, idTelemetry => TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours));
var stats = await db.Set<TEntity>()
.Where(s => idTelemetries.Contains(s.IdTelemetry))
.GroupBy(s => s.IdTelemetry, (key, group) => group.OrderByDescending(el => el.DateEnd).First())
.ToArrayAsync(token);
var result = stats.Select(s => ConvertToDto(s, timeZoneOffsets[s.IdTelemetry]));
return result;
}
public async Task<IEnumerable<TDto>> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token)
{
var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours);
var geDateUtc = geDate.ToUniversalTime();
var leDateUtc = leDate.ToUniversalTime();
var stats = await db.Set<TEntity>()
.Where(s => s.IdTelemetry == idTelemetry)
.Where(s => s.DateStart >= geDateUtc)
.Where(s => s.DateEnd <= leDateUtc)
.ToArrayAsync(token);
var result = stats.Select(s => ConvertToDto(s, timeSpan));
return result;
}
public async Task<int> InsertRangeAsync(IEnumerable<TDto> dataSaubStats, CancellationToken token)
{
var entities = dataSaubStats.Select(data => ConvertToEntity(data));
db.Set<TEntity>().AddRange(entities);
return await db.SaveChangesAsync(token);
}
private static TDto ConvertToDto(TEntity entity, TimeSpan timeSpan)
{
var dto = entity.Adapt<TDto>();
dto.DateStart = dto.DateStart.ToOffset(timeSpan);
dto.DateEnd = dto.DateEnd.ToOffset(timeSpan);
return dto;
}
private static TEntity ConvertToEntity(TDto dto)
{
var entity = dto.Adapt<TEntity>();
entity.DateStart = dto.DateStart.ToUniversalTime();
entity.DateEnd = dto.DateEnd.ToUniversalTime();
return entity;
}
private IQueryable<TEntity> BuildQuery(TelemetryPartDeleteRequest request)
{
var query = db.Set<TEntity>()
.Where(o => o.IdTelemetry == request.IdTelemetry);
if (request.LeDate is not null)
{
var leDate = request.LeDate.Value.ToUniversalTime();
query = query.Where(o => o.DateStart <= leDate);
}
if (request.GeDate is not null)
{
var geDate = request.GeDate.Value.ToUniversalTime();
query = query.Where(o => o.DateEnd >= geDate);
}
return query;
}
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
{
var query = BuildQuery(request);
db.Set<TEntity>().RemoveRange(query);
return await db.SaveChangesAsync(token);
}
}

View File

@ -1,21 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Repository;
/// <summary>
/// Абстрактный репозиторий для работы с данными data_saub_stat
/// </summary>
public class DataSaubStatDrillingQualityRepository : DataSaubStatAbstractRepository<DataSaubStatDrillingQuality, DataSaubStatDrillingQualityDto>
{
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="dbContext"></param>
/// <param name="telemetryService"></param>
public DataSaubStatDrillingQualityRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService) : base(dbContext, telemetryService)
{
}
}

View File

@ -1,18 +1,111 @@
using AsbCloudApp.Data; using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository; namespace AsbCloudInfrastructure.Repository;
public class DataSaubStatRepository<TEntity, TDto> : IDataSaubStatRepository<TDto>
public class DataSaubStatRepository : DataSaubStatAbstractRepository<DataSaubStat, DataSaubStatDto> where TDto : AsbCloudApp.Data.IDataSaubStatDto
where TEntity : class, AsbCloudDb.Model.IDataSaubStat
{ {
/// <summary> private readonly IAsbCloudDbContext db;
/// <inheritdoc/> private readonly ITelemetryService telemetryService;
/// </summary>
/// <param name="dbContext"></param>
/// <param name="telemetryService"></param>
public DataSaubStatRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService) : base(dbContext, telemetryService)
{
public DataSaubStatRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService)
{
db = dbContext;
this.telemetryService = telemetryService;
}
public async Task<IEnumerable<TDto>> GetLastsAsync(int[] idTelemetries, CancellationToken token)
{
var timeZoneOffsets = idTelemetries
.Distinct()
.ToDictionary(idTelemetry => idTelemetry, idTelemetry => TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours));
var stats = await db.Set<TEntity>()
.Where(s => idTelemetries.Contains(s.IdTelemetry))
.GroupBy(s => s.IdTelemetry, (key, group) => group.OrderByDescending(el => el.DateEnd).First())
.ToArrayAsync(token);
var result = stats.Select(s => ConvertToDto(s, timeZoneOffsets[s.IdTelemetry]));
return result;
}
public async Task<IEnumerable<TDto>> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token)
{
var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours);
var geDateUtc = geDate.ToUniversalTime();
var leDateUtc = leDate.ToUniversalTime();
var stats = await db.Set<TEntity>()
.Where(s => s.IdTelemetry == idTelemetry)
.Where(s => s.DateStart >= geDateUtc)
.Where(s => s.DateEnd <= leDateUtc)
.ToArrayAsync(token);
var result = stats.Select(s => ConvertToDto(s, timeSpan));
return result;
}
public async Task<int> InsertRangeAsync(IEnumerable<TDto> dataSaubStats, CancellationToken token)
{
var entities = dataSaubStats.Select(data => ConvertToEntity(data));
db.Set<TEntity>().AddRange(entities);
return await db.SaveChangesAsync(token);
}
private static TDto ConvertToDto(TEntity entity, TimeSpan timeSpan)
{
var dto = entity.Adapt<TDto>();
dto.DateStart = dto.DateStart.ToOffset(timeSpan);
dto.DateEnd = dto.DateEnd.ToOffset(timeSpan);
return dto;
}
private static TEntity ConvertToEntity(TDto dto)
{
var entity = dto.Adapt<TEntity>();
entity.DateStart = dto.DateStart.ToUniversalTime();
entity.DateEnd = dto.DateEnd.ToUniversalTime();
return entity;
}
private IQueryable<TEntity> BuildQuery(TelemetryPartDeleteRequest request)
{
var query = db.Set<TEntity>()
.Where(o => o.IdTelemetry == request.IdTelemetry);
if (request.LeDate is not null)
{
var leDate = request.LeDate.Value.ToUniversalTime();
query = query.Where(o => o.DateStart <= leDate);
}
if (request.GeDate is not null)
{
var geDate = request.GeDate.Value.ToUniversalTime();
query = query.Where(o => o.DateEnd >= geDate);
}
return query;
}
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
{
var query = BuildQuery(request);
db.Set<TEntity>().RemoveRange(query);
return await db.SaveChangesAsync(token);
} }
} }

View File

@ -12,7 +12,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services; namespace AsbCloudInfrastructure.Services;
public class DataSaubStatDrillingQualityService : IDataSaubStatService public class DataSaubStatDrillingQualityService : IDataSaubStatDrillingQualityService
{ {
private IDataSaubStatRepository<DataSaubStatDrillingQualityDto> dataSaubStatDrillingQualityRepository; private IDataSaubStatRepository<DataSaubStatDrillingQualityDto> dataSaubStatDrillingQualityRepository;
private ITelemetryDataSaubService dataSaubService; private ITelemetryDataSaubService dataSaubService;

View File

@ -51,7 +51,7 @@ public class DataSaubStatService : IDataSaubStatService
var idTelemetry = idTelemetries[i]; var idTelemetry = idTelemetries[i];
var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch;
var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token); var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token);
if(onProgressCallback != null) if (onProgressCallback != null)
onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length); onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length);
} }
} }

View File

@ -33,6 +33,7 @@ public class Startup
backgroundWorker.Add<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30)); backgroundWorker.Add<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));
backgroundWorker.Add<WorkOperationDetection>(TimeSpan.FromMinutes(0)); backgroundWorker.Add<WorkOperationDetection>(TimeSpan.FromMinutes(0));
backgroundWorker.Add<WorkDataSaubStat>(TimeSpan.FromMinutes(0)); backgroundWorker.Add<WorkDataSaubStat>(TimeSpan.FromMinutes(0));
backgroundWorker.Add<WorkDataSaubStatDrillingQuality>(TimeSpan.FromMinutes(0));
backgroundWorker.Add<WorkLimitingParameterCalc>(TimeSpan.FromMinutes(0)); backgroundWorker.Add<WorkLimitingParameterCalc>(TimeSpan.FromMinutes(0));
backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(0)); backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(0));