我目前正在实现.NET 7框架的一些新特性。其中一部分涉及到新的缓存机制。
在启动时,我已经配置了缓存:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
builder.Services.AddCors();
builder.Services.AddOutputCache();
//builder.Services.InitializeApplication(builder.Configuration);
var app = builder.Build();
app.UseOutputCache();
app.UseCors();
//app.UseAuthentication();
//app.UseAuthorization();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGroup("reports-api/requests")
.MapRequestsApi();
app.MapHealthChecks("/healthcheck");
app.Run();路由组如下所示:
public static class RequestsEndpoint
{
public static RouteGroupBuilder MapRequestsApi(this RouteGroupBuilder group)
{
group.MapGet("/all", async (IMediator mediator) =>
{
await Task.Delay(2000);
return await mediator.Send(new RetrieveRequestsQuery());
})
.CacheOutput(x => x.Tag("requests"));
group.MapPost("/add", async (string details, IMediator mediator, IOutputCacheStore store) =>
{
await mediator.Send(new AddRequestCommand { Details = details });
await store.EvictByTagAsync("requests", CancellationToken.None);
});
group.MapGet("/{id}", async (Guid requestId, IMediator mediator) =>
{
await mediator.Send(new RetrieveRequestDetailsQuery()
{
Id = requestId
});
});
//group.MapPut("/{id}", UpdateRequest);
//group.MapDelete("/{id}", DeleteRequest);
return group;
}
}当我想从缓存中为请求列表提供服务时,或者当我想要退出缓存(列表中的新项)时,带有标记的缓存机制可以正常工作。
但是,我希望每个项目都有某种缓存--当我根据ID检索请求时,我只想缓存这些值,直到PUT或修补程序更改了详细信息为止。
我可以做的是用相同的标记(“请求”)注册group.MapGet("/{id}")端点。然而,如果有一个更新,我被迫驱逐一切。那可不太理想。
我在看这个视频(输出缓存微软),他们看的是一个叫做输出缓存微软的东西
我只能在.NET 7中找到接口: IOutputCachePolicy,它要求我实现以下方法:
public class ByIdCachePolicy : IOutputCachePolicy
{
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellation) => throw new NotImplementedException();
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation) => throw new NotImplementedException();
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation) => throw new NotImplementedException();
}文档中没有关于如何实现这一点的线索,我也找不到默认策略的代码。我们应该如何实现这个接口?
发布于 2022-11-29 08:48:41
我设法实现了我想要的解决办法:
group.MapGet("/{id}", async (Guid requestId, IMediator mediator) =>
{
await Task.Delay(2000);
return await mediator.Send(new RetrieveRequestDetailsQuery
{
Id = requestId
});
})
.CacheOutput(cachePolicyBuilder => cachePolicyBuilder.With(context =>
{
if (context.HttpContext.Request.QueryString.Value != null)
{
var queryParams = HttpUtility.ParseQueryString(context.HttpContext.Request.QueryString.Value);
context.Tags.Add(queryParams["requestId"]!);
}
return true;
}));
group.MapPut("/{id}",
async (Guid id, IOutputCacheStore store, CancellationToken ct) =>
await store.EvictByTagAsync(id.ToString(), CT));使用cachePolicyBuilder With方法,我可以访问缓存上下文,并可以查看查询字符串&添加自定义标记(by ID)。
但是,这并不简单,因为和函数允许您过滤缓存的请求。我在这里做的是总是返回true,但也添加了自定义标记。
不太理想,但有效.
编辑
在深入研究它之后,我最终使用了以下策略:
public class ByIdCachePolicy : IOutputCachePolicy
{
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellation)
{
var idRoute = context.HttpContext.Request.RouteValues["id"];
if (idRoute == null)
{
return ValueTask.CompletedTask;
}
context.Tags.Add(idRoute.ToString()!);
return ValueTask.CompletedTask;
}
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation)=> ValueTask.CompletedTask;
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
}就像这样:
group.MapGet("/{id}", async (Guid id, IMediator mediator) =>
{
await Task.Delay(2000);
return await mediator.Send(new RetrieveRequestDetailsQuery
{
Id = id
});
}).CacheOutput(x => x.AddPolicy<ByIdCachePolicy>());https://stackoverflow.com/questions/74610528
复制相似问题