mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
feat(dir): ✨⚡️ add in-memory caching
This commit is contained in:
parent
2cede3e539
commit
89f15c99f0
10 changed files with 95 additions and 27 deletions
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -27,12 +29,15 @@ public static class GetLanguages
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request,
|
||||
[EnumeratorCancellation] CancellationToken ct)
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var language in Query(ctx).WithCancellation(ct)) yield return language;
|
||||
await foreach (var language in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetLanguages),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return language;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -30,11 +32,15 @@ public static class GetLicenses
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var license in Query(ctx).WithCancellation(ct)) yield return license;
|
||||
await foreach (var license in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetLicenses),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return license;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -71,11 +72,11 @@ public static class GetListDetails
|
|||
public sealed record Request(int Id) : IRequest<Response?>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IRequestHandler<Request, Response?>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IRequestHandler<Request, Response?>
|
||||
{
|
||||
public Task<Response?> Handle(Request request, CancellationToken _)
|
||||
{
|
||||
return Query(ctx, request.Id);
|
||||
return cache.GetOrCreateAsync($"{nameof(GetListDetails)}_{request.Id}", entry => Query(ctx, request.Id));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -42,11 +44,15 @@ public static class GetLists
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var list in Query(ctx).WithCancellation(ct)) yield return list;
|
||||
await foreach (var list in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetLists),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return list;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -29,12 +31,15 @@ public static class GetMaintainers
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request,
|
||||
[EnumeratorCancellation] CancellationToken ct)
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var maintainer in Query(ctx).WithCancellation(ct)) yield return maintainer;
|
||||
await foreach (var maintainer in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetMaintainers),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return maintainer;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -32,12 +34,15 @@ public static class GetSoftware
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request,
|
||||
[EnumeratorCancellation] CancellationToken ct)
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var software in Query(ctx).WithCancellation(ct)) yield return software;
|
||||
await foreach (var software in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetSoftware),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return software;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -32,12 +34,15 @@ public static class GetSyntaxes
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request,
|
||||
[EnumeratorCancellation] CancellationToken ct)
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var syntax in Query(ctx).WithCancellation(ct)) yield return syntax;
|
||||
await foreach (var syntax in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetSyntaxes),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return syntax;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FilterLists.Directory.Infrastructure;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using JetBrains.Annotations;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Application.Queries;
|
||||
|
||||
|
|
@ -28,12 +30,15 @@ public static class GetTags
|
|||
public sealed record Request : IStreamRequest<Response>;
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class Handler(QueryDbContext ctx) : IStreamRequestHandler<Request, Response>
|
||||
private sealed class Handler(QueryDbContext ctx, IMemoryCache cache) : IStreamRequestHandler<Request, Response>
|
||||
{
|
||||
public async IAsyncEnumerable<Response> Handle(Request request,
|
||||
[EnumeratorCancellation] CancellationToken ct)
|
||||
public async IAsyncEnumerable<Response> Handle(Request request, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
await foreach (var tag in Query(ctx).WithCancellation(ct)) yield return tag;
|
||||
await foreach (var tag in cache.GetOrCreateAsyncEnumerable(
|
||||
nameof(GetTags),
|
||||
Query(ctx).WithCancellation(ct))
|
||||
.WithCancellation(ct))
|
||||
yield return tag;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public static void AddInfrastructure(this IHostApplicationBuilder builder)
|
|||
so.EnableRetryOnFailure([0])
|
||||
.MigrationsAssembly(MigrationsAssembly))
|
||||
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
|
||||
|
||||
builder.Services.AddHostedService<MigrationService>();
|
||||
builder.Services.AddMemoryCache();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure;
|
||||
|
||||
public static class MemoryCacheExtension
|
||||
{
|
||||
public static async IAsyncEnumerable<TResponse> GetOrCreateAsyncEnumerable<TResponse>(
|
||||
this IMemoryCache cache,
|
||||
object key,
|
||||
ConfiguredCancelableAsyncEnumerable<TResponse> query,
|
||||
MemoryCacheEntryOptions? options = null) where TResponse : class
|
||||
{
|
||||
if (cache.TryGetValue(key, out List<TResponse>? cachedElements))
|
||||
{
|
||||
foreach (var element in cachedElements ?? []) yield return element;
|
||||
}
|
||||
else
|
||||
{
|
||||
var elementsToCache = new List<TResponse>();
|
||||
await foreach (var element in query)
|
||||
{
|
||||
elementsToCache.Add(element);
|
||||
yield return element;
|
||||
}
|
||||
|
||||
cache.Set(key, elementsToCache, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue