using MediatR; using BuildFlow.Application.Chat.DTOs; using BuildFlow.Shared.Domain.Exceptions; using BuildFlow.Domain.Interfaces; using BuildFlow.Infrastructure.Persistence; using BuildFlow.Application.Chat.Queries; namespace BuildFlow.Application.Chat.Handlers; /// /// Get会话Detail查询处理器。执行业务校验后持久化。 /// public class GetConversationDetailQueryHandler(RagDbContext db, IChatMessageCache cache) : IRequestHandler { public async Task Handle(GetConversationDetailQuery request, CancellationToken ct) { var conversation = await db.Conversations.FindAsync([request.Id], ct) ?? throw new NotFoundException("会话不存在"); // 先查 Redis 缓存 var cached = await cache.GetMessagesAsync(request.Id, ct); if (cached is not null) { var messages = cached.Select(m => new ChatMessageDto(m.Id, m.Role, m.Content, m.TokenUsage, m.CreatedAt)).ToList(); return new ConversationDetailDto(conversation.Id, conversation.Title, conversation.UserId, conversation.KnowledgeBaseId, conversation.CreatedAt, messages); } // 缓存 miss,查数据库 var dbMessages = await db.ChatMessages .Where(m => m.ConversationId == request.Id) .OrderBy(m => m.CreatedAt) .Select(m => new ChatMessageDto(m.Id, m.Role.ToString(), m.Content, m.TokenUsage, m.CreatedAt)) .ToListAsync(ct); // 回填 Redis var cachedMessages = dbMessages.Select(m => new CachedChatMessage(m.Id, m.Role, m.Content, m.TokenUsage, m.CreatedAt)).ToList(); await cache.SetMessagesAsync(request.Id, cachedMessages, ct); return new ConversationDetailDto(conversation.Id, conversation.Title, conversation.UserId, conversation.KnowledgeBaseId, conversation.CreatedAt, dbMessages); } }