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;
using AsbCloudApp.Data;
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 TelemetryDateMin { get; set; }
///
/// Дата последних данных в БД
///
public DateTime TelemetryDateMax { get; set; }
}
private readonly ConcurrentDictionary telemetriesStats;
public TelemetryTracker(CacheDb cacheDb, IConfiguration configuration)
{
var options = new DbContextOptionsBuilder()
.UseNpgsql(configuration.GetConnectionString("DefaultConnection"))
.Options;
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
?? ParseDateFromUidOrDefault(telemetry.RemoteUid, DateTime.MinValue);
keyValuePairs[telemetry.RemoteUid] = new TrackerStat
{
RemoteUid = telemetry.RemoteUid,
TelemetryDateMin = date,
TelemetryDateMax = date,
LastTimeServer = date,
};
}
telemetriesStats = 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);
var oldRequests = dates.Select(t => new
{
Uid = cacheTelemetry.FirstOrDefault(c => c.Id == t.IdTelemetry)?.RemoteUid,
t.DateMax,
t.DateMin,
}).Where(s => !string.IsNullOrEmpty(s.Uid));
foreach (var oldReq in oldRequests)
{
var telemetryStat = telemetriesStats.GetOrAdd(oldReq.Uid, (uid) => new TrackerStat { RemoteUid = uid });
var dateMin = oldReq.DateMin.Kind == DateTimeKind.Local
? oldReq.DateMin.ToUniversalTime()
: oldReq.DateMin;
var dateMax = oldReq.DateMax.Kind == DateTimeKind.Local
? oldReq.DateMax.ToUniversalTime()
: oldReq.DateMax;
telemetryStat.TelemetryDateMin = dateMin;
telemetryStat.TelemetryDateMax = dateMax;
telemetryStat.LastTimeServer = dateMax;
}
}).ContinueWith((t) =>
{
db.Dispose();
return t;
});
}
private static DateTime ParseDateFromUidOrDefault(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 = telemetriesStats.GetOrAdd(uid, _ => new TrackerStat {
RemoteUid = uid,
TelemetryDateMin = remoteDate}
);
stat.LastTimeServer = DateTime.Now;
if(stat.TelemetryDateMax.ToUniversalTime() < remoteDate.ToUniversalTime())
stat.TelemetryDateMax = remoteDate;
}
public DateTime GetLastTelemetryDateByUid(string uid) =>
telemetriesStats.GetValueOrDefault(uid)?.TelemetryDateMax ?? default;
public DatesRangeDto GetTelemetryDateRangeByUid(string uid)
{
var stat = telemetriesStats.GetValueOrDefault(uid);
var range = new DatesRangeDto
{
From = stat?.TelemetryDateMin ?? default,
To = stat?.TelemetryDateMax ?? default,
};
return range;
}
public IEnumerable GetTransmittingTelemetriesUids() =>
telemetriesStats.Keys;
}
}