using AsbCloudApp.Data.SAUB; using AsbCloudApp.Repositories; using AsbCloudDb.Model; using AsbCloudDb.Model.Subsystems; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Background.PeriodicWorks; public abstract class WorkSubsystemOperationTimeCalcAbstract : Work { protected const int idSubsystemTorqueMaster = 65537; protected const int idSubsystemSpinMaster = 65536; protected const int idSubsystemAPDRotor = 11; protected const int idSubsystemAPDSlide = 12; protected const int idSubsystemMse = 2; private static TimeSpan obsoleteTime = TimeSpan.FromDays(365 * 100); public WorkSubsystemOperationTimeCalcAbstract(string workId) : base(workId) { Timeout = TimeSpan.FromMinutes(30); } protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) { var db = services.GetRequiredService(); db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5)); var telemetryLastDetectedDates = await GetTelemetryLastDetectedDates(services, db, token); var count = telemetryLastDetectedDates.Count(); var i = 0d; foreach (var item in telemetryLastDetectedDates) { onProgressCallback($"Start handling telemetry: {item.IdTelemetry} from {item.DateDetectedLast}", i++ / count); var newOperationsSaub = await OperationTimeAsync(item.IdTelemetry, item.DateDetectedLast, db, token); if (newOperationsSaub.Any()) { db.SubsystemOperationTimes.AddRange(newOperationsSaub); await db.SaveChangesAsync(token); } } obsoleteTime = TimeSpan.FromDays(3); } protected abstract Task> OperationTimeAsync(int idTelemetry, DateTimeOffset geDate, IAsbCloudDbContext db, CancellationToken token); private static async Task> GetTelemetryLastDetectedDates(IServiceProvider services, IAsbCloudDbContext db, CancellationToken token) { var telemetryDataCache = services.GetRequiredService>(); var updatingTelemetries = telemetryDataCache.GetStat() .Where(tstat => (DateTimeOffset.Now - tstat.DateLast) < obsoleteTime); var telemetryIds = updatingTelemetries .Select(t => t.IdTelemetry) .ToArray(); IEnumerable lastDetectedDates = await GetLastSubsystemOperationTimeAsync(db, token); lastDetectedDates = lastDetectedDates .Where(s => telemetryIds.Contains(s.IdTelemetry)); var result = updatingTelemetries.Select(tstat => new TelemetryDateLast { IdTelemetry = tstat.IdTelemetry, DateDetectedLast = lastDetectedDates.FirstOrDefault(ldd => ldd.IdTelemetry == tstat.IdTelemetry)?.DateDetectedLast ?? DateTimeOffset.UnixEpoch, DateTelemetryLast = tstat.DateLast }); return result; } private static async Task> GetLastSubsystemOperationTimeAsync(IAsbCloudDbContext db, CancellationToken token) { var result = await db.SubsystemOperationTimes .GroupBy(o => o.IdTelemetry) .Select(g => new TelemetryDateLast { IdTelemetry = g.Key, DateDetectedLast = g.Max(o => o.DateEnd) }) .ToArrayAsync(token); return result; } protected class TelemetryDateLast { public int IdTelemetry { get; set; } public DateTimeOffset DateDetectedLast { get; set; } public DateTimeOffset DateTelemetryLast { get; internal set; } } }