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);