forked from ddrilling/AsbCloudServer
Merge branch 'dev' into SubsystemStat/AllActiveWell
This commit is contained in:
commit
f07b1535d2
@ -3,6 +3,9 @@
|
|||||||
namespace AsbCloudApp.Data.SAUB
|
namespace AsbCloudApp.Data.SAUB
|
||||||
{
|
{
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// телеметрия спин мастер
|
||||||
|
/// </summary>
|
||||||
public class TelemetryDataSpinDto : ITelemetryData
|
public class TelemetryDataSpinDto : ITelemetryData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -73,6 +76,16 @@ namespace AsbCloudApp.Data.SAUB
|
|||||||
/// Переменная этапа
|
/// Переменная этапа
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public short? State { get; set; }
|
public short? State { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Осцилляция включена
|
||||||
|
/// </summary>
|
||||||
|
public bool IsOscillating => State != 0 & State != 6 & State != 7;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Демпфирование включено
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDampening => State == 7 && (Mode & 2) > 0;
|
||||||
}
|
}
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сервис телеметрии
|
/// Сервис телеметрии
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -43,21 +43,12 @@ namespace AsbCloudApp.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
SimpleTimezoneDto GetTimezone(int idTelemetry);
|
SimpleTimezoneDto GetTimezone(int idTelemetry);
|
||||||
|
|
||||||
// TODO: вероятно лишнее
|
|
||||||
/// <summary>
|
|
||||||
/// Список передающих в данный момент телеметрий
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
IEnumerable<TelemetryDto> GetTransmittingTelemetries();
|
|
||||||
|
|
||||||
// TODO: вероятно лишнее
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить дату получения последних данных
|
/// Получить дату получения последних данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <param name="useUtc"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false);
|
DateTime GetLastTelemetryDate(int idTelemetry);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// получить idTelemetry по IdWell
|
/// получить idTelemetry по IdWell
|
||||||
@ -82,16 +73,6 @@ namespace AsbCloudApp.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token);
|
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>
|
||||||
/// Слить данные телеметрии в одну
|
/// Слить данные телеметрии в одну
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -100,13 +81,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> MergeAsync(int from, int to, CancellationToken token);
|
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
|
||||||
}
|
}
|
@ -32,17 +32,33 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
|||||||
|
|
||||||
public async Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token)
|
public async Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token)
|
||||||
{
|
{
|
||||||
|
var well = wellService.GetOrDefault(idWell);
|
||||||
|
if (well is null || well.Timezone is null)
|
||||||
|
return null;
|
||||||
var query = db.DailyReports.Where(r => r.IdWell == idWell);
|
var query = db.DailyReports.Where(r => r.IdWell == idWell);
|
||||||
|
|
||||||
|
DateTimeOffset ExtractDate(DateTime dateTime)
|
||||||
|
{
|
||||||
|
var dateTimeOffset = dateTime.ToUtcDateTimeOffset(well!.Timezone.Hours);
|
||||||
|
var date = new DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day, 0,0,0,TimeSpan.Zero);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
if (begin is not null)
|
if (begin is not null)
|
||||||
query = query.Where(d => d.StartDate >= begin.Value.Date);
|
{
|
||||||
|
var beginUTC = ExtractDate(begin.Value);
|
||||||
|
query = query.Where(d => d.StartDate >= beginUTC);
|
||||||
|
}
|
||||||
|
|
||||||
if (end is not null)
|
if (end is not null)
|
||||||
query = query.Where(d => d.StartDate <= end.Value.Date);
|
{
|
||||||
|
var endUTC = ExtractDate(end.Value);
|
||||||
|
query = query.Where(d => d.StartDate <= endUTC);
|
||||||
|
}
|
||||||
|
|
||||||
var entities = await query
|
var entities = await query
|
||||||
|
.OrderBy(e => e.StartDate)
|
||||||
.ToListAsync(token);
|
.ToListAsync(token);
|
||||||
|
|
||||||
return entities.Select(r => Convert(r));
|
return entities.Select(r => Convert(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,10 +141,6 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||||
var timezone = telemetryService.GetTimezone(telemetryId);
|
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)
|
foreach (var dto in dtos)
|
||||||
{
|
{
|
||||||
var entity = dto.Adapt<TelemetryMessage>();
|
var entity = dto.Adapt<TelemetryMessage>();
|
||||||
|
@ -14,13 +14,11 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
{
|
{
|
||||||
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>
|
public abstract class TelemetryDataBaseService<TDto, TModel> : ITelemetryDataService<TDto>
|
||||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
where TModel : class, AsbCloudDb.Model.ITelemetryData
|
where TModel : class, ITelemetryData
|
||||||
{
|
{
|
||||||
protected readonly IAsbCloudDbContext db;
|
protected readonly IAsbCloudDbContext db;
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
protected readonly CacheTable<Telemetry> cacheTelemetry;
|
|
||||||
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
|
||||||
protected readonly CacheTable<Well> cacheWells;
|
|
||||||
|
|
||||||
public TelemetryDataBaseService(
|
public TelemetryDataBaseService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
@ -29,9 +27,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
{
|
{
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
|
|
||||||
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((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)
|
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);
|
var entityMaxDate = entities.Max(e => e.DateTime);
|
||||||
telemetryService.SaveRequestDate(uid, entityMaxDate);
|
telemetryService.TelemetryTracker.SaveRequestDate(uid, entityMaxDate);
|
||||||
|
|
||||||
var dbset = db.Set<TModel>();
|
var dbset = db.Set<TModel>();
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
@ -91,11 +87,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
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 well = cacheWells.FirstOrDefault(w => w.Id == idWell);
|
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell) ?? -1;
|
||||||
if (well?.IdTelemetry is null)
|
if (idTelemetry == -1)
|
||||||
return default;
|
return null;
|
||||||
|
|
||||||
var idTelemetry = well?.IdTelemetry ?? default;
|
|
||||||
|
|
||||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
var timezone = telemetryService.GetTimezone(idTelemetry);
|
||||||
|
|
||||||
@ -103,7 +97,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
DateTimeOffset dateBeginUtc;
|
DateTimeOffset dateBeginUtc;
|
||||||
if (dateBegin == default)
|
if (dateBegin == default)
|
||||||
{
|
{
|
||||||
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry, true);
|
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry)
|
||||||
|
.ToUtcDateTimeOffset(timezone.Hours);
|
||||||
if (dateBeginUtc != default)
|
if (dateBeginUtc != default)
|
||||||
dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec);
|
dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec);
|
||||||
}
|
}
|
||||||
@ -153,24 +148,5 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
|
|
||||||
public abstract TModel Convert(TDto src, double timezoneOffset);
|
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 AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudInfrastructure.Services.Cache;
|
using AsbCloudInfrastructure.EfCache;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
@ -14,10 +14,12 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
namespace AsbCloudInfrastructure.Services.SAUB
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class TelemetryService : ITelemetryService
|
public class TelemetryService : ITelemetryService
|
||||||
{
|
{
|
||||||
private readonly CacheTable<Telemetry> cacheTelemetry;
|
private const string telemetryCacheTag = "telemetryCache";
|
||||||
private readonly CacheTable<Well> cacheWells;//TODO: use wellService instead of this
|
private static readonly TimeSpan telemetryCacheObsolescence = TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
private readonly ITelemetryTracker telemetryTracker;
|
private readonly ITelemetryTracker telemetryTracker;
|
||||||
private readonly ITimezoneService timezoneService;
|
private readonly ITimezoneService timezoneService;
|
||||||
@ -28,59 +30,42 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
public TelemetryService(
|
public TelemetryService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryTracker telemetryTracker,
|
ITelemetryTracker telemetryTracker,
|
||||||
ITimezoneService timezoneService,
|
ITimezoneService timezoneService)
|
||||||
CacheDb cacheDb)
|
|
||||||
{
|
{
|
||||||
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.db = db;
|
||||||
this.telemetryTracker = telemetryTracker;
|
this.telemetryTracker = telemetryTracker;
|
||||||
this.timezoneService = timezoneService;
|
this.timezoneService = timezoneService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<TelemetryDto> GetTransmittingTelemetries()
|
private Dictionary<int, Telemetry> GetTelemetryCache()
|
||||||
{
|
{
|
||||||
var telemetryDtos = new List<TelemetryDto>();
|
var cache = db.Telemetries
|
||||||
var activeTelemetriesUids = telemetryTracker.GetTransmittingTelemetriesUids();
|
.Include(t => t.Well)
|
||||||
if (!activeTelemetriesUids.Any())
|
.FromCacheDictionary(telemetryCacheTag, telemetryCacheObsolescence, t => t.Id);
|
||||||
return telemetryDtos;
|
return cache;
|
||||||
var telemetries = cacheTelemetry
|
|
||||||
.Where(t => activeTelemetriesUids.Contains(t.RemoteUid));
|
|
||||||
telemetryDtos = telemetries.Adapt<IEnumerable<TelemetryDto>>().ToList();
|
|
||||||
|
|
||||||
return telemetryDtos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveRequestDate(string uid, DateTimeOffset remoteDate) =>
|
private void DropTelemetryCache()
|
||||||
telemetryTracker.SaveRequestDate(uid, remoteDate);
|
|
||||||
|
|
||||||
public DateTime GetLastTelemetryDate(int idTelemetry, bool useUtc = false)
|
|
||||||
{
|
{
|
||||||
var lastTelemetryDate = DateTimeOffset.MinValue;
|
db.Telemetries.DropCacheDictionary(telemetryCacheTag);
|
||||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
}
|
||||||
|
|
||||||
|
public DateTime GetLastTelemetryDate(int idTelemetry)
|
||||||
|
{
|
||||||
|
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||||
|
|
||||||
if (telemetry is null)
|
if (telemetry is null)
|
||||||
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
||||||
|
|
||||||
var uid = telemetry.RemoteUid;
|
var uid = telemetry.RemoteUid;
|
||||||
var timzone = GetTimezone(idTelemetry);
|
var timzone = GetTimezone(idTelemetry);
|
||||||
|
var lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid);
|
||||||
lastTelemetryDate = telemetryTracker.GetLastTelemetryDateByUid(uid);
|
|
||||||
|
|
||||||
if (useUtc)
|
|
||||||
return lastTelemetryDate.UtcDateTime;
|
|
||||||
|
|
||||||
return lastTelemetryDate.ToRemoteDateTime(timzone.Hours);
|
return lastTelemetryDate.ToRemoteDateTime(timzone.Hours);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatesRangeDto GetDatesRange(int idTelemetry)
|
public DatesRangeDto GetDatesRange(int idTelemetry)
|
||||||
{
|
{
|
||||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||||
if (telemetry is null)
|
if (telemetry is null)
|
||||||
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
throw new Exception($"Telemetry id:{idTelemetry} does not exist");
|
||||||
|
|
||||||
@ -115,13 +100,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
TimezoneId = info.TimeZoneId
|
TimezoneId = info.TimeZoneId
|
||||||
};
|
};
|
||||||
|
|
||||||
await cacheTelemetry.UpsertAsync(telemetry, token)
|
db.Telemetries.Upsert(telemetry);
|
||||||
.ConfigureAwait(false);
|
await db.SaveChangesAsync(token);
|
||||||
|
DropTelemetryCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleTimezoneDto GetTimezone(int idTelemetry)
|
public SimpleTimezoneDto GetTimezone(int idTelemetry)
|
||||||
{
|
{
|
||||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry);
|
var telemetry = GetTelemetryCache().GetValueOrDefault(idTelemetry);
|
||||||
|
|
||||||
if (telemetry is null)
|
if (telemetry is null)
|
||||||
throw new Exception($"Telemetry id: {idTelemetry} does not exist.");
|
throw new Exception($"Telemetry id: {idTelemetry} does not exist.");
|
||||||
@ -137,58 +123,65 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
IsOverride = false,
|
IsOverride = false,
|
||||||
TimezoneId = telemetry.Info.TimeZoneId,
|
TimezoneId = telemetry.Info.TimeZoneId,
|
||||||
};
|
};
|
||||||
cacheTelemetry.Upsert(telemetry);
|
db.Telemetries.Upsert(telemetry);
|
||||||
|
db.SaveChanges();
|
||||||
|
DropTelemetryCache();
|
||||||
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (telemetry.Well?.Timezone is not null)
|
if (telemetry.Well?.Timezone is not null)
|
||||||
{
|
{
|
||||||
telemetry.TimeZone = telemetry.Well.Timezone;
|
telemetry.TimeZone = telemetry.Well.Timezone;
|
||||||
cacheTelemetry.Upsert(telemetry);
|
db.Telemetries.Upsert(telemetry);
|
||||||
|
db.SaveChanges();
|
||||||
|
DropTelemetryCache();
|
||||||
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
return telemetry.TimeZone.Adapt<SimpleTimezoneDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception($"Telemetry id: {idTelemetry} can't find timezone.");
|
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)
|
public int? GetIdTelemetryByIdWell(int idWell)
|
||||||
{
|
{
|
||||||
var well = cacheWells.FirstOrDefault(w => w.Id == idWell);
|
var telemetry = GetTelemetryCache()
|
||||||
return well?.IdTelemetry;
|
.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);
|
var telemetry = GetOrDefaultTelemetryByUid(uid);
|
||||||
if (tele is null)
|
return telemetry?.Well;
|
||||||
return null;
|
}
|
||||||
|
|
||||||
var well = cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
|
private Telemetry? GetOrDefaultTelemetryByUid(string uid)
|
||||||
return well;
|
{
|
||||||
|
var telemetry = GetTelemetryCache().FirstOrDefault(kv => kv.Value.RemoteUid == uid).Value;
|
||||||
|
return telemetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Telemetry GetOrCreateTelemetryByUid(string uid)
|
private Telemetry GetOrCreateTelemetryByUid(string uid)
|
||||||
=> cacheTelemetry.GetOrCreate(t => t.RemoteUid == uid, () => new Telemetry
|
{
|
||||||
|
var telemetry = GetOrDefaultTelemetryByUid(uid);
|
||||||
|
if (telemetry is null)
|
||||||
{
|
{
|
||||||
RemoteUid = uid,
|
var newTelemetry = new Telemetry
|
||||||
TimeZone = new SimpleTimezone
|
|
||||||
{
|
{
|
||||||
Hours = 5,
|
RemoteUid = uid,
|
||||||
IsOverride = false,
|
TimeZone = new SimpleTimezone
|
||||||
TimezoneId = "default",
|
{
|
||||||
}
|
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)
|
public async Task<int> MergeAsync(int from, int to, CancellationToken token)
|
||||||
{
|
{
|
||||||
@ -229,12 +222,15 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
|
|
||||||
stopwath.Stop();
|
stopwath.Stop();
|
||||||
Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows.");
|
Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows.");
|
||||||
|
DropTelemetryCache();
|
||||||
return affected;
|
return affected;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}");
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,4 +348,5 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return affected;
|
return affected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -229,11 +229,12 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
|||||||
{
|
{
|
||||||
static int? GetSubsytemId(short? mode, int? state)
|
static int? GetSubsytemId(short? mode, int? state)
|
||||||
{
|
{
|
||||||
|
// При изменении следующего кода сообщи в Vladimir.Sobolev@nedra.digital
|
||||||
if (state == 7 && (mode & 2) > 0)
|
if (state == 7 && (mode & 2) > 0)
|
||||||
return idSubsytemTorqueMaster;
|
return idSubsytemTorqueMaster;// демпфер
|
||||||
|
|
||||||
if (state != 0 & state != 6 & state != 7)
|
if (state != 0 & state != 6 & state != 7)
|
||||||
return idSubsytemSpinMaster;
|
return idSubsytemSpinMaster;// осцилляция
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.Middlware
|
||||||
|
{
|
||||||
|
public class UserConnectionsLimitMiddlwareTest
|
||||||
|
{
|
||||||
|
private readonly HttpClient httpClient;
|
||||||
|
|
||||||
|
public UserConnectionsLimitMiddlwareTest()
|
||||||
|
{
|
||||||
|
var host = Host.CreateDefaultBuilder(Array.Empty<string>())
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
host.Start();
|
||||||
|
httpClient = new ();
|
||||||
|
httpClient.DefaultRequestHeaders.Authorization = new("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjY1ODY2MjAsImV4cCI6MTY5ODE0NDIyMCwiaXNzIjoiYSIsImF1ZCI6ImEifQ.zqBdR4nYB87-Xyzv025waasN47i43c9FJ23RfzIvUsM");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Send_n_requests_and_get_blocked()
|
||||||
|
{
|
||||||
|
//Данные в тестовой БД
|
||||||
|
//select
|
||||||
|
// tw.id,
|
||||||
|
// t_stat.minDate,
|
||||||
|
// t_stat.maxDate
|
||||||
|
//from(
|
||||||
|
// select
|
||||||
|
|
||||||
|
// id_telemetry,
|
||||||
|
// count(1) as count,
|
||||||
|
// min("date") as minDate,
|
||||||
|
// max("date") as maxDate
|
||||||
|
|
||||||
|
// from t_telemetry_data_saub
|
||||||
|
|
||||||
|
// group by id_telemetry
|
||||||
|
//) as t_stat
|
||||||
|
//join t_well tw on tw.id_telemetry = t_stat.id_telemetry
|
||||||
|
//where tw is not null
|
||||||
|
//order by t_stat.count
|
||||||
|
//limit 10;
|
||||||
|
|
||||||
|
var wells = new []
|
||||||
|
{
|
||||||
|
(191, new DateTime(2022, 09, 01, 21, 43, 00, DateTimeKind.Utc), new DateTime(2022, 09, 04, 07, 37, 31, DateTimeKind.Utc)),
|
||||||
|
(3 , new DateTime(2021, 09, 16, 06, 13, 33, DateTimeKind.Utc), new DateTime(2021, 09, 20, 00, 29, 28, DateTimeKind.Utc)),
|
||||||
|
(199, new DateTime(2022, 09, 15, 11, 27, 18, DateTimeKind.Utc), new DateTime(2022, 09, 20, 14, 00, 23, DateTimeKind.Utc)),
|
||||||
|
(6 , new DateTime(2021, 09, 20, 00, 35, 03, DateTimeKind.Utc), new DateTime(2021, 09, 25, 06, 46, 17, DateTimeKind.Utc)),
|
||||||
|
(41 , new DateTime(2021, 12, 10, 00, 59, 52, DateTimeKind.Utc), new DateTime(2022, 10, 31, 15, 29, 24, DateTimeKind.Utc)),
|
||||||
|
(100, new DateTime(2022, 04, 24, 03, 04, 05, DateTimeKind.Utc), new DateTime(2022, 04, 29, 11, 38, 36, DateTimeKind.Utc)),
|
||||||
|
(154, new DateTime(2022, 03, 28, 10, 09, 14, DateTimeKind.Utc), new DateTime(2022, 06, 14, 15, 01, 12, DateTimeKind.Utc)),
|
||||||
|
(5 , new DateTime(2021, 09, 25, 08, 09, 37, DateTimeKind.Utc), new DateTime(2021, 10, 01, 14, 39, 51, DateTimeKind.Utc)),
|
||||||
|
(1 , new DateTime(2021, 09, 10, 01, 32, 42, DateTimeKind.Utc), new DateTime(2021, 09, 18, 00, 35, 22, DateTimeKind.Utc)),
|
||||||
|
(112, new DateTime(2022, 04, 20, 16, 47, 51, DateTimeKind.Utc), new DateTime(2022, 04, 28, 15, 04, 33, DateTimeKind.Utc)),
|
||||||
|
};
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
for (; i < 5; i++)
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var well = wells[i];
|
||||||
|
var url = MakeUrl(well.Item1, well.Item2, well.Item3);
|
||||||
|
var response = await httpClient.GetAsync(url);
|
||||||
|
//await response.Content.ReadAsStringAsync();
|
||||||
|
await Task.Delay(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
var well = wells[i];
|
||||||
|
var url = MakeUrl(well.Item1, well.Item2, well.Item3);
|
||||||
|
var response = await httpClient.GetAsync(url);
|
||||||
|
Assert.Equal(System.Net.HttpStatusCode.TooManyRequests, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string MakeUrl(int idWell, DateTime dateBegin, DateTime dateEnd)
|
||||||
|
{
|
||||||
|
var interval = (dateEnd - dateBegin).TotalSeconds;
|
||||||
|
var dateBeginString = dateBegin.ToString("yyyy-MM-ddZ");
|
||||||
|
var url = $"http://127.0.0.1:5000/api/TelemetryDataSaub/{idWell}?begin={dateBeginString}&intervalSec={interval}&approxPointsCount={interval}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ public class EventServiceTest
|
|||||||
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>();
|
||||||
var telemetryService = new TelemetryService(context, telemetryTracker.Object, imezoneServiceMock.Object, cacheDb);
|
var telemetryService = new TelemetryService(context, telemetryTracker.Object, imezoneServiceMock.Object);
|
||||||
service = new EventService(context, telemetryService);
|
service = new EventService(context, telemetryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
|||||||
|
|
||||||
context = TestHelpter.MakeTestContext();
|
context = TestHelpter.MakeTestContext();
|
||||||
cacheDb = new CacheDb();
|
cacheDb = new CacheDb();
|
||||||
telemetryService = new TelemetryService(context, telemetryTracker.Object, timezoneService.Object, cacheDb);
|
telemetryService = new TelemetryService(context, telemetryTracker.Object, timezoneService.Object);
|
||||||
|
|
||||||
var info = new TelemetryInfoDto
|
var info = new TelemetryInfoDto
|
||||||
{
|
{
|
||||||
|
@ -54,23 +54,6 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
return Ok();
|
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>
|
||||||
/// Принимает список новых сообщений от телеметрии
|
/// Принимает список новых сообщений от телеметрии
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,19 +2,23 @@
|
|||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Middlewares
|
namespace AsbCloudWebApi.Middlewares
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class PermissionsMiddlware
|
public class PermissionsMiddlware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate next;
|
private readonly RequestDelegate next;
|
||||||
|
private readonly UserConnectionsLimitMiddlware userConnectionsLimitMiddlware;
|
||||||
|
|
||||||
public PermissionsMiddlware(RequestDelegate next)
|
public PermissionsMiddlware(RequestDelegate next, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
this.next = next;
|
this.next = next;
|
||||||
|
userConnectionsLimitMiddlware = new UserConnectionsLimitMiddlware(next, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext context)
|
||||||
@ -30,11 +34,14 @@ namespace AsbCloudWebApi.Middlewares
|
|||||||
var idUser = context.User.GetUserId();
|
var idUser = context.User.GetUserId();
|
||||||
if (idUser is null)
|
if (idUser is null)
|
||||||
{
|
{
|
||||||
context.User = null;
|
|
||||||
await context.ForbidAsync();
|
await context.ForbidAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var controllerName = endpoint!.Metadata
|
||||||
|
.GetMetadata<Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor>()
|
||||||
|
?.ControllerName;
|
||||||
|
|
||||||
bool isAuthorized;
|
bool isAuthorized;
|
||||||
if (idUser == 1)
|
if (idUser == 1)
|
||||||
isAuthorized = true;
|
isAuthorized = true;
|
||||||
@ -43,40 +50,34 @@ namespace AsbCloudWebApi.Middlewares
|
|||||||
var permissionName = permission.Name;
|
var permissionName = permission.Name;
|
||||||
if (string.IsNullOrEmpty(permissionName))
|
if (string.IsNullOrEmpty(permissionName))
|
||||||
{
|
{
|
||||||
var controller = endpoint.Metadata
|
|
||||||
.GetMetadata<Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor>()
|
|
||||||
?.ControllerName;
|
|
||||||
|
|
||||||
var httpMethod = endpoint.Metadata
|
var httpMethod = endpoint.Metadata
|
||||||
.GetMetadata<Microsoft.AspNetCore.Routing.HttpMethodMetadata>()
|
.GetMetadata<Microsoft.AspNetCore.Routing.HttpMethodMetadata>()
|
||||||
.HttpMethods[0]
|
?.HttpMethods[0]
|
||||||
.ToLower();
|
.ToLower();
|
||||||
|
|
||||||
permissionName = httpMethod switch
|
permissionName = httpMethod switch
|
||||||
{
|
{
|
||||||
"get" or "delete" => $"{controller}.{httpMethod}",
|
"get" or "delete" => $"{controllerName}.{httpMethod}",
|
||||||
"post" or "put" or "patch" => $"{controller}.edit",
|
"post" or "put" or "patch" => $"{controllerName}.edit",
|
||||||
_ => throw new NotImplementedException(),
|
_ => throw new NotImplementedException(),
|
||||||
};
|
};
|
||||||
PermissionAttribute.Registered.Add(permissionName);
|
PermissionAttribute.Registered.Add(permissionName);
|
||||||
}
|
}
|
||||||
else if (permissionName.Contains("[controller]"))
|
else if (permissionName.Contains("[controller]"))
|
||||||
{
|
{
|
||||||
var controller = endpoint.Metadata
|
permissionName = permissionName.Replace("[controller]", controllerName);
|
||||||
.GetMetadata<Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor>()
|
|
||||||
?.ControllerName;
|
|
||||||
permissionName = permissionName.Replace("[controller]", controller);
|
|
||||||
PermissionAttribute.Registered.Add(permissionName);
|
PermissionAttribute.Registered.Add(permissionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var userService = context.RequestServices.GetRequiredService<IUserService>();
|
var userService = context.RequestServices.GetRequiredService<IUserService>();
|
||||||
isAuthorized = userService.HasPermission((int)idUser, permissionName);
|
isAuthorized = userService.HasPermission(idUser!.Value, permissionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAuthorized)
|
if (isAuthorized)
|
||||||
await next?.Invoke(context);
|
await userConnectionsLimitMiddlware.InvokeAsync(context, idUser!.Value, controllerName!);
|
||||||
else
|
else
|
||||||
await context.ForbidAsync();
|
await context.ForbidAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
71
AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs
Normal file
71
AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Middlewares
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// This is not real middleware it`s part of PermissionsMiddlware.
|
||||||
|
/// DO NOT register it in setup.cs as middleware.
|
||||||
|
/// </summary>
|
||||||
|
class UserConnectionsLimitMiddlware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate next;
|
||||||
|
private readonly int parallelRequestsToController;
|
||||||
|
private readonly byte[] body;
|
||||||
|
private readonly ConcurrentDictionary<int, ConcurrentDictionary<string, int>> stat = new ();
|
||||||
|
private readonly IEnumerable<string>? controllerNames;
|
||||||
|
|
||||||
|
public UserConnectionsLimitMiddlware(RequestDelegate next, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
this.next = next;
|
||||||
|
|
||||||
|
var parallelRequestsToController = configuration.GetSection("userLimits")?.GetValue<int>("parallelRequestsToController") ?? 5;
|
||||||
|
this.parallelRequestsToController = parallelRequestsToController > 0
|
||||||
|
? parallelRequestsToController
|
||||||
|
: 5;
|
||||||
|
|
||||||
|
controllerNames = configuration.GetSection("userLimits")?.GetValue<IEnumerable<string>>("controllerNames");
|
||||||
|
|
||||||
|
var bodyText = $"<html><head><title>Too Many Requests</title></head><body><h1>Too Many Requests</h1><p>I only allow {parallelRequestsToController} parallel requests per user. Try again soon.</p></body></html>";
|
||||||
|
body = System.Text.Encoding.UTF8.GetBytes(bodyText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InvokeAsync(HttpContext context, int idUser, string controllerName)
|
||||||
|
{
|
||||||
|
if(controllerNames?.Any(n => controllerName.StartsWith(n)) == false)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userStat = stat.GetOrAdd(idUser, idUser => new());
|
||||||
|
var count = userStat.AddOrUpdate(controllerName, 1, (key, value) => value + 1);
|
||||||
|
if(count < parallelRequestsToController)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
userStat[controllerName]--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Response.Clear();
|
||||||
|
context.Response.StatusCode = (int)System.Net.HttpStatusCode.TooManyRequests;
|
||||||
|
|
||||||
|
context.Response.Headers.RetryAfter = "1000";
|
||||||
|
context.Response.Headers.ContentType = "text/html";
|
||||||
|
await context.Response.BodyWriter.WriteAsync(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
@ -117,7 +117,7 @@ namespace AsbCloudWebApi
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseMiddleware<PermissionsMiddlware>();
|
app.UseMiddleware<PermissionsMiddlware>(Configuration);
|
||||||
app.UseMiddleware<SimplifyExceptionsMiddleware>();
|
app.UseMiddleware<SimplifyExceptionsMiddleware>();
|
||||||
app.UseMiddleware<RequerstTrackerMiddleware>();
|
app.UseMiddleware<RequerstTrackerMiddleware>();
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
"LocalConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True"
|
"LocalConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True"
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
|
"userLimits": {
|
||||||
|
"parallelRequestsToController": 5
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"smtpServer": "smtp.timeweb.ru",
|
"smtpServer": "smtp.timeweb.ru",
|
||||||
"sender": "bot@autodrilling.ru",
|
"sender": "bot@autodrilling.ru",
|
||||||
|
Loading…
Reference in New Issue
Block a user