Skip to content

Commit

Permalink
Merge pull request #17 from Lombiq/issue/NEST-370
Browse files Browse the repository at this point in the history
NEST-370: Create Media Theme caching for templates
  • Loading branch information
DemeSzabolcs authored Nov 28, 2022
2 parents 8af5587 + 80570a9 commit 24148e4
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 10 deletions.
33 changes: 27 additions & 6 deletions Lombiq.Hosting.MediaTheme.Bridge/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using Lombiq.Hosting.MediaTheme.Bridge.Constants;
using Lombiq.HelpfulLibraries.OrchardCore.DependencyInjection;
using Lombiq.Hosting.MediaTheme.Bridge.Constants;
using Lombiq.Hosting.MediaTheme.Bridge.Services;
using Lombiq.Hosting.MediaTheme.Bridge.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.Extensions.Localization;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.Themes.Services;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -18,23 +21,30 @@ public class AdminController : Controller
private readonly IMediaThemeStateStore _mediaThemeStateStore;
private readonly IUpdateModelAccessor _updateModelAccessor;
private readonly IStringLocalizer<AdminController> T;
private readonly IHtmlLocalizer<AdminController> H;
private readonly IMediaThemeManager _mediaThemeManager;
private readonly ISiteThemeService _siteThemeService;
private readonly IMediaThemeCachingService _mediaThemeCachingService;
private readonly INotifier _notifier;

public AdminController(
IAuthorizationService authorizationService,
IOrchardServices<AdminController> orchardServices,
IMediaThemeStateStore mediaThemeStateStore,
IUpdateModelAccessor updateModelAccessor,
IStringLocalizer<AdminController> stringLocalizer,
IMediaThemeManager mediaThemeManager,
ISiteThemeService siteThemeService)
ISiteThemeService siteThemeService,
IMediaThemeCachingService mediaThemeCachingService,
INotifier notifier)
{
_authorizationService = authorizationService;
_authorizationService = orchardServices.AuthorizationService.Value;
_mediaThemeStateStore = mediaThemeStateStore;
_updateModelAccessor = updateModelAccessor;
T = stringLocalizer;
T = orchardServices.StringLocalizer.Value;
_mediaThemeManager = mediaThemeManager;
_siteThemeService = siteThemeService;
_mediaThemeCachingService = mediaThemeCachingService;
_notifier = notifier;
H = orchardServices.HtmlLocalizer.Value;
}

[HttpGet]
Expand Down Expand Up @@ -78,6 +88,17 @@ public async Task<ActionResult> IndexPost(MediaThemeSettingsViewModel viewModel)
return RedirectToAction(nameof(Index));
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteMediaThemeTemplateCache()
{
if (!await IsAuthorizedToManageMediaThemeAsync()) return NotFound();

await _mediaThemeCachingService.InvalidateCachedMediaThemeTemplatesAsync();
await _notifier.SuccessAsync(H["Media Theme template cache was invalidated successfully!"]);
return RedirectToAction(nameof(Index));
}

private Task<bool> IsAuthorizedToManageMediaThemeAsync() =>
_authorizationService.AuthorizeAsync(User, ManageMediaTheme);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Lombiq.Hosting.MediaTheme.Bridge.Models;
using System.Threading.Tasks;

namespace Lombiq.Hosting.MediaTheme.Bridge.Services;

/// <summary>
/// Media Theme template cache store and invalidation functions.
/// </summary>
public interface IMediaThemeCachingService
{
/// <summary>
/// Returns <see cref="MediaTemplate"/> if cached, else tries to fetch it from the storage. If not available stores
/// and returns <see langword="null"/>.
/// </summary>
/// <param name="shapeType">The searched shape type.</param>
Task<MediaTemplate> GetMemoryCachedMediaTemplateAsync(string shapeType);

/// <summary>
/// Deletes all Media Theme templates from the cache.
/// </summary>
Task InvalidateCachedMediaThemeTemplatesAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ public class MediaTemplatesShapeBindingResolver : IShapeBindingResolver
private readonly ILiquidTemplateManager _liquidTemplateManager;
private readonly IHttpContextAccessor _hca;
private readonly HtmlEncoder _htmlEncoder;
private readonly IMediaThemeManager _mediaThemeManager;
private readonly IMediaThemeCachingService _mediaThemeCachingService;

public MediaTemplatesShapeBindingResolver(
ILiquidTemplateManager liquidTemplateManager,
IHttpContextAccessor hca,
HtmlEncoder htmlEncoder,
IMediaThemeManager mediaThemeManager)
IMediaThemeCachingService mediaThemeCachingService)
{
_liquidTemplateManager = liquidTemplateManager;
_hca = hca;
_htmlEncoder = htmlEncoder;
_mediaThemeManager = mediaThemeManager;
_mediaThemeCachingService = mediaThemeCachingService;
}

public async Task<ShapeBinding> GetShapeBindingAsync(string shapeType)
Expand All @@ -34,7 +34,7 @@ public async Task<ShapeBinding> GetShapeBindingAsync(string shapeType)
return null;
}

return await _mediaThemeManager.GetMediaTemplateByShapeTypeAsync(shapeType) is not { } mediaTemplate
return await _mediaThemeCachingService.GetMemoryCachedMediaTemplateAsync(shapeType) is not { } mediaTemplate
? null
: BuildShapeBinding(shapeType, mediaTemplate.Content);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Lombiq.Hosting.MediaTheme.Bridge.Models;
using Microsoft.Extensions.Caching.Memory;
using OrchardCore.Environment.Cache;
using System.Threading.Tasks;

namespace Lombiq.Hosting.MediaTheme.Bridge.Services;

public class MediaThemeCachingService : IMediaThemeCachingService
{
private const string MediaThemeMemoryCacheKeyPrefix = "Lombiq.Hosting.MediaTheme.Bridge";

private readonly IMemoryCache _memoryCache;
private readonly IMediaThemeManager _mediaThemeManager;
private readonly ISignal _signal;

public MediaThemeCachingService(
IMemoryCache memoryCache,
IMediaThemeManager mediaThemeManager,
ISignal signal)
{
_memoryCache = memoryCache;
_mediaThemeManager = mediaThemeManager;
_signal = signal;
}

public async Task<MediaTemplate> GetMemoryCachedMediaTemplateAsync(string shapeType)
{
var cacheKey = $"{MediaThemeMemoryCacheKeyPrefix}:{shapeType}";
if (_memoryCache.TryGetValue(cacheKey, out MediaTemplate cachedMediaTemplate))
{
return cachedMediaTemplate;
}

cachedMediaTemplate = await _mediaThemeManager.GetMediaTemplateByShapeTypeAsync(shapeType);
_memoryCache.Set(cacheKey, cachedMediaTemplate, _signal.GetToken(MediaThemeMemoryCacheKeyPrefix));

return cachedMediaTemplate;
}

public Task InvalidateCachedMediaThemeTemplatesAsync() => _signal.SignalTokenAsync(MediaThemeMemoryCacheKeyPrefix);
}
1 change: 1 addition & 0 deletions Lombiq.Hosting.MediaTheme.Bridge/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public override void ConfigureServices(IServiceCollection services)
services.AddSingleton<IDeploymentStepFactory>(new DeploymentStepFactory<MediaThemeDeploymentStep>());
services.AddScoped<IDisplayDriver<DeploymentStep>, MediaThemeDeploymentStepDriver>();
services.AddScoped<IAuthorizationHandler, ManageMediaThemeFolderAuthorizationHandler>();
services.AddScoped<IMediaThemeCachingService, MediaThemeCachingService>();
}

public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
Expand Down
7 changes: 7 additions & 0 deletions Lombiq.Hosting.MediaTheme.Bridge/Views/Admin/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@
<button type="submit" class="btn btn-primary">@T["Submit"]</button>
</div>
</form>

<form asp-action="DeleteMediaThemeTemplateCache" asp-controller="Admin" asp-area="Lombiq.Hosting.MediaTheme.Bridge" method="post" class="no-multisubmit">
@Html.ValidationSummary()
<div class="mb-3">
<button type="submit" class="btn btn-danger">@T["Invalidate Media Theme templates cache."]</button>
</div>
</form>

0 comments on commit 24148e4

Please sign in to comment.