You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ServiceStack:基于状态条件缓存对象的实现方案问询

针对体育赛事结果的ServiceStack条件缓存方案

这是个很常见的业务场景,直接用ServiceStack自带的ToOptimizedResultUsingCache确实满足不了这种“仅缓存已结束赛事”的需求,我给你两个实用的实现方案,你可以根据自己的代码风格选择:

方案一:在服务方法内直接做条件判断(简单直观)

这种方式最直接,在获取结果前先判断赛事状态,只对已结束的赛事启用缓存逻辑:

public object Get(GetEventResults request)
{
    // 先从数据源获取赛事的基础状态信息
    var eventInfo = GetEventDetails(request.EventId);
    
    if (eventInfo.IsCompleted)
    {
        // 赛事已结束,生成唯一缓存键(建议包含请求参数避免冲突)
        var cacheKey = $"EventResults_{request.EventId}_{request.Locale}";
        
        // 使用缓存逻辑,这里设置24小时过期,可根据需求调整
        return Request.ToOptimizedResultUsingCache(
            Cache, 
            cacheKey, 
            TimeSpan.FromHours(24), 
            () => GetFinalizedEventResults(request.EventId)
        );
    }
    else
    {
        // 赛事进行中,直接返回实时数据,不触发缓存
        var liveResults = GetLiveEventResults(request.EventId);
        return Request.ToOptimizedResult(liveResults);
    }
}

方案说明:

  • 先通过GetEventDetails确认赛事状态,确保只有已结束的赛事才走缓存流程
  • 缓存键加入了Locale参数作为示例,如果你有其他影响结果的请求参数,也应该加到缓存键里
  • 进行中的赛事直接调用实时数据接口,并用ToOptimizedResult做序列化优化,完全绕过缓存

方案二:自定义缓存过滤器(更优雅的属性式实现)

如果你习惯用ServiceStack的特性(Attribute)来管理缓存,可以自定义一个条件缓存特性,把状态判断逻辑封装起来:

首先,自定义缓存特性:

public class CacheCompletedEventsOnlyAttribute : CacheResponseAttribute
{
    public override ICacheResponseDecorator CreateDecorator(IRequest req, IResponse res, object dto)
    {
        // 把请求DTO转成你的实际请求类型
        var eventRequest = dto as GetEventResults;
        if (eventRequest == null)
        {
            return base.CreateDecorator(req, res, dto);
        }

        // 通过IOC获取赛事服务,查询赛事状态
        var eventService = req.TryResolve<IEventService>();
        var eventInfo = eventService.GetEventDetails(eventRequest.EventId);

        // 如果赛事未结束,返回一个不做缓存的装饰器
        if (!eventInfo.IsCompleted)
        {
            return new NoCacheDecorator();
        }

        // 赛事已结束,使用默认的缓存逻辑
        return base.CreateDecorator(req, res, dto);
    }
}

// 自定义不缓存的装饰器,直接执行原方法逻辑
public class NoCacheDecorator : ICacheResponseDecorator
{
    public object Execute(Func<object> invoke) => invoke();
    public Task<object> ExecuteAsync(Func<Task<object>> invoke) => invoke();
}

然后在你的服务方法上使用这个特性:

// 设置缓存有效期为24小时(仅对已结束赛事生效)
[CacheCompletedEventsOnly(Duration = 86400)]
public object Get(GetEventResults request)
{
    // 统一的结果获取逻辑,状态判断由过滤器处理
    var results = GetEventResultsInternal(request.EventId);
    return Request.ToOptimizedResult(results);
}

额外注意事项

  • 缓存失效处理:如果已结束的赛事后续有数据修正(比如官方更新结果),记得手动调用Cache.Remove(cacheKey)清除对应缓存,或者设置合理的过期时间让缓存自动刷新
  • 状态判断可靠性:确保赛事状态的数据源是实时且可靠的,避免因为状态判断错误导致缓存了进行中的赛事数据
  • 缓存键唯一性:一定要根据请求参数生成唯一的缓存键,避免不同赛事、不同请求条件的结果互相覆盖

内容的提问来源于stack exchange,提问作者taglius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:04:53