flutter 消息并发时处理,递归查询

收到新消息的时候执行receiveNewConversation方法

可以自己模拟一下两条数据插入,延时执行插入会话的操作
收到一条新的会话消息,先记录会话ID到列表,直到第一条处理完(插入数据库后清理这个会话ID),才处理第二条同会话ID的消息(一直在空递归中)
(递归处理的时候看能一直监听到global的那个conversation列表是否有某个会话的数据,因为在不断重复执行)

核心观念是:1.确保处理多条同会话ID的消息时一定是单线程,2.且插入第一条时要卡住,不要让第二条进来,等第一条插入数据库完成后再执行第二条

注意:如果单纯延时100毫秒再执行第二条同会话ID消息,这种方法依旧是卡不住第二条消息,还是会出现两个会话同时插入数据库,A在12:01执行插入,B在12:02执行插入,A耗时两秒,B耗时一秒,两者都是12:03同时插入消息,导致出现两个会话。

所以还是要加事务锁,第一条执行后锁住,等完成后再执行第二条

  //新会话限制列表,存放会话ID
  static List<String> newConversationList = [];

  //会话队列
  static List<WsImMessageQueue> wsImConversationQueue = [];

  //是否正在处理会话递归
  static bool wsImConversationQueueState = false;
//不存在会话,则保存会话ID到新会话列表,等插完数据库后再清除新会话列表。
// 第二条会话进来插入到消息列表要等待,等新会话列表没有这个会话ID才把消息插入数据库


  ///收到新会话处理
  receiveNewConversation(RecvChatMsg recvChatMsg, bool isOffLineMessage) {
    
    
    //会话队列添加数据
    Global.wsImConversationQueue.add(WsImMessageQueue(
        recvChatMsg: recvChatMsg, isOffLineMessage: isOffLineMessage));

    PrintUtil.prints(
        '$TAG 中台IM消息 插入会话消息到wsImConversationQueue: ${
    
    utf8.decode(recvChatMsg.body)}   Global.wsImConversationQueue的长度${
    
    Global.wsImConversationQueue.length}');

    if (!Global.wsImConversationQueueState) {
    
    
      Global.wsImConversationQueueState = true;
      //开始递归
      startProcessingConversationQueue(true);
      PrintUtil.prints(
          '$TAG 中台IM消息 递归完成:${
    
    Global.wsImConversationQueueState}');

    }
  }

  startProcessingConversationQueue(bool isExistMessage) {
    
    
    if (isExistMessage) {
    
    
      //不为空的时候执行
      if (Global.wsImConversationQueue.isNotEmpty) {
    
    
        PrintUtil.prints(
            '$TAG 中台IM消息 === > 开始执行递归方法体');
        //取第一个数据
        if (Global.wsImConversationQueue[0].recvChatMsg != null) {
    
    

          WsImMessage wsImMessage =
              addWsImMessage(Global.wsImConversationQueue[0].recvChatMsg);

          PrintUtil.prints(
              '$TAG 中台IM消息 === > 会话列表第一个会话ID${
    
    wsImMessage.conversationId}');

          //第一条新消息不会被拦截,第二条同会话的消息会被拦截,查询该会话是否在新会话列表里面,如果为true,不给执行,一直执行递归,直到第一条会话插入数据库成功再执行这个判断里面
          if (checkConversationId(wsImMessage.conversationId ?? '') == false) {
    
    
            PrintUtil.prints(
                '$TAG 中台IM消息 === > 第一个数据或者会话列表第一个会话ID已从新会话限制列表里面移除');
            WsImDBUtil().insertMessage(
                Global.wsImConversationQueue[0].recvChatMsg!,
                Global.wsImConversationQueue[0].isOffLineMessage);

            //如果下一条进来后还是没有查出来赋值,那还是会拦截不到,一般在一秒内完成,应该影响不大
            WsImConversationDb.queryId(wsImMessage.conversationId).then((value) {
    
    
              if (value.isEmpty) {
    
    
                if (wsImMessage.conversationId != null) {
    
    
                  //插入到新会话限制列表里面
                  Global.newConversationList.add(wsImMessage.conversationId!);
                  PrintUtil.prints(
                      '$TAG 中台IM消息 === > 没有该会话就添加会话ID到会话队列:${
    
    Global.newConversationList}');
                }
              } else {
    
    
              }
            });

            PrintUtil.prints(
                '$TAG 中台IM消息 === > 插入消息,新会话限制列表:${
    
    Global.newConversationList}');
            Global.wsImConversationQueue
                .remove(Global.wsImConversationQueue[0]);
            PrintUtil.prints(
                '$TAG 中台IM消息 === > 移除消息,消息队列还剩:${
    
    Global.wsImConversationQueue.length}');
          }

          Future.delayed(const Duration(milliseconds: 1000), () {
    
    
            //1秒后进行递归
            startProcessingConversationQueue(
                Global.wsImConversationQueue.isNotEmpty);
            PrintUtil.prints(
                '$TAG 中台IM消息 === > 递归完成或者下一个递归');
          });
        }
      }
    } else {
    
    
      PrintUtil.prints('$TAG 中台IM消息 === > 消息处理完成');
      Global.wsImConversationQueueState = false;
    }
  }

  //判断会话ID是否在新会话列表里面,存在说明要等待这会话ID插入数据完成后才进行其他新会话的插入
  bool checkConversationId(String id) {
    
    
    bool check = false;
    for (int i = 0; i < Global.newConversationList.length; i++) {
    
    
      if (id == Global.newConversationList[i]) {
    
    
        check = true;
      }
    }
    PrintUtil.prints(
        '$TAG 中台IM消息 === > 会话列表第一个会话ID在不在新会话限制列表里面:${
    
    check}   新会话限制列表:${
    
    Global.newConversationList}');
    return check;
  }

  ///添加消息内容
  WsImMessage addWsImMessage(RecvChatMsg? recvChatMsg) {
    
    
    //默认会话ID是:收到谁消息就是谁的会话ID
    String conId = 'c2c_${
    
    recvChatMsg?.fromUserId.toInt()}';

    //如果发送者是自己,且接收者不是自己,则是服务器下发的消息,会话ID是对方
    if ('${
    
    recvChatMsg?.fromUserId.toInt()}' == Global.userId) {
    
    
      if ('${recvChatMsg?.toUserId.toInt()}' != Global.userId) {
    
    
        conId = 'c2c_${
    
    recvChatMsg?.toUserId.toInt()}';
      }
    }

    WsImMessage wsImMessage = WsImMessage(
        userId: int.parse(Global.userId),
        conversationId: conId,
        serverMsgId: recvChatMsg?.serverMsgId.toInt(),
        fromUserId: recvChatMsg?.fromUserId.toInt(),
        toUserId: recvChatMsg?.toUserId.toInt(),
        sendTime: recvChatMsg?.sendTime.toInt(),
        messageBody: WsImMessageBody.fromJson(utf8.decode(recvChatMsg!.body)),
        messageState: WsImMessageState.wsImMessageSendSuccess,
        isSelf: 0,
        isRead: 0);

    return wsImMessage;
  }

猜你喜欢

转载自blog.csdn.net/weixin_44911775/article/details/133862725
今日推荐