Skip to content

Commit

Permalink
Merge pull request #3897 from sbwalker/dev
Browse files Browse the repository at this point in the history
improve caching for static rendering
  • Loading branch information
sbwalker authored Feb 26, 2024
2 parents 176dc17 + aac4d3e commit ce934b8
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 5 deletions.
79 changes: 79 additions & 0 deletions Oqtane.Server/Extensions/CacheExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Oqtane.Extensions
{
public static class CacheExtensions
{
private static string _cachekeys = "cachekeys";

public static TItem GetOrCreate<TItem>(this IMemoryCache cache, string key, Func<ICacheEntry, TItem> factory, bool track)
{
if (!cache.TryGetValue(key, out object result))
{
using ICacheEntry entry = cache.CreateEntry(key);
result = factory(entry);
entry.Value = result;

if (track)
{
// track the cache key
List<string> cachekeys;
if (!cache.TryGetValue(_cachekeys, out cachekeys))
{
cachekeys = new List<string>();
}
if (!cachekeys.Contains(key))
{
cachekeys.Add(key);
cache.Set(_cachekeys, cachekeys, new MemoryCacheEntryOptions { Priority = CacheItemPriority.NeverRemove });
}
}
}

return (TItem)result;
}

public static void Remove(this IMemoryCache cache, string key, bool track)
{
List<string> cachekeys;

if (track && key.EndsWith("*"))
{
// wildcard cache key removal
var prefix = key.Substring(0, key.Length - 1);
if (cache.TryGetValue(_cachekeys, out cachekeys) && cachekeys.Any())
{
for (var i = cachekeys.Count - 1; i >= 0; i--)
{
if (cachekeys[i].StartsWith(prefix))
{
cache.Remove(cachekeys[i]);
cachekeys.RemoveAt(i);
}
}
cache.Set(_cachekeys, cachekeys, new MemoryCacheEntryOptions { Priority = CacheItemPriority.NeverRemove });
}
}
else
{
cache.Remove(key);
}

// reconcile all tracked cache keys
if (track && cache.TryGetValue(_cachekeys, out cachekeys) && cachekeys.Any())
{
for (var i = cachekeys.Count - 1; i >= 0; i--)
{
if (!cache.TryGetValue(cachekeys[i], out _))
{
cachekeys.RemoveAt(i);
}
}
cache.Set(_cachekeys, cachekeys, new MemoryCacheEntryOptions { Priority = CacheItemPriority.NeverRemove });
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Caching.Memory;
using Oqtane.Extensions;
using Oqtane.Models;
using Oqtane.Shared;

Expand All @@ -18,7 +19,7 @@ public void EntityChanged(SyncEvent syncEvent)
// when site entities change (ie. site, pages, modules, etc...) a site refresh event is raised and the site cache item needs to be refreshed
if (syncEvent.EntityName == EntityNames.Site && syncEvent.Action == SyncEventActions.Refresh)
{
_cache.Remove($"site:{syncEvent.TenantId}:{syncEvent.EntityId}");
_cache.Remove($"site:{syncEvent.TenantId}:{syncEvent.EntityId}*", true);
}

// when a site entity is updated the hosting model may have changed, so the client assemblies cache items need to be refreshed
Expand Down
12 changes: 8 additions & 4 deletions Oqtane.Server/Services/SiteService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,19 @@ public async Task<Site> GetSiteAsync(int siteId)
Site site = null;
if (!_accessor.HttpContext.User.Identity.IsAuthenticated)
{
site = _cache.GetOrCreate($"site:{_accessor.HttpContext.GetAlias().SiteKey}", entry =>
site = _cache.GetOrCreate($"site:{_accessor.HttpContext.GetAlias().SiteKey}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return GetSite(siteId);
});
}, true);
}
else
else // authenticated - cached per user
{
site = GetSite(siteId);
site = _cache.GetOrCreate($"site:{_accessor.HttpContext.GetAlias().SiteKey}:{_accessor.HttpContext.User.UserId}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return GetSite(siteId);
}, true);
}
return await Task.Run(() => site);
}
Expand Down

0 comments on commit ce934b8

Please sign in to comment.