消息状态在业务层的定义和判定问题

“阅读状态”的判定从本质上讲是一个无解的问题,用户到底读没读消息是不可判定的,举个例子:就算用户在会话界面不断翻页浏览,技术上也无法判定具体用户做了什么。目前是基于一些假设实现的,用户进入会话,假设用户会浏览本会话里的的未读消息;语音消息,假设用户点击播放了就是读取了消息;,,,业务上可以重新设定逻辑并做对应实现。
发布时间: 2017-10-27 13:52

回答:

从技术角度来看,消息的状态就是发送(输入消息、发送中,发送成功/失败)和接收状态(已接收)。

从产品角度来看,消息发送和接收也都容易理解容易处理,容易混淆的是“阅读状态”。

消息的“阅读状态”是针对于会话而言的(以单聊为例,下同),需要区分对话双方,A 和 B 进行聊天,A 是否已读和 B 是否已读显然是不同的问题:

1:A 和 B 分别维护自己的阅读状态,涉及处理“新消息”和“历史消息”的关系

2:让对方看自己的阅读状态 涉及“消息回执”

“阅读状态”的判定从本质上讲是一个无解的问题,用户到底读没读消息是不可判定的,举个例子:就算用户在会话界面不断翻页浏览,技术上也无法判定具体用户做了什么。目前是基于一些假设实现的,主要假设如下:

1:用户进入会话,假设用户会浏览本会话里的的未读消息;

      对应的处理是会话有新消息,进入会话时通过调用 clearUnreadCount 设为自己已读

      请注意,融云服务器端消息是没有状态的,具体状态是根据消息的发送时间(消息达到服务器端的时间)和用户阅读时间戳(用户已读的最后一条消息的发送时间)的关系来计算得知的,clearUnreadCount 就是在不断的更新这个时间戳,用户的阅读时间戳在浏览器做本地缓存(请注意保护相应缓存),经此处理,新消息变为历史消息,所以,从服务器端再次获取的历史消息为自己已读

2:语音消息,假设用户点击播放了就是读取了消息;

      对应的处理是点击播放语音时,标为本条语音已读,数据集成时自行处理维护(如果在业务里假设用户必须播放完成才算已读,则处理时改进对应逻辑)

3:图片、文件消息等,目前默认跟随假设1,业务集成时也可以仿照假设2进行定义和处理

4:业务可以做其他的一些逻辑设定,并基于现在的数据进行处理


附相关的技术处理方式(以 Web 为例):

1:消息状态:http://support.rongcloud.cn/kb/NjE0 

2:消息回执(本质是基于 lastMessage 传递 sentTime,因为消息里的时间都是服务器端时间):

    var content = {

        lastMessageSendTime: lastMessage.sentTime,

        messageUId: lastMessage.messageUId,

        type: 1

    };

    var conversationType = RongIMLib.ConversationType.PRIVATE;

    var targetId = lastMessage.targetId;

    var msg = new RongIMLib.ReadReceiptMessage(content);

    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {

        onSuccess: function (message) {

        },

        onError: function (errorCode,message) {

        }

    });