|
|
@ -124,77 +124,85 @@ public class MessageHandler { |
|
|
|
|
|
|
|
@Async("cc-msg-executor") |
|
|
|
public void loopSendMessage() throws Exception { |
|
|
|
logger.info("开始执行循环方法"); |
|
|
|
String typeAndUserId = null,ackId = null; |
|
|
|
List<Message> messageList = null; |
|
|
|
List<String> sendTimesUpLimitMessageList = null,expiredMessageList = null; |
|
|
|
|
|
|
|
while(true){ |
|
|
|
//从redis中或取第一个待处理用户
|
|
|
|
Object o = RedisUtil.sPop(RedisKeyManager.getPendingClientSetKey()); |
|
|
|
if(o != null && StrUtil.isNotEmpty(typeAndUserId = ackId = (String)o)){ |
|
|
|
Console.log("RedisUtil.sPop: {}",o); |
|
|
|
String []stringArray = CcMessageUtil.splitTypeAndUserId(typeAndUserId); |
|
|
|
MessageConstant.DomainType toDomain = MessageConstant.DomainType.valueOf(stringArray[0]); |
|
|
|
String to = stringArray[1]; |
|
|
|
|
|
|
|
MessageConstant.InvokerMessage invokerMessage = null; |
|
|
|
if (stringArray.length >= 3 && StrUtil.isNotEmpty(stringArray[2]) ) { |
|
|
|
invokerMessage = JacksonUtil.jsonToBean(stringArray[2], MessageConstant.InvokerMessage.class); |
|
|
|
} |
|
|
|
//授权时保存的业务消息
|
|
|
|
String authBusinessMessage = stringArray.length > 3 ? stringArray[3] : null; |
|
|
|
//针对同一用户,在上一次ack还未收到/超时之前,不进行处理
|
|
|
|
Object lockObj = ResourceLock.getLockObj(ackId); |
|
|
|
logger.info("上锁:{}", lockObj); |
|
|
|
synchronized (lockObj) { |
|
|
|
//查找该用户是否有正在处理的消息
|
|
|
|
if (RedisUtil.hasKey(RedisKeyManager.getAckSetKey(ackId))) { |
|
|
|
logger.info("用户有消息正在处理"); |
|
|
|
//将当前用户重新放回到待处理列表的最后
|
|
|
|
RedisUtil.sSet(RedisKeyManager.getPendingClientSetKey(), o); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
//查找所有没有ack的消息
|
|
|
|
messageList = getMessageDao().getClientPendingMessage(toDomain, to, MAX_MESSAGE_NUM); |
|
|
|
if (CollectionUtil.isEmpty(messageList)) { |
|
|
|
logger.info("messageList是空"); |
|
|
|
continue; |
|
|
|
try { |
|
|
|
logger.info("while true"); |
|
|
|
//从redis中或取第一个待处理用户
|
|
|
|
Object o = RedisUtil.sPop(RedisKeyManager.getPendingClientSetKey()); |
|
|
|
logger.info("从redis中或取第一个待处理用户:{},{}", RedisKeyManager.getPendingClientSetKey(), o); |
|
|
|
if(o != null && StrUtil.isNotEmpty(typeAndUserId = ackId = (String)o)){ |
|
|
|
Console.log("RedisUtil.sPop: {}",o); |
|
|
|
String []stringArray = CcMessageUtil.splitTypeAndUserId(typeAndUserId); |
|
|
|
MessageConstant.DomainType toDomain = MessageConstant.DomainType.valueOf(stringArray[0]); |
|
|
|
String to = stringArray[1]; |
|
|
|
logger.info("to:{},toDomain:{}", to, toDomain); |
|
|
|
MessageConstant.InvokerMessage invokerMessage = null; |
|
|
|
if (stringArray.length >= 3 && StrUtil.isNotEmpty(stringArray[2]) ) { |
|
|
|
invokerMessage = JacksonUtil.jsonToBean(stringArray[2], MessageConstant.InvokerMessage.class); |
|
|
|
} |
|
|
|
//授权时保存的业务消息
|
|
|
|
String authBusinessMessage = stringArray.length > 3 ? stringArray[3] : null; |
|
|
|
//针对同一用户,在上一次ack还未收到/超时之前,不进行处理
|
|
|
|
Object lockObj = ResourceLock.getLockObj(ackId); |
|
|
|
logger.info("上锁:{}", lockObj); |
|
|
|
synchronized (lockObj) { |
|
|
|
//查找该用户是否有正在处理的消息
|
|
|
|
if (RedisUtil.hasKey(RedisKeyManager.getAckSetKey(ackId))) { |
|
|
|
logger.info("用户有消息正在处理"); |
|
|
|
//将当前用户重新放回到待处理列表的最后
|
|
|
|
RedisUtil.sSet(RedisKeyManager.getPendingClientSetKey(), o); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
//判断用户是否在线
|
|
|
|
boolean clientOnLine = ClientManager.isUserOnline(toDomain,to); |
|
|
|
logger.info("用户是否在线:{}", clientOnLine); |
|
|
|
//发送和处理消息
|
|
|
|
if(clientOnLine){ |
|
|
|
//发送
|
|
|
|
//1.手机所有待发送的messageId,以ackId为key放入redis
|
|
|
|
Set<String> messageIdSet = new HashSet<>(messageList.size()); |
|
|
|
OutMessageSet outMessageSet = OutMessageSet.newInstance(); |
|
|
|
for(Message message : messageList) { |
|
|
|
messageIdSet.add(message.getId()); |
|
|
|
outMessageSet.add(new OutMessage(message, authBusinessMessage)); |
|
|
|
getMessageDao().incrementSendTimes(message.getId(), DateUtil.currentSeconds()); |
|
|
|
//查找所有没有ack的消息
|
|
|
|
messageList = getMessageDao().getClientPendingMessage(toDomain, to, MAX_MESSAGE_NUM); |
|
|
|
logger.info("messageList:{}", messageList); |
|
|
|
if (CollectionUtil.isEmpty(messageList)) { |
|
|
|
logger.info("messageList是空"); |
|
|
|
continue; |
|
|
|
} |
|
|
|
RedisUtil.sSetAndTime(RedisKeyManager.getAckSetKey(ackId),REDIS_ACK_EXPIRED_SECONDS,messageIdSet.toArray()); |
|
|
|
|
|
|
|
//2.构造outMessage并且发送
|
|
|
|
outMessageSet.ackId(ackId); |
|
|
|
|
|
|
|
//发送给对应的接收者
|
|
|
|
logger.info("给{}发送消息:{}", to, outMessageSet); |
|
|
|
ClientManager.sendMessageToAuthedClient(toDomain,invokerMessage, to,outMessageSet); |
|
|
|
}else{ |
|
|
|
//不发送,根据规则检查所有“offLineDiscard”的消息设置为failed状态
|
|
|
|
for(Message message : messageList){ |
|
|
|
if(message.getRule().getOfflineDiscard() == 1){ |
|
|
|
getMessageDao().updateMessageStatus(message.getId(),MessageConstant.Status.Failed); |
|
|
|
|
|
|
|
//判断用户是否在线
|
|
|
|
boolean clientOnLine = ClientManager.isUserOnline(toDomain,to); |
|
|
|
logger.info("用户是否在线:{}", clientOnLine); |
|
|
|
//发送和处理消息
|
|
|
|
if(clientOnLine){ |
|
|
|
//发送
|
|
|
|
//1.手机所有待发送的messageId,以ackId为key放入redis
|
|
|
|
Set<String> messageIdSet = new HashSet<>(messageList.size()); |
|
|
|
OutMessageSet outMessageSet = OutMessageSet.newInstance(); |
|
|
|
for(Message message : messageList) { |
|
|
|
messageIdSet.add(message.getId()); |
|
|
|
outMessageSet.add(new OutMessage(message, authBusinessMessage)); |
|
|
|
getMessageDao().incrementSendTimes(message.getId(), DateUtil.currentSeconds()); |
|
|
|
} |
|
|
|
RedisUtil.sSetAndTime(RedisKeyManager.getAckSetKey(ackId),REDIS_ACK_EXPIRED_SECONDS,messageIdSet.toArray()); |
|
|
|
logger.info("存储redis:{},{},{}",RedisKeyManager.getAckSetKey(ackId),REDIS_ACK_EXPIRED_SECONDS,messageIdSet.toArray()); |
|
|
|
//2.构造outMessage并且发送
|
|
|
|
outMessageSet.ackId(ackId); |
|
|
|
|
|
|
|
//发送给对应的接收者
|
|
|
|
logger.info("给{}发送消息:{}", to, outMessageSet); |
|
|
|
ClientManager.sendMessageToAuthedClient(toDomain,invokerMessage, to,outMessageSet); |
|
|
|
}else{ |
|
|
|
//不发送,根据规则检查所有“offLineDiscard”的消息设置为failed状态
|
|
|
|
for(Message message : messageList){ |
|
|
|
if(message.getRule().getOfflineDiscard() == 1){ |
|
|
|
getMessageDao().updateMessageStatus(message.getId(),MessageConstant.Status.Failed); |
|
|
|
} |
|
|
|
} |
|
|
|
logger.info("没有发送消息"); |
|
|
|
} |
|
|
|
logger.info("没有发送消息"); |
|
|
|
} |
|
|
|
ResourceLock.freeLockObj(ackId); |
|
|
|
} |
|
|
|
ResourceLock.freeLockObj(ackId); |
|
|
|
} catch (Exception e) { |
|
|
|
logger.error("循环发送消息异常", e); |
|
|
|
} |
|
|
|
try { |
|
|
|
Thread.sleep(100); |
|
|
@ -472,8 +480,9 @@ public class MessageHandler { |
|
|
|
// 寄存器将要修改的数据
|
|
|
|
long value = 0; |
|
|
|
for (int j = 0; j < CCModBusEntity.SIZE_DATA_SINGLE; j++) { |
|
|
|
|
|
|
|
value <<= 8; |
|
|
|
value += modBusData[CCModBusEntity.POSITION_DATA + CCModBusEntity.SIZE_DATA_SINGLE * i + j]; |
|
|
|
value |= modBusData[CCModBusEntity.POSITION_DATA + CCModBusEntity.SIZE_DATA_SINGLE * i + j] & 0xFF; |
|
|
|
} |
|
|
|
if (origin == null || origin.longValue() != value) { |
|
|
|
register.put(String.valueOf(startAddr + i), value); |
|
|
|