This commit is contained in:
ngfrolov 2022-11-15 17:44:48 +05:00
parent 698fb33651
commit eed8c3eeaa
28 changed files with 318 additions and 101 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -55,7 +55,7 @@ namespace AsbCloudApp.Services
/// </summary>
/// <param name="idWell"></param>
/// <returns></returns>
int? GetIdTelemetryByIdWell(int idWell);
int? GetOrDefaultIdTelemetryByIdWell(int idWell);
/// <summary>
/// получить диапазон дат за которые есть данные

View File

@ -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>();

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;

View 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));
}
}
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -107,7 +107,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
public DetectedOperationServiceTest()
{
context = TestHelpter.MakeTestContext();
context = TestHelpter.MakeRealTestContext();
context.SaveChanges();
context.Telemetries.Add(telemetry);

View File

@ -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();

View File

@ -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>();

View File

@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
public FileCategoryServiceTest()
{
context = TestHelpter.MakeTestContext();
context = TestHelpter.MakeRealTestContext();
context.SaveChanges();
service = new FileCategoryService(context);
}

View File

@ -58,7 +58,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
public ScheduleServiceTest()
{
context = TestHelpter.MakeTestContext();
context = TestHelpter.MakeRealTestContext();
context.SaveChanges();
context.Deposits.Add(deposit);

View File

@ -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 = "Завулон";

View File

@ -43,7 +43,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
public WellFinalDocumentsServiceTest()
{
context = TestHelpter.MakeTestContext();
context = TestHelpter.MakeRealTestContext();
context.SaveChanges();
fileServiceMock = new Mock<FileService>();

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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>

View File

@ -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();
}
}