From 9cb9cc1cf6d77bd28ae9ea2c0ae72144a8cba4c1 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 13 Sep 2020 06:14:18 -0500 Subject: [PATCH] =?UTF-8?q?feat(directory):=20=E2=9C=A8=E2=9A=A1=20add=20i?= =?UTF-8?q?n-memory=20api=20caching?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/BaseController.cs | 34 +++++++++++++++++++ .../Controllers/LanguagesController.cs | 8 +++-- .../Controllers/LicensesController.cs | 8 +++-- .../Controllers/ListsController.cs | 11 +++--- .../Controllers/MaintainersController.cs | 8 +++-- .../Controllers/SoftwareController.cs | 8 +++-- .../Controllers/SyntaxesController.cs | 8 +++-- .../Controllers/TagsController.cs | 8 +++-- .../FilterLists.Directory.Api/Startup.cs | 1 + 9 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 services/Directory/FilterLists.Directory.Api/Controllers/BaseController.cs diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/BaseController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/BaseController.cs new file mode 100644 index 000000000..12916ecbf --- /dev/null +++ b/services/Directory/FilterLists.Directory.Api/Controllers/BaseController.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; + +namespace FilterLists.Directory.Api.Controllers +{ + public abstract class BaseController : ControllerBase + { + private readonly IMemoryCache _cache; + + protected BaseController(IMemoryCache cache) + { + _cache = cache; + } + + /// https://stackoverflow.com/a/52506210/2343739 + protected async Task CacheGetOrCreateAsync( + Func> actionAsync, + int? keySuffix = default, + TimeSpan? absoluteExpirationRelativeToNow = default, + [CallerMemberName] string key = default!) + { + var cacheKey = $"{GetType().Name}_{key}{(keySuffix is null ? string.Empty : $"_{keySuffix}")}"; + var result = await _cache.GetOrCreateAsync(cacheKey, entry => + { + entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow; + return actionAsync(); + }); + return result is null ? NotFound() : (IActionResult)Ok(result); + } + } +} \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/LanguagesController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/LanguagesController.cs index 9ab3b196c..ce60862f4 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/LanguagesController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/LanguagesController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class LanguagesController : ControllerBase + public class LanguagesController : BaseController { private readonly IMediator _mediator; - public LanguagesController(IMediator mediator) + public LanguagesController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetLanguages.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetLanguages.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/LicensesController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/LicensesController.cs index b7ed3373f..afbe7768f 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/LicensesController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/LicensesController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class LicensesController : ControllerBase + public class LicensesController : BaseController { private readonly IMediator _mediator; - public LicensesController(IMediator mediator) + public LicensesController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetLicenses.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetLicenses.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/ListsController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/ListsController.cs index 6ea329d3f..344bbb7c2 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/ListsController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/ListsController.cs @@ -6,32 +6,35 @@ using FilterLists.SharedKernel.Apis.Contracts.Directory; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class ListsController : ControllerBase + public class ListsController : BaseController { private readonly IMediator _mediator; - public ListsController(IMediator mediator) + public ListsController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetLists.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetLists.Query(), cancellationToken)); } [HttpGet("{id}")] [ProducesResponseType(typeof(ListDetailsVm), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task GetDetails(int id, CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetListDetails.Query(id), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetListDetails.Query(id), cancellationToken), id); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/MaintainersController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/MaintainersController.cs index 2e259a2f2..5e1bd3845 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/MaintainersController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/MaintainersController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class MaintainersController : ControllerBase + public class MaintainersController : BaseController { private readonly IMediator _mediator; - public MaintainersController(IMediator mediator) + public MaintainersController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetMaintainers.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetMaintainers.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/SoftwareController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/SoftwareController.cs index fb08bc5ef..896651fc8 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/SoftwareController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/SoftwareController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class SoftwareController : ControllerBase + public class SoftwareController : BaseController { private readonly IMediator _mediator; - public SoftwareController(IMediator mediator) + public SoftwareController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetSoftware.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetSoftware.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/SyntaxesController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/SyntaxesController.cs index e6e869a7e..a4c8809d2 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/SyntaxesController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/SyntaxesController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class SyntaxesController : ControllerBase + public class SyntaxesController : BaseController { private readonly IMediator _mediator; - public SyntaxesController(IMediator mediator) + public SyntaxesController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetSyntaxes.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetSyntaxes.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/TagsController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/TagsController.cs index ecc660cd2..e91267a87 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/TagsController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/TagsController.cs @@ -5,25 +5,27 @@ using FilterLists.Directory.Application.Queries; using MediatR; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; namespace FilterLists.Directory.Api.Controllers { [ApiController] [Route("[controller]")] - public class TagsController : ControllerBase + public class TagsController : BaseController { private readonly IMediator _mediator; - public TagsController(IMediator mediator) + public TagsController(IMemoryCache cache, IMediator mediator) : base(cache) { _mediator = mediator; } [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Get(CancellationToken cancellationToken) { - return Ok(await _mediator.Send(new GetTags.Query(), cancellationToken)); + return await CacheGetOrCreateAsync(() => _mediator.Send(new GetTags.Query(), cancellationToken)); } } } \ No newline at end of file diff --git a/services/Directory/FilterLists.Directory.Api/Startup.cs b/services/Directory/FilterLists.Directory.Api/Startup.cs index 26aa4eccb..754d617e3 100644 --- a/services/Directory/FilterLists.Directory.Api/Startup.cs +++ b/services/Directory/FilterLists.Directory.Api/Startup.cs @@ -18,6 +18,7 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { + services.AddMemoryCache(); services.AddRouting(o => o.LowercaseUrls = true); services.AddControllers() .AddJsonOptions(o => o.JsonSerializerOptions.IgnoreNullValues = true);