Skip to content

Commit

Permalink
Added cache clear endpoint and ignoring cache when in preview (#107)
Browse files Browse the repository at this point in the history
* Added cache clear endpoint and ignoring cache when in preview

* Added some tests for caching

* modifed cache controller to API type + respond with OK

* removed unused controller map

---------

Co-authored-by: Tom Whittington <[email protected]>
Co-authored-by: simonjfirth <[email protected]>
  • Loading branch information
3 people authored Jul 8, 2024
1 parent da53160 commit b9ea2ef
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 12 deletions.
19 changes: 19 additions & 0 deletions src/Dfe.ContentSupport.Web/Controllers/CacheController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Dfe.ContentSupport.Web.Models.Mapped;
using Dfe.ContentSupport.Web.Services;
using Microsoft.AspNetCore.Mvc;

namespace Dfe.ContentSupport.Web.Controllers;

[Route("api/[controller]")]
[ApiController]
public class CacheController(ICacheService<List<CsPage>> cache) : Controller
{
[HttpGet]
[Route("clear")]
public IActionResult Clear()
{
cache.ClearCache();

return Ok();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public static void InitDependencyInjection(this WebApplicationBuilder app)
app.Configuration.GetSection("Contentful").Bind(contentfulOptions);
app.Services.AddSingleton(contentfulOptions);




app.Services
.AddTransient<ICacheService<List<CsPage>>, CsPagesCacheService>();
app.Services.AddTransient<IContentfulService, ContentfulService>();
Expand Down
10 changes: 8 additions & 2 deletions src/Dfe.ContentSupport.Web/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static void Main(string[] args)
var azureCredentials = new DefaultAzureCredential();
builder.Configuration.AddAzureKeyVault(new Uri(keyVaultUri), azureCredentials);


builder.Services.AddControllers();
builder.Services.AddControllersWithViews();
builder.Services.AddApplicationInsightsTelemetry();

Expand Down Expand Up @@ -51,12 +51,18 @@ public static void Main(string[] args)
new { controller = "Sitemap", action = "Index" }
);


app.MapControllerRoute(
"clearCache",
pattern: "{controller=Cache}/{action=Clear}"
);

app.MapControllerRoute(
name: "home",
pattern: "{controller=Home}/{action=Home}");

app.MapControllerRoute(
name: "slug",
name: "slug",
pattern: "{slug}",
defaults: new { controller = "Home", action = "Index" });

Expand Down
20 changes: 14 additions & 6 deletions src/Dfe.ContentSupport.Web/Services/ContentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,37 @@ from url in resp
return sitemap.ToString();
}

public async Task<List<CsPage>> GetCsPages()
public async Task<List<CsPage>> GetCsPages(bool isPreview = true)
{
var pages =
await GetContentSupportPages(nameof(ContentSupportPage.IsSitemap), "true", true);
await GetContentSupportPages(nameof(ContentSupportPage.IsSitemap), "true", isPreview);
return pages.ToList();
}

public async Task<List<CsPage>> GetContentSupportPages(
string field, string value, bool isPreview)
{
var key = $"{field}_{value}";
var fromCache = cache.GetFromCache(key);
if (fromCache is not null)
if (isPreview is false)
{
return fromCache;
var fromCache = cache.GetFromCache(key);
if (fromCache is not null)
{
return fromCache;
}
}


var builder = QueryBuilder<ContentSupportPage>.New.ContentTypeIs(nameof(ContentSupportPage))
.FieldEquals($"fields.{field}", value);
var result = await contentfulService.ContentfulClient(isPreview).Query(builder);
var pages = result.Select(page => new CsPage(page)).ToList();

cache.AddToCache(key, pages);
if (isPreview is false)
{
cache.AddToCache(key, pages);
}

return pages;
}
}
5 changes: 5 additions & 0 deletions src/Dfe.ContentSupport.Web/Services/CsPagesCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public void AddToCache(string key, List<CsPage> item)
{
return cache.Get<List<CsPage>>(key);
}

public void ClearCache()
{
(cache as MemoryCache)?.Clear();
}
}
1 change: 1 addition & 0 deletions src/Dfe.ContentSupport.Web/Services/ICacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ public interface ICacheService<T>
{
void AddToCache(string key,T item);
T? GetFromCache(string key);
void ClearCache();
}
2 changes: 1 addition & 1 deletion src/Dfe.ContentSupport.Web/Services/IContentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ public interface IContentService
{
Task<CsPage?> GetContent(string slug, bool isPreview);
Task<string> GenerateSitemap(string baseUrl);
Task<List<CsPage>> GetCsPages();
Task<List<CsPage>> GetCsPages(bool isPreview = true);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Dfe.ContentSupport.Web.Controllers;
using Dfe.ContentSupport.Web.Models.Mapped;

namespace Dfe.ContentSupport.Web.Tests.Controllers;

public class CacheControllerTests
{
[Fact]
public void Clear_Calls_CacheClear()
{
var cacheServiceMock = new Mock<ICacheService<List<CsPage>>>();
var sut = new CacheController(cacheServiceMock.Object);
sut.Clear();

cacheServiceMock.Verify(o => o.ClearCache(), Times.Once);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ private HomeController GetController()
[Fact]
public async void Home_Returns_View()
{
_contentServiceMock.Setup(o => o.GetCsPages()).ReturnsAsync([]);
_contentServiceMock.Setup(o => o.GetCsPages(It.IsAny<bool>())).ReturnsAsync([]);

var sut = GetController();
var result = await sut.Home();
Expand Down
36 changes: 34 additions & 2 deletions tests/Dfe.ContentSupport.Web.Tests/Services/ContentServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,48 @@ public async void GetCsPages_Calls_Client_Once()
}

[Fact]
public async void GetCsPages_Calls_Cache_Correct_Key()
public async void GetCsPages_NotPreview_Calls_Cache_Correct_Key()
{
const string expectedKey = "IsSitemap_true";
SetupResponse();
var sut = GetService();
await sut.GetCsPages(false);

_cacheMock.Verify(o => o.GetFromCache(expectedKey), Times.Once);
}

[Fact]
public async void GetCsPages_Preview_Calls_Cache_Correct_Key()
{
const string expectedKey = "IsSitemap_true";
SetupResponse();
var sut = GetService();
await sut.GetCsPages();

_cacheMock.Verify(o => o.GetFromCache(expectedKey));
_cacheMock.Verify(o => o.GetFromCache(expectedKey), Times.Never);
}

[Fact]
public async void GetCsPages_NotPreview_Calls_AddCache_Correct_Key()
{
const string expectedKey = "IsSitemap_true";
SetupResponse();
var sut = GetService();
await sut.GetCsPages(false);

_cacheMock.Verify(o => o.AddToCache(expectedKey, It.IsAny<List<CsPage>>()), Times.Once);
}

[Fact]
public async void GetCsPages_Preview_Calls_AddCache_Correct_Key()
{
const string expectedKey = "IsSitemap_true";
SetupResponse();
var sut = GetService();
await sut.GetCsPages();

_cacheMock.Verify(o => o.AddToCache(expectedKey, It.IsAny<List<CsPage>>()), Times.Never);
}

[Fact]
public async void GetContent_Calls_Cache_Correct_Key()
Expand Down

0 comments on commit b9ea2ef

Please sign in to comment.