Извлечен интерфейс из TelemetryDataCache<TDto>для тестов.

This commit is contained in:
ngfrolov 2023-10-24 09:23:07 +05:00
parent b8462253b3
commit bf9895667d
Signed by untrusted user who does not match committer: ng.frolov
GPG Key ID: E99907A0357B29A7
11 changed files with 108 additions and 37 deletions

View File

@ -0,0 +1,62 @@
using AsbCloudApp.Data;
using AsbCloudApp.Requests;
using System;
using System.Collections.Generic;
namespace AsbCloudApp.Repositories
{
/// <summary>
/// Хранилище кеша
/// </summary>
/// <typeparam name="TDto"></typeparam>
public interface ITelemetryDataCache<TDto> where TDto : ITelemetryData
{
/// <summary>
/// добавить в кеш чанк записей по телеметрии
/// </summary>
/// <param name="idTelemetry"></param>
/// <param name="range"></param>
void AddRange(int idTelemetry, IEnumerable<TDto> range);
/// <summary>
/// вернуть последнюю записть
/// </summary>
/// <param name="idTelemetry"></param>
/// <returns></returns>
TDto? GetLastOrDefault(int idTelemetry);
/// <summary>
/// Получить кешированые записи
/// </summary>
/// <param name="idTelemetry"></param>
/// <param name="dateBegin"></param>
/// <param name="intervalSec"></param>
/// <param name="approxPointsCount">приблизительное кол-во возвращаемых записей после их прореживания</param>
/// <returns></returns>
IEnumerable<TDto>? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600, int approxPointsCount = 1024);
/// <summary>
/// Получить кешированые записи
/// </summary>
/// <param name="idTelemetry"></param>
/// <param name="request"></param>
/// <returns></returns>
IEnumerable<TDto>? GetOrDefault(int idTelemetry, TelemetryDataRequest request);
/// <summary>
/// Получить диапазон дат телеметрии.
/// Дата первой записи телеметрии храниться отдельно и запоняется при инициализации
/// </summary>
/// <param name="idTelemetry"></param>
/// <returns></returns>
DatesRangeDto? GetOrDefaultDataDateRange(int idTelemetry);
/// <summary>
/// Получение первой и последней записи телеметрии.
/// Первая запись телеметрии храниться отдельно и запоняется при инициализации
/// </summary>
/// <param name="idTelemetry"></param>
/// <returns></returns>
(TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry);
}
}

View File

@ -159,8 +159,8 @@ namespace AsbCloudInfrastructure
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetRequiredService<AsbCloudDbContext>());
services.AddSingleton(new WitsInfoService());
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
services.AddSingleton<ITelemetryDataCache<TelemetryDataSaubDto>>(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
services.AddSingleton<ITelemetryDataCache<TelemetryDataSpinDto>>(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
services.AddSingleton<BackgroundWorker>();
services.AddSingleton<NotificationBackgroundWorker>();

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb;
using AsbCloudDb.Model;
@ -18,12 +19,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
{
protected readonly IAsbCloudDbContext db;
protected readonly ITelemetryService telemetryService;
protected readonly TelemetryDataCache<TDto> telemetryDataCache;
protected readonly ITelemetryDataCache<TDto> telemetryDataCache;
public TelemetryDataBaseService(
IAsbCloudDbContext db,
ITelemetryService telemetryService,
TelemetryDataCache<TDto> telemetryDataCache)
ITelemetryDataCache<TDto> telemetryDataCache)
{
this.db = db;
this.telemetryService = telemetryService;

View File

@ -12,11 +12,11 @@ using AsbCloudInfrastructure.Background;
using System.Threading;
using AsbCloudApp.Data;
using AsbCloudApp.Requests;
using AsbCloudApp.Repositories;
namespace AsbCloudInfrastructure.Services.SAUB
{
public class TelemetryDataCache<TDto>
where TDto : AsbCloudApp.Data.ITelemetryData
public class TelemetryDataCache<TDto> : ITelemetryDataCache<TDto> where TDto : AsbCloudApp.Data.ITelemetryData
{
class TelemetryDataCacheItem
{
@ -48,7 +48,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
instance = new TelemetryDataCache<TDto>();
var worker = provider.GetRequiredService<BackgroundWorker>();
var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) => {
var work = Work.CreateByDelegate(workId, async (workId, provider, onProgress, token) =>
{
var db = provider.GetRequiredService<IAsbCloudDbContext>();
await instance.InitializeCacheFromDBAsync<TEntity>(db, onProgress, token);
});
@ -85,13 +86,13 @@ namespace AsbCloudInfrastructure.Services.SAUB
}
else
{
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
{
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
{
FirstByDate = newItems.ElementAt(0),
LastData = new CyclycArray<TDto>(activeWellCapacity)
LastData = new CyclycArray<TDto>(activeWellCapacity)
});
}
cacheItem.LastData.AddRange(newItems);
}
@ -107,14 +108,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
/// <returns></returns>
public IEnumerable<TDto>? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600d, int approxPointsCount = 1024)
{
if(!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
return null;
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);
@ -141,7 +142,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
return null;
var from = cacheItem.FirstByDate?.DateTime;
if(!cacheItem.LastData.Any())
if (!cacheItem.LastData.Any())
return null;
var to = cacheItem.LastData[^1].DateTime;
@ -190,10 +191,10 @@ namespace AsbCloudInfrastructure.Services.SAUB
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);
onProgress($"Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}", i++ / count);
var cacheItem = await GetOrDefaultCacheDataFromDbAsync<TEntity>(db, idTelemetry, capacity, hoursOffset, token);
if(cacheItem is not null)
if (cacheItem is not null)
caches.TryAdd(idTelemetry, cacheItem);
}
@ -225,7 +226,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
var dtos = entities
.AsEnumerable()
.Reverse()
.Select(entity => {
.Select(entity =>
{
var dto = entity.Adapt<TDto>();
dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
return dto;
@ -247,12 +249,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
{
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
return null;
IEnumerable<TDto> data = cacheItem.LastData;
if (!data.Any())
return null;
if (request.GeDate.HasValue)
{
var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
@ -272,7 +274,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
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);

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
@ -26,7 +27,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
IAsbCloudDbContext db,
ITelemetryService telemetryService,
ITelemetryUserService telemetryUserService,
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
: base(db, telemetryService, telemetryDataCache)
{
this.telemetryUserService = telemetryUserService;

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
@ -11,7 +12,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
public TelemetryDataSpinService(
IAsbCloudDbContext db,
ITelemetryService telemetryService,
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache)
ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache)
: base(db, telemetryService, telemetryDataCache)
{ }

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb;
using AsbCloudDb.Model;
@ -18,7 +19,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
{
private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache;
private readonly TelemetryDataCache<TelemetryDataSaubDto> dataSaubCache;
//TODO: методы использующие ITelemetryDataCache, скорее всего, тут не нужны
private readonly ITelemetryDataCache<TelemetryDataSaubDto> dataSaubCache;
private readonly ITimezoneService timezoneService;
public ITimezoneService TimeZoneService => timezoneService;
@ -26,7 +28,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
public TelemetryService(
IAsbCloudDbContext db,
IMemoryCache memoryCache,
TelemetryDataCache<TelemetryDataSaubDto> dataSaubCache,
ITelemetryDataCache<TelemetryDataSaubDto> dataSaubCache,
ITimezoneService timezoneService)
{
this.db = db;

View File

@ -36,7 +36,7 @@ public class WellInfoService
var operationsStatService = services.GetRequiredService<IOperationsStatService>();
var processMapPlanWellDrillingRepository = services.GetRequiredService<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
var subsystemOperationTimeService = services.GetRequiredService<ISubsystemOperationTimeService>();
var telemetryDataSaubCache = services.GetRequiredService<TelemetryDataCache<TelemetryDataSaubDto>>();
var telemetryDataSaubCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
var wells = await wellService.GetAllAsync(token);
@ -180,16 +180,16 @@ public class WellInfoService
public IEnumerable<int> IdsCompanies { get; set; } = null!;
}
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
private readonly TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
private readonly ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
private readonly IWitsRecordRepository<Record7Dto> witsRecord7Repository;
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
private readonly IGtrRepository gtrRepository;
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
public WellInfoService(
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
ITelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
IWitsRecordRepository<Record1Dto> witsRecord1Repository,
IGtrRepository gtrRepository)

View File

@ -11,6 +11,7 @@ using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.SAUB;
using AsbCloudInfrastructure.Services.SAUB;
using AsbCloudApp.Repositories;
namespace AsbCloudInfrastructure.Services.WellOperationService;
@ -19,10 +20,10 @@ public class OperationsStatService : IOperationsStatService
private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache;
private readonly IWellService wellService;
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService,
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
public OperationsStatService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService,
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
{
this.db = db;
this.memoryCache = memoryCache;

View File

@ -16,12 +16,12 @@ public class WellboreService : IWellboreService
const string WellboreNameFormat = "Ñòâîë {0}";
private readonly IWellService wellService;
private readonly IWellOperationRepository wellOperationRepository;
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
public WellboreService(
IWellService wellService,
IWellOperationRepository wellOperationRepository,
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
{
this.wellService = wellService;
this.wellOperationRepository = wellOperationRepository;

View File

@ -15,6 +15,7 @@ using AsbCloudInfrastructure.Services.Subsystems;
using System.Linq;
using DocumentFormat.OpenXml.InkML;
using AsbCloudDb;
using AsbCloudApp.Repositories;
namespace AsbCloudInfrastructure
{
@ -29,8 +30,8 @@ namespace AsbCloudInfrastructure
context.Database.EnshureCreatedAndMigrated();
// TODO: Сделать инициализацию кеша телеметрии более явной.
_ = provider.GetRequiredService<TelemetryDataCache<TelemetryDataSaubDto>>();
_ = provider.GetRequiredService<TelemetryDataCache<TelemetryDataSpinDto>>();
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSpinDto>>();
var backgroundWorker = provider.GetRequiredService<BackgroundWorker>();
backgroundWorker.WorkStore.AddPeriodic<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));