diff --git a/AsbCloudInfrastructure/Services/Cache/CacheTable.cs b/AsbCloudInfrastructure/Services/Cache/CacheTable.cs index f656c10d..a1d47325 100644 --- a/AsbCloudInfrastructure/Services/Cache/CacheTable.cs +++ b/AsbCloudInfrastructure/Services/Cache/CacheTable.cs @@ -14,6 +14,8 @@ namespace AsbCloudInfrastructure.Services.Cache { private const int semaphoreTimeout = 5_000; private static readonly SemaphoreSlim semaphore = new(1); + private static readonly TimeSpan minPeriodRefresh = TimeSpan.FromSeconds(3); + private readonly DbContext context; private (DateTime refreshDate, IEnumerable entities) data; private readonly List cached; @@ -26,7 +28,7 @@ namespace AsbCloudInfrastructure.Services.Cache dbSet = context.Set(); cached = (List)data.entities; if (cached.Count == 0) - Refresh(); + Refresh(false); } public TEntity this[int index] { get => cached.ElementAt(index); } @@ -89,37 +91,45 @@ namespace AsbCloudInfrastructure.Services.Cache return true; } - private void InternalRefresh() + private void InternalRefresh(bool force) { + if (!force && (data.refreshDate + minPeriodRefresh >= DateTime.Now)) + return; + cached.Clear(); var entities = dbSet.AsNoTracking().ToList(); - cached.AddRange(entities); - data.refreshDate = DateTime.Now; - } - - private async Task InternalRefreshAsync(CancellationToken token = default) - { - cached.Clear(); - var entities = await context.Set().AsNoTracking() - .ToListAsync(token).ConfigureAwait(false); + Trace.WriteLine($"CacheTable<{typeof(TEntity).Name}> refresh"); cached.AddRange(entities); data.refreshDate = DateTime.Now; } - public int Refresh() + private async Task InternalRefreshAsync(bool force, CancellationToken token = default) + { + if (!force && (data.refreshDate + minPeriodRefresh >= DateTime.Now)) + return; + + cached.Clear(); + var entities = await context.Set().AsNoTracking() + .ToListAsync(token).ConfigureAwait(false); + Trace.WriteLine($"CacheTable<{typeof(TEntity).Name}> refresh"); + cached.AddRange(entities); + data.refreshDate = DateTime.Now; + } + + public int Refresh(bool force) { Sync((wasFree) => { if (wasFree) - InternalRefresh(); + InternalRefresh(force); }); return cached.Count; } - public async Task RefreshAsync(CancellationToken token = default) + public async Task RefreshAsync(bool force, CancellationToken token = default) { await SyncAsync(async (wasFree, token) => { if (wasFree) - await InternalRefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(force, token).ConfigureAwait(false); }, token).ConfigureAwait(false); return cached.Count; } @@ -138,14 +148,14 @@ namespace AsbCloudInfrastructure.Services.Cache if (result != default) return; - InternalRefresh(); + InternalRefresh(true); result = cached.FirstOrDefault(predicate); if (result != default) return; var entry = dbSet.Add(makeNew()); context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); result = entry.Entity; }); return result; @@ -157,7 +167,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result != default) return result; - Refresh(); + Refresh(false); return cached.FirstOrDefault(); } @@ -167,7 +177,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result != default) return result; - await RefreshAsync(token); + await RefreshAsync(false, token); return cached.FirstOrDefault(); } @@ -177,7 +187,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result != default) return result; - Refresh(); + Refresh(false); return cached.FirstOrDefault(predicate); } @@ -187,7 +197,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result != default) return result; - await RefreshAsync(token); + await RefreshAsync(false, token); return cached.FirstOrDefault(predicate); } @@ -199,7 +209,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result.Any()) return result; - Refresh(); + Refresh(false); result = (predicate != default) ? cached.Where(predicate) : cached; @@ -218,7 +228,7 @@ namespace AsbCloudInfrastructure.Services.Cache if (result.Any()) return result; - await RefreshAsync(token); + await RefreshAsync(false, token); result = (predicate != default) ? cached.Where(predicate) : cached; @@ -236,7 +246,7 @@ namespace AsbCloudInfrastructure.Services.Cache else dbSet.Add(entity); context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); }); } @@ -247,7 +257,7 @@ namespace AsbCloudInfrastructure.Services.Cache else dbSet.Add(entity); await context.SaveChangesAsync(token).ConfigureAwait(false); - await InternalRefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(true, token).ConfigureAwait(false); }, token); public void Upsert(IEnumerable entities) @@ -265,7 +275,7 @@ namespace AsbCloudInfrastructure.Services.Cache dbSet.Add(entity); } context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); }); } @@ -284,7 +294,7 @@ namespace AsbCloudInfrastructure.Services.Cache dbSet.Add(entity); } await context.SaveChangesAsync(token).ConfigureAwait(false); - await InternalRefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(true, token).ConfigureAwait(false); }, token); } @@ -293,14 +303,14 @@ namespace AsbCloudInfrastructure.Services.Cache { dbSet.RemoveRange(dbSet.Where(predicate)); context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); }); public Task RemoveAsync(Func predicate, CancellationToken token = default) => SyncAsync(async (wasFree, token) => { dbSet.RemoveRange(dbSet.Where(predicate)); await context.SaveChangesAsync(token).ConfigureAwait(false); - await InternalRefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(true, token).ConfigureAwait(false); }, token); public TEntity Insert(TEntity entity) @@ -310,7 +320,7 @@ namespace AsbCloudInfrastructure.Services.Cache { var entry = dbSet.Add(entity); context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); result = entry.Entity; }); return result; @@ -323,7 +333,7 @@ namespace AsbCloudInfrastructure.Services.Cache { var entry = dbSet.Add(entity); await context.SaveChangesAsync(token).ConfigureAwait(false); - await InternalRefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(true, token).ConfigureAwait(false); result = entry.Entity; }, token); return result; @@ -335,7 +345,7 @@ namespace AsbCloudInfrastructure.Services.Cache Sync(_ => { dbSet.AddRange(newEntities); result = context.SaveChanges(); - InternalRefresh(); + InternalRefresh(true); }); return result; } @@ -346,7 +356,7 @@ namespace AsbCloudInfrastructure.Services.Cache await SyncAsync(async (wasFree, token) => { dbSet.AddRange(newEntities); result = await context.SaveChangesAsync(token).ConfigureAwait(false); - await RefreshAsync(token).ConfigureAwait(false); + await InternalRefreshAsync(true, token).ConfigureAwait(false); }, token); return result; }