using AsbCloudApp.Services; using System; using System.Collections.Generic; using System.Linq; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; using Microsoft.EntityFrameworkCore; using System.Collections.Concurrent; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; namespace AsbCloudInfrastructure.Services { public class TelemetryTracker : ITelemetryTracker { class TrackerStat { //public int Id { get; set; } public string RemoteUid { get; set; } /// /// Время последнего запроса (по времени сервера) /// public DateTime LastTimeServer { get; set; } /// /// Время указанное в данных последнего запроса (из удаленного источника) /// public DateTime LastTimeRemote { get; set; } } private readonly ConcurrentDictionary requests; public TelemetryTracker(CacheDb cacheDb, IConfiguration configuration) { var options = new DbContextOptionsBuilder() .UseNpgsql(configuration.GetConnectionString("DefaultConnection")) .Options; using var db = new AsbCloudDbContext(options); var cacheTelemetry = cacheDb.GetCachedTable(db); var keyValuePairs = new Dictionary(cacheTelemetry.Count()); foreach (var telemetry in cacheTelemetry) { var date = telemetry.Info?.DrillingStartDate ?? GetDateByUidOrDefault(telemetry.RemoteUid, DateTime.MinValue); keyValuePairs[telemetry.RemoteUid] = new TrackerStat { RemoteUid = telemetry.RemoteUid, LastTimeRemote = date, LastTimeServer = date, }; } requests = new ConcurrentDictionary(keyValuePairs); Task.Run(async () => { db.Database.SetCommandTimeout(2 * 60); var dates = await db.TelemetryDataSaub .GroupBy(d => d.IdTelemetry) .Select(g => new { IdTelemetry = g.Key, DateMax = g.Max(d => d.Date), DateMin = g.Min(d => d.Date), }) .AsNoTracking() .ToListAsync() .ConfigureAwait(false); db.Dispose(); var oldReqs = dates.Select(t => new { Uid = cacheTelemetry.FirstOrDefault(c => c.Id == t.IdTelemetry).RemoteUid, t.DateMax, }); foreach (var oldReq in oldReqs) { var request = requests.GetValueOrDefault(oldReq.Uid); if (request is not null) { if (request.LastTimeRemote < oldReq.DateMax) request.LastTimeRemote = oldReq.DateMax; if (request.LastTimeServer < oldReq.DateMax) request.LastTimeServer = oldReq.DateMax; } } }); } private static DateTime GetDateByUidOrDefault(string remoteUid, DateTime defaultValue = default) { //eg: uid = 20211102_173407926 if (string.IsNullOrEmpty(remoteUid) || (remoteUid.Length != 18)) return defaultValue; if (DateTime.TryParseExact(remoteUid, "yyyyMMdd_HHmmssfff", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeUniversal, out DateTime parsedDate)) return parsedDate; return defaultValue; } public void SaveRequestDate(string uid, DateTime remoteDate) { var stat = requests.GetValueOrDefault(uid); if(stat is null) { stat = new TrackerStat{ RemoteUid = uid }; requests[uid] = stat; } stat.LastTimeServer = DateTime.Now; stat.LastTimeRemote = remoteDate; } public DateTime GetLastTelemetryDateByUid(string uid) => requests.GetValueOrDefault(uid)?.LastTimeRemote ?? default; public IEnumerable GetTransmittingTelemetriesUids() => requests.Keys; } }