DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/TelemetryService.cs

245 lines
11 KiB
C#
Raw Normal View History

2021-04-07 18:01:56 +05:00
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
2021-07-28 09:46:58 +05:00
using Mapster;
2021-09-29 10:12:54 +05:00
using System.Collections.Generic;
using System.Linq;
2021-09-29 10:12:54 +05:00
using System;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
2021-04-07 18:01:56 +05:00
namespace AsbCloudInfrastructure.Services
{
public class TelemetryService : ITelemetryService
{
private readonly CacheTable<Telemetry> cacheTelemetry;
private readonly CacheTable<Well> cacheWells;
private readonly IAsbCloudDbContext db;
2021-04-07 18:01:56 +05:00
2021-07-28 09:46:58 +05:00
public TelemetryService(IAsbCloudDbContext db, CacheDb cacheDb)
2021-04-07 18:01:56 +05:00
{
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db);
this.db = db;
2021-04-07 18:01:56 +05:00
}
2021-04-23 10:21:25 +05:00
public int GetOrCreateTemetryIdByUid(string uid)
=> GetOrCreateTelemetryByUid(uid).Id;
2021-04-07 18:01:56 +05:00
2021-07-27 14:43:30 +05:00
public int? GetidWellByTelemetryUid(string uid)
2021-04-23 10:21:25 +05:00
=> GetWellByTelemetryUid(uid)?.Id;
public double GetTimezoneOffsetByTelemetryId(int idTelemetry) =>
cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info?.TimeZoneOffsetTotalHours??0d;
2021-04-23 10:21:25 +05:00
public void UpdateInfo(string uid, TelemetryInfoDto info)
{
2021-04-23 10:21:25 +05:00
var telemetry = GetOrCreateTelemetryByUid(uid);
2021-07-28 09:46:58 +05:00
telemetry.Info = info.Adapt<TelemetryInfo>();
2021-04-23 10:21:25 +05:00
cacheTelemetry.Upsert(telemetry);
2021-04-07 18:01:56 +05:00
}
public int? GetIdTelemetryByIdWell(int idWell)
{
2021-07-27 14:43:30 +05:00
var well = cacheWells.FirstOrDefault(w => w.Id == idWell);
if (well is null)
return null;
return well.IdTelemetry;
}
2021-04-23 10:21:25 +05:00
private Well GetWellByTelemetryUid(string uid)
2021-04-07 18:01:56 +05:00
{
2021-04-23 10:21:25 +05:00
var tele = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid, RefreshMode.IfResultEmpty);
if (tele is null)
return null;
return cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
2021-04-07 18:01:56 +05:00
}
2021-04-23 10:21:25 +05:00
// TODO: fix cacheTable before uncomment next
//private Telemetry GetOrCreateTelemetryByUid(string uid)
// => cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid)
// ?? cacheTelemetry.Insert(new Telemetry { RemoteUid = uid, });
2021-04-23 10:21:25 +05:00
private Telemetry GetOrCreateTelemetryByUid(string uid)
{
var telemetry = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid);
if (telemetry is not null)
return telemetry;
2021-04-23 10:21:25 +05:00
telemetry = db.Telemetries.OrderBy(t=>t.Info).FirstOrDefault(t => t.RemoteUid == uid);
if (telemetry is not null)
return telemetry;
var newTelemetryEntry = db.Telemetries.Add(new Telemetry { RemoteUid = uid });
db.SaveChanges();
cacheTelemetry.Refresh();
return newTelemetryEntry.Entity;
}
2021-09-29 10:12:54 +05:00
public IEnumerable<(string Key, int[] Ids)> GetRedundentRemoteUids()
{
return db.Telemetries
.ToList()
.GroupBy(t => t.RemoteUid)
.Where(g => g.Count() > 1)
.Select(g => (g.Key, g.Select(t=>t.Id).ToArray()));
}
public int Merge(IEnumerable<int> telemetryIds)
{
if (telemetryIds.Count() < 2)
throw new ArgumentException($"telemetryIds {telemetryIds} < 2. nothing to merge.", nameof(telemetryIds));
// найти телеметрию с наиболее полными справочниками и принять её за основную
// отделить основную от остальных
// связонные сущности:
// Telemetry
// TelemetryInfo
// TelemetryEvent
// TelemetryUser
// TelemetryMessage
// TelemetryDataSpin
// TelemetryDataSaub
// TelemetryAnalysis
// Well
// Оценка трудоебкости
var telemetriesGrade = db.Telemetries
.Include(t => t.Messages)
.Include(t => t.DataSaub)
.Include(t => t.DataSpin)
.Include(t => t.Well)
.Where(t => telemetryIds.Contains(t.Id))
.Select(t => new {
t.Id,
t.RemoteUid,
t.Info,
IdWell = t.Well != null ? t.Well.Id : int.MinValue,
Records = t.Messages.Count + t.DataSaub.Count + t.DataSpin.Count,
EventsAny = t.Events.Any(),
UsersAny = t.Users.Any(),
})
.OrderByDescending(t=>t.Records)
.ToList();
var telemetryDestId = telemetriesGrade.FirstOrDefault().Id;
if (telemetryDestId == default)
return 0;
var telemetriesSrcIds = telemetryIds.Where(t => t != telemetryDestId).ToList();
if(!telemetriesSrcIds.Any())
return 0;
var telemetriesSrcIdsSql = $"({string.Join(',', telemetriesSrcIds)})";
var telemetryInfoAndUid = telemetriesGrade
.Where(t => t.Info != null)
.OrderByDescending(t => t.Id)
.Select(t => (t.RemoteUid, t.Info))
.FirstOrDefault();
var wellId = telemetriesGrade
.Where(t => t.IdWell > 0)
.OrderByDescending(t => t.Id)
.Select(t => t.IdWell)
.FirstOrDefault();
// начало изменений
Console.WriteLine($"Start merge telemetries ids: [{string.Join(',', telemetriesSrcIds)}] to {telemetryDestId}");
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
var transaction = db.Database.BeginTransaction();
int rows = 0;
try
{
var telemetryDst = db.Telemetries.FirstOrDefault(t => t.Id == telemetryDestId);
telemetryDst.RemoteUid = telemetryInfoAndUid.RemoteUid;
telemetryDst.Info = telemetryInfoAndUid.Info;
if (wellId != default)
{
var well = db.Wells.FirstOrDefault(w => w.Id == wellId);
well.IdTelemetry = telemetryDestId;
}
// events merge
var telemetryDstEventsIds = db.TelemetryEvents.Where(t => t.IdTelemetry == telemetryDestId).Select(t => t.IdEvent).ToList();
var telemetrySrcEvents = db.TelemetryEvents
.Where(t => telemetriesSrcIds.Contains(t.IdTelemetry) && !telemetryDstEventsIds.Contains(t.IdEvent))
.Select(t => new TelemetryEvent
{
IdTelemetry = telemetryDestId,
IdEvent = t.IdEvent,
IdCategory = t.IdCategory,
MessageTemplate = t.MessageTemplate,
})
.ToList();
var telemetryEventNewUniq = new Dictionary<int, TelemetryEvent>();
foreach (var telemetryEvent in telemetrySrcEvents)
telemetryEventNewUniq[telemetryEvent.IdEvent] = telemetryEvent;
if (telemetrySrcEvents.Any())
db.TelemetryEvents.AddRange(telemetryEventNewUniq.Values);
// users merge
var telemetryDstUsersIds = db.TelemetryUsers.Where(t => t.IdTelemetry == telemetryDestId).Select(t => t.IdUser).ToList();
var telemetrySrcUsers = db.TelemetryUsers
.Where(t => telemetriesSrcIds.Contains(t.IdTelemetry) && !telemetryDstUsersIds.Contains(t.IdUser))
.Select(t => new TelemetryUser
{
IdTelemetry = telemetryDestId,
IdUser = t.IdUser,
Level = t.Level,
Name = t.Name,
Patronymic = t.Patronymic,
Surname = t.Surname,
}).ToList();
var telemetryUserNewUniq = new Dictionary<int, TelemetryUser>();
foreach (var telemetryUser in telemetrySrcUsers)
telemetryUserNewUniq[telemetryUser.IdUser] = telemetryUser;
if (telemetrySrcUsers.Any())
db.TelemetryUsers.AddRange(telemetryUserNewUniq.Values);
db.SaveChanges();
db.Database.SetCommandTimeout(3_000); // 5 мин
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_data_saub DISABLE TRIGGER ALL;");
rows += db.Database.ExecuteSqlRaw($"UPDATE t_telemetry_data_saub SET id_telemetry = {telemetryDestId} WHERE id_telemetry IN {telemetriesSrcIdsSql};");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_data_saub ENABLE TRIGGER ALL;");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_data_spin DISABLE TRIGGER ALL;");
rows += db.Database.ExecuteSqlRaw($"UPDATE t_telemetry_data_spin SET id_telemetry = {telemetryDestId} WHERE id_telemetry IN {telemetriesSrcIdsSql};");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_data_spin ENABLE TRIGGER ALL;");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_analysis DISABLE TRIGGER ALL;");
rows += db.Database.ExecuteSqlRaw($"UPDATE t_telemetry_analysis SET id_telemetry = {telemetryDestId} WHERE id_telemetry IN {telemetriesSrcIdsSql};");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_analysis ENABLE TRIGGER ALL;");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_message DISABLE TRIGGER ALL;");
rows += db.Database.ExecuteSqlRaw($"UPDATE t_telemetry_message SET id_telemetry = {telemetryDestId} WHERE id_telemetry IN {telemetriesSrcIdsSql};");
db.Database.ExecuteSqlRaw($"ALTER TABLE t_telemetry_message ENABLE TRIGGER ALL;");
rows += db.Database.ExecuteSqlRaw($"DELETE FROM t_telemetry_event WHERE id_telemetry IN {telemetriesSrcIdsSql};");
rows += db.Database.ExecuteSqlRaw($"DELETE FROM t_telemetry_user WHERE id_telemetry IN {telemetriesSrcIdsSql};");
rows += db.Database.ExecuteSqlRaw($"DELETE FROM t_telemetry WHERE id IN {telemetriesSrcIdsSql};");
transaction.Commit();
sw.Stop();
Console.WriteLine($"Successfully commited in {1d*sw.ElapsedMilliseconds/1000d: #0.00} sec.");
}
catch(Exception ex)
{
Console.WriteLine("Fail. Rollback.");
transaction.Rollback();
return 0;
}
return rows;
}
2021-04-07 18:01:56 +05:00
}
}