forked from ddrilling/AsbCloudServer
Reviewed-on: http://test.digitaldrilling.ru:8080/DDrilling/AsbCloudServer/pulls/140
This commit is contained in:
commit
58c9b55631
@ -6,7 +6,6 @@ using System.Linq;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -24,8 +23,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public CyclycArray<TDto> LastData { get; init; } = null!;
|
public CyclycArray<TDto> LastData { get; init; } = null!;
|
||||||
public double TimezoneHours { get; init; } = 5;
|
public double TimezoneHours { get; init; } = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IServiceProvider provider = null!;
|
|
||||||
private const int activeWellCapacity = 12 * 60 * 60;
|
private const int activeWellCapacity = 12 * 60 * 60;
|
||||||
private const int doneWellCapacity = 65 * 60;
|
private const int doneWellCapacity = 65 * 60;
|
||||||
|
|
||||||
@ -56,7 +54,6 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
work.Timeout = TimeSpan.FromMinutes(15);
|
work.Timeout = TimeSpan.FromMinutes(15);
|
||||||
worker.WorkStore.RunOnceQueue.Enqueue(work);
|
worker.WorkStore.RunOnceQueue.Enqueue(work);
|
||||||
}
|
}
|
||||||
instance.provider = provider;
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +67,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
if (!range.Any())
|
if (!range.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var newItems = range
|
range = range.OrderBy(x => x.DateTime);
|
||||||
.OrderBy(i => i.DateTime);
|
|
||||||
|
|
||||||
foreach (var item in newItems)
|
foreach (var item in range)
|
||||||
item.IdTelemetry = idTelemetry;
|
item.IdTelemetry = idTelemetry;
|
||||||
|
|
||||||
TelemetryDataCacheItem cacheItem;
|
TelemetryDataCacheItem cacheItem;
|
||||||
@ -86,14 +82,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
|
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
|
||||||
{
|
{
|
||||||
FirstByDate = newItems.ElementAt(0),
|
FirstByDate = range.ElementAt(0),
|
||||||
LastData = new CyclycArray<TDto>(activeWellCapacity)
|
LastData = new CyclycArray<TDto>(activeWellCapacity)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheItem.LastData.AddRange(newItems);
|
cacheItem.LastData.AddRange(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -167,39 +163,44 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
private async Task InitializeCacheFromDBAsync<TEntity>(IAsbCloudDbContext db, Action<string, double?> onProgress, CancellationToken token)
|
private async Task InitializeCacheFromDBAsync<TEntity>(IAsbCloudDbContext db, Action<string, double?> onProgress, CancellationToken token)
|
||||||
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
||||||
{
|
{
|
||||||
if (isLoading)
|
|
||||||
throw new Exception("Multiple cache loading detected.");
|
|
||||||
|
|
||||||
isLoading = true;
|
|
||||||
|
|
||||||
var defaultTimeout = db.Database.GetCommandTimeout();
|
var defaultTimeout = db.Database.GetCommandTimeout();
|
||||||
db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
|
db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
|
||||||
|
|
||||||
Well[] wells = await db.Set<Well>()
|
if (isLoading)
|
||||||
.Include(well => well.Telemetry)
|
throw new Exception("Multiple cache loading detected.");
|
||||||
.Include(well => well.Cluster)
|
|
||||||
.Where(well => well.IdTelemetry != null)
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
|
|
||||||
var count = wells.Length;
|
try
|
||||||
var i = 0d;
|
{
|
||||||
foreach (Well well in wells)
|
isLoading = true;
|
||||||
{
|
|
||||||
var capacity = well.IdState == 1
|
Well[] wells = await db.Set<Well>()
|
||||||
? activeWellCapacity
|
.Include(well => well.Telemetry)
|
||||||
: doneWellCapacity;
|
.Include(well => well.Cluster)
|
||||||
|
.Where(well => well.IdTelemetry != null)
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
var idTelemetry = well.IdTelemetry!.Value;
|
var count = wells.Length;
|
||||||
var hoursOffset = well.Timezone.Hours;
|
var i = 0d;
|
||||||
|
foreach (Well well in wells)
|
||||||
|
{
|
||||||
|
var capacity = well.IdState == 1
|
||||||
|
? activeWellCapacity
|
||||||
|
: doneWellCapacity;
|
||||||
|
|
||||||
onProgress($"Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}", i++ / count);
|
var idTelemetry = well.IdTelemetry!.Value;
|
||||||
var cacheItem = await GetOrDefaultCacheDataFromDbAsync<TEntity>(db, idTelemetry, capacity, hoursOffset, token);
|
var hoursOffset = well.Timezone.Hours;
|
||||||
if (cacheItem is not null)
|
|
||||||
caches.TryAdd(idTelemetry, cacheItem);
|
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)
|
||||||
|
caches.TryAdd(idTelemetry, cacheItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
isLoading = false;
|
||||||
|
db.Database.SetCommandTimeout(defaultTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoading = false;
|
|
||||||
db.Database.SetCommandTimeout(defaultTimeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<TelemetryDataCacheItem?> GetOrDefaultCacheDataFromDbAsync<TEntity>(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset, CancellationToken token)
|
private static async Task<TelemetryDataCacheItem?> GetOrDefaultCacheDataFromDbAsync<TEntity>(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset, CancellationToken token)
|
||||||
@ -249,12 +250,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
{
|
{
|
||||||
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
IEnumerable<TDto> data = cacheItem.LastData;
|
IEnumerable<TDto> data = cacheItem.LastData;
|
||||||
|
|
||||||
if (!data.Any())
|
if (!data.Any())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (request.GeDate.HasValue)
|
if (request.GeDate.HasValue)
|
||||||
{
|
{
|
||||||
var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
var geDate = request.GeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
||||||
@ -274,7 +275,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var leDate = request.LeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
var leDate = request.LeDate.Value.ToRemoteDateTime(cacheItem.TimezoneHours);
|
||||||
data = data.Where(d => d.DateTime >= request.LeDate);
|
data = data.Where(d => d.DateTime >= request.LeDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Divider > 1)
|
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);
|
data = data.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace AsbCloudInfrastructure.Services;
|
|||||||
|
|
||||||
public class WellboreService : IWellboreService
|
public class WellboreService : IWellboreService
|
||||||
{
|
{
|
||||||
const string WellboreNameFormat = "Ñòâîë {0}";
|
const string WellboreNameFormat = "Ствол {0}";
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly IWellOperationRepository wellOperationRepository;
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Background;
|
||||||
|
using AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.ServicesTests.SAUB;
|
||||||
|
|
||||||
|
public class TelemetryDataSaubCacheTests
|
||||||
|
{
|
||||||
|
private const int idTelemetry = 1;
|
||||||
|
|
||||||
|
private readonly IEnumerable<TelemetryDataSaubDto> fakeTelemetries = new[]
|
||||||
|
{
|
||||||
|
new TelemetryDataSaubDto()
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly IServiceProvider serviceProviderMock = Substitute.For<IServiceProvider>();
|
||||||
|
|
||||||
|
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
private readonly Type telemetryDataCacheType;
|
||||||
|
|
||||||
|
public TelemetryDataSaubCacheTests()
|
||||||
|
{
|
||||||
|
serviceProviderMock.GetService<BackgroundWorker>().Returns(new BackgroundWorker(serviceProviderMock));
|
||||||
|
|
||||||
|
telemetryDataCache = TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(serviceProviderMock);
|
||||||
|
|
||||||
|
telemetryDataCacheType = telemetryDataCache.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddRange_ShouldReturn_AddedElementToCache()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
telemetryDataCacheType.GetField("isLoading", BindingFlags.NonPublic | BindingFlags.Instance)?.SetValue(telemetryDataCache, false);
|
||||||
|
|
||||||
|
//act
|
||||||
|
telemetryDataCache.AddRange(idTelemetry, fakeTelemetries);
|
||||||
|
var lastTelemetry = telemetryDataCache.GetLastOrDefault(idTelemetry);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(lastTelemetry, fakeTelemetries.Last());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddRange_ShouldReturn_NotAddedToCache()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
telemetryDataCacheType.GetField("isLoading", BindingFlags.NonPublic | BindingFlags.Instance)?.SetValue(telemetryDataCache, true);
|
||||||
|
|
||||||
|
//act
|
||||||
|
telemetryDataCache.AddRange(idTelemetry, fakeTelemetries);
|
||||||
|
var lastTelemetry = telemetryDataCache.GetLastOrDefault(idTelemetry);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.NotEqual(lastTelemetry, fakeTelemetries.Last());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user