diff --git a/AsbCloudApp/Services/ITelemetryService.cs b/AsbCloudApp/Services/ITelemetryService.cs index 0975d0cf..c4e50b35 100644 --- a/AsbCloudApp/Services/ITelemetryService.cs +++ b/AsbCloudApp/Services/ITelemetryService.cs @@ -1,12 +1,12 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.SAUB; using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace AsbCloudApp.Services { +#nullable enable /// /// Сервис телеметрии /// @@ -43,21 +43,12 @@ namespace AsbCloudApp.Services /// SimpleTimezoneDto GetTimezone(int idTelemetry); - // TODO: вероятно лишнее - /// - /// Список передающих в данный момент телеметрий - /// - /// - IEnumerable GetTransmittingTelemetries(); - - // TODO: вероятно лишнее /// /// Получить дату получения последних данных /// /// - /// /// - DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false); + DateTime GetLastTelemetryDate(int idTelemetry); /// /// получить idTelemetry по IdWell @@ -82,16 +73,6 @@ namespace AsbCloudApp.Services /// Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token); - // TODO: вероятно лишнее - /// - /// обновить данные о временной зоне (используется панелью) - /// - /// - /// - /// - /// - Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto telemetryTimeZoneInfo, CancellationToken token); - /// /// Слить данные телеметрии в одну /// @@ -100,13 +81,7 @@ namespace AsbCloudApp.Services /// /// Task MergeAsync(int from, int to, CancellationToken token); - - // TODO: вероятно лишнее - /// - /// сохранить данные о запросе - /// - /// - /// - void SaveRequestDate(string uid, DateTimeOffset remoteDate); } + +#nullable disable } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs index 11db53f7..541003e5 100644 --- a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs @@ -141,10 +141,6 @@ namespace AsbCloudInfrastructure.Services.SAUB var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid); var timezone = telemetryService.GetTimezone(telemetryId); - var maxDateDto = dtos.Max(m => m.Date); - var maxDateUtc = maxDateDto.ToUtcDateTimeOffset(timezone.Hours); - telemetryService.SaveRequestDate(uid, maxDateDto); - foreach (var dto in dtos) { var entity = dto.Adapt(); diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index 285ac3d8..a1881174 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -14,13 +14,11 @@ namespace AsbCloudInfrastructure.Services.SAUB { public abstract class TelemetryDataBaseService : ITelemetryDataService where TDto : AsbCloudApp.Data.ITelemetryData - where TModel : class, AsbCloudDb.Model.ITelemetryData + where TModel : class, ITelemetryData { protected readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; - protected readonly CacheTable cacheTelemetry; protected readonly CacheTable cacheTelemetryUsers; - protected readonly CacheTable cacheWells; public TelemetryDataBaseService( IAsbCloudDbContext db, @@ -29,9 +27,7 @@ namespace AsbCloudInfrastructure.Services.SAUB { this.db = db; this.telemetryService = telemetryService; - cacheTelemetry = cacheDb.GetCachedTable((AsbCloudDbContext)db); cacheTelemetryUsers = cacheDb.GetCachedTable((AsbCloudDbContext)db); - cacheWells = cacheDb.GetCachedTable((AsbCloudDbContext)db); } public virtual async Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token = default) @@ -65,7 +61,7 @@ namespace AsbCloudInfrastructure.Services.SAUB }); var entityMaxDate = entities.Max(e => e.DateTime); - telemetryService.SaveRequestDate(uid, entityMaxDate); + telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate); var dbset = db.Set(); var stopwatch = Stopwatch.StartNew(); @@ -91,11 +87,9 @@ namespace AsbCloudInfrastructure.Services.SAUB DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default) { - var well = cacheWells.FirstOrDefault(w => w.Id == idWell); - if (well?.IdTelemetry is null) - return default; - - var idTelemetry = well?.IdTelemetry ?? default; + var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell) ?? -1; + if (idTelemetry == -1) + return null; var timezone = telemetryService.GetTimezone(idTelemetry); @@ -103,7 +97,8 @@ namespace AsbCloudInfrastructure.Services.SAUB DateTimeOffset dateBeginUtc; if (dateBegin == default) { - dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry, true); + dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry) + .ToUtcDateTimeOffset(timezone.Hours); if (dateBeginUtc != default) dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec); } @@ -153,24 +148,5 @@ namespace AsbCloudInfrastructure.Services.SAUB public abstract TModel Convert(TDto src, double timezoneOffset); - private static double AssumeTimezoneOffset(DateTime nearToCurrentDate) - { - var offset = 5d; - if (nearToCurrentDate.Kind == DateTimeKind.Unspecified) - { - var now = DateTime.UtcNow; - var minutes = 60 * (now.Hour - nearToCurrentDate.Hour) + now.Minute - nearToCurrentDate.Minute; - var minutesPositive = (1440_0000 + minutes) % 1440; //60*24 - var halfsHours = Math.Round(1d * minutesPositive / 30d); // quarters are ignored - var hours = halfsHours / 2; - offset = hours < 12 ? hours : 24 - hours; - } - if (nearToCurrentDate.Kind == DateTimeKind.Local) - offset = TimeZoneInfo.Local.BaseUtcOffset.TotalHours; - - return offset; - } - - } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs index d327a02c..21390596 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs @@ -3,7 +3,7 @@ using AsbCloudApp.Data.SAUB; using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.Cache; +using AsbCloudInfrastructure.EfCache; using Mapster; using Microsoft.EntityFrameworkCore; using System; @@ -14,10 +14,12 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.SAUB { +#nullable enable public class TelemetryService : ITelemetryService { - private readonly CacheTable cacheTelemetry; - private readonly CacheTable cacheWells;//TODO: use wellService instead of this + private const string telemetryCacheTag = "telemetryCache"; + private static readonly TimeSpan telemetryCacheObsolescence = TimeSpan.FromMinutes(5); + private readonly IAsbCloudDbContext db; private readonly ITelemetryTracker telemetryTracker; private readonly ITimezoneService timezoneService; @@ -28,59 +30,42 @@ namespace AsbCloudInfrastructure.Services.SAUB public TelemetryService( IAsbCloudDbContext db, ITelemetryTracker telemetryTracker, - ITimezoneService timezoneService, - CacheDb cacheDb) + ITimezoneService timezoneService) { - cacheTelemetry = cacheDb.GetCachedTable((AsbCloudDbContext)db); - cacheWells = cacheDb.GetCachedTable( - (AsbCloudDbContext)db, - $"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}", - nameof(Well.Telemetry), - $"{nameof(Well.RelationCompaniesWells)}.{nameof(RelationCompanyWell.Company)}", - nameof(Well.WellType)); this.db = db; this.telemetryTracker = telemetryTracker; this.timezoneService = timezoneService; } - public IEnumerable GetTransmittingTelemetries() + private Dictionary GetTelemetryCache() { - var telemetryDtos = new List(); - var activeTelemetriesUids = telemetryTracker.GetTransmittingTelemetriesUids(); - if (!activeTelemetriesUids.Any()) - return telemetryDtos; - var telemetries = cacheTelemetry - .Where(t => activeTelemetriesUids.Contains(t.RemoteUid)); - telemetryDtos = telemetries.Adapt>().ToList(); - - return telemetryDtos; + var cache = db.Telemetries + .Include(t => t.Well) + .FromCacheDictionary(telemetryCacheTag, telemetryCacheObsolescence, t => t.Id); + return cache; } - public void SaveRequestDate(string uid, DateTimeOffset remoteDate) => - telemetryTracker.SaveRequestDate(uid, remoteDate); - - public DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false) + private void DropTelemetryCache() { - var lastTelemetryDate = DateTimeOffset.MinValue; - var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry); + db.Telemetries.DropCacheDictionary(telemetryCacheTag); + } + + public DateTime GetLastTelemetryDate(int idTelemetry) + { + var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry); if (telemetry is null) throw new Exception($"Telemetry id:{idTelemetry} does not exist"); var uid = telemetry.RemoteUid; var timzone = GetTimezone(idTelemetry); - - lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid); - - if (useUtc) - return lastTelemetryDate.UtcDateTime; - + var lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid); return lastTelemetryDate.ToRemoteDateTime(timzone.Hours); } public DatesRangeDto GetDatesRange(int idTelemetry) { - var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry); + var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry); if (telemetry is null) throw new Exception($"Telemetry id:{idTelemetry} does not exist"); @@ -115,13 +100,14 @@ namespace AsbCloudInfrastructure.Services.SAUB TimezoneId = info.TimeZoneId }; - await cacheTelemetry.UpsertAsync(telemetry, token) - .ConfigureAwait(false); + db.Telemetries.Upsert(telemetry); + await db.SaveChangesAsync(token); + DropTelemetryCache(); } public SimpleTimezoneDto GetTimezone(int idTelemetry) { - var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry); + var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry); if (telemetry is null) throw new Exception($"Telemetry id: {idTelemetry} does not exist."); @@ -137,58 +123,65 @@ namespace AsbCloudInfrastructure.Services.SAUB IsOverride = false, TimezoneId = telemetry.Info.TimeZoneId, }; - cacheTelemetry.Upsert(telemetry); + db.Telemetries.Upsert(telemetry); + db.SaveChanges(); + DropTelemetryCache(); return telemetry.TimeZone.Adapt(); } if (telemetry.Well?.Timezone is not null) { telemetry.TimeZone = telemetry.Well.Timezone; - cacheTelemetry.Upsert(telemetry); + db.Telemetries.Upsert(telemetry); + db.SaveChanges(); + DropTelemetryCache(); return telemetry.TimeZone.Adapt(); } throw new Exception($"Telemetry id: {idTelemetry} can't find timezone."); } - public async Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto timeone, - CancellationToken token) - { - var telemetry = GetOrCreateTelemetryByUid(uid); - var newTelemetryTimeZone = timeone.Adapt(); - if (newTelemetryTimeZone?.Equals(telemetry.TimeZone) == true) - return; - await cacheTelemetry.UpsertAsync(telemetry, token) - .ConfigureAwait(false); - } - public int? GetIdTelemetryByIdWell(int idWell) { - var well = cacheWells.FirstOrDefault(w => w.Id == idWell); - return well?.IdTelemetry; + var telemetry = GetTelemetryCache() + .FirstOrDefault(t => t.Value.Well?.Id == idWell).Value; + return telemetry?.Id; } - private Well GetWellByTelemetryUid(string uid) + private Well? GetWellByTelemetryUid(string uid) { - var tele = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid); - if (tele is null) - return null; + var telemetry = GetOrDefaultTelemetryByUid(uid); + return telemetry?.Well; + } - var well = cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id); - return well; + private Telemetry? GetOrDefaultTelemetryByUid(string uid) + { + var telemetry = GetTelemetryCache().FirstOrDefault(kv => kv.Value.RemoteUid == uid).Value; + return telemetry; } private Telemetry GetOrCreateTelemetryByUid(string uid) - => cacheTelemetry.GetOrCreate(t => t.RemoteUid == uid, () => new Telemetry + { + var telemetry = GetOrDefaultTelemetryByUid(uid); + if (telemetry is null) { - RemoteUid = uid, - TimeZone = new SimpleTimezone + var newTelemetry = new Telemetry { - Hours = 5, - IsOverride = false, - TimezoneId = "default", - } - }); + RemoteUid = uid, + TimeZone = new SimpleTimezone + { + Hours = 5, + IsOverride = false, + TimezoneId = "default", + } + }; + var entry = db.Telemetries.Add(newTelemetry); + db.SaveChanges(); + DropTelemetryCache(); + return entry.Entity; + } + return telemetry; + } public async Task MergeAsync(int from, int to, CancellationToken token) { @@ -229,12 +222,15 @@ namespace AsbCloudInfrastructure.Services.SAUB stopwath.Stop(); Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows."); + DropTelemetryCache(); return affected; } catch (Exception ex) { System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}"); - await transaction.RollbackAsync(token).ConfigureAwait(false); +#pragma warning disable CA2016 // Перенаправьте параметр "CancellationToken" в методы + await transaction.RollbackAsync(); +#pragma warning restore CA2016 // Перенаправьте параметр "CancellationToken" в методы return -1; } } @@ -352,4 +348,5 @@ namespace AsbCloudInfrastructure.Services.SAUB return affected; } } +#nullable disable } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs index 33750bdd..4a77088a 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs @@ -54,23 +54,6 @@ namespace AsbCloudWebApi.Controllers.SAUB return Ok(); } - /// - /// Обновляет часовой пояс скважины - /// - /// Уникальный идентификатор отправителя - /// Информация о часовом поясе - /// Токен отмены задачи - /// - [HttpPost] - [Route("{uid}/timezone")] - public async Task UpdateTimeZoneAsync(string uid, SimpleTimezoneDto timezone, - CancellationToken token) - { - await telemetryService.UpdateTimezoneAsync(uid, timezone, token) - .ConfigureAwait(false); - return Ok(); - } - /// /// Принимает список новых сообщений от телеметрии ///