diff --git a/AsbCloudApp/Repositories/ITelemetryDataCache.cs b/AsbCloudApp/Repositories/ITelemetryDataCache.cs
index 851fce0b..f2fa41b0 100644
--- a/AsbCloudApp/Repositories/ITelemetryDataCache.cs
+++ b/AsbCloudApp/Repositories/ITelemetryDataCache.cs
@@ -49,7 +49,7 @@ namespace AsbCloudApp.Repositories
///
///
///
- DatesRangeDto? GetOrDefaultCachedDateRange(int idTelemetry);
+ DatesRangeDto? GetOrDefaultCachedDataDateRange(int idTelemetry);
///
/// Получить диапазон дат телеметрии.
@@ -57,7 +57,7 @@ namespace AsbCloudApp.Repositories
///
///
///
- DatesRangeDto? GetOrDefaultDataDateRange(int idTelemetry);
+ DatesRangeDto? GetOrDefaultWellDataDateRange(int idTelemetry);
///
/// Получение первой и последней записи телеметрии.
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
index 0e07ee09..f5fd2d8b 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
@@ -12,6 +12,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Requests;
+using Mapster;
namespace AsbCloudInfrastructure.Services.SAUB
{
@@ -67,10 +68,10 @@ namespace AsbCloudInfrastructure.Services.SAUB
});
var stopwatch = Stopwatch.StartNew();
- var dbset = db.Set();
+ var dbSet = db.Set();
try
{
- return await db.Database.ExecInsertOrUpdateAsync(dbset, entities, token).ConfigureAwait(false);
+ return await db.Database.ExecInsertOrUpdateAsync(dbSet, entities, token).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -101,7 +102,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
DateTimeOffset dateBeginUtc;
if (dateBegin == default)
{
- var dateRange = telemetryDataCache.GetOrDefaultDataDateRange(telemetry.Id);
+ var dateRange = telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
dateBeginUtc = (dateRange?.To.ToUniversalTime() ?? DateTimeOffset.UtcNow)
.AddSeconds(-intervalSec);
}
@@ -226,17 +227,17 @@ namespace AsbCloudInfrastructure.Services.SAUB
if ((DateTimeOffset.UtcNow - geDate) < TimeSpan.FromHours(12))
{
- // пробуем обойтись кешем
- var cechedRange = telemetryDataCache.GetOrDefaultCachedDateRange(telemetry.Id);
- if (cechedRange?.From <= geDate)
+ // пробуем обойтись кэшем
+ var cachedRange = telemetryDataCache.GetOrDefaultCachedDataDateRange(telemetry.Id);
+ if (cachedRange is not null)
{
- var datesRange = new DatesRangeDto
- {
- From = geDate.DateTime,
- To = cechedRange.To
- };
- if (leDate.HasValue && leDate > geDate)
- datesRange.To = leDate.Value.Date;
+ var datesRange = new DatesRangeDto {From = cachedRange.From, To = cachedRange.To };
+ if (geDate >= cachedRange.From)
+ datesRange.From = geDate.ToOffset(cachedRange.From.Offset);
+
+ if (leDate.HasValue && leDate <= cachedRange.To)
+ datesRange.To = leDate.Value.ToOffset(cachedRange.To.Offset);
+
return datesRange;
}
}
@@ -248,7 +249,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
if(leDate.HasValue)
query = query.Where(entity => entity.DateTime <= leDate.Value.ToUniversalTime());
- var gquery = query
+ var groupQuery = query
.GroupBy(entity => entity.IdTelemetry)
.Select(group => new
{
@@ -256,14 +257,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
MaxDate = group.Max(entity => entity.DateTime),
});
- var result = await gquery.FirstOrDefaultAsync(token);
+ var result = await groupQuery.FirstOrDefaultAsync(token);
if (result is null)
return null;
var range = new DatesRangeDto
{
- From = result.MinDate.ToOffset(TimeSpan.FromHours(telemetry.TimeZone!.Hours)).DateTime,
- To = result.MaxDate.ToOffset(TimeSpan.FromHours(telemetry.TimeZone!.Hours)).DateTime,
+ From = result.MinDate.ToOffset(telemetry.TimeZone!.Offset),
+ To = result.MaxDate.ToOffset(telemetry.TimeZone!.Offset),
};
return range;
}
@@ -274,7 +275,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
if (telemetry is null)
return default;
- return telemetryDataCache.GetOrDefaultDataDateRange(telemetry.Id);
+ return telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
}
protected abstract TDto Convert(TEntity src, double timezoneOffset);
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
index 9d99c700..3b9f7166 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
@@ -13,347 +13,350 @@ using AsbCloudApp.Data;
using AsbCloudApp.Requests;
using AsbCloudApp.Repositories;
-namespace AsbCloudInfrastructure.Services.SAUB
+namespace AsbCloudInfrastructure.Services.SAUB;
+
+public class TelemetryDataCache : ITelemetryDataCache where TDto : AsbCloudApp.Data.ITelemetryData
{
- public class TelemetryDataCache : ITelemetryDataCache where TDto : AsbCloudApp.Data.ITelemetryData
+ class TelemetryDataCacheItem
{
- class TelemetryDataCacheItem
+ public TDto FirstByDate { get; init; } = default!;
+ public CyclicArray LastData { get; init; } = null!;
+ public double TimezoneHours { get; init; } = 5;
+ public TimeSpan TimezoneOffset => TimeSpan.FromHours(TimezoneHours);
+ }
+
+ private const int activeWellCapacity = 12 * 60 * 60;
+ private const int doneWellCapacity = 65 * 60;
+
+ // key == idTelemetry
+ private readonly ConcurrentDictionary caches;
+ private bool isLoading = false;
+
+ private TelemetryDataCache()
+ {
+ caches = new();
+ }
+
+ private static TelemetryDataCache? instance;
+
+ public static TelemetryDataCache GetInstance(IServiceProvider provider)
+ where TEntity : class, AsbCloudDb.Model.ITelemetryData
+ {
+ if (instance is null)
{
- public TDto FirstByDate { get; init; } = default!;
- public CyclicArray LastData { get; init; } = null!;
- public double TimezoneHours { get; init; } = 5;
+ instance = new TelemetryDataCache();
+ var worker = provider.GetRequiredService();
+ var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
+ var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) =>
+ {
+ var db = provider.GetRequiredService();
+ await instance.InitializeCacheFromDBAsync(db, onProgress, token);
+ });
+ work.Timeout = TimeSpan.FromMinutes(15);
+ worker.Enqueue(work);
+ }
+ return instance;
+ }
+
+ ///
+ /// Добавить новые элементы в кеш
+ ///
+ ///
+ ///
+ public void AddRange(int idTelemetry, IEnumerable range)
+ {
+ if (!range.Any())
+ return;
+
+ range = range.OrderBy(x => x.DateTime);
+
+ foreach (var item in range)
+ item.IdTelemetry = idTelemetry;
+
+ TelemetryDataCacheItem cacheItem;
+ if (isLoading)
+ {
+ if (caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? localCacheItem))
+ cacheItem = localCacheItem;
+ else
+ return;
+ }
+ else
+ {
+ cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
+ {
+ FirstByDate = range.ElementAt(0),
+ LastData = new CyclicArray(activeWellCapacity)
+ });
}
- private const int activeWellCapacity = 12 * 60 * 60;
- private const int doneWellCapacity = 65 * 60;
+ cacheItem.LastData.AddRange(range);
+ }
- // key == idTelemetry
- private readonly ConcurrentDictionary caches;
- private bool isLoading = false;
+ ///
+ /// Получить данные из кеша.
+ /// Если dateBegin меньше минимального элемента в кеше, то вернется null.
+ /// Даже если intervalSec частично перекрыт данными из кеша.
+ ///
+ ///
+ ///
+ ///
+ /// кол-во элементов до которых эти данные прореживаются
+ ///
+ public IEnumerable? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600d, int approxPointsCount = 1024)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
- private TelemetryDataCache()
+ var cacheLastData = cacheItem.LastData;
+
+ if (!cacheLastData.Any() || cacheLastData[0].DateTime > dateBegin)
+ return null;
+
+ var dateEnd = dateBegin.AddSeconds(intervalSec);
+ var items = cacheLastData
+ .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;
+ }
+
+ public IEnumerable GetStat()
+ {
+ var result = caches.Select(cacheItem => new TelemetryDataStatDto
{
- caches = new();
- }
+ IdTelemetry = cacheItem.Key,
+ DateFirst = cacheItem.Value.FirstByDate.DateTime,
+ DateLast = cacheItem.Value.LastData[^1].DateTime,
+ TimezoneOffsetHours = cacheItem.Value.TimezoneHours,
+ });
+ return result;
+ }
- private static TelemetryDataCache? instance;
+ public virtual TDto? GetLastOrDefault(int idTelemetry)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return default;
- public static TelemetryDataCache GetInstance(IServiceProvider provider)
- where TEntity : class, AsbCloudDb.Model.ITelemetryData
- {
- if (instance is null)
- {
- instance = new TelemetryDataCache();
- var worker = provider.GetRequiredService();
- var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
- var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) =>
- {
- var db = provider.GetRequiredService();
- await instance.InitializeCacheFromDBAsync(db, onProgress, token);
- });
- work.Timeout = TimeSpan.FromMinutes(15);
- worker.Enqueue(work);
- }
- return instance;
- }
+ return cacheItem.LastData.LastOrDefault();
+ }
- ///
- /// Добавить новые элементы в кеш
- ///
- ///
- ///
- public void AddRange(int idTelemetry, IEnumerable range)
- {
- if (!range.Any())
- return;
+ public DatesRangeDto? GetOrDefaultWellDataDateRange(int idTelemetry)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
+
+ if (!cacheItem.LastData.Any())
+ return null;
- range = range.OrderBy(x => x.DateTime);
+ var to = FromDate(cacheItem.FirstByDate.DateTime, cacheItem.TimezoneOffset);
+ var from = FromDate(cacheItem.LastData[^1].DateTime, cacheItem.TimezoneOffset);
- foreach (var item in range)
- item.IdTelemetry = idTelemetry;
+ return new DatesRangeDto { From = from, To = to };
+ }
- TelemetryDataCacheItem cacheItem;
- if (isLoading)
- {
- if (caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? localCacheItem))
- cacheItem = localCacheItem;
- else
- return;
- }
- else
- {
- cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
- {
- FirstByDate = range.ElementAt(0),
- LastData = new CyclicArray(activeWellCapacity)
- });
- }
-
- cacheItem.LastData.AddRange(range);
- }
+ public DatesRangeDto? GetOrDefaultCachedDataDateRange(int idTelemetry)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
- ///
- /// Получить данные из кеша.
- /// Если dateBegin меньше минимального элемента в кеше, то вернется null.
- /// Даже если intervalSec частично перекрыт данными из кеша.
- ///
- ///
- ///
- ///
- /// кол-во элементов до которых эти данные прореживаются
- ///
- public IEnumerable? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600d, int approxPointsCount = 1024)
- {
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return null;
+ if (cacheItem.LastData.Count < 2)
+ return null;
- var cacheLastData = cacheItem.LastData;
+ var to = FromDate(cacheItem.LastData[^1].DateTime, cacheItem.TimezoneOffset);
+ var from = FromDate(cacheItem.LastData[0].DateTime, cacheItem.TimezoneOffset);
- if (!cacheLastData.Any() || cacheLastData[0].DateTime > dateBegin)
- return null;
+ return new DatesRangeDto { From = from, To = to };
+ }
- var dateEnd = dateBegin.AddSeconds(intervalSec);
- var items = cacheLastData
- .Where(i => i.DateTime >= dateBegin && i.DateTime <= dateEnd);
+ public (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
- var ratio = items.Count() / approxPointsCount;
- if (ratio > 1)
- items = items
- .Where((_, index) => index % ratio == 0);
+ if (!cacheItem.LastData.Any())
+ return null;
- return items;
- }
+ var last = cacheItem.LastData[^1];
+ var first = cacheItem.FirstByDate;
+ return (first, last);
+ }
- public IEnumerable GetStat()
- {
- var result = caches.Select(cacheItem => new TelemetryDataStatDto
- {
- IdTelemetry = cacheItem.Key,
- DateFirst = cacheItem.Value.FirstByDate.DateTime,
- DateLast = cacheItem.Value.LastData[^1].DateTime,
- TimezoneOffsetHours = cacheItem.Value.TimezoneHours,
- });
- return result;
- }
+ private async Task InitializeCacheFromDBAsync(IAsbCloudDbContext db, Action onProgress, CancellationToken token)
+ where TEntity : class, AsbCloudDb.Model.ITelemetryData
+ {
+ var defaultTimeout = db.Database.GetCommandTimeout();
+ db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
- public virtual TDto? GetLastOrDefault(int idTelemetry)
- {
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return default;
+ if (isLoading)
+ throw new Exception("Multiple cache loading detected.");
- return cacheItem.LastData.LastOrDefault();
- }
-
- public DatesRangeDto? GetOrDefaultDataDateRange(int idTelemetry)
- {
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return null;
-
- if (!cacheItem.LastData.Any())
- return null;
-
- var from = DateTime.SpecifyKind(cacheItem.FirstByDate.DateTime, DateTimeKind.Unspecified);
- var to = DateTime.SpecifyKind(cacheItem.LastData[^1].DateTime, DateTimeKind.Unspecified);
-
- return new DatesRangeDto
- {
- From = new DateTimeOffset(from, TimeSpan.FromHours(cacheItem.TimezoneHours)),
- To = new DateTimeOffset(to, TimeSpan.FromHours(cacheItem.TimezoneHours))
- };
- }
-
- public DatesRangeDto? GetOrDefaultCachedDateRange(int idTelemetry)
- {
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return null;
-
- if (cacheItem.LastData.Count < 2)
- return null;
-
- var to = cacheItem.LastData[^1].DateTime;
- var from = cacheItem.LastData[0].DateTime;
-
- return new DatesRangeDto { From = from, To = to };
- }
-
- public (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry)
- {
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return null;
-
- if (!cacheItem.LastData.Any())
- return null;
-
- var last = cacheItem.LastData[^1];
- var first = cacheItem.FirstByDate;
- return (first, last);
- }
-
- private async Task InitializeCacheFromDBAsync(IAsbCloudDbContext db, Action onProgress, CancellationToken token)
- where TEntity : class, AsbCloudDb.Model.ITelemetryData
- {
- var defaultTimeout = db.Database.GetCommandTimeout();
- db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
-
- if (isLoading)
- throw new Exception("Multiple cache loading detected.");
-
- try
- {
- isLoading = true;
-
- Well[] wells = await db.Set()
- .Include(well => well.Telemetry)
- .Include(well => well.Cluster)
- .Where(well => well.IdTelemetry != null)
- .ToArrayAsync(token);
-
- var count = wells.Length;
- var i = 0d;
- foreach (Well well in wells)
- {
- var capacity = well.IdState == 1
- ? activeWellCapacity
- : doneWellCapacity;
-
- var idTelemetry = well.IdTelemetry!.Value;
- var hoursOffset = well.Timezone.Hours;
-
- onProgress($"Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}", i++ / count);
- var cacheItem = await GetOrDefaultCacheDataFromDbAsync(db, idTelemetry, capacity, hoursOffset, token);
- if (cacheItem is not null)
- caches.TryAdd(idTelemetry, cacheItem);
- }
- }
- finally
- {
- isLoading = false;
- db.Database.SetCommandTimeout(defaultTimeout);
- }
- }
-
- private static async Task GetOrDefaultCacheDataFromDbAsync(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset, CancellationToken token)
- where TEntity : class, AsbCloudDb.Model.ITelemetryData
- {
- var query = db.Set()
- .Where(i => i.IdTelemetry == idTelemetry);
-
- var firstDbEntity = await query
- .OrderBy(i => i.DateTime)
- .FirstOrDefaultAsync(token);
-
- if (firstDbEntity is null)
- return default;
-
- var first = firstDbEntity.Adapt();
- first.DateTime = firstDbEntity.DateTime.ToRemoteDateTime(hoursOffset);
-
- var entities = await query
- .OrderByDescending(i => i.DateTime)
- .Take(capacity)
+ try
+ {
+ isLoading = true;
+
+ Well[] wells = await db.Set()
+ .Include(well => well.Telemetry)
+ .Include(well => well.Cluster)
+ .Where(well => well.IdTelemetry != null)
.ToArrayAsync(token);
- var dtos = entities
- .AsEnumerable()
- .Reverse()
- .Select(entity =>
- {
- var dto = entity.Adapt();
- dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
- return dto;
- });
-
- var cacheItem = new CyclicArray(capacity);
- cacheItem.AddRange(dtos);
-
- var item = new TelemetryDataCacheItem
+ var count = wells.Length;
+ var i = 0d;
+ foreach (Well well in wells)
{
- FirstByDate = first,
- LastData = cacheItem,
- TimezoneHours = hoursOffset,
- };
- return item;
+ var capacity = well.IdState == 1
+ ? activeWellCapacity
+ : doneWellCapacity;
+
+ var idTelemetry = well.IdTelemetry!.Value;
+ var hoursOffset = well.Timezone.Hours;
+
+ onProgress($"Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}", i++ / count);
+ var cacheItem = await GetOrDefaultCacheDataFromDbAsync(db, idTelemetry, capacity, hoursOffset, token);
+ if (cacheItem is not null)
+ caches.TryAdd(idTelemetry, cacheItem);
+ }
}
-
- public IEnumerable? GetOrDefault(int idTelemetry, TelemetryDataRequest request)
+ finally
{
- if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
- return null;
-
- IEnumerable data = cacheItem.LastData;
-
- if (!data.Any())
- return null;
-
- if (request.GeDate.HasValue)
- {
- var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
- if (data.First().DateTime > geDate)
- return null;
-
- data = data.Where(d => d.DateTime >= geDate);
- }
- else
- {
- if (request.Order == 0)
- return null;
- }
-
- if (request.LeDate.HasValue)
- {
- var leDate = request.LeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
- data = data.Where(d => d.DateTime <= request.LeDate);
- }
-
- if (request.Divider > 1)
- data = data.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
-
- switch (request.Order)
- {
- case 1: // Поздние вперед
- data = data
- .OrderByDescending(d => d.DateTime)
- .Skip(request.Skip)
- .Take(request.Take)
- .OrderBy(d => d.DateTime);
- break;
- default: // Ранние вперед
- data = data
- .OrderBy(d => d.DateTime)
- .Skip(request.Skip)
- .Take(request.Take);
- break;
- }
-
- return data;
- }
-
- public IEnumerable GetIds(TelemetryDataRequest request)
- {
- var data = caches.Where(i => i.Value.LastData.Count > 0);
-
- if (request.GeDate.HasValue)
- {
- data = data
- .Where(item => {
- var lastItem = item.Value.LastData.Last();
- var geDate = request.GeDate.Value.ToOffset(TimeSpan.FromHours(item.Value.TimezoneHours));
- return lastItem.DateTime >= geDate;
- });
- }
-
- if (request.LeDate.HasValue)
- {
- data = data
- .Where(item => {
- var firstItem = item.Value.LastData.First();
- var leDate = request.LeDate.Value.ToOffset(TimeSpan.FromHours(item.Value.TimezoneHours));
- return firstItem.DateTime <= leDate;
- });
- }
-
- var telemetryIds = data.Select(item => item.Key);
- return telemetryIds;
+ isLoading = false;
+ db.Database.SetCommandTimeout(defaultTimeout);
}
}
+
+ private static async Task GetOrDefaultCacheDataFromDbAsync(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset, CancellationToken token)
+ where TEntity : class, AsbCloudDb.Model.ITelemetryData
+ {
+ var query = db.Set()
+ .Where(i => i.IdTelemetry == idTelemetry);
+
+ var firstDbEntity = await query
+ .OrderBy(i => i.DateTime)
+ .FirstOrDefaultAsync(token);
+
+ if (firstDbEntity is null)
+ return default;
+
+ var first = firstDbEntity.Adapt();
+ first.DateTime = firstDbEntity.DateTime.ToRemoteDateTime(hoursOffset);
+
+ var entities = await query
+ .OrderByDescending(i => i.DateTime)
+ .Take(capacity)
+ .ToArrayAsync(token);
+
+ var dtos = entities
+ .AsEnumerable()
+ .Reverse()
+ .Select(entity =>
+ {
+ var dto = entity.Adapt();
+ dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
+ return dto;
+ });
+
+ var cacheItem = new CyclicArray(capacity);
+ cacheItem.AddRange(dtos);
+
+ var item = new TelemetryDataCacheItem
+ {
+ FirstByDate = first,
+ LastData = cacheItem,
+ TimezoneHours = hoursOffset,
+ };
+ return item;
+ }
+
+ public IEnumerable? GetOrDefault(int idTelemetry, TelemetryDataRequest request)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
+
+ IEnumerable data = cacheItem.LastData;
+
+ if (!data.Any())
+ return null;
+
+ if (request.GeDate.HasValue)
+ {
+ var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
+ if (data.First().DateTime > geDate)
+ return null;
+
+ data = data.Where(d => d.DateTime >= geDate);
+ }
+ else
+ {
+ if (request.Order == 0)
+ return null;
+ }
+
+ if (request.LeDate.HasValue)
+ {
+ var leDate = request.LeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
+ data = data.Where(d => d.DateTime <= request.LeDate);
+ }
+
+ if (request.Divider > 1)
+ data = data.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
+
+ switch (request.Order)
+ {
+ case 1: // Поздние вперед
+ data = data
+ .OrderByDescending(d => d.DateTime)
+ .Skip(request.Skip)
+ .Take(request.Take)
+ .OrderBy(d => d.DateTime);
+ break;
+ default: // Ранние вперед
+ data = data
+ .OrderBy(d => d.DateTime)
+ .Skip(request.Skip)
+ .Take(request.Take);
+ break;
+ }
+
+ return data;
+ }
+
+ public IEnumerable GetIds(TelemetryDataRequest request)
+ {
+ var data = caches.Where(i => i.Value.LastData.Count > 0);
+
+ if (request.GeDate.HasValue)
+ {
+ data = data
+ .Where(item => {
+ var lastItem = item.Value.LastData.Last();
+ var geDate = request.GeDate.Value.ToOffset(TimeSpan.FromHours(item.Value.TimezoneHours));
+ return lastItem.DateTime >= geDate;
+ });
+ }
+
+ if (request.LeDate.HasValue)
+ {
+ data = data
+ .Where(item => {
+ var firstItem = item.Value.LastData.First();
+ var leDate = request.LeDate.Value.ToOffset(TimeSpan.FromHours(item.Value.TimezoneHours));
+ return firstItem.DateTime <= leDate;
+ });
+ }
+
+ var telemetryIds = data.Select(item => item.Key);
+ return telemetryIds;
+ }
+
+ private static DateTimeOffset FromDate(DateTime dateTime, TimeSpan timezoneOffset)
+ {
+ var dateTimeNoKind = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
+ var dateTimeOffset = new DateTimeOffset(dateTimeNoKind, timezoneOffset);
+ return dateTimeOffset;
+ }
}
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
index c0675221..7977b1ab 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs
@@ -51,7 +51,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
public DatesRangeDto GetDatesRange(int idTelemetry)
{
- var cacheDataRange = dataSaubCache.GetOrDefaultDataDateRange(idTelemetry)
+ var cacheDataRange = dataSaubCache.GetOrDefaultWellDataDateRange(idTelemetry)
?? new ();
return cacheDataRange;
}