From 539d04d3cfd0c8d377ccc54da5994d10d4b2fbf0 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 21 Feb 2023 18:01:03 +0500 Subject: [PATCH] remove EfCacheExtensions, replace by IMemoryCache --- .../EfCache/EfCacheExtensions.cs | 421 ------------------ .../MemoryCacheExtentions.cs | 105 ++++- .../Repository/UserRoleRepository.cs | 34 +- .../Services/MeasureService.cs | 21 +- .../Services/SAUB/EventService.cs | 8 +- .../Services/SAUB/MessageService.cs | 10 +- .../Services/SAUB/TelemetryService.cs | 20 +- .../Services/SAUB/TelemetryTracker.cs | 2 +- .../Services/WellService.cs | 19 +- 9 files changed, 157 insertions(+), 483 deletions(-) delete mode 100644 AsbCloudInfrastructure/EfCache/EfCacheExtensions.cs diff --git a/AsbCloudInfrastructure/EfCache/EfCacheExtensions.cs b/AsbCloudInfrastructure/EfCache/EfCacheExtensions.cs deleted file mode 100644 index c618534d..00000000 --- a/AsbCloudInfrastructure/EfCache/EfCacheExtensions.cs +++ /dev/null @@ -1,421 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.EfCache -{ -#nullable enable - /// - /// Кеширование запросов EF.
- /// Кеш не отслеживается ChangeTracker. - ///
- public static class EfCacheExtensions - { - private static readonly Dictionary caches = new(16); - private static readonly TimeSpan semaphoreTimeout = TimeSpan.FromSeconds(25); - private static readonly SemaphoreSlim semaphore = new(1); - private static readonly TimeSpan minCacheTime = TimeSpan.FromSeconds(2); - private static readonly TimeSpan defaultObsolescence = TimeSpan.FromMinutes(4); - - private class YieldConvertedData : IEnumerable - { - private struct ConvertedData - { - public TEntity? Entity; - public TModel? Model; - } - - ConvertedData[] data; - public Func convert { get; } - - public YieldConvertedData(TEntity[] entities, Func convert) - { - data = (entities.Select(x => new ConvertedData { - Entity = x, - Model = default })) - .ToArray(); - this.convert = convert; - } - - class YieldConvertedDataEnumerator : IEnumerator - { - private readonly ConvertedData[] data; - private readonly Func convert; - private int position = -1; - - public YieldConvertedDataEnumerator(ConvertedData[] data, Func convert) - { - this.data = data; - this.convert = convert; - } - - public TModel Current - { - get - { - if (data[position].Entity is TEntity entity) - { - var dto = convert(entity); - data[position].Entity = default; - data[position].Model = dto; - } - return data[position].Model!; - } - } - - object IEnumerator.Current => Current!; - - public void Dispose() - { - } - - public bool MoveNext() - { - position++; - return (position < data.Length); - } - - public void Reset() - { - position = -1; - } - } - - public IEnumerator GetEnumerator() - { - var result = new YieldConvertedDataEnumerator(data, convert); - return result; - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - private class CacheItem - { - internal IEnumerable? Data; - internal DateTime DateObsolete; - internal DateTime DateObsoleteTotal; - internal readonly SemaphoreSlim semaphore = new(1); - - internal IEnumerable GetData() - { - if (Data is IEnumerable typedData) - return typedData; - throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique."); - } - - internal IEnumerable GetData(Func convert, int attempt = 1) - { - if (Data is IEnumerable typedData) - return typedData; - if (Data is IEnumerable typedEntityData) - { - if (semaphore.Wait(0)) - { - try - { - var convertedData = new YieldConvertedData(typedEntityData.ToArray(), convert); - Data = convertedData; - return convertedData; - } - finally - { - semaphore.Release(); - } - } - else - { - if (semaphore.Wait(semaphoreTimeout)) - { - semaphore.Release(); - } - else - { - semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetData. Can't wait too long while converting cache data"); - } - } - } - if (attempt > 0) - return GetData(convert, --attempt); - throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique."); - } - } - - private static CacheItem GetOrAddCache(string tag, Func valueFactory, TimeSpan obsolete) - { - CacheItem cache; - while (!caches.ContainsKey(tag)) - { - if (semaphore.Wait(0)) - { - try - { - if (!caches.ContainsKey(tag)) - { - cache = new CacheItem(); - caches.Add(tag, cache); - } - } - finally - { - semaphore.Release(); - } - break; - } - else - { - if (semaphore.Wait(semaphoreTimeout)) - { - semaphore.Release(); - } - else - { - semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - - cache = caches[tag]; - - if (cache.DateObsolete < DateTime.Now) - { - if (cache.semaphore.Wait(0)) - { - try - { - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = valueFactory(); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - } - finally - { - cache.semaphore.Release(); - } - } - else if (cache.DateObsoleteTotal < DateTime.Now) - { - if (cache.semaphore.Wait(semaphoreTimeout)) - { - cache.semaphore.Release(); - } - else - { - cache.semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - return cache; - } - - private static async Task GetOrAddCacheAsync(string tag, Func> valueFactoryAsync, TimeSpan obsolete, CancellationToken token) - { - CacheItem cache; - while (!caches.ContainsKey(tag)) - { - if (semaphore.Wait(0)) - { - try - { - if (!caches.ContainsKey(tag)) - { - cache = new CacheItem(); - caches.Add(tag, cache); - } - } - finally - { - semaphore.Release(); - } - break; - } - else - { - if (await semaphore.WaitAsync(semaphoreTimeout, token)) - { - semaphore.Release(); - } - else - { - semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - - cache = caches[tag]; - - if (cache.DateObsolete < DateTime.Now) - { - if (cache.semaphore.Wait(0)) - { - try - { - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = await valueFactoryAsync(token); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - } - finally - { - cache.semaphore.Release(); - } - } - else if (cache.DateObsoleteTotal < DateTime.Now) - { - if (await cache.semaphore.WaitAsync(semaphoreTimeout, token)) - { - cache.semaphore.Release(); - } - else - { - cache.semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting updated cache"); - } - } - } - return cache; - } - - /// - /// Кешировать запрос в List<>. Кеш tag = typeof(TEntity).Name - /// - /// - /// - /// - public static IEnumerable FromCache(this IQueryable query) - where TEntity : class - { - var tag = typeof(TEntity).Name; - return FromCache(query, tag, defaultObsolescence); - } - - /// - /// Кешировать запрос в List<>. - /// - /// - /// - /// Метка кеша - /// Период устаревания данных - /// - public static IEnumerable FromCache(this IQueryable query, string tag, TimeSpan obsolescence) - where TEntity : class - { - object[] factory() => query.AsNoTracking().ToArray(); - var cache = GetOrAddCache(tag, factory, obsolescence); - return cache.GetData(); - } - - /// - /// Кешировать запрос с последующим преобразованием из в .
- /// Преобразование выполняется после получения из БД, результат кешируется в List<>. - ///
- /// - /// - /// - /// Метка кеша - /// Период устаревания данных - /// Преобразование данных БД в DTO - /// - public static IEnumerable FromCache(this IQueryable query, string tag, TimeSpan obsolescence, Func convert) - where TEntity : class - { - object[] factory() => query.AsNoTracking().ToArray(); - var cache = GetOrAddCache(tag, factory, obsolescence); - return cache.GetData(convert); - } - - public static Task> FromCacheAsync(this IQueryable query, CancellationToken token) - where TEntity : class - { - var tag = typeof(TEntity).Name; - return FromCacheAsync(query, tag, defaultObsolescence, token); - } - - /// - /// Асинхронно кешировать запрос в List<>.
- ///
- /// - /// - /// Метка кеша - /// Период устаревания данных - /// - /// - public static async Task> FromCacheAsync(this IQueryable query, string tag, TimeSpan obsolescence, CancellationToken token) - where TEntity : class - { - async Task factory(CancellationToken token) - => await query.AsNoTracking().ToArrayAsync(token); - var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token); - return cache.GetData(); - } - - /// - /// Асинхронно кешировать запрос с последующим преобразованием из в .
- /// Преобразование выполняется после получения из БД, результат кешируется в List<>. - ///
- /// - /// - /// - /// Метка кеша - /// Период устаревания данных - /// Преобразование данных БД в DTO - /// - /// - public static async Task> FromCacheAsync(this IQueryable query, string tag, TimeSpan obsolescence, Func convert, CancellationToken token) - where TEntity : class - { - async Task factory(CancellationToken token) - => await query.AsNoTracking().ToArrayAsync(token); - var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token); - return cache.GetData(convert); - } - - /// - /// drops cache with tag = typeof(T).Name - /// - /// - /// - public static void DropCache(this IQueryable query) - { - var tag = typeof(T).Name; - DropCache(query, tag); - } - - /// - /// Очистить кеш - /// - /// - /// - /// Метка кеша - public static void DropCache(this IQueryable query, string tag) - { - caches.Remove(tag, out var _); - } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/MemoryCacheExtentions.cs b/AsbCloudInfrastructure/MemoryCacheExtentions.cs index 28e791e9..f227781f 100644 --- a/AsbCloudInfrastructure/MemoryCacheExtentions.cs +++ b/AsbCloudInfrastructure/MemoryCacheExtentions.cs @@ -9,36 +9,121 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure { +#nullable enable public static class MemoryCacheExtentions { private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); + /// + /// Создать кеш на основе асинхронного запроса к БД. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + /// + public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, IQueryable query, CancellationToken token) + where T : class + { + var getter = async (CancellationToken token) => + { + var entities = await query + .ToArrayAsync(token); + return entities.AsEnumerable(); + }; + return memoryCache.GetOrCreateBasicAsync(getter, token); + } + + [Obsolete(message: "use GetOrCreateBasicAsync(this IMemoryCache memoryCache, IQueryable query, CancellationToken token)")] public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, IAsbCloudDbContext dbContext, CancellationToken token) where T : class { - var cacheTag = typeof(T).FullName; - var cache = memoryCache.GetOrCreateAsync(cacheTag, async (cacheEntry) => { + var getter = async (CancellationToken token) => + { + var entities = await dbContext.Set() + .ToArrayAsync(token); + return entities.AsEnumerable(); + }; + return memoryCache.GetOrCreateBasicAsync(getter, token); + } + + /// + /// Создать кеш на основе результата выполнения произвольной асинхронной функции. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + /// + public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, Func>> getterAsync, CancellationToken token) + where T : class + { + var key = typeof(T).FullName; + var cache = memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; cacheEntry.SlidingExpiration = CacheOlescence; - - var entities = await dbContext.Set().ToArrayAsync(token); - return entities.AsEnumerable(); + var entities = await getterAsync(token); + return entities; }); return cache; } + /// + /// Создать кеш на основе запроса к БД. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, IQueryable query) + where T : class + { + var getter = () => query.ToArray(); + return memoryCache.GetOrCreateBasic(getter); + } + + [Obsolete(message: "use GetOrCreateBasic(this IMemoryCache memoryCache, IQueryable query)")] public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, IAsbCloudDbContext dbContext) where T : class { - var cacheTag = typeof(T).FullName; - var cache = memoryCache.GetOrCreate(cacheTag, cacheEntry => { + var getter = () => dbContext.Set().ToArray(); + return memoryCache.GetOrCreateBasic(getter); + } + + /// + /// Создать кеш на основе результата выполнения произвольной функции. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, Func> getter) + where T : class + { + var key = typeof(T).FullName; + var cache = memoryCache.GetOrCreate(key, cacheEntry => { cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; cacheEntry.SlidingExpiration = CacheOlescence; - - var entities = dbContext.Set().ToArray(); - return entities.AsEnumerable(); + return getter(); }); return cache; } + + /// + /// Сбросить кеш. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + public static void DropBasic(this IMemoryCache memoryCache) + where T : class + { + var key = typeof(T).FullName; + memoryCache.Remove(key); + } } } diff --git a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs index 053aaf7e..9bbe20cc 100644 --- a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs +++ b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs @@ -4,9 +4,9 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; using Mapster; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; @@ -19,14 +19,12 @@ namespace AsbCloudInfrastructure.Repository public class UserRoleRepository : IUserRoleRepository { private readonly IAsbCloudDbContext dbContext; - private const string userRoleCacheTag = "UserRole"; - private const string relationUserRoleUserRoleCacheTag = "RelationUserRoleUserRole"; - private const string relationUserRolePermissionsCacheTag = "RelationUserRolePermissions"; - private static readonly TimeSpan relationCacheObsolence = TimeSpan.FromMinutes(15); + private readonly IMemoryCache memoryCache; - public UserRoleRepository(IAsbCloudDbContext dbContext) + public UserRoleRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) { this.dbContext = dbContext; + this.memoryCache = memoryCache; } public async Task InsertAsync(UserRoleDto dto, CancellationToken token) @@ -239,30 +237,30 @@ namespace AsbCloudInfrastructure.Repository } private Task> GetCacheUserRoleAsync(CancellationToken token) - => dbContext.UserRoles + => memoryCache.GetOrCreateBasicAsync(dbContext.Set() .Include(r => r.RelationUserRolePermissions) .Include(r => r.RelationUserRoleUserRoles) - .Include(r => r.RelationUsersUserRoles) - .FromCacheAsync(userRoleCacheTag, relationCacheObsolence, token); + .Include(r => r.RelationUsersUserRoles), token); + private IEnumerable GetCacheUserRole() - => dbContext.UserRoles + => memoryCache.GetOrCreateBasic(dbContext.Set() .Include(r => r.RelationUserRolePermissions) .Include(r => r.RelationUserRoleUserRoles) - .Include(r => r.RelationUsersUserRoles) - .FromCache(userRoleCacheTag, relationCacheObsolence); + .Include(r => r.RelationUsersUserRoles)); + private void DropCacheUserRole() - => dbContext.RelationUserUserRoles.DropCache(userRoleCacheTag); + => memoryCache.DropBasic(); private void DropCacheRelationUserRoleUserRole() - => dbContext.RelationUserUserRoles.DropCache(relationUserRoleUserRoleCacheTag); + => memoryCache.DropBasic(); private IEnumerable GetCacheRelationUserRolePermissions() - => dbContext.RelationUserRolePermissions + => memoryCache.GetOrCreateBasic(dbContext.Set() .Include(r => r.UserRole) - .Include(r => r.Permission) - .FromCache(relationUserRolePermissionsCacheTag, relationCacheObsolence); + .Include(r => r.Permission)); + private void DropCacheRelationUserRolePermissions() - => dbContext.RelationUserRolePermissions.DropCache(relationUserRolePermissionsCacheTag); + => memoryCache.DropBasic(); private UserRoleDto Convert(UserRole entity) { diff --git a/AsbCloudInfrastructure/Services/MeasureService.cs b/AsbCloudInfrastructure/Services/MeasureService.cs index 919654ea..56157786 100644 --- a/AsbCloudInfrastructure/Services/MeasureService.cs +++ b/AsbCloudInfrastructure/Services/MeasureService.cs @@ -2,9 +2,10 @@ using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; using Mapster; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -15,20 +16,28 @@ namespace AsbCloudInfrastructure.Services public class MeasureService : IMeasureService { private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; private readonly IWellService wellService; - private static readonly System.TimeSpan cacheObsolescence = System.TimeSpan.FromMinutes(15); + private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(20); - public MeasureService(IAsbCloudDbContext db, IWellService wellService) + public MeasureService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) { this.db = db; + this.memoryCache = memoryCache; this.wellService = wellService; } public async Task> GetCategoriesAsync(CancellationToken token) { - var entities = await db.MeasureCategories.FromCacheAsync("MeasureCategories", cacheObsolescence, token).ConfigureAwait(false); - var dto = entities.ToDictionary(e => e.Id, e => e.Name); - return dto; + var key = typeof(MeasureCategory).FullName; + var cache = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { + cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; + cacheEntry.SlidingExpiration = CacheOlescence; + var entities = await db.Set() + .ToDictionaryAsync(e => e.Id, e => e.Name, token); + return entities; + }); + return cache; } public async Task GetLastAsync(int idWell, int idCategory, CancellationToken token) diff --git a/AsbCloudInfrastructure/Services/SAUB/EventService.cs b/AsbCloudInfrastructure/Services/SAUB/EventService.cs index 744e3f57..56fe1737 100644 --- a/AsbCloudInfrastructure/Services/SAUB/EventService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/EventService.cs @@ -2,7 +2,7 @@ using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; +using Microsoft.Extensions.Caching.Memory; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -13,11 +13,13 @@ namespace AsbCloudInfrastructure.Services.SAUB public class EventService : IEventService { private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; private readonly ITelemetryService telemetryService; - public EventService(IAsbCloudDbContext db, ITelemetryService telemetryService) + public EventService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) { this.db = db; + this.memoryCache = memoryCache; this.telemetryService = telemetryService; } @@ -37,7 +39,7 @@ namespace AsbCloudInfrastructure.Services.SAUB MessageTemplate = dto.Message }); var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryEvents, entities, token); - db.TelemetryEvents.DropCache(); + memoryCache.DropBasic(); } } } diff --git a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs index cd4a1749..7f63f65c 100644 --- a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs @@ -4,9 +4,9 @@ using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; using Mapster; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; @@ -19,11 +19,13 @@ namespace AsbCloudInfrastructure.Services.SAUB public class MessageService : IMessageService { private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; private readonly ITelemetryService telemetryService; - public MessageService(IAsbCloudDbContext db, ITelemetryService telemetryService) + public MessageService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) { this.db = db; + this.memoryCache = memoryCache; this.telemetryService = telemetryService; } @@ -39,7 +41,7 @@ namespace AsbCloudInfrastructure.Services.SAUB if (idTelemetry is null) return result; - var allEvents = await db.TelemetryEvents.FromCacheAsync(token); + var allEvents = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); var events = allEvents.Where(e => e.IdTelemetry == idTelemetry); if (!events.Any()) @@ -93,7 +95,7 @@ namespace AsbCloudInfrastructure.Services.SAUB if (messagesList.Count == 0) return result; - var allUsers = await db.TelemetryUsers.FromCacheAsync(token); + var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); var users = allUsers.Where(u => u.IdTelemetry == idTelemetry); var eventsDict = events.ToDictionary(x=>x.IdEvent, x => x); diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs index b2e15216..fd74ad3e 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs @@ -3,9 +3,9 @@ using AsbCloudApp.Data.SAUB; using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; using Mapster; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; @@ -17,10 +17,8 @@ namespace AsbCloudInfrastructure.Services.SAUB #nullable enable public class TelemetryService : ITelemetryService { - private const string CacheTag = "TelemetryCache"; - private static readonly TimeSpan telemetryCacheObsolescence = TimeSpan.FromMinutes(5); - private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; private readonly ITelemetryTracker telemetryTracker; private readonly ITimezoneService timezoneService; @@ -29,25 +27,27 @@ namespace AsbCloudInfrastructure.Services.SAUB public TelemetryService( IAsbCloudDbContext db, + IMemoryCache memoryCache, ITelemetryTracker telemetryTracker, ITimezoneService timezoneService) { this.db = db; + this.memoryCache = memoryCache; this.telemetryTracker = telemetryTracker; this.timezoneService = timezoneService; } private IEnumerable GetTelemetryCache() { - var cache = db.Set() + var getter = () => db.Set() .Include(t => t.Well) - .FromCache(CacheTag, telemetryCacheObsolescence); - return cache; + .ToArray(); + return memoryCache.GetOrCreateBasic(getter); } private void DropTelemetryCache() { - db.Telemetries.DropCache(CacheTag); + memoryCache.DropBasic(); } public DateTime GetLastTelemetryDate(int idTelemetry) @@ -228,9 +228,7 @@ namespace AsbCloudInfrastructure.Services.SAUB catch (Exception ex) { System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}"); -#pragma warning disable CA2016 // Перенаправьте параметр "CancellationToken" в методы - await transaction.RollbackAsync(); -#pragma warning restore CA2016 // Перенаправьте параметр "CancellationToken" в методы + await transaction.RollbackAsync(CancellationToken.None); return -1; } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryTracker.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryTracker.cs index d3f80a9b..b7d5eefe 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryTracker.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryTracker.cs @@ -47,7 +47,7 @@ namespace AsbCloudInfrastructure.Services.SAUB .Options; var db = new AsbCloudDbContext(contextOptions); - var cacheTelemetry = memoryCache.GetOrCreateBasic(db); + var cacheTelemetry = memoryCache.GetOrCreateBasic(db.Set()); var keyValuePairs = new Dictionary(cacheTelemetry.Count()); foreach (var telemetry in cacheTelemetry) { diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index 516b3aad..39374cf1 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -4,7 +4,6 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using AsbCloudInfrastructure.EfCache; using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; @@ -20,9 +19,6 @@ namespace AsbCloudInfrastructure.Services #nullable enable public class WellService : CrudCacheRepositoryBase, IWellService { - private const string relationCompaniesWellsCacheTag = "RelationCompaniesWells"; - private static readonly TimeSpan relationCompaniesWellsCacheObsolence = TimeSpan.FromMinutes(15); - private readonly ITelemetryService telemetryService; private readonly ICrudRepository companyTypesService; private readonly ITimezoneService timezoneService; @@ -50,13 +46,18 @@ namespace AsbCloudInfrastructure.Services } private Task> GetCacheRelationCompanyWellAsync(CancellationToken token) - => dbContext.RelationCompaniesWells - .Include(r => r.Company) - .Include(r => r.Well) - .FromCacheAsync(relationCompaniesWellsCacheTag, relationCompaniesWellsCacheObsolence, token); + { + var getter = async (CancellationToken token) + => (await dbContext.Set() + .Include(r => r.Company) + .Include(r => r.Well) + .ToArrayAsync(token)) + .AsEnumerable(); + return memoryCache.GetOrCreateBasicAsync(getter, token); + } private void DropCacheRelationCompanyWell() - => dbContext.RelationCompaniesWells.DropCache(relationCompaniesWellsCacheTag); + => memoryCache.DropBasic(); public DateTimeOffset GetLastTelemetryDate(int idWell) {