feat(integration): 支持TypeReference泛型的降级缓存机制

- 在IntegrationFallbackService中新增支持TypeReference的executeWithFallback方法
- 新增getFallbackFromCache和parseFallbackCacheValue方法处理泛型缓存
- 更新DeviceStatusIntegrationService使用TypeReference保留泛型信息
- 更新RenderWorkerConfigIntegrationService使用TypeReference并修正缓存键
- 更新ScenicConfigIntegrationService使用TypeReference保留泛型信息
- 添加必要的Jackson TypeReference导入依赖
This commit is contained in:
2025-12-16 10:00:49 +08:00
parent b207b5805a
commit a5903a9831
4 changed files with 101 additions and 8 deletions

View File

@@ -1,5 +1,6 @@
package com.ycwl.basic.integration.common.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ycwl.basic.integration.common.config.IntegrationProperties;
import com.ycwl.basic.utils.JacksonUtil;
import lombok.RequiredArgsConstructor;
@@ -79,6 +80,57 @@ public class IntegrationFallbackService {
}
}
/**
* 执行操作,失败时降级到缓存结果(支持TypeReference泛型)
*
* @param serviceName 服务名称 (如: zt-device, zt-scenic)
* @param cacheKey 缓存键
* @param operation 主要操作
* @param typeReference 类型引用,用于保留泛型信息
* @param <T> 结果类型
* @return 操作结果或缓存的结果
*/
public <T> T executeWithFallback(String serviceName, String cacheKey, Supplier<T> operation, TypeReference<T> typeReference) {
String fullKey = buildFullCacheKey(serviceName, cacheKey);
String cachedValue = null;
boolean isPreferredCache = false;
try {
cachedValue = redisTemplate.opsForValue().get(fullKey);
isPreferredCache = cachedValue != null && isFallbackCachePreferred(serviceName, fullKey);
} catch (Exception e) {
log.warn("[{}] 读取降级缓存失败,将继续尝试远端获取, cacheKey: {}", serviceName, cacheKey, e);
}
if (isPreferredCache) {
T preferredCacheResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, typeReference);
if (preferredCacheResult != null) {
log.debug("[{}] 命中优先缓存(<=1分钟),直接返回, cacheKey: {}", serviceName, cacheKey);
return preferredCacheResult;
}
}
try {
T result = operation.get();
if (result != null) {
// 操作成功,保存结果用于将来的降级
storeFallbackCache(serviceName, cacheKey, result);
}
return result;
} catch (Exception e) {
log.warn("[{}] 操作失败,尝试降级到缓存结果, cacheKey: {}", serviceName, cacheKey, e);
T fallbackResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, typeReference);
if (fallbackResult == null) {
fallbackResult = getFallbackFromCache(serviceName, cacheKey, typeReference);
}
if (fallbackResult == null) {
log.error("[{}] 操作失败且无缓存数据, cacheKey: {}", serviceName, cacheKey);
throw e;
}
log.info("[{}] 成功从降级缓存获取结果, cacheKey: {}", serviceName, cacheKey);
return fallbackResult;
}
}
/**
* 执行操作,失败时降级到缓存结果,无返回值版本
*
@@ -138,6 +190,23 @@ public class IntegrationFallbackService {
return null;
}
/**
* 从降级缓存获取结果(支持TypeReference泛型)
*/
private <T> T getFallbackFromCache(String serviceName, String cacheKey, TypeReference<T> typeReference) {
try {
String fullKey = buildFullCacheKey(serviceName, cacheKey);
String cachedValue = redisTemplate.opsForValue().get(fullKey);
if (cachedValue != null) {
log.debug("[{}] 从降级缓存获取结果, key: {}", serviceName, fullKey);
return JacksonUtil.parseObject(cachedValue, typeReference);
}
} catch (Exception e) {
log.warn("[{}] 从降级缓存获取结果失败, cacheKey: {}", serviceName, cacheKey, e);
}
return null;
}
/**
* 判断当前降级缓存是否应该优先使用。
* 规则:缓存写入后的 1 分钟内优先使用,超过 1 分钟则优先尝试远端;远端失败再降级到缓存。
@@ -178,6 +247,21 @@ public class IntegrationFallbackService {
}
}
/**
* 解析降级缓存值(支持TypeReference泛型)
*/
private <T> T parseFallbackCacheValue(String serviceName, String cacheKey, String cachedValue, TypeReference<T> typeReference) {
if (cachedValue == null) {
return null;
}
try {
return JacksonUtil.parseObject(cachedValue, typeReference);
} catch (Exception e) {
log.warn("[{}] 解析降级缓存失败, cacheKey: {}", serviceName, cacheKey, e);
return null;
}
}
/**
* 清除降级缓存
*

View File

@@ -1,5 +1,6 @@
package com.ycwl.basic.integration.device.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ycwl.basic.integration.common.exception.IntegrationException;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
@@ -49,6 +50,9 @@ public class DeviceStatusIntegrationService {
);
}
/**
* 获取所有在线设备(带降级,使用TypeReference保留泛型信息)
*/
public List<DeviceStatusDTO> getAllOnlineDevices() {
log.debug("获取所有在线设备");
return fallbackService.executeWithFallback(
@@ -58,7 +62,7 @@ public class DeviceStatusIntegrationService {
CommonResponse<List<DeviceStatusDTO>> response = deviceStatusClient.getAllOnlineDevices();
return handleResponse(response, "获取所有在线设备失败");
},
List.class
new TypeReference<List<DeviceStatusDTO>>() {}
);
}

View File

@@ -1,5 +1,6 @@
package com.ycwl.basic.integration.render.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ycwl.basic.integration.common.exception.IntegrationException;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
@@ -29,7 +30,7 @@ public class RenderWorkerConfigIntegrationService {
private static final String SERVICE_NAME = "zt-render-worker";
/**
* 获取工作器所有配置(带降级)
* 获取工作器所有配置(带降级,使用TypeReference保留泛型信息
*/
public List<RenderWorkerConfigV2DTO> getWorkerConfigs(Long workerId) {
log.debug("获取渲染工作器配置列表, workerId: {}", workerId);
@@ -42,7 +43,7 @@ public class RenderWorkerConfigIntegrationService {
List<RenderWorkerConfigV2DTO> configs = handleResponse(response, "获取渲染工作器配置列表失败");
return configs != null ? configs : Collections.emptyList();
},
List.class
new TypeReference<List<RenderWorkerConfigV2DTO>>() {}
);
}
@@ -70,12 +71,12 @@ public class RenderWorkerConfigIntegrationService {
log.debug("获取渲染工作器平铺配置, workerId: {}", workerId);
return fallbackService.executeWithFallback(
SERVICE_NAME,
"worker:config:" + workerId,
"worker:flat:config:" + workerId,
() -> {
List<RenderWorkerConfigV2DTO> configs = getWorkerConfigsInternal(workerId);
return flattenConfigs(configs);
},
Map.class
new TypeReference<Map<String, Object>>() {}
);
}

View File

@@ -1,5 +1,6 @@
package com.ycwl.basic.integration.scenic.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ycwl.basic.integration.common.exception.IntegrationException;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
@@ -22,6 +23,9 @@ public class ScenicConfigIntegrationService {
private static final String SERVICE_NAME = "zt-scenic";
/**
* 获取景区配置列表(带降级,使用TypeReference保留泛型信息)
*/
public List<ScenicConfigV2DTO> listConfigs(Long scenicId) {
log.debug("获取景区配置列表, scenicId: {}", scenicId);
return fallbackService.executeWithFallback(
@@ -31,7 +35,7 @@ public class ScenicConfigIntegrationService {
CommonResponse<List<ScenicConfigV2DTO>> response = scenicConfigV2Client.listConfigs(scenicId);
return handleResponse(response, "获取景区配置列表失败");
},
List.class
new TypeReference<List<ScenicConfigV2DTO>>() {}
);
}