forked from ddrilling/AsbCloudServer
#7579139 Tests
This commit is contained in:
parent
698fb33651
commit
eed8c3eeaa
@ -90,12 +90,16 @@ namespace System.Collections.Generic
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (used == 0)
|
||||||
|
return default;
|
||||||
|
|
||||||
var i = (current + 1 + index) % used;
|
var i = (current + 1 + index) % used;
|
||||||
return array[i];
|
return array[i];
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var i = (current + 1 + index) % used;
|
var devider = used > 0 ? used : array.Length;
|
||||||
|
var i = (current + 1 + index) % devider;
|
||||||
array[i] = value;
|
array[i] = value;
|
||||||
UpdatedInvoke(current, value);
|
UpdatedInvoke(current, value);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
#nullable enable
|
||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -22,7 +22,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="approxPointsCount">кол-во элементов до которых эти данные прореживаются</param>
|
/// <param name="approxPointsCount">кол-во элементов до которых эти данные прореживаются</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<TDto>> GetAsync(int idWell,
|
Task<IEnumerable<TDto>?> GetOrDefaultAsync(int idWell,
|
||||||
DateTime dateBegin = default, double intervalSec = 600d,
|
DateTime dateBegin = default, double intervalSec = 600d,
|
||||||
int approxPointsCount = 1024, CancellationToken token = default);
|
int approxPointsCount = 1024, CancellationToken token = default);
|
||||||
|
|
||||||
@ -36,3 +36,4 @@ namespace AsbCloudApp.Services
|
|||||||
Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default);
|
Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
@ -55,7 +55,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
int? GetIdTelemetryByIdWell(int idWell);
|
int? GetOrDefaultIdTelemetryByIdWell(int idWell);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// получить диапазон дат за которые есть данные
|
/// получить диапазон дат за которые есть данные
|
||||||
|
@ -16,6 +16,7 @@ using AsbCloudInfrastructure.Services.SAUB;
|
|||||||
using AsbCloudInfrastructure.Services.Subsystems;
|
using AsbCloudInfrastructure.Services.Subsystems;
|
||||||
using AsbCloudInfrastructure.Services.WellOperationService;
|
using AsbCloudInfrastructure.Services.WellOperationService;
|
||||||
using AsbCloudInfrastructure.Validators;
|
using AsbCloudInfrastructure.Validators;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using FluentValidation.AspNetCore;
|
using FluentValidation.AspNetCore;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -100,6 +101,8 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddSingleton(new WitsInfoService());
|
services.AddSingleton(new WitsInfoService());
|
||||||
services.AddSingleton(new CacheDb());
|
services.AddSingleton(new CacheDb());
|
||||||
services.AddSingleton(new InstantDataRepository());
|
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<ITelemetryTracker, TelemetryTracker>();
|
||||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||||
services.AddSingleton<IBackgroundWorkerService, BackgroundWorkerService>();
|
services.AddSingleton<IBackgroundWorkerService, BackgroundWorkerService>();
|
||||||
|
@ -27,7 +27,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
public async Task<DrillParamsDto?> GetDefaultDrillParamsAsync(int idWell,
|
public async Task<DrillParamsDto?> GetDefaultDrillParamsAsync(int idWell,
|
||||||
double startDepth, double endDepth, CancellationToken token = default)
|
double startDepth, double endDepth, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
|
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -113,7 +113,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
public DatesRangeDto GetDatesRangeOrDefault(int idWell)
|
public DatesRangeDto GetDatesRangeOrDefault(int idWell)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return null;
|
return null;
|
||||||
var range = telemetryService.GetDatesRange((int)idTelemetry);
|
var range = telemetryService.GetDatesRange((int)idTelemetry);
|
||||||
|
@ -34,7 +34,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
int take = 32,
|
int take = 32,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -10,26 +10,31 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
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 TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
where TModel : class, ITelemetryData
|
where TEntity : class, ITelemetryData
|
||||||
{
|
{
|
||||||
protected readonly IAsbCloudDbContext db;
|
protected readonly IAsbCloudDbContext db;
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
||||||
|
private readonly TelemetryDataCache<TDto> telemetryDataCache;
|
||||||
|
|
||||||
public TelemetryDataBaseService(
|
public TelemetryDataBaseService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
|
TelemetryDataCache<TDto> telemetryDataCache,
|
||||||
CacheDb cacheDb)
|
CacheDb cacheDb)
|
||||||
{
|
{
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((AsbCloudDbContext)db);
|
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((AsbCloudDbContext)db);
|
||||||
|
this.telemetryDataCache = telemetryDataCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (dtos == default || !dtos.Any())
|
if (dtos == default || !dtos.Any())
|
||||||
@ -53,6 +58,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var idTelemetry = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
var idTelemetry = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
var timezone = telemetryService.GetTimezone(idTelemetry);
|
||||||
|
|
||||||
|
telemetryDataCache.AddRange(idTelemetry, dtos);
|
||||||
|
|
||||||
var entities = dtosList.Select(dto =>
|
var entities = dtosList.Select(dto =>
|
||||||
{
|
{
|
||||||
var entity = Convert(dto, timezone.Hours);
|
var entity = Convert(dto, timezone.Hours);
|
||||||
@ -63,7 +70,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var entityMaxDate = entities.Max(e => e.DateTime);
|
var entityMaxDate = entities.Max(e => e.DateTime);
|
||||||
telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate);
|
telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate);
|
||||||
|
|
||||||
var dbset = db.Set<TModel>();
|
var dbset = db.Set<TEntity>();
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -82,12 +89,15 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: It shouldn`t be nullable. Throw exceptions instead and return empty.
|
||||||
/// <inheritdoc/>
|
/// <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,
|
DateTime dateBegin = default, double intervalSec = 600d,
|
||||||
int approxPointsCount = 1024, CancellationToken token = default)
|
int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell) ?? -1;
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell) ?? -1;
|
||||||
if (idTelemetry == -1)
|
if (idTelemetry == -1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -110,8 +120,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
if (dateBeginUtc == default)
|
if (dateBeginUtc == default)
|
||||||
dateBeginUtc = DateTime.UtcNow.AddSeconds(-intervalSec);
|
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 dateEnd = dateBeginUtc.AddSeconds(intervalSec);
|
||||||
var dbSet = db.Set<TModel>();
|
var dbSet = db.Set<TEntity>();
|
||||||
|
|
||||||
var query = dbSet
|
var query = dbSet
|
||||||
.Where(d => d.IdTelemetry == idTelemetry
|
.Where(d => d.IdTelemetry == idTelemetry
|
||||||
@ -144,9 +158,10 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return dtos;
|
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 System.Linq;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
namespace AsbCloudInfrastructure.Services.SAUB
|
||||||
{
|
{
|
||||||
public class TelemetryDataCache<TDto, TEntity>
|
public class TelemetryDataCache<TDto>
|
||||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
where TEntity : class, ITelemetryData
|
|
||||||
{
|
{
|
||||||
private const int activeWellCapacity = 24 * 60 * 60;
|
private const int activeWellCapacity = 24 * 60 * 60;
|
||||||
private const int doneWellCapacity = 65 * 60;
|
private const int doneWellCapacity = 65 * 60;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<int, CyclycArray<TDto>> caches;
|
private readonly ConcurrentDictionary<int, CyclycArray<TDto>> caches;
|
||||||
|
private bool isLoading = false;
|
||||||
|
|
||||||
public TelemetryDataCache(IAsbCloudDbContext db)
|
private TelemetryDataCache()
|
||||||
{
|
{
|
||||||
caches = new ();
|
caches = new();
|
||||||
LoadCaches(db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadCaches(IAsbCloudDbContext db)
|
private static TelemetryDataCache<TDto>? instance;
|
||||||
|
|
||||||
|
//TODO: Move initialize fromDB to bacground service task
|
||||||
|
public static TelemetryDataCache<TDto> GetInstance<TEntity>(IConfiguration configuration)
|
||||||
|
where TEntity : class, ITelemetryData
|
||||||
{
|
{
|
||||||
Well[] wells = db.Set<Well>()
|
if (instance is null)
|
||||||
.Include(well => well.Telemetry)
|
|
||||||
.Where(well => well.IdTelemetry != null)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
foreach (Well well in wells)
|
|
||||||
{
|
{
|
||||||
var capacity = well.IdState == 1
|
instance = new TelemetryDataCache<TDto>();
|
||||||
? activeWellCapacity
|
_ = Task.Run(() =>
|
||||||
: 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<TDto> GetCacheDataFromDb(IAsbCloudDbContext db, int idTelemetry, int capacity, double hoursOffset)
|
|
||||||
{
|
{
|
||||||
var entities = db.Set<TEntity>()
|
using var db = MakeContext(configuration);
|
||||||
.Where(i => i.IdTelemetry == idTelemetry)
|
instance.InitializeCacheFromDB<TEntity>(db);
|
||||||
.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;
|
return instance;
|
||||||
|
}
|
||||||
|
public static TelemetryDataCache<TDto> GetInstance<TEntity>(IAsbCloudDbContext db, out Task initializationTask)
|
||||||
|
where TEntity : class, ITelemetryData
|
||||||
|
{
|
||||||
|
if (instance is null)
|
||||||
|
{
|
||||||
|
instance = new TelemetryDataCache<TDto>();
|
||||||
|
initializationTask = Task.Run(() =>
|
||||||
|
{
|
||||||
|
instance.InitializeCacheFromDB<TEntity>(db);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
initializationTask = Task.CompletedTask;
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить элементы в кеш
|
/// Добавить новые элементы в кеш
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <param name="range"></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
|
var newItems = range
|
||||||
.OrderBy(i => i.DateTime);
|
.OrderBy(i => i.DateTime);
|
||||||
foreach (var item in newItems)
|
foreach (var item in newItems)
|
||||||
@ -95,7 +100,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
if(!caches.TryGetValue(idTelemetry, out CyclycArray<TDto>? cacheItem))
|
if(!caches.TryGetValue(idTelemetry, out CyclycArray<TDto>? cacheItem))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (cacheItem is null || cacheItem[0].DateTime > dateBegin)
|
if (cacheItem is null || !cacheItem.Any() || cacheItem[0].DateTime > dateBegin)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||||
@ -109,6 +114,77 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
|
|
||||||
return items;
|
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
|
#nullable disable
|
@ -16,8 +16,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public TelemetryDataSaubService(
|
public TelemetryDataSaubService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
|
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache,
|
||||||
CacheDb cacheDb)
|
CacheDb cacheDb)
|
||||||
: base(db, telemetryService, cacheDb)
|
: base(db, telemetryService, telemetryDataCache, cacheDb)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
|
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
|
||||||
|
@ -13,8 +13,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public TelemetryDataSpinService(
|
public TelemetryDataSpinService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
|
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache,
|
||||||
CacheDb cacheDb)
|
CacheDb cacheDb)
|
||||||
: base(db, telemetryService, cacheDb)
|
: base(db, telemetryService, telemetryDataCache, cacheDb)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)
|
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.");
|
throw new Exception($"Telemetry id: {idTelemetry} can't find timezone.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? GetIdTelemetryByIdWell(int idWell)
|
public int? GetOrDefaultIdTelemetryByIdWell(int idWell)
|
||||||
{
|
{
|
||||||
var telemetry = GetTelemetryCache()
|
var telemetry = GetTelemetryCache()
|
||||||
.FirstOrDefault(t => t.Value.Well?.Id == idWell).Value;
|
.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()
|
public ClusterServiceTest()
|
||||||
{
|
{
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
wellService = new Mock<IWellService>();
|
wellService = new Mock<IWellService>();
|
||||||
context.Deposits.RemoveRange(context.Deposits);
|
context.Deposits.RemoveRange(context.Deposits);
|
||||||
context.Clusters.RemoveRange(context.Clusters);
|
context.Clusters.RemoveRange(context.Clusters);
|
||||||
|
@ -21,7 +21,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
|
|
||||||
protected override ICrudService<DepositDto> MakeService()
|
protected override ICrudService<DepositDto> MakeService()
|
||||||
{
|
{
|
||||||
var dbContext = TestHelpter.MakeTestContext();
|
var dbContext = TestHelpter.MakeRealTestContext();
|
||||||
return new CrudCacheServiceBase<DepositDto, Deposit>(dbContext);
|
return new CrudCacheServiceBase<DepositDto, Deposit>(dbContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
|
|
||||||
public DetectedOperationServiceTest()
|
public DetectedOperationServiceTest()
|
||||||
{
|
{
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
|
||||||
context.Telemetries.Add(telemetry);
|
context.Telemetries.Add(telemetry);
|
||||||
|
@ -90,7 +90,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
{
|
{
|
||||||
AsbCloudInfrastructure.DependencyInjection.MapsterSetup();
|
AsbCloudInfrastructure.DependencyInjection.MapsterSetup();
|
||||||
|
|
||||||
db = TestHelpter.MakeTestContext();
|
db = TestHelpter.MakeRealTestContext();
|
||||||
db.Wells.AddRange(wells);
|
db.Wells.AddRange(wells);
|
||||||
db.Companies.AddRange(companies);
|
db.Companies.AddRange(companies);
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
@ -19,7 +19,7 @@ public class EventServiceTest
|
|||||||
|
|
||||||
public EventServiceTest()
|
public EventServiceTest()
|
||||||
{
|
{
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
cacheDb = new CacheDb();
|
cacheDb = new CacheDb();
|
||||||
var telemetryTracker = new Mock<ITelemetryTracker>();
|
var telemetryTracker = new Mock<ITelemetryTracker>();
|
||||||
var imezoneServiceMock = new Mock<ITimezoneService>();
|
var imezoneServiceMock = new Mock<ITimezoneService>();
|
||||||
|
@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
public FileCategoryServiceTest()
|
public FileCategoryServiceTest()
|
||||||
{
|
{
|
||||||
|
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
service = new FileCategoryService(context);
|
service = new FileCategoryService(context);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
|
|
||||||
public ScheduleServiceTest()
|
public ScheduleServiceTest()
|
||||||
{
|
{
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
|
||||||
context.Deposits.Add(deposit);
|
context.Deposits.Add(deposit);
|
||||||
|
@ -40,7 +40,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
timezoneService.Setup(s => s.GetByCoordinates(It.IsAny<double>(), It.IsAny<double>()))
|
timezoneService.Setup(s => s.GetByCoordinates(It.IsAny<double>(), It.IsAny<double>()))
|
||||||
.Returns(timezone);
|
.Returns(timezone);
|
||||||
|
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
cacheDb = new CacheDb();
|
cacheDb = new CacheDb();
|
||||||
telemetryService = new TelemetryService(context, telemetryTracker.Object, timezoneService.Object);
|
telemetryService = new TelemetryService(context, telemetryTracker.Object, timezoneService.Object);
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
public async Task UpdateDataAsync()
|
public async Task UpdateDataAsync()
|
||||||
{
|
{
|
||||||
// Arrange
|
// 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 now = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(timezone.Hours)).DateTime;
|
||||||
var tuser = "Завулон";
|
var tuser = "Завулон";
|
||||||
|
@ -43,7 +43,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
|
|
||||||
public WellFinalDocumentsServiceTest()
|
public WellFinalDocumentsServiceTest()
|
||||||
{
|
{
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeRealTestContext();
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
|
||||||
fileServiceMock = new Mock<FileService>();
|
fileServiceMock = new Mock<FileService>();
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
using AsbCloudApp.Services;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudDb.Model;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
using Moq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Tests
|
namespace AsbCloudWebApi.Tests
|
||||||
{
|
{
|
||||||
@ -9,7 +10,7 @@ namespace AsbCloudWebApi.Tests
|
|||||||
{
|
{
|
||||||
// Попробовать когда-нибудь https://github.com/MichalJankowskii/Moq.EntityFrameworkCore
|
// Попробовать когда-нибудь https://github.com/MichalJankowskii/Moq.EntityFrameworkCore
|
||||||
|
|
||||||
public static AsbCloudDbContext MakeTestContext()
|
public static AsbCloudDbContext MakeRealTestContext()
|
||||||
{
|
{
|
||||||
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||||
//.UseInMemoryDatabase(System.Guid.NewGuid().ToString())
|
//.UseInMemoryDatabase(System.Guid.NewGuid().ToString())
|
||||||
@ -22,5 +23,38 @@ namespace AsbCloudWebApi.Tests
|
|||||||
context.Database.EnsureCreated();
|
context.Database.EnsureCreated();
|
||||||
return context;
|
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)
|
if (!isCompanyOwnsWell)
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
var content = await telemetryDataService.GetAsync(idWell, begin,
|
var content = await telemetryDataService.GetOrDefaultAsync(idWell, begin,
|
||||||
intervalSec, approxPointsCount, token).ConfigureAwait(false);
|
intervalSec, approxPointsCount, token).ConfigureAwait(false);
|
||||||
|
|
||||||
return Ok(content);
|
return Ok(content);
|
||||||
|
@ -89,7 +89,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
if (!isCompanyOwnsWell)
|
if (!isCompanyOwnsWell)
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
int? idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
int? idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return NoContent();
|
return NoContent();
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
|||||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return NoContent();
|
return NoContent();
|
||||||
var dtos = await witsRecordRepository.GetLastAsync((int)idTelemetry, token);
|
var dtos = await witsRecordRepository.GetLastAsync((int)idTelemetry, token);
|
||||||
@ -96,7 +96,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
|||||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return NoContent();
|
return NoContent();
|
||||||
var dtos = await witsRecordRepository.GetAsync((int)idTelemetry, begin, end, token);
|
var dtos = await witsRecordRepository.GetAsync((int)idTelemetry, begin, end, token);
|
||||||
@ -118,7 +118,7 @@ namespace AsbCloudWebApi.Controllers.WITS
|
|||||||
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
[FromServices] IWitsRecordRepository<TDto> witsRecordRepository,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell);
|
||||||
if (idTelemetry is null)
|
if (idTelemetry is null)
|
||||||
return NoContent();
|
return NoContent();
|
||||||
var dtos = await witsRecordRepository.GetStatAsync((int)idTelemetry, token);
|
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 AsbCloudApp.Data.DailyReport;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure;
|
||||||
using AsbCloudInfrastructure.Services.DailyReport;
|
using AsbCloudInfrastructure.Services.DailyReport;
|
||||||
|
using AsbCloudInfrastructure.Services.SAUB;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using DocumentFormat.OpenXml.Wordprocessing;
|
using DocumentFormat.OpenXml.Wordprocessing;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -17,9 +19,6 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace ConsoleApp1
|
namespace ConsoleApp1
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
private static AsbCloudDbContext db = ServiceFactory.Context;
|
private static AsbCloudDbContext db = ServiceFactory.Context;
|
||||||
@ -27,23 +26,13 @@ namespace ConsoleApp1
|
|||||||
// use ServiceFactory to make services
|
// use ServiceFactory to make services
|
||||||
static void Main(/*string[] args*/)
|
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();
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user