开发过程中的一点小记录——云信相关

叁叁肆2018-09-28 15:22

本文来自网易云社区

作者:汪昕濛

遗留问题排查
项目需要从云信拉取用户与官方帐号之间的历史消息,产品反映之前的接口只能拉取一个月的历史消息,想要把这个时间段设长一点。
乍一听觉得很奇怪,获取历史消息的接口,怎么会有这样子的约束。
首先我询问了一下以前做这块的开发小哥哥为什么设置只取一个月的历史消息,答曰:云信有限制,调试所得最优时间。
实在纳闷,云信这种通用的组件,应该不会做这样的限制。仔细研究了一下云信的接口文档,也没有提到有关时间限制的问题,最多只是提到了返回数据的数量问题。
   
既然不是别人接口的问题,那肯定就是我们自己的代码有问题了。现有给云信发送的查询参数是这么拼接的,可以查询到21天前的历史消息。
	Map params = new HashMap();
	params.put("from", senderAccount.getAccid());
	params.put("to", receiverAccount.getAccid());
	params.put("limit", "100");
	params.put("reverse", "2");
	long now = System.currentTimeMillis();
	params.put("begintime", String.valueOf(now-21 * 24 * 3600 * 1000));
	params.put("endtime", String.valueOf(now));
看了又看,没看出什么问题,那么把参数调整一下,试试会不会报错吧。
	Map params = new HashMap();
	params.put("from", senderAccount.getAccid());
	params.put("to", receiverAccount.getAccid());
	params.put("limit", "100");
	params.put("reverse", "2");
	long now = System.currentTimeMillis();
	params.put("begintime", String.valueOf(now-31 * 24 * 3600 * 1000));
	params.put("endtime", String.valueOf(now));
开发小哥哥诚不欺我,果然报错了。返回的错误信息如下:{"desc":"bad time","code":414}
查询云信的接口文档得知:414状态码表示参数错误。改动到的参数,毫无疑问只有beginTime这一处了。
调试时重点观察了一下begintime的值,发现一个跟诡异的地方,它居然比now还大。直觉告诉我,这肯定是后面一串拼接的表达式的问题,单独打印了一下,居然是负值。
恍然大悟,由于后面是int类型的值,int类型的最大长度为-2147483648~2147483647,当数值超出int类型的长度时,会截断高位,使之变为负数,结果自然就不对了。
想必云信接口报错也是因为beginTime > endTime导致的。
简单粗暴地把beginTime设置为0,就可以愉快地查询历史记录了。

现有接口完善
解决了这个问题,就要再来解决每次最多只返回100条历史消息的问题了。
查看文档发现,云信接口可以支持返回消息记录按时间降序排列。那么在此基础上,我们只需要以endTime为基准,分批取数据,并从当前批次历史消息最早的一个记录中,取到发送时间,将endTime推进到它的时刻,再继续查询,就能取到全部的历史记录了。示例如下:
贴下最终代码:
	String endTime = String.valueOf(System.currentTimeMillis());
	JSONArray msgs = new JSONArray();
	Map params = new HashMap();
	params.put("from", senderAccount.getAccid());
	params.put("to", receiverAccount.getAccid());
	params.put("limit", "100");
	params.put("reverse", "2");//按时间倒序返回
	params.put("begintime", "0");
	while(true) {
		params.put("endtime", endTime);
		String resposeContent = RequestUtil.doPostRequest("https://api.netease.im/nimserver/history/querySessionMsg.action", params, makeYunXinHeaderMap(), true);
		if(StringUtils.isBlank(resposeContent)) {
			break;
		}
		JSONObject result = JSONObject.fromObject(resposeContent);
		if(result.getInt("code") != HttpStatus.SC_OK) {
			logger.info("query yunxin message history error, result:"+resposeContent+" & "+senderId + " to " + receiverId);
			break;
		}
		JSONArray subMsgs = result.getJSONArray("msgs");
		msgs.addAll(subMsgs);
		//少于100条记录说明历史记录已全部返回,不用分批次再查询
		if(subMsgs.size() < 100) {
			break;
		}
		endTime = subMsgs.getJSONObject(subMsgs.size() - 1).getString("sendtime");
	} 
	return msgs;



网易云免费体验馆,0成本体验20+款云产品! 

更多网易研发、产品、运营经验分享请访问网易云社区