TelemetryUserService добавлен microsoft cache

This commit is contained in:
ngfrolov 2022-11-18 12:58:53 +05:00
parent abb6a513fd
commit de6bbcfa72
7 changed files with 129 additions and 38 deletions

View File

@ -1,4 +1,6 @@
namespace AsbCloudApp.Data.SAUB using AsbCloudDb.Model;
namespace AsbCloudApp.Data.SAUB
{ {
/// <summary> /// <summary>
/// Пользователь панели оператора /// Пользователь панели оператора
@ -27,5 +29,26 @@
/// Уровень доступа /// Уровень доступа
/// </summary> /// </summary>
public int Level { get; set; } public int Level { get; set; }
/// <summary>
/// Собрать отображаемое имя пользователя
/// </summary>
/// <returns></returns>
public string MakeDisplayName()
{
if (!string.IsNullOrEmpty(Surname))
{
var s = Surname;
if (!string.IsNullOrEmpty(Name))
{
s += $"{Name[0]}.";
if (!string.IsNullOrEmpty(Patronymic))
s += $" {Patronymic[0]}.";
}
return s;
}
else
return $"User #{Id}";
}
} }
} }

View File

@ -1,15 +1,33 @@
using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.SAUB;
using System;
using System.Collections.Generic; 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>
public interface ITelemetryUserService public interface ITelemetryUserService
{ {
/// <summary>
/// get user by ids
/// </summary>
/// <param name="idTelemetry"></param>
/// <param name="idUser"></param>
/// <returns></returns>
TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser);
/// <summary>
/// get users by id telemetry and predicate
/// </summary>
/// <param name="idTelemetry"></param>
/// <param name="predicate"></param>
/// <returns></returns>
IEnumerable<TelemetryUserDto> GetUsers(int idTelemetry, Func<TelemetryUserDto, bool>? predicate = default);
/// <summary> /// <summary>
/// получает и сохраняет/обновляет список пользователей панели оператора /// получает и сохраняет/обновляет список пользователей панели оператора
/// </summary> /// </summary>
@ -19,4 +37,5 @@ namespace AsbCloudApp.Services
/// <returns></returns> /// <returns></returns>
Task UpsertAsync(string uid, IEnumerable<TelemetryUserDto> dtos, CancellationToken token = default); Task UpsertAsync(string uid, IEnumerable<TelemetryUserDto> dtos, CancellationToken token = default);
} }
#nullable disable
} }

View File

@ -19,18 +19,15 @@ namespace AsbCloudInfrastructure.Services.SAUB
{ {
protected readonly IAsbCloudDbContext db; protected readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
protected readonly CacheTable<TelemetryUser> cacheTelemetryUsers;
private readonly TelemetryDataCache<TDto> telemetryDataCache; private readonly TelemetryDataCache<TDto> telemetryDataCache;
public TelemetryDataBaseService( public TelemetryDataBaseService(
IAsbCloudDbContext db, IAsbCloudDbContext db,
ITelemetryService telemetryService, ITelemetryService telemetryService,
TelemetryDataCache<TDto> telemetryDataCache, TelemetryDataCache<TDto> telemetryDataCache)
CacheDb cacheDb)
{ {
this.db = db; this.db = db;
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
cacheTelemetryUsers = cacheDb.GetCachedTable<TelemetryUser>((AsbCloudDbContext)db);
this.telemetryDataCache = telemetryDataCache; this.telemetryDataCache = telemetryDataCache;
} }

View File

@ -1,32 +1,33 @@
using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using DocumentFormat.OpenXml.Drawing.Charts;
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.SAUB namespace AsbCloudInfrastructure.Services.SAUB
{ {
#nullable enable
public class TelemetryDataSaubService : TelemetryDataBaseService<TelemetryDataSaubDto, TelemetryDataSaub> public class TelemetryDataSaubService : TelemetryDataBaseService<TelemetryDataSaubDto, TelemetryDataSaub>
{ {
private readonly ITelemetryUserService telemetryUserService;
public TelemetryDataSaubService( public TelemetryDataSaubService(
IAsbCloudDbContext db, IAsbCloudDbContext db,
ITelemetryService telemetryService, ITelemetryService telemetryService,
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache, ITelemetryUserService telemetryUserService,
CacheDb cacheDb) TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
: base(db, telemetryService, telemetryDataCache, cacheDb) : base(db, telemetryService, telemetryDataCache)
{ } {
this.telemetryUserService = telemetryUserService;
}
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset) public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
{ {
var entity = src.Adapt<TelemetryDataSaub>(); var entity = src.Adapt<TelemetryDataSaub>();
var telemetryUser = cacheTelemetryUsers? var telemetryUser = telemetryUserService
.FirstOrDefault(u => u.IdTelemetry == src.IdTelemetry && (u.Name == src.User || u.Surname == src.User)); .GetUsers(src.IdTelemetry, u => (u.Name == src.User || u.Surname == src.User))
entity.IdUser = telemetryUser?.IdUser; .FirstOrDefault();
entity.IdUser = telemetryUser?.Id;
entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset); entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset);
return entity; return entity;
} }
@ -34,11 +35,11 @@ namespace AsbCloudInfrastructure.Services.SAUB
public override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset) public override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset)
{ {
var dto = src.Adapt<TelemetryDataSaubDto>(); var dto = src.Adapt<TelemetryDataSaubDto>();
var telemetryUser = cacheTelemetryUsers? var telemetryUser = telemetryUserService.GetOrDefault(src.IdTelemetry, src.IdUser??int.MinValue);
.FirstOrDefault(u => u.IdTelemetry == src.IdTelemetry && u.IdUser == src.IdUser);
dto.User = telemetryUser?.MakeDisplayName(); dto.User = telemetryUser?.MakeDisplayName();
dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset);
return dto; return dto;
} }
} }
#nullable disable
} }

View File

@ -1,10 +1,7 @@
using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using Mapster; using Mapster;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.SAUB namespace AsbCloudInfrastructure.Services.SAUB
{ {
@ -13,9 +10,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
public TelemetryDataSpinService( public TelemetryDataSpinService(
IAsbCloudDbContext db, IAsbCloudDbContext db,
ITelemetryService telemetryService, ITelemetryService telemetryService,
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache, TelemetryDataCache<TelemetryDataSpinDto> telemetryDataCache)
CacheDb cacheDb) : base(db, telemetryService, telemetryDataCache)
: base(db, telemetryService, telemetryDataCache, cacheDb)
{ } { }
public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset) public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)

View File

@ -3,7 +3,9 @@ using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb; using AsbCloudDb;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.EfCache; using Mapster;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -11,15 +13,49 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.SAUB namespace AsbCloudInfrastructure.Services.SAUB
{ {
#nullable enable
public class TelemetryUserService : ITelemetryUserService public class TelemetryUserService : ITelemetryUserService
{ {
private const string CacheTag = "TelemetryUserCacheTag";
private readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5);
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
private readonly IMemoryCache memoryCache;
public TelemetryUserService(IAsbCloudDbContext db, ITelemetryService telemetryService) public TelemetryUserService(IAsbCloudDbContext db,
ITelemetryService telemetryService,
IMemoryCache memoryCache)
{ {
this.db = db; this.db = db;
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
this.memoryCache = memoryCache;
}
public TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser)
{
var entity = GetCache()
.FirstOrDefault(u => u.IdTelemetry == idTelemetry && u.IdUser == idUser);
if(entity is null)
return null;
return Convert(entity);
}
public IEnumerable<TelemetryUserDto> GetUsers(int idTelemetry, Func<TelemetryUserDto, bool>? predicate = null)
{
var entities = GetCache()
.Where(u => u.IdTelemetry == idTelemetry);
foreach (var entity in entities)
{
var dto = Convert(entity);
if(predicate?.Invoke(dto)??true)
yield return dto;
}
yield break;
} }
public async Task UpsertAsync(string uid, IEnumerable<TelemetryUserDto> dtos, CancellationToken token = default) public async Task UpsertAsync(string uid, IEnumerable<TelemetryUserDto> dtos, CancellationToken token = default)
@ -29,17 +65,37 @@ namespace AsbCloudInfrastructure.Services.SAUB
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid); var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
var entities = dtos.Distinct(new TelemetryUserDtoComparer()).Select(dto => new TelemetryUser var entities = dtos.Distinct(new TelemetryUserDtoComparer()).Select(dto => {
{ var entity = dto.Adapt<TelemetryUser>();
IdUser = dto.Id, entity.IdUser = dto.Id;
IdTelemetry = telemetryId, entity.IdTelemetry = telemetryId;
Level = dto.Level, return entity;
Name = dto.Name,
Patronymic = dto.Patronymic,
Surname = dto.Surname,
}); });
var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryUsers, entities, token); var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryUsers, entities, token);
db.TelemetryUsers.DropCache(); DropCache();
}
private IEnumerable<TelemetryUser> GetCache()
{
var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => {
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration = CacheOlescence;
var entities = db.Set<TelemetryUser>().ToArray();
return entities;
});
return cache;
}
private void DropCache()
=> memoryCache.Remove(CacheTag);
private static TelemetryUserDto Convert(TelemetryUser entity)
{
var dto = entity.Adapt<TelemetryUserDto>();
dto.Id = entity.IdUser;
return dto;
} }
} }
#nullable disable
} }

View File

@ -1,5 +1,4 @@
using AsbCloudApp.Data; using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR; using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;