refactor(api): rm HybridCache

This commit is contained in:
Collin Barrett 2025-06-08 10:59:21 -05:00 committed by Collin Barrett
parent a8831f94a6
commit 3076eac77a
10 changed files with 187 additions and 237 deletions

View file

@ -1,33 +1,27 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetLanguages
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetLanguages);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Languages
.Where(l => l.FilterListLanguages.Any())
.OrderBy(l => l.Iso6391)
.Select(l => new Response(
l.Id,
l.Iso6391,
l.Name,
l.FilterListLanguages
.OrderBy(fl => fl.FilterListId)
.Select(fl => fl.FilterListId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Languages
.Where(l => l.FilterListLanguages.Any())
.OrderBy(l => l.Iso6391)
.Select(l => new Response(
l.Id,
l.Iso6391,
l.Name,
l.FilterListLanguages
.OrderBy(fl => fl.FilterListId)
.Select(fl => fl.FilterListId)
))
.TagWith(nameof(GetLanguages))
.ToListAsync(ct);
}
}

View file

@ -1,36 +1,30 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetLicenses
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetLicenses);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Licenses
.Where(l => l.FilterLists.Any())
.OrderBy(l => l.Id)
.Select(l => new Response(
l.Id,
l.Name,
l.Url,
l.PermitsModification,
l.PermitsDistribution,
l.PermitsCommercialUse,
l.FilterLists
.OrderBy(f => f.Id)
.Select(f => f.Id)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Licenses
.Where(l => l.FilterLists.Any())
.OrderBy(l => l.Id)
.Select(l => new Response(
l.Id,
l.Name,
l.Url,
l.PermitsModification,
l.PermitsDistribution,
l.PermitsCommercialUse,
l.FilterLists
.OrderBy(f => f.Id)
.Select(f => f.Id)
))
.TagWith(nameof(GetLicenses))
.ToListAsync(ct);
}
}

View file

@ -1,78 +1,72 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetListDetails
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<Response?> ExecuteAsync(int id, CancellationToken ct)
{
var key = $"{nameof(GetListDetails)}_{id}";
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.FilterLists
.Select(f => new Response
{
Id = f.Id,
Name = f.Name,
Description = f.Description,
LicenseId = f.LicenseId,
SyntaxIds = f.FilterListSyntaxes
.OrderBy(fs => fs.SyntaxId)
.Select(fs => fs.SyntaxId),
LanguageIds = f.FilterListLanguages
.OrderBy(fl => fl.LanguageId)
.Select(fl => fl.LanguageId),
TagIds = f.FilterListTags
.OrderBy(ft => ft.TagId)
.Select(ft => ft.TagId),
ViewUrls = f.ViewUrls
.OrderBy(u => u.SegmentNumber)
.ThenBy(u => u.Primariness)
.Select(u => new ViewUrlResponse
(
u.SegmentNumber,
u.Primariness,
u.Url
)),
HomeUrl = f.HomeUrl,
OnionUrl = f.OnionUrl,
PolicyUrl = f.PolicyUrl,
SubmissionUrl = f.SubmissionUrl,
IssuesUrl = f.IssuesUrl,
ForumUrl = f.ForumUrl,
ChatUrl = f.ChatUrl,
EmailAddress = f.EmailAddress,
DonateUrl = f.DonateUrl,
MaintainerIds = f.FilterListMaintainers
.OrderBy(fm => fm.MaintainerId)
.Select(fm => fm.MaintainerId),
UpstreamFilterListIds = f.UpstreamFilterLists
.OrderBy(ff => ff.UpstreamFilterListId)
.Select(ff => ff.UpstreamFilterListId),
ForkFilterListIds = f.ForkFilterLists
.OrderBy(ff => ff.ForkFilterListId)
.Select(ff => ff.ForkFilterListId),
IncludedInFilterListIds = f.IncludedInFilterLists
.OrderBy(fm => fm.IncludedInFilterListId)
.Select(fm => fm.IncludedInFilterListId),
IncludesFilterListIds = f.IncludesFilterLists
.OrderBy(fm => fm.IncludesFilterListId)
.Select(fm => fm.IncludesFilterListId),
DependencyFilterListIds = f.DependencyFilterLists
.OrderBy(fd => fd.DependencyFilterListId)
.Select(fd => fd.DependencyFilterListId),
DependentFilterListIds = f.DependentFilterLists
.OrderBy(fd => fd.DependentFilterListId)
.Select(fd => fd.DependentFilterListId)
})
.TagWith(key)
.SingleOrDefaultAsync(l => l.Id == id, cancel),
cancellationToken: ct);
return await ctx.FilterLists
.Select(f => new Response
{
Id = f.Id,
Name = f.Name,
Description = f.Description,
LicenseId = f.LicenseId,
SyntaxIds = f.FilterListSyntaxes
.OrderBy(fs => fs.SyntaxId)
.Select(fs => fs.SyntaxId),
LanguageIds = f.FilterListLanguages
.OrderBy(fl => fl.LanguageId)
.Select(fl => fl.LanguageId),
TagIds = f.FilterListTags
.OrderBy(ft => ft.TagId)
.Select(ft => ft.TagId),
ViewUrls = f.ViewUrls
.OrderBy(u => u.SegmentNumber)
.ThenBy(u => u.Primariness)
.Select(u => new ViewUrlResponse
(
u.SegmentNumber,
u.Primariness,
u.Url
)),
HomeUrl = f.HomeUrl,
OnionUrl = f.OnionUrl,
PolicyUrl = f.PolicyUrl,
SubmissionUrl = f.SubmissionUrl,
IssuesUrl = f.IssuesUrl,
ForumUrl = f.ForumUrl,
ChatUrl = f.ChatUrl,
EmailAddress = f.EmailAddress,
DonateUrl = f.DonateUrl,
MaintainerIds = f.FilterListMaintainers
.OrderBy(fm => fm.MaintainerId)
.Select(fm => fm.MaintainerId),
UpstreamFilterListIds = f.UpstreamFilterLists
.OrderBy(ff => ff.UpstreamFilterListId)
.Select(ff => ff.UpstreamFilterListId),
ForkFilterListIds = f.ForkFilterLists
.OrderBy(ff => ff.ForkFilterListId)
.Select(ff => ff.ForkFilterListId),
IncludedInFilterListIds = f.IncludedInFilterLists
.OrderBy(fm => fm.IncludedInFilterListId)
.Select(fm => fm.IncludedInFilterListId),
IncludesFilterListIds = f.IncludesFilterLists
.OrderBy(fm => fm.IncludesFilterListId)
.Select(fm => fm.IncludesFilterListId),
DependencyFilterListIds = f.DependencyFilterLists
.OrderBy(fd => fd.DependencyFilterListId)
.Select(fd => fd.DependencyFilterListId),
DependentFilterListIds = f.DependentFilterLists
.OrderBy(fd => fd.DependentFilterListId)
.Select(fd => fd.DependentFilterListId)
})
.TagWith($"{nameof(GetListDetails)}_{id}")
.SingleOrDefaultAsync(l => l.Id == id, ct);
}
}

View file

@ -1,48 +1,42 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetLists
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetLists);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.FilterLists
.OrderBy(f => f.Id)
.Select(f => new Response
(
f.Id,
f.Name,
f.Description,
f.LicenseId,
f.FilterListSyntaxes
.OrderBy(fs => fs.SyntaxId)
.Select(fs => fs.SyntaxId),
f.FilterListLanguages
.OrderBy(fl => fl.LanguageId)
.Select(fl => fl.LanguageId),
f.FilterListTags
.OrderBy(ft => ft.TagId)
.Select(ft => ft.TagId),
f.ViewUrls
.OrderBy(u => u.SegmentNumber)
.ThenBy(u => u.Primariness)
.Select(u => u.Url)
.FirstOrDefault(),
f.FilterListMaintainers
.OrderBy(fm => fm.MaintainerId)
.Select(fm => fm.MaintainerId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.FilterLists
.OrderBy(f => f.Id)
.Select(f => new Response
(
f.Id,
f.Name,
f.Description,
f.LicenseId,
f.FilterListSyntaxes
.OrderBy(fs => fs.SyntaxId)
.Select(fs => fs.SyntaxId),
f.FilterListLanguages
.OrderBy(fl => fl.LanguageId)
.Select(fl => fl.LanguageId),
f.FilterListTags
.OrderBy(ft => ft.TagId)
.Select(ft => ft.TagId),
f.ViewUrls
.OrderBy(u => u.SegmentNumber)
.ThenBy(u => u.Primariness)
.Select(u => u.Url)
.FirstOrDefault(),
f.FilterListMaintainers
.OrderBy(fm => fm.MaintainerId)
.Select(fm => fm.MaintainerId)
))
.TagWith(nameof(GetLists))
.ToListAsync(ct);
}
}

View file

@ -1,35 +1,29 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetMaintainers
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetMaintainers);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Maintainers
.Where(m => m.FilterListMaintainers.Any())
.OrderBy(m => m.Id)
.Select(m => new Response(
m.Id,
m.Name,
m.Url,
m.EmailAddress,
m.TwitterHandle,
m.FilterListMaintainers
.OrderBy(fm => fm.FilterListId)
.Select(fm => fm.FilterListId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Maintainers
.Where(m => m.FilterListMaintainers.Any())
.OrderBy(m => m.Id)
.Select(m => new Response(
m.Id,
m.Name,
m.Url,
m.EmailAddress,
m.TwitterHandle,
m.FilterListMaintainers
.OrderBy(fm => fm.FilterListId)
.Select(fm => fm.FilterListId)
))
.TagWith(nameof(GetMaintainers))
.ToListAsync(ct);
}
}

View file

@ -1,37 +1,31 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetSoftware
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetSoftware);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Software
.Where(s => s.SoftwareSyntaxes.Any(ss => ss.Syntax.FilterListSyntaxes.Any()))
.OrderBy(s => s.Id)
.Select(s => new Response
(
s.Id,
s.Name,
s.Description,
s.HomeUrl,
s.DownloadUrl,
s.SupportsAbpUrlScheme,
s.SoftwareSyntaxes
.OrderBy(ss => ss.SyntaxId)
.Select(ss => ss.SyntaxId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Software
.Where(s => s.SoftwareSyntaxes.Any(ss => ss.Syntax.FilterListSyntaxes.Any()))
.OrderBy(s => s.Id)
.Select(s => new Response
(
s.Id,
s.Name,
s.Description,
s.HomeUrl,
s.DownloadUrl,
s.SupportsAbpUrlScheme,
s.SoftwareSyntaxes
.OrderBy(ss => ss.SyntaxId)
.Select(ss => ss.SyntaxId)
))
.TagWith(nameof(GetSoftware))
.ToListAsync(ct);
}
}

View file

@ -1,38 +1,32 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetSyntaxes
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetSyntaxes);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Syntaxes
.Where(s => s.FilterListSyntaxes.Any())
.OrderBy(s => s.Id)
.Select(s => new Response
(
s.Id,
s.Name,
s.Description,
s.Url,
s.FilterListSyntaxes
.OrderBy(fs => fs.FilterListId)
.Select(fs => fs.FilterListId),
s.SoftwareSyntaxes
.OrderBy(ss => ss.SoftwareId)
.Select(ss => ss.SoftwareId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Syntaxes
.Where(s => s.FilterListSyntaxes.Any())
.OrderBy(s => s.Id)
.Select(s => new Response
(
s.Id,
s.Name,
s.Description,
s.Url,
s.FilterListSyntaxes
.OrderBy(fs => fs.FilterListId)
.Select(fs => fs.FilterListId),
s.SoftwareSyntaxes
.OrderBy(ss => ss.SoftwareId)
.Select(ss => ss.SoftwareId)
))
.TagWith(nameof(GetSyntaxes))
.ToListAsync(ct);
}
}

View file

@ -1,34 +1,28 @@
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Hybrid;
namespace FilterLists.Directory.Application.Queries;
public static class GetTags
{
public class Query(QueryDbContext ctx, HybridCache cache)
public class Query(QueryDbContext ctx)
{
public async Task<List<Response>> ExecuteAsync(CancellationToken ct)
{
const string key = nameof(GetTags);
return await cache.GetOrCreateAsync(
key,
async cancel =>
await ctx.Tags
.Where(t => t.FilterListTags.Any())
.OrderBy(t => t.Id)
.Select(t => new Response
(
t.Id,
t.Name,
t.Description,
t.FilterListTags
.OrderBy(flt => flt.FilterListId)
.Select(flt => flt.FilterListId)
))
.TagWith(key)
.ToListAsync(cancel),
cancellationToken: ct);
return await ctx.Tags
.Where(t => t.FilterListTags.Any())
.OrderBy(t => t.Id)
.Select(t => new Response
(
t.Id,
t.Name,
t.Description,
t.FilterListTags
.OrderBy(flt => flt.FilterListId)
.Select(flt => flt.FilterListId)
))
.TagWith(nameof(GetTags))
.ToListAsync(ct);
}
}

View file

@ -25,6 +25,5 @@ public static void AddInfrastructure(this IHostApplicationBuilder builder)
StringComparison.OrdinalIgnoreCase)));
builder.Services.AddHostedService<MigrationService>();
builder.Services.AddHybridCache();
}
}

View file

@ -6,7 +6,6 @@
<ItemGroup>
<PackageReference Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" Version="8.2.2"/>
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="9.5.0"/>
</ItemGroup>
</Project>