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);
}
}