forked from ddrilling/AsbCloudServer
Merge branch 'refactor_telemetryService' into dev
This commit is contained in:
commit
3d644753ed
@ -1,12 +1,12 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Сервис телеметрии
|
||||
/// </summary>
|
||||
@ -43,21 +43,12 @@ namespace AsbCloudApp.Services
|
||||
/// <returns></returns>
|
||||
SimpleTimezoneDto GetTimezone(int idTelemetry);
|
||||
|
||||
// TODO: вероятно лишнее
|
||||
/// <summary>
|
||||
/// Список передающих в данный момент телеметрий
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<TelemetryDto> GetTransmittingTelemetries();
|
||||
|
||||
// TODO: вероятно лишнее
|
||||
/// <summary>
|
||||
/// Получить дату получения последних данных
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <param name="useUtc"></param>
|
||||
/// <returns></returns>
|
||||
DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false);
|
||||
DateTime GetLastTelemetryDate(int idTelemetry);
|
||||
|
||||
/// <summary>
|
||||
/// получить idTelemetry по IdWell
|
||||
@ -82,16 +73,6 @@ namespace AsbCloudApp.Services
|
||||
/// <returns></returns>
|
||||
Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token);
|
||||
|
||||
// TODO: вероятно лишнее
|
||||
/// <summary>
|
||||
/// обновить данные о временной зоне (используется панелью)
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="telemetryTimeZoneInfo"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto telemetryTimeZoneInfo, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Слить данные телеметрии в одну
|
||||
/// </summary>
|
||||
@ -100,13 +81,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> MergeAsync(int from, int to, CancellationToken token);
|
||||
|
||||
// TODO: вероятно лишнее
|
||||
/// <summary>
|
||||
/// сохранить данные о запросе
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="remoteDate"></param>
|
||||
void SaveRequestDate(string uid, DateTimeOffset remoteDate);
|
||||
}
|
||||
|
||||
#nullable disable
|
||||
}
|
@ -141,10 +141,6 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||
var timezone = telemetryService.GetTimezone(telemetryId);
|
||||
|
||||
var maxDateDto = dtos.Max(m => m.Date);
|
||||
var maxDateUtc = maxDateDto.ToUtcDateTimeOffset(timezone.Hours);
|
||||
telemetryService.SaveRequestDate(uid, maxDateDto);
|
||||
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var entity = dto.Adapt<TelemetryMessage>();
|
||||
|
@ -14,13 +14,11 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>
|
||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||
where TModel : class, AsbCloudDb.Model.ITelemetryData
|
||||
where TModel : class, ITelemetryData
|
||||
{
|
||||
protected readonly IAsbCloudDbContext db;
|
||||
private readonly ITelemetryService telemetryService;
|
||||
protected readonly CacheTable<Telemetry> cacheTelemetry;
|
||||
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
||||
protected readonly CacheTable<Well> cacheWells;
|
||||
|
||||
public TelemetryDataBaseService(
|
||||
IAsbCloudDbContext db,
|
||||
@ -29,9 +27,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
this.db = db;
|
||||
this.telemetryService = telemetryService;
|
||||
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
|
||||
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((AsbCloudDbContext)db);
|
||||
cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db);
|
||||
}
|
||||
|
||||
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
||||
@ -65,7 +61,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
});
|
||||
|
||||
var entityMaxDate = entities.Max(e => e.DateTime);
|
||||
telemetryService.SaveRequestDate(uid, entityMaxDate);
|
||||
telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate);
|
||||
|
||||
var dbset = db.Set<TModel>();
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
@ -91,11 +87,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
DateTime dateBegin = default, double intervalSec = 600d,
|
||||
int approxPointsCount = 1024, CancellationToken token = default)
|
||||
{
|
||||
var well = cacheWells.FirstOrDefault(w => w.Id == idWell);
|
||||
if (well?.IdTelemetry is null)
|
||||
return default;
|
||||
|
||||
var idTelemetry = well?.IdTelemetry ?? default;
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell) ?? -1;
|
||||
if (idTelemetry == -1)
|
||||
return null;
|
||||
|
||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
||||
|
||||
@ -103,7 +97,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
DateTimeOffset dateBeginUtc;
|
||||
if (dateBegin == default)
|
||||
{
|
||||
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry, true);
|
||||
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry)
|
||||
.ToUtcDateTimeOffset(timezone.Hours);
|
||||
if (dateBeginUtc != default)
|
||||
dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec);
|
||||
}
|
||||
@ -153,24 +148,5 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
|
||||
public abstract TModel Convert(TDto src, double timezoneOffset);
|
||||
|
||||
private static double AssumeTimezoneOffset(DateTime nearToCurrentDate)
|
||||
{
|
||||
var offset = 5d;
|
||||
if (nearToCurrentDate.Kind == DateTimeKind.Unspecified)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var minutes = 60 * (now.Hour - nearToCurrentDate.Hour) + now.Minute - nearToCurrentDate.Minute;
|
||||
var minutesPositive = (1440_0000 + minutes) % 1440; //60*24
|
||||
var halfsHours = Math.Round(1d * minutesPositive / 30d); // quarters are ignored
|
||||
var hours = halfsHours / 2;
|
||||
offset = hours < 12 ? hours : 24 - hours;
|
||||
}
|
||||
if (nearToCurrentDate.Kind == DateTimeKind.Local)
|
||||
offset = TimeZoneInfo.Local.BaseUtcOffset.TotalHours;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ using AsbCloudApp.Data.SAUB;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.Cache;
|
||||
using AsbCloudInfrastructure.EfCache;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
@ -14,10 +14,12 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.SAUB
|
||||
{
|
||||
#nullable enable
|
||||
public class TelemetryService : ITelemetryService
|
||||
{
|
||||
private readonly CacheTable<Telemetry> cacheTelemetry;
|
||||
private readonly CacheTable<Well> cacheWells;//TODO: use wellService instead of this
|
||||
private const string telemetryCacheTag = "telemetryCache";
|
||||
private static readonly TimeSpan telemetryCacheObsolescence = TimeSpan.FromMinutes(5);
|
||||
|
||||
private readonly IAsbCloudDbContext db;
|
||||
private readonly ITelemetryTracker telemetryTracker;
|
||||
private readonly ITimezoneService timezoneService;
|
||||
@ -28,59 +30,42 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
public TelemetryService(
|
||||
IAsbCloudDbContext db,
|
||||
ITelemetryTracker telemetryTracker,
|
||||
ITimezoneService timezoneService,
|
||||
CacheDb cacheDb)
|
||||
ITimezoneService timezoneService)
|
||||
{
|
||||
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
|
||||
cacheWells = cacheDb.GetCachedTable<Well>(
|
||||
(AsbCloudDbContext)db,
|
||||
$"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}",
|
||||
nameof(Well.Telemetry),
|
||||
$"{nameof(Well.RelationCompaniesWells)}.{nameof(RelationCompanyWell.Company)}",
|
||||
nameof(Well.WellType));
|
||||
this.db = db;
|
||||
this.telemetryTracker = telemetryTracker;
|
||||
this.timezoneService = timezoneService;
|
||||
}
|
||||
|
||||
public IEnumerable<TelemetryDto> GetTransmittingTelemetries()
|
||||
private Dictionary<int, Telemetry> GetTelemetryCache()
|
||||
{
|
||||
var telemetryDtos = new List<TelemetryDto>();
|
||||
var activeTelemetriesUids = telemetryTracker.GetTransmittingTelemetriesUids();
|
||||
if (!activeTelemetriesUids.Any())
|
||||
return telemetryDtos;
|
||||
var telemetries = cacheTelemetry
|
||||
.Where(t => activeTelemetriesUids.Contains(t.RemoteUid));
|
||||
telemetryDtos = telemetries.Adapt<IEnumerable<TelemetryDto>>().ToList();
|
||||
|
||||
return telemetryDtos;
|
||||
var cache = db.Telemetries
|
||||
.Include(t => t.Well)
|
||||
.FromCacheDictionary(telemetryCacheTag, telemetryCacheObsolescence, t => t.Id);
|
||||
return cache;
|
||||
}
|
||||
|
||||
public void SaveRequestDate(string uid, DateTimeOffset remoteDate) =>
|
||||
telemetryTracker.SaveRequestDate(uid, remoteDate);
|
||||
|
||||
public DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false)
|
||||
private void DropTelemetryCache()
|
||||
{
|
||||
var lastTelemetryDate = DateTimeOffset.MinValue;
|
||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
||||
db.Telemetries.DropCacheDictionary(telemetryCacheTag);
|
||||
}
|
||||
|
||||
public DateTime GetLastTelemetryDate(int idTelemetry)
|
||||
{
|
||||
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||
|
||||
if (telemetry is null)
|
||||
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
||||
|
||||
var uid = telemetry.RemoteUid;
|
||||
var timzone = GetTimezone(idTelemetry);
|
||||
|
||||
lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid);
|
||||
|
||||
if (useUtc)
|
||||
return lastTelemetryDate.UtcDateTime;
|
||||
|
||||
var lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid);
|
||||
return lastTelemetryDate.ToRemoteDateTime(timzone.Hours);
|
||||
}
|
||||
|
||||
public DatesRangeDto GetDatesRange(int idTelemetry)
|
||||
{
|
||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
||||
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||
if (telemetry is null)
|
||||
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
||||
|
||||
@ -115,13 +100,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
TimezoneId = info.TimeZoneId
|
||||
};
|
||||
|
||||
await cacheTelemetry.UpsertAsync(telemetry, token)
|
||||
.ConfigureAwait(false);
|
||||
db.Telemetries.Upsert(telemetry);
|
||||
await db.SaveChangesAsync(token);
|
||||
DropTelemetryCache();
|
||||
}
|
||||
|
||||
public SimpleTimezoneDto GetTimezone(int idTelemetry)
|
||||
{
|
||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
||||
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||
|
||||
if (telemetry is null)
|
||||
throw new Exception($"Telemetry id: {idTelemetry} does not exist.");
|
||||
@ -137,58 +123,65 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
IsOverride = false,
|
||||
TimezoneId = telemetry.Info.TimeZoneId,
|
||||
};
|
||||
cacheTelemetry.Upsert(telemetry);
|
||||
db.Telemetries.Upsert(telemetry);
|
||||
db.SaveChanges();
|
||||
DropTelemetryCache();
|
||||
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
||||
}
|
||||
|
||||
if (telemetry.Well?.Timezone is not null)
|
||||
{
|
||||
telemetry.TimeZone = telemetry.Well.Timezone;
|
||||
cacheTelemetry.Upsert(telemetry);
|
||||
db.Telemetries.Upsert(telemetry);
|
||||
db.SaveChanges();
|
||||
DropTelemetryCache();
|
||||
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
||||
}
|
||||
|
||||
throw new Exception($"Telemetry id: {idTelemetry} can't find timezone.");
|
||||
}
|
||||
|
||||
public async Task UpdateTimezoneAsync(string uid, SimpleTimezoneDto timeone,
|
||||
CancellationToken token)
|
||||
{
|
||||
var telemetry = GetOrCreateTelemetryByUid(uid);
|
||||
var newTelemetryTimeZone = timeone.Adapt<SimpleTimezone>();
|
||||
if (newTelemetryTimeZone?.Equals(telemetry.TimeZone) == true)
|
||||
return;
|
||||
await cacheTelemetry.UpsertAsync(telemetry, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public int? GetIdTelemetryByIdWell(int idWell)
|
||||
{
|
||||
var well = cacheWells.FirstOrDefault(w => w.Id == idWell);
|
||||
return well?.IdTelemetry;
|
||||
var telemetry = GetTelemetryCache()
|
||||
.FirstOrDefault(t => t.Value.Well?.Id == idWell).Value;
|
||||
return telemetry?.Id;
|
||||
}
|
||||
|
||||
private Well GetWellByTelemetryUid(string uid)
|
||||
private Well? GetWellByTelemetryUid(string uid)
|
||||
{
|
||||
var tele = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid);
|
||||
if (tele is null)
|
||||
return null;
|
||||
var telemetry = GetOrDefaultTelemetryByUid(uid);
|
||||
return telemetry?.Well;
|
||||
}
|
||||
|
||||
var well = cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
|
||||
return well;
|
||||
private Telemetry? GetOrDefaultTelemetryByUid(string uid)
|
||||
{
|
||||
var telemetry = GetTelemetryCache().FirstOrDefault(kv => kv.Value.RemoteUid == uid).Value;
|
||||
return telemetry;
|
||||
}
|
||||
|
||||
private Telemetry GetOrCreateTelemetryByUid(string uid)
|
||||
=> cacheTelemetry.GetOrCreate(t => t.RemoteUid == uid, () => new Telemetry
|
||||
{
|
||||
var telemetry = GetOrDefaultTelemetryByUid(uid);
|
||||
if (telemetry is null)
|
||||
{
|
||||
RemoteUid = uid,
|
||||
TimeZone = new SimpleTimezone
|
||||
var newTelemetry = new Telemetry
|
||||
{
|
||||
Hours = 5,
|
||||
IsOverride = false,
|
||||
TimezoneId = "default",
|
||||
}
|
||||
});
|
||||
RemoteUid = uid,
|
||||
TimeZone = new SimpleTimezone
|
||||
{
|
||||
Hours = 5,
|
||||
IsOverride = false,
|
||||
TimezoneId = "default",
|
||||
}
|
||||
};
|
||||
var entry = db.Telemetries.Add(newTelemetry);
|
||||
db.SaveChanges();
|
||||
DropTelemetryCache();
|
||||
return entry.Entity;
|
||||
}
|
||||
return telemetry;
|
||||
}
|
||||
|
||||
public async Task<int> MergeAsync(int from, int to, CancellationToken token)
|
||||
{
|
||||
@ -229,12 +222,15 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
|
||||
stopwath.Stop();
|
||||
Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows.");
|
||||
DropTelemetryCache();
|
||||
return affected;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}");
|
||||
await transaction.RollbackAsync(token).ConfigureAwait(false);
|
||||
#pragma warning disable CA2016 // Перенаправьте параметр "CancellationToken" в методы
|
||||
await transaction.RollbackAsync();
|
||||
#pragma warning restore CA2016 // Перенаправьте параметр "CancellationToken" в методы
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -352,4 +348,5 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
return affected;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
||||
|
@ -54,23 +54,6 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет часовой пояс скважины
|
||||
/// </summary>
|
||||
/// <param name="uid">Уникальный идентификатор отправителя</param>
|
||||
/// <param name="timezone">Информация о часовом поясе</param>
|
||||
/// <param name="token">Токен отмены задачи</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("{uid}/timezone")]
|
||||
public async Task<IActionResult> UpdateTimeZoneAsync(string uid, SimpleTimezoneDto timezone,
|
||||
CancellationToken token)
|
||||
{
|
||||
await telemetryService.UpdateTimezoneAsync(uid, timezone, token)
|
||||
.ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Принимает список новых сообщений от телеметрии
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user