Наработки
Some checks failed
Unit tests / test (push) Failing after 47s

This commit is contained in:
Roman Efremov 2025-01-13 17:45:49 +05:00
parent aa0540d2af
commit 750788d550
66 changed files with 238 additions and 234 deletions

View File

@ -4,6 +4,7 @@ using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using System.Net; using System.Net;
using DD.Persistence.Models.Common;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;

View File

@ -13,7 +13,7 @@ namespace DD.Persistence.API.Controllers;
[Route("api/[controller]")] [Route("api/[controller]")]
public class DataSaubController : TimeSeriesController<DataSaubDto> public class DataSaubController : TimeSeriesController<DataSaubDto>
{ {
public DataSaubController(ITimeSeriesDataRepository<DataSaubDto> timeSeriesDataRepository) : base(timeSeriesDataRepository) public DataSaubController(ITimestampedValuesRepository<DataSaubDto> timeSeriesDataRepository) : base(timeSeriesDataRepository)
{ {
} }

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using System.Net; using System.Net;
using DD.Persistence.Models.Common;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using DD.Persistence.ModelsAbstractions;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;
@ -9,11 +9,11 @@ namespace DD.Persistence.API.Controllers;
[Authorize] [Authorize]
[Route("api/[controller]")] [Route("api/[controller]")]
public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDto> public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDto>
where TDto : class, ITimeSeriesAbstractDto, new() where TDto : class, ITimestampAbstractDto, new()
{ {
private readonly ITimeSeriesDataRepository<TDto> timeSeriesDataRepository; private readonly ITimestampedValuesRepository<TDto> timeSeriesDataRepository;
public TimeSeriesController(ITimeSeriesDataRepository<TDto> timeSeriesDataRepository) public TimeSeriesController(ITimestampedValuesRepository<TDto> timeSeriesDataRepository)
{ {
this.timeSeriesDataRepository = timeSeriesDataRepository; this.timeSeriesDataRepository = timeSeriesDataRepository;
} }

View File

@ -4,6 +4,7 @@ using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using System.Net; using System.Net;
using DD.Persistence.Models.Common;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using System.Net; using System.Net;
using DD.Persistence.Models.Common;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Services.Interfaces; using DD.Persistence.Services.Interfaces;
using System.Net; using System.Net;
using DD.Persistence.Models.Common;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;

View File

@ -4,6 +4,7 @@ using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;
public class ChangeLogClient : BaseClient, IChangeLogClient public class ChangeLogClient : BaseClient, IChangeLogClient

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models.Common;
using DD.Persistence.ModelsAbstractions;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;
@ -6,7 +7,7 @@ namespace DD.Persistence.Client.Clients.Interfaces;
/// Клиент для работы с временными данными /// Клиент для работы с временными данными
/// </summary> /// </summary>
/// <typeparam name="TDto"></typeparam> /// <typeparam name="TDto"></typeparam>
public interface ITimeSeriesClient<TDto> : IDisposable where TDto : class, ITimeSeriesAbstractDto public interface ITimeSeriesClient<TDto> : IDisposable where TDto : class, ITimestampAbstractDto
{ {
/// <summary> /// <summary>
/// Добавление записей /// Добавление записей

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using Refit; using Refit;
namespace DD.Persistence.Client.Clients.Interfaces; namespace DD.Persistence.Client.Clients.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using Refit; using Refit;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using Refit; using Refit;
namespace DD.Persistence.Client.Clients.Interfaces.Refit; namespace DD.Persistence.Client.Clients.Interfaces.Refit;

View File

@ -2,6 +2,7 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using Refit; using Refit;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients.Interfaces.Refit namespace DD.Persistence.Client.Clients.Interfaces.Refit
{ {

View File

@ -1,9 +1,10 @@
using DD.Persistence.Models; using DD.Persistence.Models.Common;
using DD.Persistence.ModelsAbstractions;
using Refit; using Refit;
namespace DD.Persistence.Client.Clients.Interfaces.Refit; namespace DD.Persistence.Client.Clients.Interfaces.Refit;
public interface IRefitTimeSeriesClient<TDto> : IRefitClient, IDisposable public interface IRefitTimeSeriesClient<TDto> : IRefitClient, IDisposable
where TDto : class, ITimeSeriesAbstractDto where TDto : class, ITimestampAbstractDto
{ {
private const string BaseRoute = "/api/dataSaub"; private const string BaseRoute = "/api/dataSaub";

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using Refit; using Refit;
namespace DD.Persistence.Client.Clients.Interfaces.Refit; namespace DD.Persistence.Client.Clients.Interfaces.Refit;

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models;
using Refit; using Refit;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients.Interfaces.Refit; namespace DD.Persistence.Client.Clients.Interfaces.Refit;
public interface IRefitWitsDataClient : IRefitClient, IDisposable public interface IRefitWitsDataClient : IRefitClient, IDisposable

View File

@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Base;
using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;

View File

@ -4,6 +4,7 @@ using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;

View File

@ -2,10 +2,11 @@
using DD.Persistence.Client.Clients.Base; using DD.Persistence.Client.Clients.Base;
using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models; using DD.Persistence.Models.Common;
using DD.Persistence.ModelsAbstractions;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;
public class TimeSeriesClient<TDto> : BaseClient, ITimeSeriesClient<TDto> where TDto : class, ITimeSeriesAbstractDto public class TimeSeriesClient<TDto> : BaseClient, ITimeSeriesClient<TDto> where TDto : class, ITimestampAbstractDto
{ {
private readonly IRefitTimeSeriesClient<TDto> timeSeriesClient; private readonly IRefitTimeSeriesClient<TDto> timeSeriesClient;

View File

@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Base;
using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;
public class TimestampedSetClient : BaseClient, ITimestampedSetClient public class TimestampedSetClient : BaseClient, ITimestampedSetClient

View File

@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Base;
using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Client.Clients; namespace DD.Persistence.Client.Clients;
public class WitsDataClient : BaseClient, IWitsDataClient public class WitsDataClient : BaseClient, IWitsDataClient

View File

@ -1,8 +1,9 @@
 
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using DD.Persistence.Models;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using DD.Persistence.ModelsAbstractions;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Model; namespace DD.Persistence.Database.Model;

View File

@ -1,11 +1,12 @@
using Microsoft.EntityFrameworkCore; using DD.Persistence.Database.EntityAbstractions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace DD.Persistence.Database.Entity; namespace DD.Persistence.Database.Entity;
[PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))] [PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))]
public class ParameterData public class ParameterData : ITimestampedItem
{ {
[Required, Comment("Дискриминатор системы")] [Required, Comment("Дискриминатор системы")]
public Guid DiscriminatorId { get; set; } public Guid DiscriminatorId { get; set; }

View File

@ -1,10 +1,11 @@
using Microsoft.EntityFrameworkCore; using DD.Persistence.Database.EntityAbstractions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace DD.Persistence.Database.Model namespace DD.Persistence.Database.Model
{ {
[PrimaryKey(nameof(Key), nameof(Created))] [PrimaryKey(nameof(Key), nameof(Timestamp))]
public class Setpoint public class Setpoint : ITimestampedItem
{ {
[Comment("Ключ")] [Comment("Ключ")]
public Guid Key { get; set; } public Guid Key { get; set; }
@ -13,7 +14,7 @@ namespace DD.Persistence.Database.Model
public required object Value { get; set; } public required object Value { get; set; }
[Comment("Дата создания уставки")] [Comment("Дата создания уставки")]
public DateTimeOffset Created { get; set; } public DateTimeOffset Timestamp { get; set; }
[Comment("Id автора последнего изменения")] [Comment("Id автора последнего изменения")]
public Guid IdUser { get; set; } public Guid IdUser { get; set; }

View File

@ -1,10 +1,11 @@
using DD.Persistence.Database.EntityAbstractions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace DD.Persistence.Database.Entity namespace DD.Persistence.Database.Entity
{ {
public class TechMessage public class TechMessage : ITimestampedItem
{ {
[Key, Comment("Id события")] [Key, Comment("Id события")]
public Guid EventId { get; set; } public Guid EventId { get; set; }

View File

@ -1,11 +0,0 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace DD.Persistence.Database.Entity;
[Comment("Общая таблица данных временных рядов")]
[PrimaryKey(nameof(IdDiscriminator), nameof(Timestamp))]
public record TimestampedSet(
[property: Comment("Дискриминатор ссылка на тип сохраняемых данных")] Guid IdDiscriminator,
[property: Comment("Отметка времени, строго в UTC")] DateTimeOffset Timestamp,
[property: Column(TypeName = "jsonb"), Comment("Набор сохраняемых данных")] IDictionary<string, object> Set);

View File

@ -1,18 +1,19 @@
using DD.Persistence.Database.Model; using DD.Persistence.Database.EntityAbstractions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace DD.Persistence.Database.Entity; namespace DD.Persistence.Database.Entity;
[PrimaryKey(nameof(BagId), nameof(Timestamp))] [PrimaryKey(nameof(DiscriminatorId), nameof(Timestamp))]
public class TagBag : ITimestampedData public class TimestampedValues : ITimestampedItem
{ {
[Comment("Временная отметка"), Key] [Comment("Временная отметка"), Key]
public DateTimeOffset Timestamp { get; set; } public DateTimeOffset Timestamp { get; set; }
public Guid BagId { get; set; } [Comment("Дискриминатор системы"),]
public Guid DiscriminatorId { get; set; }
[Column(TypeName = "jsonb")] [Comment("Данные"), Column(TypeName = "jsonb")]
public required object[] Values { get; set; } public required object[] Values { get; set; }
} }

View File

@ -1,5 +1,4 @@
 namespace DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Model;
/// <summary> /// <summary>
/// Часть записи, описывающая изменение /// Часть записи, описывающая изменение

View File

@ -1,5 +1,5 @@
namespace DD.Persistence.Database.Model; namespace DD.Persistence.Database.EntityAbstractions;
public interface ITimestampedData public interface ITimestampedItem
{ {
/// <summary> /// <summary>
/// Дата (должна быть обязательно в UTC) /// Дата (должна быть обязательно в UTC)

View File

@ -2,8 +2,8 @@ using DD.Persistence.Client;
using DD.Persistence.Client.Clients; using DD.Persistence.Client.Clients;
using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Database.Model; using DD.Persistence.Database.EntityAbstractions;
using DD.Persistence.Models; using DD.Persistence.ModelsAbstractions;
using Mapster; using Mapster;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -12,8 +12,8 @@ using Xunit;
namespace DD.Persistence.IntegrationTests.Controllers; namespace DD.Persistence.IntegrationTests.Controllers;
public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrationTest public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrationTest
where TEntity : class, ITimestampedData, new() where TEntity : class, ITimestampedItem, new()
where TDto : class, ITimeSeriesAbstractDto, new() where TDto : class, ITimestampAbstractDto, new()
{ {
private readonly ITimeSeriesClient<TDto> timeSeriesClient; private readonly ITimeSeriesClient<TDto> timeSeriesClient;

View File

@ -6,6 +6,7 @@ using DD.Persistence.Repositories;
using DD.Persistence.Repository.Repositories; using DD.Persistence.Repository.Repositories;
using DD.Persistence.Database.Entity; using DD.Persistence.Database.Entity;
using System.Reflection; using System.Reflection;
using DD.Persistence.Repository.RepositoriesCached;
namespace DD.Persistence.Repository; namespace DD.Persistence.Repository;
public static class DependencyInjection public static class DependencyInjection
@ -35,9 +36,9 @@ public static class DependencyInjection
MapsterSetup(); MapsterSetup();
services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TagBagDataRepository>(); services.AddTransient<ITimestampedValuesRepository<DataSaubDto>, TagBagDataRepository>();
services.AddTransient<ISetpointRepository, SetpointRepository>(); services.AddTransient<ISetpointRepository, SetpointRepository>();
//services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TimeSeriesDataCachedRepository<DataSaub, DataSaubDto>>(); //services.AddTransient<ITimestampedValuesRepository<DataSaubDto>, TimeSeriesDataCachedRepository<DataSaub, DataSaubDto>>();
services.AddTransient<IChangeLogRepository, ChangeLogRepository>(); services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
services.AddTransient<ITimestampedSetRepository, TimestampedSetRepository>(); services.AddTransient<ITimestampedSetRepository, TimestampedSetRepository>();
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>(); services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using DD.Persistence.Database.Model;
using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Models.Common;
using DD.Persistence.ModelsAbstractions;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Repository; namespace DD.Persistence.Repository;

View File

@ -5,6 +5,7 @@ using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using UuidExtensions; using UuidExtensions;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repository.Repositories; namespace DD.Persistence.Repository.Repositories;
public class ChangeLogRepository : IChangeLogRepository public class ChangeLogRepository : IChangeLogRepository

View File

@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
using DD.Persistence.Database.Entity; using DD.Persistence.Database.Entity;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repository.Repositories; namespace DD.Persistence.Repository.Repositories;
public class ParameterRepository : IParameterRepository public class ParameterRepository : IParameterRepository

View File

@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
using DD.Persistence.Database.Model; using DD.Persistence.Database.Model;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repository.Repositories namespace DD.Persistence.Repository.Repositories
{ {
@ -35,8 +36,8 @@ namespace DD.Persistence.Repository.Repositories
.ToArrayAsync(token); .ToArrayAsync(token);
var filteredEntities = entities var filteredEntities = entities
.GroupBy(e => e.Key) .GroupBy(e => e.Key)
.Select(e => e.OrderBy(o => o.Created)) .Select(e => e.OrderBy(o => o.Timestamp))
.Select(e => e.Where(e => e.Created <= historyMoment).Last()); .Select(e => e.Where(e => e.Timestamp <= historyMoment).Last());
var dtos = filteredEntities var dtos = filteredEntities
.Select(e => e.Adapt<SetpointValueDto>()); .Select(e => e.Adapt<SetpointValueDto>());
@ -47,7 +48,7 @@ namespace DD.Persistence.Repository.Repositories
{ {
var query = GetQueryReadOnly(); var query = GetQueryReadOnly();
var entities = await query var entities = await query
.Where(e => e.Created >= dateBegin) .Where(e => e.Timestamp >= dateBegin)
.Take(take) .Take(take)
.ToArrayAsync(token); .ToArrayAsync(token);
var dtos = entities var dtos = entities
@ -62,8 +63,8 @@ namespace DD.Persistence.Repository.Repositories
.GroupBy(e => 1) .GroupBy(e => 1)
.Select(group => new .Select(group => new
{ {
Min = group.Min(e => e.Created), Min = group.Min(e => e.Timestamp),
Max = group.Max(e => e.Created), Max = group.Max(e => e.Timestamp),
}); });
var values = await query.FirstOrDefaultAsync(token); var values = await query.FirstOrDefaultAsync(token);
var result = new DatesRangeDto() var result = new DatesRangeDto()
@ -95,7 +96,7 @@ namespace DD.Persistence.Repository.Repositories
Key = setpointKey, Key = setpointKey,
Value = newValue, Value = newValue,
IdUser = idUser, IdUser = idUser,
Created = DateTimeOffset.UtcNow Timestamp = DateTimeOffset.UtcNow
}; };
await db.Set<Setpoint>().AddAsync(entity, token); await db.Set<Setpoint>().AddAsync(entity, token);

View File

@ -7,10 +7,11 @@ using DD.Persistence.Models;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using UuidExtensions; using UuidExtensions;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repository.Repositories namespace DD.Persistence.Repository.Repositories
{ {
public class TechMessagesRepository : ITechMessagesRepository public class TechMessagesRepository : ITechMessagesRepository
{ {
private readonly IDataSourceSystemRepository sourceSystemRepository; private readonly IDataSourceSystemRepository sourceSystemRepository;
private DbContext db; private DbContext db;

View File

@ -1,103 +0,0 @@
using Microsoft.EntityFrameworkCore;
using DD.Persistence.Database.Model;
using DD.Persistence.Models;
namespace DD.Persistence.Repository.Repositories;
public class TimeSeriesDataCachedRepository<TEntity, TDto> : TimeSeriesDataRepository<TEntity, TDto>
where TEntity : class, ITimestampedData, new()
where TDto : class, ITimeSeriesAbstractDto, new()
{
public static TDto? FirstByDate { get; private set; }
public static CyclicArray<TDto> LastData { get; } = new CyclicArray<TDto>(CacheItemsCount);
private const int CacheItemsCount = 3600;
public TimeSeriesDataCachedRepository(DbContext db) : base(db)
{
Task.Run(async () =>
{
var firstDateItem = await base.GetFirstAsync(CancellationToken.None);
if (firstDateItem == null)
{
return;
}
FirstByDate = firstDateItem;
var dtos = await base.GetLastAsync(CacheItemsCount, CancellationToken.None);
dtos = dtos.OrderBy(d => d.Date);
LastData.AddRange(dtos);
}).Wait();
}
public override async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
{
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
{
var dtos = await base.GetGtDate(dateBegin, token);
return dtos;
}
var items = LastData
.Where(i => i.Date >= dateBegin);
return items;
}
public override async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await base.AddRange(dtos, token);
if (result > 0)
{
dtos = dtos.OrderBy(x => x.Date);
FirstByDate = dtos.First();
LastData.AddRange(dtos);
}
return result;
}
public override async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
{
if (FirstByDate == null)
return null;
return await Task.Run(() =>
{
return new DatesRangeDto
{
From = FirstByDate.Date,
To = LastData[^1].Date
};
});
}
public override async Task<IEnumerable<TDto>> GetResampledData(
DateTimeOffset dateBegin,
double intervalSec = 600d,
int approxPointsCount = 1024,
CancellationToken token = default)
{
var dtos = LastData.Where(i => i.Date >= dateBegin);
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
{
dtos = await base.GetGtDate(dateBegin, token);
}
var dateEnd = dateBegin.AddSeconds(intervalSec);
dtos = dtos
.Where(i => i.Date <= dateEnd);
var ratio = dtos.Count() / approxPointsCount;
if (ratio > 1)
dtos = dtos
.Where((_, index) => index % ratio == 0);
return dtos;
}
}

View File

@ -2,6 +2,7 @@
using DD.Persistence.Database.Entity; using DD.Persistence.Database.Entity;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repository.Repositories; namespace DD.Persistence.Repository.Repositories;

View File

@ -1,20 +1,22 @@
using Mapster; using DD.Persistence.Database.Entity;
using Microsoft.EntityFrameworkCore; using DD.Persistence.Models.Common;
using DD.Persistence.Database.Model; using DD.Persistence.ModelsAbstractions;
using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using Mapster;
using Microsoft.EntityFrameworkCore;
namespace DD.Persistence.Repository.Repositories; namespace DD.Persistence.Repository.Repositories;
public class TagBagRepository : ITimeSeriesDataRepository public class TimestampedValuesRepository<TDto> : ITimestampedValuesRepository<TDto>
where TDto : class, ITimestampAbstractDto, new()
{ {
private readonly DbContext db; private readonly DbContext db;
public TagBagRepository(DbContext db) public TimestampedValuesRepository(DbContext db)
{ {
this.db = db; this.db = db;
} }
protected virtual IQueryable<TEntity> GetQueryReadOnly() => this.db.Set<TEntity>(); protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => this.db.Set<TimestampedValues>();
public virtual async Task<DatesRangeDto?> GetDatesRange(CancellationToken token) public virtual async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
{ {
@ -31,7 +33,7 @@ public class TagBagRepository : ITimeSeriesDataRepository
public virtual async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token) public virtual async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
{ {
var query = this.db.Set<TEntity>().Where(e => e.Timestamp > date); var query = GetQueryReadOnly().Where(e => e.Timestamp > date);
var entities = await query.ToArrayAsync(token); var entities = await query.ToArrayAsync(token);
var dtos = entities.Select(e => e.Adapt<TDto>()); var dtos = entities.Select(e => e.Adapt<TDto>());
@ -41,9 +43,9 @@ public class TagBagRepository : ITimeSeriesDataRepository
public virtual async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token) public virtual async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
{ {
var entities = dtos.Select(d => d.Adapt<TEntity>()); var entities = dtos.Select(d => d.Adapt<TimestampedValues>());
await db.Set<TEntity>().AddRangeAsync(entities, token); await db.Set<TimestampedValues>().AddRangeAsync(entities, token);
var result = await db.SaveChangesAsync(token); var result = await db.SaveChangesAsync(token);
return result; return result;
@ -85,7 +87,7 @@ public class TagBagRepository : ITimeSeriesDataRepository
var dateEnd = dateBegin.AddSeconds(intervalSec); var dateEnd = dateBegin.AddSeconds(intervalSec);
dtos = dtos dtos = dtos
.Where(i => i.Date <= dateEnd); .Where(i => i.Timestamp <= dateEnd);
var ratio = dtos.Count() / approxPointsCount; var ratio = dtos.Count() / approxPointsCount;
if (ratio > 1) if (ratio > 1)

View File

@ -1,8 +1,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repository.Repositories;
namespace DD.Persistence.Repository.Repositories; namespace DD.Persistence.Repository.RepositoriesCached;
public class DataSourceSystemCachedRepository : DataSourceSystemRepository public class DataSourceSystemCachedRepository : DataSourceSystemRepository
{ {
private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey"; private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey";

View File

@ -0,0 +1,104 @@
//using Microsoft.EntityFrameworkCore;
//using DD.Persistence.Models.Common;
//using DD.Persistence.ModelsAbstractions;
//using DD.Persistence.Database.EntityAbstractions;
//namespace DD.Persistence.Repository.Repositories;
//public class TimestampedValuesCachedRepository<TEntity, TDto> : TimeSeriesDataRepository<TEntity, TDto>
// where TEntity : class, ITimestampedItem, new()
// where TDto : class, ITimestampAbstractDto, new()
//{
// public static TDto? FirstByDate { get; private set; }
// public static CyclicArray<TDto> LastData { get; } = new CyclicArray<TDto>(CacheItemsCount);
// private const int CacheItemsCount = 3600;
// public TimestampedValuesCachedRepository(DbContext db) : base(db)
// {
// Task.Run(async () =>
// {
// var firstDateItem = await base.GetFirstAsync(CancellationToken.None);
// if (firstDateItem == null)
// {
// return;
// }
// FirstByDate = firstDateItem;
// var dtos = await base.GetLastAsync(CacheItemsCount, CancellationToken.None);
// dtos = dtos.OrderBy(d => d.Timestamp);
// LastData.AddRange(dtos);
// }).Wait();
// }
// public override async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
// {
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
// {
// var dtos = await base.GetGtDate(dateBegin, token);
// return dtos;
// }
// var items = LastData
// .Where(i => i.Timestamp >= dateBegin);
// return items;
// }
// public override async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
// {
// var result = await base.AddRange(dtos, token);
// if (result > 0)
// {
// dtos = dtos.OrderBy(x => x.Timestamp);
// FirstByDate = dtos.First();
// LastData.AddRange(dtos);
// }
// return result;
// }
// public override async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
// {
// if (FirstByDate == null)
// return null;
// return await Task.Run(() =>
// {
// return new DatesRangeDto
// {
// From = FirstByDate.Timestamp,
// To = LastData[^1].Timestamp
// };
// });
// }
// public override async Task<IEnumerable<TDto>> GetResampledData(
// DateTimeOffset dateBegin,
// double intervalSec = 600d,
// int approxPointsCount = 1024,
// CancellationToken token = default)
// {
// var dtos = LastData.Where(i => i.Timestamp >= dateBegin);
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
// {
// dtos = await base.GetGtDate(dateBegin, token);
// }
// var dateEnd = dateBegin.AddSeconds(intervalSec);
// dtos = dtos
// .Where(i => i.Timestamp <= dateEnd);
// var ratio = dtos.Count() / approxPointsCount;
// if (ratio > 1)
// dtos = dtos
// .Where((_, index) => index % ratio == 0);
// return dtos;
// }
//}

View File

@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models.Common;
namespace DD.Persistence.API; namespace DD.Persistence.API;

View File

@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.Models.Common;
namespace DD.Persistence.API; namespace DD.Persistence.API;

View File

@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using DD.Persistence.Models; using DD.Persistence.ModelsAbstractions;
namespace DD.Persistence.API; namespace DD.Persistence.API;
@ -7,7 +7,7 @@ namespace DD.Persistence.API;
/// Интерфейс для работы с API временных данных /// Интерфейс для работы с API временных данных
/// </summary> /// </summary>
public interface ITimeSeriesDataApi<TDto> : ITimeSeriesBaseDataApi<TDto> public interface ITimeSeriesDataApi<TDto> : ITimeSeriesBaseDataApi<TDto>
where TDto : class, ITimeSeriesAbstractDto, new() where TDto : class, ITimestampAbstractDto, new()
{ {
/// <summary> /// <summary>
/// Получить список объектов, удовлетворяющий диапазон дат /// Получить список объектов, удовлетворяющий диапазон дат

View File

@ -66,7 +66,7 @@ public static class EFExtensions
/// и опционально указания направления сортировки "asc" или "desc" /// и опционально указания направления сортировки "asc" или "desc"
/// </param> /// </param>
/// <example> /// <example>
/// var query = query("Date desc"); /// var query = query("Timestamp desc");
/// </example> /// </example>
/// <returns>Запрос с примененной сортировкой</returns> /// <returns>Запрос с примененной сортировкой</returns>
public static IOrderedQueryable<TSource> SortBy<TSource>( public static IOrderedQueryable<TSource> SortBy<TSource>(

View File

@ -1,4 +1,4 @@
namespace DD.Persistence.Models; namespace DD.Persistence.Models.Common;
/// <summary> /// <summary>
/// Диапазон дат /// Диапазон дат

View File

@ -1,4 +1,4 @@
namespace DD.Persistence.Models; namespace DD.Persistence.Models.Common;
/// <summary> /// <summary>
/// Контейнер для поддержки постраничного просмотра таблиц /// Контейнер для поддержки постраничного просмотра таблиц

View File

@ -1,41 +0,0 @@
namespace DD.Persistence.Models;
public class DataSaubDto : ITimeSeriesAbstractDto
{
public DateTimeOffset Date { get; set; } = DateTimeOffset.UtcNow;
public int? Mode { get; set; }
public string? User { get; set; }
public double? WellDepth { get; set; }
public double? BitDepth { get; set; }
public double? BlockPosition { get; set; }
public double? BlockSpeed { get; set; }
public double? Pressure { get; set; }
public double? AxialLoad { get; set; }
public double? HookWeight { get; set; }
public double? RotorTorque { get; set; }
public double? RotorSpeed { get; set; }
public double? Flow { get; set; }
public short MseState { get; set; }
public int IdFeedRegulator { get; set; }
public double? Mse { get; set; }
public double? Pump0Flow { get; set; }
public double? Pump1Flow { get; set; }
public double? Pump2Flow { get; set; }
}

View File

@ -1,8 +1,17 @@
namespace DD.Persistence.Models; namespace DD.Persistence.Models;
/// <summary> /// <summary>
/// набор данных с отметкой времени /// Набор данных с отметкой времени
/// </summary> /// </summary>
/// <param name="Timestamp">отметка времени</param> public class TimestampedSetDto
/// <param name="Set">набор данных</param> {
public record TimestampedSetDto(DateTimeOffset Timestamp, IDictionary<string, object> Set); /// <summary>
/// Временная отметка
/// </summary>
public DateTimeOffset Timestamp { get; set; }
/// <summary>
/// Набор данных
/// </summary>
public required object[] Set { get; set; }
}

View File

@ -1,12 +1,12 @@
namespace DD.Persistence.Models; namespace DD.Persistence.ModelsAbstractions;
/// <summary> /// <summary>
/// Интерфейс, описывающий временные данные /// Интерфейс, описывающий временные данные
/// </summary> /// </summary>
public interface ITimeSeriesAbstractDto public interface ITimestampAbstractDto
{ {
/// <summary> /// <summary>
/// временная отметка /// временная отметка
/// </summary> /// </summary>
DateTimeOffset Date { get; set; } DateTimeOffset Timestamp { get; set; }
} }

View File

@ -1,4 +1,4 @@
namespace DD.Persistence.Models; namespace DD.Persistence.ModelsAbstractions;
public interface IWithSectionPart public interface IWithSectionPart
{ {
public double DepthStart { get; set; } public double DepthStart { get; set; }

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;
public interface IParameterRepository public interface IParameterRepository

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;

View File

@ -1,4 +1,4 @@
using DD.Persistence.Models; using DD.Persistence.Models.Common;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;

View File

@ -1,4 +1,4 @@
using DD.Persistence.Models; using DD.Persistence.Models.Common;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Requests; using DD.Persistence.Models.Requests;
namespace DD.Persistence.Repositories namespace DD.Persistence.Repositories

View File

@ -1,10 +1,11 @@
namespace DD.Persistence.Repositories; using DD.Persistence.Models;
namespace DD.Persistence.Repositories;
/// <summary> /// <summary>
/// Интерфейс по работе с прореженными данными /// Интерфейс по работе с прореженными данными
/// </summary> /// </summary>
public interface ITimeSeriesBaseRepository<TDto> public interface ITimeSeriesBaseRepository
where TDto : class, new()
{ {
/// <summary> /// <summary>
/// Получить список объектов с прореживанием /// Получить список объектов с прореживанием
@ -12,7 +13,7 @@ public interface ITimeSeriesBaseRepository<TDto>
/// <param name="dateBegin">дата начала</param> /// <param name="dateBegin">дата начала</param>
/// <param name="approxPointsCount"></param> /// <param name="approxPointsCount"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<TDto>> GetResampledData( Task<IEnumerable<TimestampedSetDto>> GetResampledData(
DateTimeOffset dateBegin, DateTimeOffset dateBegin,
double intervalSec = 600d, double intervalSec = 600d,
int approxPointsCount = 1024, int approxPointsCount = 1024,

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.ModelsAbstractions;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;
@ -6,8 +7,8 @@ namespace DD.Persistence.Repositories;
/// Интерфейс по работе с временными данными /// Интерфейс по работе с временными данными
/// </summary> /// </summary>
/// <typeparam name="TDto"></typeparam> /// <typeparam name="TDto"></typeparam>
public interface ITimeSeriesDataRepository<TDto> : ISyncRepository<TDto>, ITimeSeriesBaseRepository<TDto> public interface ITimestampedValuesRepository<TDto> : ISyncRepository<TDto>, ITimeSeriesBaseRepository
where TDto : class, ITimeSeriesAbstractDto, new() where TDto : class, ITimestampAbstractDto, new()
{ {
/// <summary> /// <summary>
/// Добавление записей /// Добавление записей
@ -15,5 +16,5 @@ public interface ITimeSeriesDataRepository<TDto> : ISyncRepository<TDto>, ITimeS
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token); Task<int> AddRange(IEnumerable<TimestampedSetDto> dtos, CancellationToken token);
} }

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
namespace DD.Persistence.Services.Interfaces; namespace DD.Persistence.Services.Interfaces;

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Configurations; using DD.Persistence.Models.Configurations;
using DD.Persistence.Models.Enumerations; using DD.Persistence.Models.Enumerations;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;