From 64641c5bc3814bbd63c2defce2948c52e4af247d Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 8 Nov 2022 17:49:04 +0500 Subject: [PATCH] =?UTF-8?q?#7579139=20=D0=BF=D0=B5=D1=80=D0=B2=D0=B0=D1=8F?= =?UTF-8?q?=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20=D0=BA=D0=B5=D1=88?= =?UTF-8?q?=D0=B0=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=B0.=20=D0=9D=D0=B5?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B5=20=D0=BF=D1=80=D0=BE=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/AsbCloudApp.csproj | 4 - .../Services/SAUB/TelemetryDataBaseService.cs | 2 +- .../Services/SAUB/TelemetryDataCache.cs | 101 +++++++++++++++++- 3 files changed, 97 insertions(+), 10 deletions(-) diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 7a10181c..8ca1bbfe 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -18,10 +18,6 @@ - - - - diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index a1881174..cee2cae8 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -82,7 +82,7 @@ namespace AsbCloudInfrastructure.Services.SAUB return 0; } } - + /// public virtual async Task> GetAsync(int idWell, DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default) diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs index b96622fe..1caa0102 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs @@ -1,23 +1,114 @@ using AsbCloudDb.Model; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections; using System; -using AsbCloudApp.Services; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Mapster; #nullable enable namespace AsbCloudInfrastructure.Services.SAUB { - public class TelemetryDataCache + public class TelemetryDataCache + where TDto : AsbCloudApp.Data.ITelemetryData + where TEntity : class, ITelemetryData { - private readonly ConcurrentDictionary> caches; - private static TelemetryDataCache? instance; + private const int activeWellCapacity = 24 * 60 * 60; + private const int doneWellCapacity = 65 * 60; + private readonly ConcurrentDictionary> caches; + public TelemetryDataCache(IAsbCloudDbContext db) { caches = new (); + LoadCaches(db); } + private void LoadCaches(IAsbCloudDbContext db) + { + Well[] wells = db.Set() + .Include(well => well.Telemetry) + .Where(well => well.IdTelemetry != null) + .ToArray(); + + foreach (Well well in wells) + { + var capacity = well.IdState == 1 + ? activeWellCapacity + : doneWellCapacity; + + var idTelemetry = well.IdTelemetry!.Value; + var hoursOffset = well.Timezone.Hours; + + IEnumerable cacheItemData = GetCacheDataFromDb(db, idTelemetry, capacity, hoursOffset); + var cacheItem = new CyclycArray(capacity); + cacheItem.AddRange(cacheItemData); + caches.TryAdd(idTelemetry, cacheItem); + } + } + + private static IEnumerable GetCacheDataFromDb(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset) + { + var entities = db.Set() + .Where(i => i.IdTelemetry == idTelemetry) + .OrderByDescending(i => i.DateTime) + .Take(capacity) + .ToArray() + .OrderBy(i => i.DateTime); + + var dtos = entities.Select(entity => { + var dto = entity.Adapt(); + dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset); + return dto; + }); + + return dtos; + } + + /// + /// Добавить элементы в кеш + /// + /// + /// + public void AddRange(int idTelemetry, IEnumerable range) + { + var cacheItem = caches.GetOrAdd(idTelemetry, _ => new CyclycArray(activeWellCapacity)); + var newItems = range + .OrderBy(i => i.DateTime); + foreach (var item in newItems) + item.IdTelemetry = idTelemetry; + cacheItem.AddRange(newItems); + } + + /// + /// Получить данные из кеша.
+ /// Если dateBegin меньше минимального элемента в кеше, то вернется null. + /// Даже если intervalSec частично перекрыт данными из кеша. + ///
+ /// + /// + /// + /// кол-во элементов до которых эти данные прореживаются + /// + public IEnumerable? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600d, int approxPointsCount = 1024) + { + if(!caches.TryGetValue(idTelemetry, out CyclycArray? cacheItem)) + return null; + + if (cacheItem is null || cacheItem[0].DateTime > dateBegin) + return null; + + var dateEnd = dateBegin.AddSeconds(intervalSec); + var items = cacheItem + .Where(i => i.DateTime >= dateBegin && i.DateTime <= dateEnd); + + var ratio = items.Count() / approxPointsCount; + if (ratio > 1) + items = items + .Where((_, index) => index % ratio == 0); + + return items; + } } } #nullable disable \ No newline at end of file