forked from ddrilling/AsbCloudServer
#7579139 Tests
This commit is contained in:
parent
698fb33651
commit
eed8c3eeaa
@ -90,12 +90,16 @@ namespace System.Collections.Generic
|
||||
{
|
||||
get
|
||||
{
|
||||
if (used == 0)
|
||||
return default;
|
||||
|
||||
var i = (current + 1 + index) % used;
|
||||
return array[i];
|
||||
}
|
||||
set
|
||||
{
|
||||
var i = (current + 1 + index) % used;
|
||||
var devider = used > 0 ? used : array.Length;
|
||||
var i = (current + 1 + index) % devider;
|
||||
array[i] = value;
|
||||
UpdatedInvoke(current, value);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
@ -22,7 +22,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="approxPointsCount">кол-во элементов до которых эти данные прореживаются</param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<TDto>> GetAsync(int idWell,
|
||||
Task<IEnumerable<TDto>?> GetOrDefaultAsync(int idWell,
|
||||
DateTime dateBegin = default, double intervalSec = 600d,
|
||||
int approxPointsCount = 1024, CancellationToken token = default);
|
||||
|
||||
@ -35,4 +35,5 @@ namespace AsbCloudApp.Services
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
}
|
||||
#nullable disable
|
@ -55,7 +55,7 @@ namespace AsbCloudApp.Services
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <returns></returns>
|
||||
int? GetIdTelemetryByIdWell(int idWell);
|
||||
int? GetOrDefaultIdTelemetryByIdWell(int idWell);
|
||||
|
||||
/// <summary>
|
||||
/// получить диапазон дат за которые есть данные
|
||||
|
@ -16,6 +16,7 @@ using AsbCloudInfrastructure.Services.SAUB;
|
||||
using AsbCloudInfrastructure.Services.Subsystems;
|
||||
using AsbCloudInfrastructure.Services.WellOperationService;
|
||||
using AsbCloudInfrastructure.Validators;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using FluentValidation.AspNetCore;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -100,6 +101,8 @@ namespace AsbCloudInfrastructure
|
||||
services.AddSingleton(new WitsInfoService());
|
||||
services.AddSingleton(new CacheDb());
|
||||
services.AddSingleton(new InstantDataRepository());
|
||||
services.AddSingleton(provider=> TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(configuration));
|
||||
services.AddSingleton(provider=> TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(configuration));
|
||||
services.AddSingleton<ITelemetryTracker, TelemetryTracker>();
|
||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||
services.AddSingleton<IBackgroundWorkerService, BackgroundWorkerService>();
|
||||
|
@ -27,7 +27,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
public async Task<DrillParamsDto?> GetDefaultDrillParamsAsync(int idWell,
|
||||
double startDepth, double endDepth, CancellationToken token = default)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
|
||||
if (idTelemetry is null)
|
||||
return null;
|
||||
|
@ -113,7 +113,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
public DatesRangeDto GetDatesRangeOrDefault(int idWell)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return null;
|
||||
var range = telemetryService.GetDatesRange((int)idTelemetry);
|
||||
|
@ -34,7 +34,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
int take = 32,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return null;
|
||||
|
||||
|
@ -10,26 +10,31 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>
|
||||
public abstract class TelemetryDataBaseService<TDto, TEntity> : ITelemetryDataService<TDto>
|
||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||
where TModel : class, ITelemetryData
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
protected readonly IAsbCloudDbContext db;
|
||||
private readonly ITelemetryService telemetryService;
|
||||
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
||||
private readonly TelemetryDataCache<TDto> telemetryDataCache;
|
||||
|
||||
public TelemetryDataBaseService(
|
||||
IAsbCloudDbContext db,
|
||||
ITelemetryService telemetryService,
|
||||
TelemetryDataCache<TDto> telemetryDataCache,
|
||||
CacheDb cacheDb)
|
||||
{
|
||||
this.db = db;
|
||||
this.telemetryService = telemetryService;
|
||||
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((AsbCloudDbContext)db);
|
||||
this.telemetryDataCache = telemetryDataCache;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
||||
{
|
||||
if (dtos == default || !dtos.Any())
|
||||
@ -53,6 +58,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
var idTelemetry = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
||||
|
||||
telemetryDataCache.AddRange(idTelemetry, dtos);
|
||||
|
||||
var entities = dtosList.Select(dto =>
|
||||
{
|
||||
var entity = Convert(dto, timezone.Hours);
|
||||
@ -63,7 +70,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
var entityMaxDate = entities.Max(e => e.DateTime);
|
||||
telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate);
|
||||
|
||||
var dbset = db.Set<TModel>();
|
||||
var dbset = db.Set<TEntity>();
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
@ -82,12 +89,15 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: It shouldn`t be nullable. Throw exceptions instead and return empty.
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<IEnumerable<TDto>> GetAsync(int idWell,
|
||||
public virtual async Task<IEnumerable<TDto>?> GetOrDefaultAsync(int idWell,
|
||||
DateTime dateBegin = default, double intervalSec = 600d,
|
||||
int approxPointsCount = 1024, CancellationToken token = default)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell) ?? -1;
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell) ?? -1;
|
||||
if (idTelemetry == -1)
|
||||
return null;
|
||||
|
||||
@ -110,8 +120,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
if (dateBeginUtc == default)
|
||||
dateBeginUtc = DateTime.UtcNow.AddSeconds(-intervalSec);
|
||||
|
||||
var cacheData = telemetryDataCache.GetOrDefault(idTelemetry, dateBeginUtc.ToRemoteDateTime(timezone.Hours), intervalSec, approxPointsCount);
|
||||
if (cacheData is not null)
|
||||
return cacheData;
|
||||
|
||||
var dateEnd = dateBeginUtc.AddSeconds(intervalSec);
|
||||
var dbSet = db.Set<TModel>();
|
||||
var dbSet = db.Set<TEntity>();
|
||||
|
||||
var query = dbSet
|
||||
.Where(d => d.IdTelemetry == idTelemetry
|
||||
@ -144,9 +158,10 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public abstract TDto Convert(TModel src, double timezoneOffset);
|
||||
public abstract TDto Convert(TEntity src, double timezoneOffset);
|
||||
|
||||
public abstract TModel Convert(TDto src, double timezoneOffset);
|
||||
public abstract TEntity Convert(TDto src, double timezoneOffset);
|
||||
|
||||
}
|
||||
}
|
||||
#nullable disable
|
@ -5,74 +5,79 @@ using System;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Mapster;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
#nullable enable
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
public class TelemetryDataCache<TDto, TEntity>
|
||||
public class TelemetryDataCache<TDto>
|
||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
private const int activeWellCapacity = 24 * 60 * 60;
|
||||
private const int doneWellCapacity = 65 * 60;
|
||||
|
||||
private readonly ConcurrentDictionary<int, CyclycArray<TDto>> caches;
|
||||
|
||||
public TelemetryDataCache(IAsbCloudDbContext db)
|
||||
private bool isLoading = false;
|
||||
|
||||
private TelemetryDataCache()
|
||||
{
|
||||
caches = new ();
|
||||
LoadCaches(db);
|
||||
caches = new();
|
||||
}
|
||||
|
||||
private void LoadCaches(IAsbCloudDbContext db)
|
||||
{
|
||||
Well[] wells = db.Set<Well>()
|
||||
.Include(well => well.Telemetry)
|
||||
.Where(well => well.IdTelemetry != null)
|
||||
.ToArray();
|
||||
private static TelemetryDataCache<TDto>? instance;
|
||||
|
||||
foreach (Well well in wells)
|
||||
//TODO: Move initialize fromDB to bacground service task
|
||||
public static TelemetryDataCache<TDto> GetInstance<TEntity>(IConfiguration configuration)
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
if (instance is null)
|
||||
{
|
||||
var capacity = well.IdState == 1
|
||||
? activeWellCapacity
|
||||
: doneWellCapacity;
|
||||
|
||||
var idTelemetry = well.IdTelemetry!.Value;
|
||||
var hoursOffset = well.Timezone.Hours;
|
||||
|
||||
IEnumerable<TDto> cacheItemData = GetCacheDataFromDb(db, idTelemetry, capacity, hoursOffset);
|
||||
var cacheItem = new CyclycArray<TDto>(capacity);
|
||||
cacheItem.AddRange(cacheItemData);
|
||||
caches.TryAdd(idTelemetry, cacheItem);
|
||||
instance = new TelemetryDataCache<TDto>();
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
using var db = MakeContext(configuration);
|
||||
instance.InitializeCacheFromDB<TEntity>(db);
|
||||
});
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static IEnumerable<TDto> GetCacheDataFromDb(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset)
|
||||
public static TelemetryDataCache<TDto> GetInstance<TEntity>(IAsbCloudDbContext db, out Task initializationTask)
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
var entities = db.Set<TEntity>()
|
||||
.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<TDto>();
|
||||
dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
|
||||
return dto;
|
||||
});
|
||||
|
||||
return dtos;
|
||||
if (instance is null)
|
||||
{
|
||||
instance = new TelemetryDataCache<TDto>();
|
||||
initializationTask = Task.Run(() =>
|
||||
{
|
||||
instance.InitializeCacheFromDB<TEntity>(db);
|
||||
});
|
||||
}
|
||||
else
|
||||
initializationTask = Task.CompletedTask;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить элементы в кеш
|
||||
/// Добавить новые элементы в кеш
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <param name="range"></param>
|
||||
public void AddRange(int idTelemetry, IEnumerable<TDto> range)
|
||||
public void AddRange(int idTelemetry, IEnumerable<TDto> range)
|
||||
{
|
||||
var cacheItem = caches.GetOrAdd(idTelemetry, _ => new CyclycArray<TDto>(activeWellCapacity));
|
||||
CyclycArray<TDto> cacheItem;
|
||||
if (isLoading)
|
||||
{
|
||||
if (caches.TryGetValue(idTelemetry, out CyclycArray<TDto>? localCacheItem))
|
||||
cacheItem = localCacheItem;
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheItem = caches.GetOrAdd(idTelemetry, _ => new CyclycArray<TDto>(activeWellCapacity));
|
||||
}
|
||||
|
||||
var newItems = range
|
||||
.OrderBy(i => i.DateTime);
|
||||
foreach (var item in newItems)
|
||||
@ -95,7 +100,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
if(!caches.TryGetValue(idTelemetry, out CyclycArray<TDto>? cacheItem))
|
||||
return null;
|
||||
|
||||
if (cacheItem is null || cacheItem[0].DateTime > dateBegin)
|
||||
if (cacheItem is null || !cacheItem.Any() || cacheItem[0].DateTime > dateBegin)
|
||||
return null;
|
||||
|
||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||
@ -109,6 +114,77 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private void InitializeCacheFromDB<TEntity>(IAsbCloudDbContext db)
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
if (isLoading)
|
||||
throw new Exception("Multiple cache loading detected.");
|
||||
|
||||
isLoading = true;
|
||||
Well[] wells = Array.Empty<Well>();
|
||||
try
|
||||
{
|
||||
wells = db.Set<Well>()
|
||||
.Include(well => well.Telemetry)
|
||||
.Include(well => well.Cluster)
|
||||
.Where(well => well.IdTelemetry != null)
|
||||
.ToArray();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
;
|
||||
}
|
||||
foreach (Well well in wells)
|
||||
{
|
||||
var capacity = well.IdState == 1
|
||||
? activeWellCapacity
|
||||
: doneWellCapacity;
|
||||
|
||||
var idTelemetry = well.IdTelemetry!.Value;
|
||||
var hoursOffset = well.Timezone.Hours;
|
||||
|
||||
IEnumerable<TDto> cacheItemData = GetCacheDataFromDb<TEntity>(db, idTelemetry, capacity, hoursOffset);
|
||||
var cacheItem = new CyclycArray<TDto>(capacity);
|
||||
cacheItem.AddRange(cacheItemData);
|
||||
caches.TryAdd(idTelemetry, cacheItem);
|
||||
|
||||
System.Diagnostics.Trace.TraceInformation($"cache<{typeof(TDto).Name}> for well: {well.Cluster?.Caption}/{well.Caption} loaded");
|
||||
}
|
||||
|
||||
System.Diagnostics.Trace.TraceInformation($"cache<{typeof(TDto).Name}> load complete");
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
private static IAsbCloudDbContext MakeContext(IConfiguration configuration)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
var db = new AsbCloudDbContext(options);
|
||||
return db;
|
||||
}
|
||||
|
||||
private static IEnumerable<TDto> GetCacheDataFromDb<TEntity>(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset)
|
||||
where TEntity : class, ITelemetryData
|
||||
{
|
||||
var entities = db.Set<TEntity>()
|
||||
.Where(i => i.IdTelemetry == idTelemetry)
|
||||
.OrderByDescending(i => i.DateTime)
|
||||
.Take(capacity)
|
||||
.ToArray()
|
||||
.AsEnumerable()
|
||||
.Reverse();
|
||||
|
||||
var dtos = entities.Select(entity => {
|
||||
var dto = entity.Adapt<TDto>();
|
||||
dto.DateTime = entity.DateTime.ToRemoteDateTime(hoursOffset);
|
||||
return dto;
|
||||
});
|
||||
|
||||
return dtos;
|
||||
}
|
||||
}
|
||||
}
|
||||
#nullable disable
|
@ -16,8 +16,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
public TelemetryDataSaubService(
|
||||
IAsbCloudDbContext db,
|
||||
ITelemetryService telemetryService,
|
||||
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache,
|
||||
CacheDb cacheDb)
|
||||
: base(db, telemetryService, cacheDb)
|
||||
: base(db, telemetryService, telemetryDataCache, cacheDb)
|
||||
{ }
|
||||
|
||||
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
|
||||
|
@ -13,8 +13,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
public TelemetryDataSpinService(
|
||||
IAsbCloudDbContext db,
|
||||
ITelemetryService telemetryService,
|
||||
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache,
|
||||
CacheDb cacheDb)
|
||||
: base(db, telemetryService, cacheDb)
|
||||
: base(db, telemetryService, telemetryDataCache, cacheDb)
|
||||
{ }
|
||||
|
||||
public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)
|
||||
|
@ -141,7 +141,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
throw new Exception($"Telemetry id: {idTelemetry} can't find timezone.");
|
||||
}
|
||||
|
||||
public int? GetIdTelemetryByIdWell(int idWell)
|
||||
public int? GetOrDefaultIdTelemetryByIdWell(int idWell)
|
||||
{
|
||||
var telemetry = GetTelemetryCache()
|
||||
.FirstOrDefault(t => t.Value.Well?.Id == idWell).Value;
|
||||
|
93
AsbCloudWebApi.Tests/CacheTests/TelemetryDataCacheTest.cs
Normal file
93
AsbCloudWebApi.Tests/CacheTests/TelemetryDataCacheTest.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.SAUB;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.Tests.CacheTests
|
||||
{
|
||||
public class TelemetryDataCacheTest
|
||||
{
|
||||
private const int IdTelemetryOk = 10;
|
||||
private static readonly DateTime baseDate = DateTime.Now;
|
||||
private static readonly SimpleTimezone timezone = new() { Hours = TimeZoneInfo.Local.BaseUtcOffset.TotalHours };
|
||||
|
||||
private static readonly Well[] wellData = new Well[]{
|
||||
new(){ Id = 1, IdTelemetry = IdTelemetryOk, IdState = 1, Caption = "", Timezone = timezone}
|
||||
};
|
||||
private static readonly TTelemetryData[] telemetryData = new TTelemetryData[]{
|
||||
new ( IdTelemetryOk, baseDate.AddSeconds(1), timezone.Hours ),
|
||||
new ( IdTelemetryOk, baseDate.AddSeconds(2), timezone.Hours ),
|
||||
new ( IdTelemetryOk, baseDate.AddSeconds(3), timezone.Hours ),
|
||||
new ( IdTelemetryOk, baseDate.AddSeconds(4), timezone.Hours ),
|
||||
};
|
||||
private readonly Mock<IAsbCloudDbContext> dbMock;
|
||||
|
||||
private TelemetryDataCache<TTelemetryData> cacheTest;
|
||||
|
||||
public class TTelemetryData : ITelemetryData, AsbCloudApp.Data.ITelemetryData
|
||||
{
|
||||
private DateTimeOffset _dateTime;
|
||||
|
||||
public TTelemetryData(int idTelemetry, DateTime dateTime, double hoursOffset)
|
||||
{
|
||||
IdTelemetry = idTelemetry;
|
||||
DateTime = dateTime;
|
||||
var offset = TimeSpan.FromHours(hoursOffset);
|
||||
var dateTimeUTC = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
|
||||
_dateTime = new DateTimeOffset(dateTimeUTC, offset)
|
||||
.ToUniversalTime();
|
||||
}
|
||||
|
||||
public int IdTelemetry { get; set; }
|
||||
public DateTime DateTime { get; set; }
|
||||
DateTimeOffset ITelemetryData.DateTime { get => _dateTime; set => _dateTime = value; }
|
||||
}
|
||||
|
||||
public TelemetryDataCacheTest()
|
||||
{
|
||||
dbMock = new Mock<IAsbCloudDbContext>();
|
||||
dbMock
|
||||
.AddDbSetMock(wellData)
|
||||
.AddDbSetMock(telemetryData);
|
||||
|
||||
cacheTest = TelemetryDataCache<TTelemetryData>.GetInstance<TTelemetryData>(dbMock.Object, out Task cacheInitialization);
|
||||
cacheInitialization.Wait();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_existing_cache_returns_some()
|
||||
{
|
||||
var startDate = baseDate.AddSeconds(3);
|
||||
var data = cacheTest.GetOrDefault(IdTelemetryOk, startDate, 600, 600);
|
||||
Assert.NotNull(data);
|
||||
Assert.NotEmpty(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_non_existing_cache_returns_null()
|
||||
{
|
||||
var startDate = baseDate.AddSeconds(-1);
|
||||
var data = cacheTest.GetOrDefault(IdTelemetryOk, startDate, 600, 600);
|
||||
Assert.Null(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_new_data_should_replace_IdTelemetry()
|
||||
{
|
||||
var startDate = baseDate.AddSeconds(4);
|
||||
var newTelemetryData = new TTelemetryData[]{
|
||||
new ( 0, startDate, timezone.Hours),
|
||||
new ( 0, startDate.AddSeconds(1), timezone.Hours),
|
||||
};
|
||||
cacheTest.AddRange(IdTelemetryOk, newTelemetryData);
|
||||
var data = cacheTest.GetOrDefault(IdTelemetryOk, startDate, 600, 600);
|
||||
|
||||
Assert.NotNull(data);
|
||||
Assert.True(data?.Count() > 2);
|
||||
Assert.All(data!, p => Assert.Equal(IdTelemetryOk, p.IdTelemetry));
|
||||
}
|
||||
}
|
||||
}
|
@ -69,7 +69,7 @@ public class ClusterServiceTest
|
||||
|
||||
public ClusterServiceTest()
|
||||
{
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
wellService = new Mock<IWellService>();
|
||||
context.Deposits.RemoveRange(context.Deposits);
|
||||
context.Clusters.RemoveRange(context.Clusters);
|
||||
|
@ -21,7 +21,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
|
||||
protected override ICrudService<DepositDto> MakeService()
|
||||
{
|
||||
var dbContext = TestHelpter.MakeTestContext();
|
||||
var dbContext = TestHelpter.MakeRealTestContext();
|
||||
return new CrudCacheServiceBase<DepositDto, Deposit>(dbContext);
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
|
||||
public DetectedOperationServiceTest()
|
||||
{
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
context.SaveChanges();
|
||||
|
||||
context.Telemetries.Add(telemetry);
|
||||
|
@ -90,7 +90,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
{
|
||||
AsbCloudInfrastructure.DependencyInjection.MapsterSetup();
|
||||
|
||||
db = TestHelpter.MakeTestContext();
|
||||
db = TestHelpter.MakeRealTestContext();
|
||||
db.Wells.AddRange(wells);
|
||||
db.Companies.AddRange(companies);
|
||||
db.SaveChanges();
|
||||
|
@ -19,7 +19,7 @@ public class EventServiceTest
|
||||
|
||||
public EventServiceTest()
|
||||
{
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
cacheDb = new CacheDb();
|
||||
var telemetryTracker = new Mock<ITelemetryTracker>();
|
||||
var imezoneServiceMock = new Mock<ITimezoneService>();
|
||||
|
@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
public FileCategoryServiceTest()
|
||||
{
|
||||
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
context.SaveChanges();
|
||||
service = new FileCategoryService(context);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
|
||||
public ScheduleServiceTest()
|
||||
{
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
context.SaveChanges();
|
||||
|
||||
context.Deposits.Add(deposit);
|
||||
|
@ -40,7 +40,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
timezoneService.Setup(s => s.GetByCoordinates(It.IsAny<double>(), It.IsAny<double>()))
|
||||
.Returns(timezone);
|
||||
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
cacheDb = new CacheDb();
|
||||
telemetryService = new TelemetryService(context, telemetryTracker.Object, timezoneService.Object);
|
||||
|
||||
@ -64,7 +64,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
public async Task UpdateDataAsync()
|
||||
{
|
||||
// Arrange
|
||||
var telemetryDataSaubService = new TelemetryDataSaubService(context, telemetryService, cacheDb);
|
||||
var telemetryDataSaubService = new TelemetryDataSaubService(context, telemetryService, null, cacheDb);
|
||||
|
||||
var now = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(timezone.Hours)).DateTime;
|
||||
var tuser = "Завулон";
|
||||
|
@ -43,7 +43,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
|
||||
public WellFinalDocumentsServiceTest()
|
||||
{
|
||||
context = TestHelpter.MakeTestContext();
|
||||
context = TestHelpter.MakeRealTestContext();
|
||||
context.SaveChanges();
|
||||
|
||||
fileServiceMock = new Mock<FileService>();
|
||||
|
@ -1,7 +1,8 @@
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudDb.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudWebApi.Tests
|
||||
{
|
||||
@ -9,7 +10,7 @@ namespace AsbCloudWebApi.Tests
|
||||
{
|
||||
// Попробовать когда-нибудь https://github.com/MichalJankowskii/Moq.EntityFrameworkCore
|
||||
|
||||
public static AsbCloudDbContext MakeTestContext()
|
||||
public static AsbCloudDbContext MakeRealTestContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
//.UseInMemoryDatabase(System.Guid.NewGuid().ToString())
|
||||
@ -22,5 +23,38 @@ namespace AsbCloudWebApi.Tests
|
||||
context.Database.EnsureCreated();
|
||||
return context;
|
||||
}
|
||||
|
||||
public static Mock<IAsbCloudDbContext> AddDbSetMock<T>(this Mock<IAsbCloudDbContext> contextMock, IEnumerable<T> dbSetData)
|
||||
where T : class
|
||||
{
|
||||
var dbSetMock = MakeDbSetMock(dbSetData);
|
||||
contextMock.Setup(o => o.Set<T>())
|
||||
.Returns(() => dbSetMock.Object);
|
||||
|
||||
return contextMock;
|
||||
}
|
||||
|
||||
public static Mock<DbSet<T>> MakeDbSetMock<T>()
|
||||
where T : class
|
||||
{
|
||||
var dbSetData = new List<T>();
|
||||
return MakeDbSetMock(dbSetData);
|
||||
}
|
||||
|
||||
public static Mock<DbSet<T>> MakeDbSetMock<T>(IEnumerable<T> dbSetData)
|
||||
where T : class
|
||||
{
|
||||
var dbSetDataQueriable = dbSetData
|
||||
.ToList()
|
||||
.AsQueryable();
|
||||
|
||||
Mock<DbSet<T>> dbSetMock = new();
|
||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.Provider).Returns(() => dbSetDataQueriable.Provider);
|
||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.Expression).Returns(() => dbSetDataQueriable.Expression);
|
||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.ElementType).Returns(() => dbSetDataQueriable.ElementType);
|
||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.GetEnumerator()).Returns(() => dbSetDataQueriable.GetEnumerator());
|
||||
|
||||
return dbSetMock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
||||
if (!isCompanyOwnsWell)
|
||||
return Forbid();
|
||||
|
||||
var content = await telemetryDataService.GetAsync(idWell, begin,
|
||||
var content = await telemetryDataService.GetOrDefaultAsync(idWell, begin,
|
||||
intervalSec, approxPointsCount, token).ConfigureAwait(false);
|
||||
|
||||
return Ok(content);
|
||||
|
@ -89,7 +89,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
||||
if (!isCompanyOwnsWell)
|
||||
return Forbid();
|
||||
|
||||
int? idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
int? idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return NoContent();
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||
CancellationToken token)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return NoContent();
|
||||
var dtos = await witsRecordRepository.GetLastAsync((int)idTelemetry, token);
|
||||
@ -96,7 +96,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||
CancellationToken token)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return NoContent();
|
||||
var dtos = await witsRecordRepository.GetAsync((int)idTelemetry, begin, end, token);
|
||||
@ -118,7 +118,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||
CancellationToken token)
|
||||
{
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is null)
|
||||
return NoContent();
|
||||
var dtos = await witsRecordRepository.GetStatAsync((int)idTelemetry, token);
|
||||
|
@ -1 +1 @@
|
||||
<!doctype html><html lang="ru"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><title>DDrilling</title><script defer="defer" src="/vendors.1920da1d.js"></script><script defer="defer" src="/main.101601f2.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="ru"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><title>DDrilling</title><script defer="defer" src="/vendors.1920da1d.js"></script><script defer="defer" src="/main.25114aff.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
@ -2,7 +2,9 @@
|
||||
using AsbCloudApp.Data.DailyReport;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure;
|
||||
using AsbCloudInfrastructure.Services.DailyReport;
|
||||
using AsbCloudInfrastructure.Services.SAUB;
|
||||
using ClosedXML.Excel;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -17,33 +19,20 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace ConsoleApp1
|
||||
{
|
||||
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
private static AsbCloudDbContext db = ServiceFactory.Context;
|
||||
|
||||
|
||||
// use ServiceFactory to make services
|
||||
static void Main(/*string[] args*/)
|
||||
{
|
||||
DependencyInjection.MapsterSetup();
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
var set1 = new int[15].Select((v,i) => i.ToString());
|
||||
var set2 = new int[5].Select((v, i) => (i + 1000).ToString());
|
||||
var set3 = new int[5].Select((v, i) => (i + 2000).ToString());
|
||||
var set4 = new int[5].Select((v, i) => (i + 4000).ToString());
|
||||
var set5 = new int[8].Select((v, i) => (i + 5000).ToString());
|
||||
var set6 = new int[3].Select((v, i) => (i + 6000).ToString());
|
||||
|
||||
var ca = new CyclycArray<string>(10);
|
||||
ca.AddRange(set1);
|
||||
ca.AddRange(set2);
|
||||
ca.AddRange(set3);
|
||||
ca.AddRange(set4);
|
||||
ca.AddRange(set5);
|
||||
ca.AddRange(set6);
|
||||
|
||||
Console.WriteLine($"total time: ms");
|
||||
sw.Stop();
|
||||
Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms");
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user