perf: optimize authorization scoreline and workers

This commit is contained in:
2026-07-30 09:12:27 +08:00
parent 4bea745b79
commit bedc77bffd
52 changed files with 21911 additions and 347 deletions

View File

@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.OutputCaching;
using Tiku.Application.Tenancy;
namespace Tiku.Api.Caching;
internal sealed class TenantPublicCacheInvalidator(IOutputCacheStore outputCacheStore)
: ITenantPublicCacheInvalidator
{
public ValueTask InvalidateCoreAsync(Guid tenantId, CancellationToken cancellationToken) =>
outputCacheStore.EvictByTagAsync($"tenant:{tenantId:N}", cancellationToken);
public async Task InvalidateAsync(Guid tenantId, CancellationToken cancellationToken = default) =>
await InvalidateCoreAsync(tenantId, cancellationToken);
}

View File

@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.OutputCaching;
using Microsoft.Extensions.Primitives;
using Tiku.Application.Security;
namespace Tiku.Api.Caching;
internal sealed class TenantPublicOutputCachePolicy : IOutputCachePolicy
{
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
{
var request = context.HttpContext.Request;
var tenantId = context.HttpContext.RequestServices.GetRequiredService<ITenantContext>().TenantId;
var enabled = HttpMethods.IsGet(request.Method) &&
tenantId.HasValue &&
StringValues.IsNullOrEmpty(request.Headers.Authorization) &&
context.HttpContext.User.Identity?.IsAuthenticated != true;
context.EnableOutputCaching = enabled;
context.AllowCacheLookup = enabled;
context.AllowCacheStorage = enabled;
context.AllowLocking = true;
if (enabled)
{
var resolvedTenantId = tenantId.GetValueOrDefault();
context.CacheVaryByRules.QueryKeys = "*";
context.CacheVaryByRules.HeaderNames = new StringValues("Accept-Encoding");
context.CacheVaryByRules.VaryByValues["tenant"] = resolvedTenantId.ToString("N");
context.Tags.Add($"tenant:{resolvedTenantId:N}");
}
return ValueTask.CompletedTask;
}
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken) =>
ValueTask.CompletedTask;
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken)
{
var response = context.HttpContext.Response;
if (response.StatusCode != StatusCodes.Status200OK ||
!StringValues.IsNullOrEmpty(response.Headers.SetCookie) ||
context.HttpContext.User.Identity?.IsAuthenticated == true)
{
context.AllowCacheStorage = false;
}
return ValueTask.CompletedTask;
}
}