You've already forked FrameTour-BE
feat(integration): 支持TypeReference泛型的降级缓存机制
- 在IntegrationFallbackService中新增支持TypeReference的executeWithFallback方法 - 新增getFallbackFromCache和parseFallbackCacheValue方法处理泛型缓存 - 更新DeviceStatusIntegrationService使用TypeReference保留泛型信息 - 更新RenderWorkerConfigIntegrationService使用TypeReference并修正缓存键 - 更新ScenicConfigIntegrationService使用TypeReference保留泛型信息 - 添加必要的Jackson TypeReference导入依赖
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.integration.common.service;
|
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.integration.common.config.IntegrationProperties;
|
||||||
import com.ycwl.basic.utils.JacksonUtil;
|
import com.ycwl.basic.utils.JacksonUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -30,7 +31,7 @@ public class IntegrationFallbackService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行操作,失败时降级到缓存结果
|
* 执行操作,失败时降级到缓存结果
|
||||||
*
|
*
|
||||||
* @param serviceName 服务名称 (如: zt-device, zt-scenic)
|
* @param serviceName 服务名称 (如: zt-device, zt-scenic)
|
||||||
* @param cacheKey 缓存键
|
* @param cacheKey 缓存键
|
||||||
* @param operation 主要操作
|
* @param operation 主要操作
|
||||||
@@ -78,6 +79,57 @@ public class IntegrationFallbackService {
|
|||||||
return fallbackResult;
|
return fallbackResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行操作,失败时降级到缓存结果(支持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;
|
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 分钟则优先尝试远端;远端失败再降级到缓存。
|
* 规则:缓存写入后的 1 分钟内优先使用,超过 1 分钟则优先尝试远端;远端失败再降级到缓存。
|
||||||
@@ -177,6 +246,21 @@ public class IntegrationFallbackService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析降级缓存值(支持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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除降级缓存
|
* 清除降级缓存
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.integration.device.service;
|
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.exception.IntegrationException;
|
||||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
@@ -49,6 +50,9 @@ public class DeviceStatusIntegrationService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有在线设备(带降级,使用TypeReference保留泛型信息)
|
||||||
|
*/
|
||||||
public List<DeviceStatusDTO> getAllOnlineDevices() {
|
public List<DeviceStatusDTO> getAllOnlineDevices() {
|
||||||
log.debug("获取所有在线设备");
|
log.debug("获取所有在线设备");
|
||||||
return fallbackService.executeWithFallback(
|
return fallbackService.executeWithFallback(
|
||||||
@@ -58,7 +62,7 @@ public class DeviceStatusIntegrationService {
|
|||||||
CommonResponse<List<DeviceStatusDTO>> response = deviceStatusClient.getAllOnlineDevices();
|
CommonResponse<List<DeviceStatusDTO>> response = deviceStatusClient.getAllOnlineDevices();
|
||||||
return handleResponse(response, "获取所有在线设备失败");
|
return handleResponse(response, "获取所有在线设备失败");
|
||||||
},
|
},
|
||||||
List.class
|
new TypeReference<List<DeviceStatusDTO>>() {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.integration.render.service;
|
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.exception.IntegrationException;
|
||||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
@@ -29,7 +30,7 @@ public class RenderWorkerConfigIntegrationService {
|
|||||||
private static final String SERVICE_NAME = "zt-render-worker";
|
private static final String SERVICE_NAME = "zt-render-worker";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取工作器所有配置(带降级)
|
* 获取工作器所有配置(带降级,使用TypeReference保留泛型信息)
|
||||||
*/
|
*/
|
||||||
public List<RenderWorkerConfigV2DTO> getWorkerConfigs(Long workerId) {
|
public List<RenderWorkerConfigV2DTO> getWorkerConfigs(Long workerId) {
|
||||||
log.debug("获取渲染工作器配置列表, workerId: {}", workerId);
|
log.debug("获取渲染工作器配置列表, workerId: {}", workerId);
|
||||||
@@ -37,12 +38,12 @@ public class RenderWorkerConfigIntegrationService {
|
|||||||
SERVICE_NAME,
|
SERVICE_NAME,
|
||||||
"worker:configs:" + workerId,
|
"worker:configs:" + workerId,
|
||||||
() -> {
|
() -> {
|
||||||
CommonResponse<List<RenderWorkerConfigV2DTO>> response =
|
CommonResponse<List<RenderWorkerConfigV2DTO>> response =
|
||||||
renderWorkerConfigV2Client.getWorkerConfigs(workerId);
|
renderWorkerConfigV2Client.getWorkerConfigs(workerId);
|
||||||
List<RenderWorkerConfigV2DTO> configs = handleResponse(response, "获取渲染工作器配置列表失败");
|
List<RenderWorkerConfigV2DTO> configs = handleResponse(response, "获取渲染工作器配置列表失败");
|
||||||
return configs != null ? configs : Collections.emptyList();
|
return configs != null ? configs : Collections.emptyList();
|
||||||
},
|
},
|
||||||
List.class
|
new TypeReference<List<RenderWorkerConfigV2DTO>>() {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,12 +71,12 @@ public class RenderWorkerConfigIntegrationService {
|
|||||||
log.debug("获取渲染工作器平铺配置, workerId: {}", workerId);
|
log.debug("获取渲染工作器平铺配置, workerId: {}", workerId);
|
||||||
return fallbackService.executeWithFallback(
|
return fallbackService.executeWithFallback(
|
||||||
SERVICE_NAME,
|
SERVICE_NAME,
|
||||||
"worker:config:" + workerId,
|
"worker:flat:config:" + workerId,
|
||||||
() -> {
|
() -> {
|
||||||
List<RenderWorkerConfigV2DTO> configs = getWorkerConfigsInternal(workerId);
|
List<RenderWorkerConfigV2DTO> configs = getWorkerConfigsInternal(workerId);
|
||||||
return flattenConfigs(configs);
|
return flattenConfigs(configs);
|
||||||
},
|
},
|
||||||
Map.class
|
new TypeReference<Map<String, Object>>() {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.integration.scenic.service;
|
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.exception.IntegrationException;
|
||||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
@@ -22,6 +23,9 @@ public class ScenicConfigIntegrationService {
|
|||||||
|
|
||||||
private static final String SERVICE_NAME = "zt-scenic";
|
private static final String SERVICE_NAME = "zt-scenic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取景区配置列表(带降级,使用TypeReference保留泛型信息)
|
||||||
|
*/
|
||||||
public List<ScenicConfigV2DTO> listConfigs(Long scenicId) {
|
public List<ScenicConfigV2DTO> listConfigs(Long scenicId) {
|
||||||
log.debug("获取景区配置列表, scenicId: {}", scenicId);
|
log.debug("获取景区配置列表, scenicId: {}", scenicId);
|
||||||
return fallbackService.executeWithFallback(
|
return fallbackService.executeWithFallback(
|
||||||
@@ -31,7 +35,7 @@ public class ScenicConfigIntegrationService {
|
|||||||
CommonResponse<List<ScenicConfigV2DTO>> response = scenicConfigV2Client.listConfigs(scenicId);
|
CommonResponse<List<ScenicConfigV2DTO>> response = scenicConfigV2Client.listConfigs(scenicId);
|
||||||
return handleResponse(response, "获取景区配置列表失败");
|
return handleResponse(response, "获取景区配置列表失败");
|
||||||
},
|
},
|
||||||
List.class
|
new TypeReference<List<ScenicConfigV2DTO>>() {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user