forked from ddrilling/AsbCloudServer
152 lines
6.2 KiB
C#
152 lines
6.2 KiB
C#
using AsbCloudDb.Model;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System;
|
|
using System.Data.Common;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Collections.Generic;
|
|
using AsbCloudInfrastructure.Background;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace AsbCloudInfrastructure.Services
|
|
{
|
|
|
|
internal static class LimitingParameterCalcWorkFactory
|
|
{
|
|
private const string workId = "Limiting parameter calc";
|
|
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
|
|
|
|
public static WorkPeriodic MakeWork()
|
|
{
|
|
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
|
|
{
|
|
Timeout = TimeSpan.FromMinutes(30)
|
|
};
|
|
return workPeriodic;
|
|
}
|
|
|
|
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
|
|
private static async Task WorkAction(string _, IServiceProvider serviceProvider, CancellationToken token)
|
|
{
|
|
using var db = serviceProvider.GetRequiredService<IAsbCloudDbContext>();
|
|
var lastDetectedDates = await db.LimitingParameter
|
|
.GroupBy(o => o.IdTelemetry)
|
|
.Select(g => new
|
|
{
|
|
IdTelemetry = g.Key,
|
|
LastDate = g.Max(o => o.DateEnd)
|
|
})
|
|
.ToListAsync(token);
|
|
|
|
var telemetryIds = await db.Telemetries
|
|
.Where(t => t.Info != null && t.TimeZone != null)
|
|
.Select(t => t.Id)
|
|
.ToListAsync(token);
|
|
|
|
var telemetryLastDetectedDates = telemetryIds
|
|
.GroupJoin(lastDetectedDates,
|
|
t => t,
|
|
o => o.IdTelemetry,
|
|
(outer, inner) => new
|
|
{
|
|
IdTelemetry = outer,
|
|
inner.SingleOrDefault()?.LastDate,
|
|
});
|
|
|
|
foreach (var item in telemetryLastDetectedDates)
|
|
{
|
|
var newLimitingParameters = await GetLimitingParameterAsync(item.IdTelemetry, item.LastDate ?? DateTimeOffset.MinValue, db, token);
|
|
if (newLimitingParameters?.Any() == true)
|
|
{
|
|
db.LimitingParameter.AddRange(newLimitingParameters);
|
|
await db.SaveChangesAsync(token);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static async Task<IEnumerable<LimitingParameter>> GetLimitingParameterAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
|
|
{
|
|
var query =
|
|
$"select " +
|
|
$"limiting_parameters.date, limiting_parameters.id_feed_regulator, limiting_parameters.well_depth " +
|
|
$"from ( " +
|
|
$"select " +
|
|
$"date, id_feed_regulator, well_depth, " +
|
|
$"lag(id_feed_regulator, 1) over (order by date) as id_feed_regulator_lag, " +
|
|
$"lead(id_feed_regulator, 1) over (order by date) as id_feed_regulator_lead " +
|
|
$"from t_telemetry_data_saub " +
|
|
$"where id_feed_regulator is not null " +
|
|
$"and id_telemetry = {idTelemetry}" +
|
|
$"and date >= '{begin:u}'" +
|
|
$"order by date) as limiting_parameters " +
|
|
$"where id_feed_regulator_lag is null " +
|
|
$"or (id_feed_regulator != id_feed_regulator_lag and id_feed_regulator_lead != id_feed_regulator_lag) " +
|
|
$"order by date;";
|
|
|
|
var limitingParameters = new List<LimitingParameter>(32);
|
|
using (var result = await ExecuteReaderAsync(db, query, token))
|
|
{
|
|
LimitingParameter? limitingLast = null;
|
|
while (result.Read())
|
|
{
|
|
var date = result.GetFieldValue<DateTimeOffset>(0);
|
|
var idLimiting = result.GetFieldValue<short>(1);
|
|
var wellDepth = result.GetFieldValue<float>(2);
|
|
|
|
if (limitingLast is null)
|
|
{
|
|
limitingLast = new LimitingParameter
|
|
{
|
|
DateStart = date,
|
|
DepthStart = wellDepth,
|
|
IdFeedRegulator = idLimiting
|
|
};
|
|
}
|
|
|
|
if (limitingLast.IdFeedRegulator != idLimiting)
|
|
{
|
|
limitingParameters.Add(new LimitingParameter {
|
|
IdTelemetry = idTelemetry,
|
|
IdFeedRegulator = limitingLast.IdFeedRegulator,
|
|
DateStart = limitingLast.DateStart,
|
|
DateEnd = date,
|
|
DepthStart = limitingLast.DepthStart,
|
|
DepthEnd = wellDepth
|
|
});
|
|
|
|
limitingLast = new LimitingParameter
|
|
{
|
|
DateStart = date,
|
|
DepthStart = wellDepth,
|
|
IdFeedRegulator = idLimiting
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
return limitingParameters;
|
|
}
|
|
|
|
private static async Task<DbDataReader> ExecuteReaderAsync(IAsbCloudDbContext db, string query, CancellationToken token)
|
|
{
|
|
var connection = db.Database.GetDbConnection();
|
|
if (
|
|
connection?.State is null ||
|
|
connection.State == ConnectionState.Broken ||
|
|
connection.State == ConnectionState.Closed)
|
|
{
|
|
await db.Database.OpenConnectionAsync(token);
|
|
connection = db.Database.GetDbConnection();
|
|
}
|
|
using var command = connection.CreateCommand();
|
|
command.CommandText = query;
|
|
|
|
var result = await command.ExecuteReaderAsync(token);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
}
|