using AutoMapper; using IM_API.Application.Interfaces; using IM_API.Domain.Events; using IM_API.Dtos; using IM_API.Exceptions; using IM_API.Interface.Services; using IM_API.Models; using IM_API.Services; using IM_API.Tools; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; namespace IM_API.Application.EventHandlers { public class ConversationEventHandler : IEventHandler { private readonly IConversationService _conversationService; private readonly ILogger _logger; private readonly ImContext _context; private readonly IMapper _mapper; public ConversationEventHandler( IConversationService conversationService, ILogger logger, ImContext imContext, IMapper mapper ) { _conversationService = conversationService; _logger = logger; _context = imContext; _mapper = mapper; } /* * 此方法有并发问题,当双方同时第一次发送消息时, * 会出现同时创建的情况,其中一方会报错, * 导致也未走到更新逻辑,会话丢失 */ public async Task Handle(MessageCreatedEvent @event) { //此处仅处理私聊会话创建 if (@event.ChatType == ChatType.GROUP) { return; } var conversation = await _context.Conversations.FirstOrDefaultAsync( x => x.UserId == @event.MsgSenderId && x.TargetId == @event.MsgRecipientId ); //如果首次发消息则创建双方会话 if (conversation is null) { Conversation senderCon = _mapper.Map(@event); Conversation ReceptCon = _mapper.Map(@event); ReceptCon.UserId = @event.MsgRecipientId; ReceptCon.TargetId = @event.MsgSenderId; ReceptCon.UnreadCount += 1; ReceptCon.LastReadMessageId = null; _context.Conversations.AddRange(senderCon,ReceptCon); await _context.SaveChangesAsync(); } else { Conversation senderCon = conversation; Conversation? ReceptCon = await _context.Conversations.FirstOrDefaultAsync( x => x.UserId == @event.MsgRecipientId && x.TargetId == @event.MsgSenderId); if (ReceptCon is null) { _logger.LogError("ConversationEventHandlerError:接收者会话对象缺失!Event:{Event}", JsonConvert.SerializeObject(@event)); throw new BaseException(CodeDefine.SYSTEM_ERROR); } //更新发送者conversation senderCon.UnreadCount = 0; senderCon.LastReadMessageId = @event.MessageId; senderCon.LastMessage = @event.MessageContent; senderCon.LastMessageTime = DateTime.Now; //更新接收者conversation ReceptCon.UnreadCount += 1; ReceptCon.LastMessage = @event.MessageContent; senderCon.LastMessageTime = DateTime.Now; _context.Conversations.UpdateRange(senderCon, ReceptCon); await _context.SaveChangesAsync(); } } } }