persistence/Persistence.Repository/Repositories/TimeSeriesDataCachedRepository.cs

106 lines
3.0 KiB
C#

using Mapster;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using Persistence.Database.Model;
using Persistence.Models;
namespace Persistence.Repository.Repositories;
public class TimeSeriesDataCachedRepository<TEntity, TDto> : TimeSeriesDataRepository<TEntity, TDto>
where TEntity : class, ITimestampedData, new()
where TDto : class, ITimeSeriesAbstractDto, new()
{
public static TDto? FirstByDate { get; private set; }
public static CyclicArray<TDto> LastData { get; } = new CyclicArray<TDto>(CacheItemsCount);
private const int CacheItemsCount = 3600;
public TimeSeriesDataCachedRepository(DbContext db) : base(db)
{
Task.Run(async () =>
{
var firstDateItem = await base.GetFirstAsync(CancellationToken.None);
if (firstDateItem == null)
{
return;
}
FirstByDate = firstDateItem;
var dtos = await base.GetLastAsync(CacheItemsCount, CancellationToken.None);
dtos = dtos.OrderBy(d => d.Date);
LastData.AddRange(dtos);
}).Wait();
}
public override async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
{
if (LastData.Count() == 0 || LastData[0].Date > dateBegin)
{
var dtos = await base.GetGtDate(dateBegin, token);
return dtos;
}
var items = LastData
.Where(i => i.Date >= dateBegin);
return items;
}
public override async Task<int> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await base.InsertRange(dtos, token);
if (result > 0)
{
dtos = dtos.OrderBy(x => x.Date);
FirstByDate = dtos.First();
LastData.AddRange(dtos);
}
return result;
}
public override async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
{
if (FirstByDate == null)
return null;
return await Task.Run(() =>
{
return new DatesRangeDto
{
From = FirstByDate.Date,
To = LastData[^1].Date
};
});
}
public override async Task<IEnumerable<TDto>> GetResampledData(
DateTimeOffset dateBegin,
double intervalSec = 600d,
int approxPointsCount = 1024,
CancellationToken token = default)
{
var dtos = LastData.Where(i => i.Date >= dateBegin);
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
{
dtos = await base.GetGtDate(dateBegin, token);
}
var dateEnd = dateBegin.AddSeconds(intervalSec);
dtos = dtos
.Where(i => i.Date <= dateEnd);
var ratio = dtos.Count() / approxPointsCount;
if (ratio > 1)
dtos = dtos
.Where((_, index) => index % ratio == 0);
return dtos;
}
}