PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/com/linbox/im/server/service/impl/InboxService.java

https://gitlab.com/Mr.Tomato/linbox_server
Java | 236 lines | 183 code | 50 blank | 3 comment | 29 complexity | 553f39ff9317505e05057c855ff06b89 MD5 | raw file
  1. package com.linbox.im.server.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.linbox.im.message.UnreadMsg;
  4. import com.linbox.im.server.constant.RedisKey;
  5. import com.linbox.im.server.service.IInboxService;
  6. import com.linbox.im.server.service.StopcockService;
  7. import com.linbox.im.message.Message;
  8. import com.linbox.im.server.storage.UnreadLoopData;
  9. import org.apache.commons.lang.StringUtils;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Service;
  14. import redis.clients.jedis.Jedis;
  15. import redis.clients.jedis.JedisPool;
  16. import redis.clients.jedis.ScanParams;
  17. import redis.clients.jedis.ScanResult;
  18. import java.util.LinkedList;
  19. import java.util.List;
  20. import java.util.Map;
  21. /**
  22. * Created by lrsec on 7/2/15.
  23. */
  24. @Service
  25. public class InboxService extends StopcockService<String> implements IInboxService {
  26. public static final Logger logger = LoggerFactory.getLogger(InboxService.class);
  27. @Autowired
  28. private JedisPool jedisPool;
  29. public void updateSessionMsg(String id, String sessionId, Message msg) {
  30. updateMsg(id, sessionId, msg);
  31. }
  32. public void updateGroupMsg(String id, String groupId, Message msg) {
  33. updateMsg(id, groupId, msg);
  34. }
  35. private void updateMsg(String id, String field, Message msg) {
  36. if (StringUtils.isBlank(id) || StringUtils.isBlank(field)) {
  37. logger.error("Get empty id or field when updating unread message. id: {}. field: {}", StringUtils.trimToEmpty(id), StringUtils.trimToEmpty(field));
  38. return;
  39. }
  40. String redisKey = RedisKey.getInboxKey(id);
  41. String json = JSON.toJSONString(msg);
  42. if (StringUtils.isBlank(json)) {
  43. logger.error("Message format is not correct. Get a empty json string when updating unread for user: {}. field: {}", StringUtils.trimToEmpty(id), StringUtils.trimToEmpty(field));
  44. return;
  45. }
  46. lock(redisKey);
  47. try {
  48. try (Jedis jedis = jedisPool.getResource()) {
  49. String oldMsg = jedis.hget(redisKey, field);
  50. UnreadMsg oldUnreadMsg = JSON.parseObject(oldMsg, UnreadMsg.class);
  51. UnreadMsg newUnreadMsg;
  52. if (oldUnreadMsg == null || (oldUnreadMsg.msgId < msg.msgId)) {
  53. newUnreadMsg = new UnreadMsg();
  54. newUnreadMsg.msg = msg;
  55. newUnreadMsg.msgId = msg.msgId;
  56. newUnreadMsg.count = oldUnreadMsg == null ? 1 : (oldUnreadMsg.count + msg.msgId - oldUnreadMsg.msgId);
  57. newUnreadMsg.userId = (StringUtils.equals(id, msg.fromUserId)) ? msg.fromUserId : msg.toUserId;
  58. newUnreadMsg.remoteId = (StringUtils.equals(id, msg.fromUserId)) ? msg.toUserId : msg.fromUserId;
  59. newUnreadMsg.type = msg.type;
  60. } else {
  61. newUnreadMsg = oldUnreadMsg;
  62. }
  63. if (newUnreadMsg == null) {
  64. logger.error("The message is stale. Message in redis: {}. Message received: {}", JSON.toJSONString(oldUnreadMsg), JSON.toJSONString(msg));
  65. return;
  66. }
  67. jedis.hset(redisKey, field, JSON.toJSONString(newUnreadMsg));
  68. }
  69. } finally {
  70. unlock(redisKey);
  71. }
  72. }
  73. public void removeSessionMsg (String id, String sessionId, long msgId) {
  74. removeMsg(id, sessionId, msgId);
  75. }
  76. public void removeGroupMsg(String id, String groupId, long msgId) {
  77. removeMsg(id, groupId, msgId);
  78. }
  79. private void removeMsg(String id, String field, long msgId) {
  80. if (StringUtils.isBlank(id) || StringUtils.isBlank(field)) {
  81. logger.error("Get empty id or field when removing unread message. id: {}. field: {}", StringUtils.trimToEmpty(id), StringUtils.trimToEmpty(field));
  82. return;
  83. }
  84. String redisKey = RedisKey.getInboxKey(id);
  85. lock(redisKey);
  86. try {
  87. try(Jedis jedis = jedisPool.getResource()) {
  88. String json = jedis.hget(redisKey, field);
  89. UnreadMsg msg = JSON.parseObject(json, UnreadMsg.class);
  90. if (msg != null) {
  91. if (msg.msgId <= msgId) {
  92. jedis.hdel(redisKey, field);
  93. } else {
  94. msg.count = msg.msgId - msgId;
  95. jedis.hset(redisKey, field, JSON.toJSONString(msg));
  96. }
  97. }
  98. }
  99. } catch(Exception e) {
  100. logger.error("Remove message fail.", e);
  101. } finally {
  102. unlock(redisKey);
  103. }
  104. }
  105. public String getSessionJson(String id, String sessionId) {
  106. return getJson(id, sessionId);
  107. }
  108. public String getGroupJson(String id, String groupId) {
  109. return getJson(id, groupId);
  110. }
  111. public UnreadLoopData getAllJson(String id, long offset, int limit) {
  112. UnreadLoopData data = new UnreadLoopData();
  113. if (StringUtils.isBlank(id)) {
  114. logger.error("Get empty id when getting all unread message. id: {}.", StringUtils.trimToEmpty(id));
  115. return data;
  116. }
  117. String redisKey = RedisKey.getInboxKey(id);
  118. lock(redisKey);
  119. try {
  120. try(Jedis jedis = jedisPool.getResource()) {
  121. long cusor = offset;
  122. int currentLimit = limit;
  123. ScanParams params = new ScanParams();
  124. do {
  125. params.count(currentLimit);
  126. ScanResult<Map.Entry<String, String>> result = jedis.hscan(redisKey, Long.toString(cusor), params);
  127. List<Map.Entry<String, String>> entities = result.getResult();
  128. if (entities != null) {
  129. for(Map.Entry<String, String> e : entities) {
  130. data.unreads.add(e.getValue());
  131. }
  132. }
  133. cusor = Long.parseLong(result.getStringCursor());
  134. currentLimit = limit - data.unreads.size();
  135. } while (data.unreads.size() < limit && cusor != 0);
  136. }
  137. } finally {
  138. unlock(redisKey);
  139. }
  140. return data;
  141. }
  142. private String getJson(String id, String field) {
  143. String result = null;
  144. if (StringUtils.isBlank(id) || StringUtils.isBlank(field)) {
  145. logger.error("Get empty id or session_id when getting group unread message. user id: {}. field: {}", StringUtils.trimToEmpty(id), StringUtils.trimToEmpty(field));
  146. return null;
  147. }
  148. String redisKey = RedisKey.getInboxKey(id);
  149. lock(redisKey);
  150. try {
  151. try (Jedis jedis = jedisPool.getResource()) {
  152. result = jedis.hget(redisKey, field);
  153. }
  154. } finally {
  155. unlock(redisKey);
  156. }
  157. return result;
  158. }
  159. @Override
  160. public int getTotalUnreadCount(String id) {
  161. int count = 0;
  162. if (StringUtils.isBlank(id)) {
  163. logger.error("Id is empty when getting total unread count");
  164. return count;
  165. }
  166. List<String> unreads = new LinkedList<>();
  167. String redisKey = RedisKey.getInboxKey(id);
  168. lock(redisKey);
  169. try {
  170. try(Jedis jedis = jedisPool.getResource()) {
  171. unreads.addAll(jedis.hvals(redisKey));
  172. for (String s : unreads) {
  173. UnreadMsg msg = JSON.parseObject(s, UnreadMsg.class);
  174. if (msg == null) {
  175. logger.error("A unread record could not be parsed to UnreadMsg. JSON: {}. User id: {}", s, id);
  176. continue;
  177. }
  178. count += msg.count;
  179. }
  180. }
  181. } finally {
  182. unlock(redisKey);
  183. }
  184. return count;
  185. }
  186. }