|
@@ -0,0 +1,92 @@
|
|
|
+package vip.xiaonuo.coldchain.core.alarm.service.messagepush;
|
|
|
+
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.context.annotation.Primary;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import vip.xiaonuo.coldchain.core.alarm.bean.NotificationChannel;
|
|
|
+import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarm;
|
|
|
+import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarmUser;
|
|
|
+import vip.xiaonuo.coldchain.core.alarm.mapper.SensorAlarmMapper;
|
|
|
+import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author jackzhou
|
|
|
+ * @version 1.0
|
|
|
+ * @project jfcloud-coldchain
|
|
|
+ * @description
|
|
|
+ * @date 2024/11/27 16:09:54
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Primary
|
|
|
+public class RedisSensorAlarmMessagePushService {
|
|
|
+ private final Map<String, MessagePushService> pushServices;
|
|
|
+ private final SensorAlarmMapper sensorAlarmMapper;
|
|
|
+ private final RedisTemplate<String, Object> redisTemplate;
|
|
|
+
|
|
|
+ @Async("coldChainAsyncTask")
|
|
|
+ public void pushAlarmMessage(SensorAlarm alarm) {
|
|
|
+ String deviceID = alarm.getDeviceId();
|
|
|
+ String alarmType = alarm.getAlarmType();
|
|
|
+ List<String> openids = Optional.ofNullable(alarm.getAlarmUsers()).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).map(SensorAlarmUser::getOpenId).filter(Objects::nonNull).toList();
|
|
|
+
|
|
|
+ for (String openid : openids) {
|
|
|
+ if (hasExceededPushLimit(openid, deviceID, alarmType)) {
|
|
|
+ log.info("用户 {} 对设备 {} 的告警类型 {} \n在过去{}分钟内推送次数超过限制,跳过推送", openid, deviceID, alarmType, JfcloudColdChainConstants.MESS_PUSH_TIME_WINDOW / 60 / 1000);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (NotificationChannel channel : alarm.getNotificationChannel()) {
|
|
|
+ MessagePushService pushService = pushServices.get(channel.name());
|
|
|
+ if (pushService != null) {
|
|
|
+ try {
|
|
|
+ pushService.sendAlarmMessage(alarm);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("推送消息失败,渠道: {},错误: {}", channel.getChannelName(), e.getMessage());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.warn("不支持的通知渠道: {}", channel.getChannelName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ recordPushTime(openid, deviceID, alarmType);
|
|
|
+ }
|
|
|
+
|
|
|
+ alarm.setNotified(true);
|
|
|
+ saveAlarmToDatabase(alarm);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean hasExceededPushLimit(String openid, String deviceID, String alarmType) {
|
|
|
+ String key = generatePushHistoryKey(openid, deviceID, alarmType);
|
|
|
+ List<Object> pushTimes = redisTemplate.opsForList().range(key, 0, -1);
|
|
|
+ if (pushTimes == null || pushTimes.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
+ pushTimes.removeIf(time -> currentTime - (Long) time > JfcloudColdChainConstants.MESS_PUSH_TIME_WINDOW);
|
|
|
+ return pushTimes.size() >= JfcloudColdChainConstants.MESS_PUSH_MAX_PUSH_COUNT;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void recordPushTime(String openid, String deviceID, String alarmType) {
|
|
|
+ String key = generatePushHistoryKey(openid, deviceID, alarmType);
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
+ redisTemplate.opsForList().rightPush(key, currentTime);
|
|
|
+ redisTemplate.opsForList().trim(key, -JfcloudColdChainConstants.MESS_PUSH_MAX_PUSH_COUNT, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveAlarmToDatabase(SensorAlarm alarm) {
|
|
|
+ try {
|
|
|
+ sensorAlarmMapper.insert(alarm);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("保存告警信息到数据库失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String generatePushHistoryKey(String openid, String deviceID, String alarmType) {
|
|
|
+ return JfcloudColdChainConstants.REDIS_PUSH_HISTORY_KEY_PREFIX + ":" + openid + ":" + deviceID + ":" + alarmType;
|
|
|
+ }
|
|
|
+}
|