flutter 消息并发时处理,递归查询
收到新消息的时候执行receiveNewConversation方法
可以自己模拟一下两条数据插入,延时执行插入会话的操作
收到一条新的会话消息,先记录会话ID到列表,直到第一条处理完(插入数据库后清理这个会话ID),才处理第二条同会话ID的消息(一直在空递归中)
(递归处理的时候看能一直监听到global的那个conversation列表是否有某个会话的数据,因为在不断重复执行)
核心观念是:1.确保处理多条同会话ID的消息时一定是单线程,2.且插入第一条时要卡住,不要让第二条进来,等第一条插入数据库完成后再执行第二条
注意:如果单纯延时100毫秒再执行第二条同会话ID消息,这种方法依旧是卡不住第二条消息,还是会出现两个会话同时插入数据库,A在12:01执行插入,B在12:02执行插入,A耗时两秒,B耗时一秒,两者都是12:03同时插入消息,导致出现两个会话。
所以还是要加事务锁,第一条执行后锁住,等完成后再执行第二条
//新会话限制列表,存放会话IDstatic 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是:收到谁消息就是谁的会话IDString 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;}
相关文章:
flutter 消息并发时处理,递归查询
收到新消息的时候执行receiveNewConversation方法 可以自己模拟一下两条数据插入,延时执行插入会话的操作 收到一条新的会话消息,先记录会话ID到列表,直到第一条处理完(插入数据库后清理这个会话ID),才处理…...
第五十八章 学习常用技能 - 查看查询缓存
文章目录 第五十八章 学习常用技能 - 查看查询缓存查看查询缓存建立索引使用调谐表工具 第五十八章 学习常用技能 - 查看查询缓存 查看查询缓存 对于 SQL(用作嵌入式 SQL 时除外),系统会生成可重用代码来访问数据,并将该代码放置…...
AI 辅助学 Java | 专栏 1 帮你学 Java
在利用 ChatGPT 辅助学 Java 之前,你得先知道,它到底能辅助你干什么?如何能帮你更好的学习 Java。 苍何:作为一个语言模型,你能给 Java 的初学者提供什么帮助?请罗列具体的点。 ChatGPT:当你是一个 Java 初学者时,我可以提供以下具体的帮助和指导: 基本语法和语言特…...
2023_Spark_实验十六:编写LoggerLevel方法及getLocalSparkSession方法
一、搭建Spark项目结构 在SparkProject模块的pom.xml文件中增加一下依赖,并等待依赖包下载完毕,如上图。 <!-- Spark及Scala的版本号 --><properties><scala.version>2.11</scala.version><spark.version>2.1.1</sp…...
彻底搞懂:防止表单重复提交,前端限制还是后端限制?
欢迎大家来到小米的技术分享专栏!今天我将为大家带来一个热门话题:如何有效地防止表单重复提交。在开发中,我们常常会遇到这样的问题:用户频繁点击提交按钮,导致数据重复提交,给系统和用户体验带来不必要的…...
OCPP1.6协议
目录 导言 功能简介 本地授权列表 类型 IdToken IdTagInfo 授权状态 协议指令 1、授权 1.1 说明 1.2 Authorize.req 1.3 Authorize.conf 1.4 JSON格式 1.5 代码 2、启动通知 2.1 说明 2.2 BootNotification.req 2.3 BootNotification.conf 2.4 JSON格式 2…...
【数据存储:小端模式和大端模式】
一、引言 在计算机科学中,数据存储模式是指如何将数据存储在计算机内存中的方式。小端模式和大端模式是两种主要的字节序方式,它们决定了字节在内存中的排列顺序。这种字节顺序的选择对于跨平台编程和数据传输至关重要。在这篇博客中,我们将…...
【git】gitlab安装、备份
gitlab官网 官网:官网 中文官网:中文官网 作为一个英文不好的程序员,所以我都去中文网站去看了。下面也是带着大家去走走 安装gitlab 我不想写具体的安装方法,直接去逛网看下面是我的截图。步骤非常详细。 安装文档地址&…...
C51--基本认知
单片机基本认知: 1、什么是单片机 单片机是一种集成电路芯片。 把具有数据处理能力的中央处理器 CPU、随机存储器RAM、只读存储器ROM。 多种 I / O 口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器…...
centos7 安装 mysql 8.0
文章目录 环境介绍一、安装前准备 1.卸载MariaDB 1.1 查看是否安装mariadb1.2 卸载1.3 检查是否卸载干净 2.检查依赖 2.1 查看是否安装libaio2.2 查看是否安装numactl 二、安装MySQL 1.下载资源包 1.1 官网下载1.2 wget下载 2.解压3.重命名4.创建存储数据文件5.设置用户组并赋…...
Vue15 计算属性VS监视属性(侦听属性)
计算属性VS监视属性(侦听属性) computed和watch之间的区别: 1.computed能完成的功能,watch都可以完成。 2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。 两个重要的小…...
快速全面掌握数据库系统核心知识点
快速全面掌握数据库系统核心知识点 一、数据库系统二、三级模式-两层映射三、三级模式-视图四、数据库设计过程五、E-R模型六、关系代数七、规范化理论八、函数依赖九、规范化理论-键十、规范化理论-求候选键十一、规范化理论-范式十二、规范化理论-第一范式十三、规范化理论-第…...
学习笔记 | 音视频 | 推流项目框架及细节
推流项目: 跑起来项目,再调,创造问题,注意项目跑起来包括哪些步骤 前期准备:环境的配置 依赖库要交叉编译,编译还需注意依赖的库对应的头文件(注意是绝对路径还是相对路径) Rv1126_lib、arm_libx264、arm_libx265、arm_libsrt、arm32_ffmpeg_srt、arm_openssl Ubuntu搭…...
拓扑几何学
目录 一,欧拉定理 1,平面图论图 2,单连通多面体 3,一般多面体 一,欧拉定理 1,平面图论图 在一个联通无向图中,点数-边数面数 1 如: 7-126 1 如果把最外面的五边形外面也算…...
1.12.C++项目:仿muduo库实现并发服务器之LoopThreadPool模块的设计
文章目录 一、LoopThreadPool模块二、实现思想(一)功能(二)意义(三)功能设计 三、代码 一、LoopThreadPool模块 1.线程数量可配置(0或多个) 2. 对所有的线程进行管理,其…...
SpringBoot介绍
一、什么是SpringBoot 在使用传统的Spring去做Java EE(Java Enterprise Edition)开发中,大量的 XML 文件存在于项目之中,导致JavaEE项目变得慢慢笨重起来,繁琐的配置和整合第三方框架的配置,导致了开发和部…...
2022最新版-李宏毅机器学习深度学习课程-P17 卷积神经网络CNN
一、CNN 用于图像分类 需要图片大小统一 彩色图像分为R G B 三层,展平后首尾相接 值代表着颜色的强度 图像识别中不需要全连接的,参数太多了 观测1:通过判断多个小局部图像就能判断出图片标签 感受野的定义 简化1 感受野可以重叠ÿ…...
微博清理僵尸粉
1.选择chrome或者firefox浏览器 2.登陆微博账号 3.chrome右键点检查,选择console firefox右键点检查,选择控制台 4.粘贴下面代码到console或者控制台并且回车 let removeTargetFans false; /*是否删除符合条件的粉丝,默认关闭*/let dee…...
创建React Native的第一个hello world工程
创建React Native的第一个hello world工程 需要安装好node、npm环境 如果之前没有安装过react-native-cli脚手架的,可以按照下述步骤直接安装。如果已经安装过的,但是在使用这个脚手架初始化工程的时候遇到下述报错的话 cli.init(root, projectname);…...
基础课3——自然语言处理的应用
自然语言处理是一种将人类语言转换为机器语言,以实现人机交互的技术。应用非常广泛,例如: 人机交互:自然语言处理技术可以应用于人机交互,让机器能够理解和运用人类语言,从而实现更加智能化的交互体验。 机…...
理解 Git 的三个工作区:工作区、暂存区和版本库
文章目录 创建 Git 本地仓库配置Git认识⼯作区、暂存区、版本库添加⽂件--场景查看 .git ⽂件添加⽂件--场景⼆ 创建 Git 本地仓库 要提前说的是,仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来。创建⼀个 Gi…...
web前端基础训练-----创建用户反馈表单
1,实验代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>用户反馈表单</title></head><body><form><fieldset><h1>用户反馈</h1><hr/><h4>亲爱的用…...
Scrum 敏捷管理流程图及敏捷管理工具
敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例: 转自:Leangoo.com 免费敏捷工具 这个流程图涵盖了Scrum框架的主要阶段和活动,其中包括…...
Android Handler/Looper视角看UI线程的原理
概述 Handler/Looper机制是android系统非重要且基础的机制,即使在rtos或者linux操作系统上开发应用框架时,也经常借鉴这个机制。通过该机制机制可以让一个线程循环处理事件,事件处理逻辑即在Handler的handleMessge种。本文建议android8.1源码…...
【网络】网络入门
网络入门 一、网络发展二、网络协议初识1、认识"协议"2、协议分层3、OSI七层模型4、TCP/IP五层(或四层)模型 三、网络传输基本流程1、同局域网的两台主机通信2、跨网络的两台主机通信 四、网络中的地址管理1、IP地址2、认识MAC地址 一、网络发展 独立模式:…...
GO-实现简单文本格式 文本字体颜色、大小、突出
毫无疑问GO的生态就是一坨大便。老子英文水平小学啊。 实现简单文本格式 文本字体颜色、大小、突出显示等。 创建要给docx文件容器【我估算的】 doc : document.New() defer doc.Close() doc.SaveToFile("simple.docx") 把容器保存为文件 设置标题 创建自然段…...
铅华洗尽,粉黛不施,人工智能AI基于ProPainter技术去除图片以及视频水印(Python3.10)
视频以及图片修复技术是一项具有挑战性的AI视觉任务,它涉及在视频或者图片序列中填补缺失或损坏的区域,同时保持空间和时间的连贯性。该技术在视频补全、对象移除、视频恢复等领域有广泛应用。近年来,两种突出的方案在视频修复中崭露头角&…...
latex,不带行号的algorithm
\usepackage{algorithm,algorithmic}\begin{algorithm} \caption{The Example Algorithm} \label{alg123} \begin{algorithmic} \STATE{\textbf{Input:} ...} \STATE{\textbf{Output:} ...} \IF{...} \STATE{...} \ENDIF \RETURN{...} \end{algorithmic} \end{algorithm}...
RocketMQ高性能核心原理与源码架构剖析
文章目录 一、源码环境搭建主要功能模块源码启动服务启动nameServer启动Broker发送消息消费消息 二、源码热身阶段NameServer的启动过程关注重点源码重点 Broker服务启动过程关注重点源码重点 Netty服务注册框架关注重点源码重点关于RocketMQ的同步结果推送与异步结果推送 Brok…...
MATLAB中zp2tf函数用法
目录 语法 说明 示例 质点弹簧系统的传递函数 zp2tf函数的功能是将零极点增益滤波器参数转换为传递函数形式。。 语法 [b,a] zp2tf(z,p,k) 说明 [b, a] zp2tf(z, p, k) 将一个分解的传递函数表示方式转换。 将单输入/多输出(SIMO)系统的多输出…...
龙岗区最新通告/提高seo关键词排名
goldengate for sqlserver 日志暴涨的解决办法 gg for sqlserver 2008 R2 开启后,sqlserver的日志会出现暴涨的情况,解决办法如下: 1.先确认是否数据库设置问题导致 如: 1)查看ggerror中,是否有报错! 2)…...
哪里有学习做网站的/网络营销方式都有哪些
2016-12-12 11:57:12使用ajax的开发项目过程中,经常需要将json格式的字符串返回到前端,前端解析成js对象(JSON )。如果直接以json的格式返回则方便很多,有时候通过后台直接写到页面中则会以字符串的方式存在,那么就用到了将字符串…...
网站建设 技术要求/品牌管理
我正在使用Apache-Commons FileUpload库将文件上传到服务器.一切正常,但是突然提交文件时,由于某些原因FileItem.isFormField()返回true.这是我的代码FileUpload.java Servletif (ServletFileUpload.isMultipartContent(request)){List items new ServletFileUpload(new DiskF…...
在香港建设黄色网站是否违法/免费的推文制作网站
原因是Protocol buffers协议多了以后后整个项目比较大,超过了idea的限制了,调节下配置就可以了。找到idea安装目录bin/idea.properties文件 idea.max.intellisense.filesize92500 #默认2500...
泰安网站的建设/海口百度seo公司
1. 前言 说起 Github,大家可能都觉得那只是程序员的聚集地。今天就要告诉大家,Github 不仅仅是 Coder 们的专属,它同时也是一个巨大的资源宝库! 由于我也算是个半吊子的程序员了,所以用 Github 也算久的了࿰…...
芜湖网站建设推广/网络推广网站有哪些
有序数组的 Two Sum两数平方和反转字符串中的元音字符回文字符串归并两个有序数组判断链表是否存在环最长子序列 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。 有序数组的 Two Sum Leetcode :167. Two Sum II - Inpu…...