首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET 7创建自定义输出缓存策略

.NET 7创建自定义输出缓存策略
EN

Stack Overflow用户
提问于 2022-11-29 07:35:44
回答 1查看 29关注 0票数 0

我目前正在实现.NET 7框架的一些新特性。其中一部分涉及到新的缓存机制。

在启动时,我已经配置了缓存:

代码语言:javascript
复制
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();

路由组如下所示:

代码语言:javascript
复制
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,它要求我实现以下方法:

代码语言:javascript
复制
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();
}

文档中没有关于如何实现这一点的线索,我也找不到默认策略的代码。我们应该如何实现这个接口?

EN

回答 1

Stack Overflow用户

发布于 2022-11-29 08:48:41

我设法实现了我想要的解决办法:

代码语言:javascript
复制
 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,但也添加了自定义标记。

不太理想,但有效.

编辑

在深入研究它之后,我最终使用了以下策略:

代码语言:javascript
复制
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;
}

就像这样:

代码语言:javascript
复制
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>());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74610528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档