namespace Dpz.Core.Service.Mediator.Features.Video.Commands;

/// <summary>
/// 已过时:请使用 AddDanmakuCountHandler 和 RabbitMQ 消息队列替代。
/// 原 MediatR 同步处理模式已迁移到异步消息队列,提供更好的性能和可靠性。
/// </summary>
[Obsolete(
    "请使用 Web.Jobs 项目中的 AddDanmakuCountHandler 替代。MediatR 同步处理已迁移到 RabbitMQ 异步消息队列。",
    false
)]
public class AddDanmakuCountEvent(
    IRepository<global::Dpz.Core.Public.Entity.Video> repository,
    IRepository<Barrage> barrageRepository,
    IFusionCache fusionCache
) : IRequestHandler<AddDanmakuCountRequest>
{
    /// <summary>
    /// 回填视频弹幕计数并同步更新相关缓存。
    /// </summary>
    public async ValueTask<Unit> Handle(
        AddDanmakuCountRequest request,
        CancellationToken cancellationToken
    )
    {
        var count = await barrageRepository
            .SearchFor(x => x.Group == request.DanmakuGroup)
            .CountAsync(cancellationToken);
        var update = Builders<global::Dpz.Core.Public.Entity.Video>.Update.Set(
            x => x.DanmakuCount,
            count
        );
        await repository.UpdateAsync(x => x.Id == request.DanmakuGroup, update, cancellationToken);

        var key = $"{CacheKey.VideoListKey}:{request.DanmakuGroup}";
        var cacheValue = await fusionCache.TryGetAsync<VmVideo>(key, token: cancellationToken);
        if (cacheValue.HasValue)
        {
            cacheValue.Value.DanmakuCount = count;
            await fusionCache.SetAsync(
                key,
                cacheValue.Value,
                TimeSpan.FromDays(1),
                [CacheKey.VideoListKey],
                token: cancellationToken
            );
        }

        var listCache = await fusionCache.TryGetAsync<List<VmVideo>>(
            CacheKey.VideoListKey,
            token: cancellationToken
        );
        if (listCache.HasValue)
        {
            var video = listCache.Value.FirstOrDefault(x => x.Id == request.DanmakuGroup);
            if (video != null)
            {
                video.DanmakuCount = count;
                await fusionCache.SetAsync(
                    CacheKey.VideoListKey,
                    listCache.Value,
                    TimeSpan.FromDays(1),
                    [CacheKey.VideoListKey],
                    token: cancellationToken
                );
            }
        }

        return Unit.Value;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个基于 MediatR 模式的命令处理器类,用于处理视频弹幕计数的更新操作。

类的基本信息

类名: AddDanmakuCountEvent
命名空间: Dpz.Core.Service.Mediator.Features.Video.Commands
实现接口: IRequestHandler<AddDanmakuCountRequest>

重要标识

该类被标记为 [Obsolete],表示已过时,建议使用新的异步消息队列方案替代:

  • 推荐使用 Web.Jobs 项目中的 AddDanmakuCountHandler
  • 从 MediatR 同步处理迁移到 RabbitMQ 异步消息队列

依赖注入

构造函数通过主构造函数语法注入三个依赖:

IRepository<global::Dpz.Core.Public.Entity.Video> repository     // 视频数据仓储
IRepository<Barrage> barrageRepository                           // 弹幕数据仓储  
IFusionCache fusionCache                                         // 缓存服务

核心功能 - Handle 方法

该方法执行以下操作:

1. 统计弹幕数量

var count = await barrageRepository
    .SearchFor(x => x.Group == request.DanmakuGroup)
    .CountAsync(cancellationToken);

根据弹幕分组ID查询对应的弹幕总数。

2. 更新数据库

var update = Builders<global::Dpz.Core.Public.Entity.Video>.Update.Set(
    x => x.DanmakuCount, count
);
await repository.UpdateAsync(x => x.Id == request.DanmakuGroup, update, cancellationToken);

使用 MongoDB 的 Update Builder 更新视频实体的弹幕计数字段。

3. 更新缓存

代码分两步更新缓存:

更新单个视频缓存

  • 检查是否存在特定视频的缓存
  • 如果存在,更新其弹幕计数并重新设置缓存

更新视频列表缓存

  • 检查视频列表缓存是否存在
  • 在列表中找到对应视频并更新其弹幕计数
  • 重新设置整个列表缓存

设计特点

  1. 数据一致性: 同时更新数据库和缓存,确保数据一致性
  2. 缓存策略: 使用1天的缓存过期时间
  3. 异步处理: 全程使用异步操作,支持取消令牌
  4. 缓存标签: 使用 CacheKey.VideoListKey 作为缓存标签便于管理

架构演进

这个类体现了系统架构的演进过程,从同步的 MediatR 处理模式迁移到异步的消息队列模式,以获得更好的性能和可靠性。

评论加载中...