You've already forked FrameTour-BE
refactor(device): 重构设备信息获取逻辑,增加缓存降级策略
- 新增 DeviceV2DTO 转换为 DeviceEntity 的方法 - 引入成功结果缓存,用于失败时降级 - 优化 getDevice 和 getDeviceByDeviceNo 方法,增加异常处理和缓存逻辑 - 清理缓存时增加成功结果缓存的清理
This commit is contained in:
@@ -5,52 +5,107 @@ import com.ycwl.basic.mapper.DeviceMapper;
|
|||||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
|
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
||||||
|
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class DeviceRepository {
|
public class DeviceRepository {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceMapper deviceMapper;
|
private DeviceMapper deviceMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, String> redisTemplate;
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
|
@Autowired
|
||||||
|
private DeviceIntegrationService deviceIntegrationService;
|
||||||
|
|
||||||
public static final String DEVICE_ONLINE_CACHE_KEY = "device:online_status:%s";
|
public static final String DEVICE_ONLINE_CACHE_KEY = "device:online_status:%s";
|
||||||
public static final String DEVICE_CACHE_KEY = "device:%s";
|
public static final String DEVICE_CACHE_KEY = "device:%s";
|
||||||
public static final String DEVICE_CONFIG_CACHE_KEY = "device:%s:config";
|
public static final String DEVICE_CONFIG_CACHE_KEY = "device:%s:config";
|
||||||
|
public static final String DEVICE_CACHE_SUCCESS_KEY = "device:success:%s";
|
||||||
|
public static final String DEVICE_NO_CACHE_SUCCESS_KEY = "device:success:no:%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将DeviceV2DTO转换为DeviceEntity
|
||||||
|
*/
|
||||||
|
private DeviceEntity convertToEntity(DeviceV2DTO dto) {
|
||||||
|
if (dto == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DeviceEntity entity = new DeviceEntity();
|
||||||
|
entity.setId(dto.getId());
|
||||||
|
entity.setName(dto.getName());
|
||||||
|
entity.setNo(dto.getNo());
|
||||||
|
entity.setScenicId(dto.getScenicId());
|
||||||
|
// DeviceV2DTO中的isActive对应DeviceEntity中的status
|
||||||
|
entity.setStatus(dto.getIsActive());
|
||||||
|
// 转换时间格式:LocalDateTime -> Date
|
||||||
|
if (dto.getCreateTime() != null) {
|
||||||
|
entity.setCreateAt(Date.from(dto.getCreateTime().atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
}
|
||||||
|
if (dto.getUpdateTime() != null) {
|
||||||
|
entity.setUpdateAt(Date.from(dto.getUpdateTime().atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
public DeviceEntity getDevice(Long deviceId) {
|
public DeviceEntity getDevice(Long deviceId) {
|
||||||
if (redisTemplate.hasKey(String.format(DEVICE_CACHE_KEY, deviceId))) {
|
log.debug("获取设备信息, deviceId: {}", deviceId);
|
||||||
return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(DEVICE_CACHE_KEY, deviceId)), DeviceEntity.class);
|
try {
|
||||||
}
|
DeviceV2DTO deviceDto = deviceIntegrationService.getDevice(deviceId);
|
||||||
DeviceEntity device = deviceMapper.getByDeviceId(deviceId);
|
DeviceEntity device = convertToEntity(deviceDto);
|
||||||
if (null != device) {
|
if (device != null) {
|
||||||
|
// 存储到常规缓存
|
||||||
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceId), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceId), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
||||||
|
// 存储到成功结果缓存,用于失败时降级
|
||||||
|
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_SUCCESS_KEY, deviceId), JacksonUtil.toJSONString(device), 7, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("调用zt-device服务失败, deviceId: {}, 尝试返回缓存结果", deviceId, e);
|
||||||
|
String cachedDevice = redisTemplate.opsForValue().get(String.format(DEVICE_CACHE_SUCCESS_KEY, deviceId));
|
||||||
|
if (cachedDevice != null) {
|
||||||
|
log.info("返回缓存的设备信息, deviceId: {}", deviceId);
|
||||||
|
return JacksonUtil.parseObject(cachedDevice, DeviceEntity.class);
|
||||||
|
}
|
||||||
|
log.error("无法获取设备信息且无缓存数据, deviceId: {}", deviceId);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceEntity getDeviceByDeviceNo(String deviceNo) {
|
public DeviceEntity getDeviceByDeviceNo(String deviceNo) {
|
||||||
if (redisTemplate.hasKey(String.format(DEVICE_CACHE_KEY, deviceNo))) {
|
log.debug("根据设备编号获取设备信息, deviceNo: {}", deviceNo);
|
||||||
return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(DEVICE_CACHE_KEY, deviceNo)), DeviceEntity.class);
|
try {
|
||||||
}
|
DeviceV2DTO deviceDto = deviceIntegrationService.getDeviceByNo(deviceNo);
|
||||||
DeviceEntity device = deviceMapper.getByDeviceNo(deviceNo);
|
DeviceEntity device = convertToEntity(deviceDto);
|
||||||
if (null == device) {
|
if (device != null) {
|
||||||
device = deviceMapper.getByDeviceNo2(deviceNo);
|
// 存储到常规缓存
|
||||||
}
|
|
||||||
if (null != device) {
|
|
||||||
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceNo), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceNo), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
||||||
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getId()), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getId()), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
|
||||||
} else {
|
// 存储到成功结果缓存,用于失败时降级
|
||||||
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, deviceNo), "null", 60L, TimeUnit.SECONDS);
|
redisTemplate.opsForValue().set(String.format(DEVICE_NO_CACHE_SUCCESS_KEY, deviceNo), JacksonUtil.toJSONString(device), 7, TimeUnit.DAYS);
|
||||||
|
redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_SUCCESS_KEY, device.getId()), JacksonUtil.toJSONString(device), 7, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("调用zt-device服务失败, deviceNo: {}, 尝试返回缓存结果", deviceNo, e);
|
||||||
|
String cachedDevice = redisTemplate.opsForValue().get(String.format(DEVICE_NO_CACHE_SUCCESS_KEY, deviceNo));
|
||||||
|
if (cachedDevice != null) {
|
||||||
|
log.info("返回缓存的设备信息, deviceNo: {}", deviceNo);
|
||||||
|
return JacksonUtil.parseObject(cachedDevice, DeviceEntity.class);
|
||||||
|
}
|
||||||
|
log.error("无法获取设备信息且无缓存数据, deviceNo: {}", deviceNo);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceConfigEntity getDeviceConfig(Long deviceId) {
|
public DeviceConfigEntity getDeviceConfig(Long deviceId) {
|
||||||
@@ -82,6 +137,8 @@ public class DeviceRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
redisTemplate.delete(String.format(DEVICE_CACHE_KEY, deviceNo));
|
redisTemplate.delete(String.format(DEVICE_CACHE_KEY, deviceNo));
|
||||||
|
// 清理成功结果缓存
|
||||||
|
redisTemplate.delete(String.format(DEVICE_NO_CACHE_SUCCESS_KEY, deviceNo));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public boolean clearDeviceCache(Long deviceId) {
|
public boolean clearDeviceCache(Long deviceId) {
|
||||||
@@ -92,6 +149,8 @@ public class DeviceRepository {
|
|||||||
}
|
}
|
||||||
redisTemplate.delete(String.format(DEVICE_CACHE_KEY, deviceId));
|
redisTemplate.delete(String.format(DEVICE_CACHE_KEY, deviceId));
|
||||||
redisTemplate.delete(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId));
|
redisTemplate.delete(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId));
|
||||||
|
// 清理成功结果缓存
|
||||||
|
redisTemplate.delete(String.format(DEVICE_CACHE_SUCCESS_KEY, deviceId));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user