You've already forked FrameTour-BE
Merge branch 'render-worker-microservice'
# Conflicts: # src/main/java/com/ycwl/basic/integration/scenic/service/ScenicIntegrationService.java # src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
package com.ycwl.basic.controller.pc;
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
import com.ycwl.basic.integration.scenic.dto.config.DefaultConfigDTO;
|
import com.ycwl.basic.integration.scenic.dto.config.DefaultConfigDTO;
|
||||||
import com.ycwl.basic.integration.scenic.service.DefaultConfigIntegrationService;
|
import com.ycwl.basic.integration.scenic.service.ScenicDefaultConfigIntegrationService;
|
||||||
import com.ycwl.basic.utils.ApiConst;
|
import com.ycwl.basic.utils.ApiConst;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DefaultConfigController {
|
public class DefaultConfigController {
|
||||||
|
|
||||||
private final DefaultConfigIntegrationService defaultConfigIntegrationService;
|
private final ScenicDefaultConfigIntegrationService scenicDefaultConfigIntegrationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取默认配置列表
|
* 获取默认配置列表
|
||||||
@@ -29,7 +29,7 @@ public class DefaultConfigController {
|
|||||||
public ApiResponse<List<DefaultConfigDTO>> listDefaultConfigs() {
|
public ApiResponse<List<DefaultConfigDTO>> listDefaultConfigs() {
|
||||||
log.info("获取默认配置列表");
|
log.info("获取默认配置列表");
|
||||||
try {
|
try {
|
||||||
List<DefaultConfigDTO> configs = defaultConfigIntegrationService.listDefaultConfigs();
|
List<DefaultConfigDTO> configs = scenicDefaultConfigIntegrationService.listDefaultConfigs();
|
||||||
return ApiResponse.success(configs);
|
return ApiResponse.success(configs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取默认配置列表失败", e);
|
log.error("获取默认配置列表失败", e);
|
||||||
@@ -44,7 +44,7 @@ public class DefaultConfigController {
|
|||||||
public ApiResponse<DefaultConfigDTO> getDefaultConfig(@PathVariable String configKey) {
|
public ApiResponse<DefaultConfigDTO> getDefaultConfig(@PathVariable String configKey) {
|
||||||
log.info("获取默认配置, configKey: {}", configKey);
|
log.info("获取默认配置, configKey: {}", configKey);
|
||||||
try {
|
try {
|
||||||
DefaultConfigDTO config = defaultConfigIntegrationService.getDefaultConfig(configKey);
|
DefaultConfigDTO config = scenicDefaultConfigIntegrationService.getDefaultConfig(configKey);
|
||||||
return ApiResponse.success(config);
|
return ApiResponse.success(config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取默认配置失败, configKey: {}", configKey, e);
|
log.error("获取默认配置失败, configKey: {}", configKey, e);
|
||||||
@@ -59,7 +59,7 @@ public class DefaultConfigController {
|
|||||||
public ApiResponse<DefaultConfigDTO> createDefaultConfig(@RequestBody DefaultConfigDTO request) {
|
public ApiResponse<DefaultConfigDTO> createDefaultConfig(@RequestBody DefaultConfigDTO request) {
|
||||||
log.info("创建默认配置, configKey: {}", request.getConfigKey());
|
log.info("创建默认配置, configKey: {}", request.getConfigKey());
|
||||||
try {
|
try {
|
||||||
DefaultConfigDTO config = defaultConfigIntegrationService.createDefaultConfig(request);
|
DefaultConfigDTO config = scenicDefaultConfigIntegrationService.createDefaultConfig(request);
|
||||||
return ApiResponse.success(config);
|
return ApiResponse.success(config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("创建默认配置失败, configKey: {}", request.getConfigKey(), e);
|
log.error("创建默认配置失败, configKey: {}", request.getConfigKey(), e);
|
||||||
@@ -75,7 +75,7 @@ public class DefaultConfigController {
|
|||||||
@RequestBody DefaultConfigDTO request) {
|
@RequestBody DefaultConfigDTO request) {
|
||||||
log.info("更新默认配置, configKey: {}", configKey);
|
log.info("更新默认配置, configKey: {}", configKey);
|
||||||
try {
|
try {
|
||||||
DefaultConfigDTO config = defaultConfigIntegrationService.updateDefaultConfig(configKey, request);
|
DefaultConfigDTO config = scenicDefaultConfigIntegrationService.updateDefaultConfig(configKey, request);
|
||||||
return ApiResponse.success(config);
|
return ApiResponse.success(config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("更新默认配置失败, configKey: {}", configKey, e);
|
log.error("更新默认配置失败, configKey: {}", configKey, e);
|
||||||
@@ -90,7 +90,7 @@ public class DefaultConfigController {
|
|||||||
public ApiResponse<Void> deleteDefaultConfig(@PathVariable String configKey) {
|
public ApiResponse<Void> deleteDefaultConfig(@PathVariable String configKey) {
|
||||||
log.info("删除默认配置, configKey: {}", configKey);
|
log.info("删除默认配置, configKey: {}", configKey);
|
||||||
try {
|
try {
|
||||||
defaultConfigIntegrationService.deleteDefaultConfig(configKey);
|
scenicDefaultConfigIntegrationService.deleteDefaultConfig(configKey);
|
||||||
return ApiResponse.buildResponse(ApiConst.Code.CODE_SUCCESS.code(), null, "删除成功");
|
return ApiResponse.buildResponse(ApiConst.Code.CODE_SUCCESS.code(), null, "删除成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("删除默认配置失败, configKey: {}", configKey, e);
|
log.error("删除默认配置失败, configKey: {}", configKey, e);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.controller.pc;
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
import com.ycwl.basic.integration.device.dto.config.*;
|
import com.ycwl.basic.integration.device.dto.config.*;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.device.dto.device.*;
|
import com.ycwl.basic.integration.device.dto.device.*;
|
||||||
import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
|
import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
|
||||||
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
||||||
@@ -35,7 +36,7 @@ public class DeviceV2Controller {
|
|||||||
* 设备V2核心信息分页列表
|
* 设备V2核心信息分页列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public ApiResponse<DeviceV2ListResponse> listDevices(@RequestParam(defaultValue = "1") Integer page,
|
public ApiResponse<PageResponse<DeviceV2DTO>> listDevices(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) String name,
|
@RequestParam(required = false) String name,
|
||||||
@RequestParam(required = false) String no,
|
@RequestParam(required = false) String no,
|
||||||
@@ -51,7 +52,7 @@ public class DeviceV2Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DeviceV2ListResponse response = deviceIntegrationService.listDevices(page, pageSize, name, no, type, isActive, scenicId);
|
PageResponse<DeviceV2DTO> response = deviceIntegrationService.listDevices(page, pageSize, name, no, type, isActive, scenicId);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分页查询设备核心信息列表失败", e);
|
log.error("分页查询设备核心信息列表失败", e);
|
||||||
@@ -63,7 +64,7 @@ public class DeviceV2Controller {
|
|||||||
* 设备V2带配置信息分页列表
|
* 设备V2带配置信息分页列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/with-config")
|
@GetMapping("/with-config")
|
||||||
public ApiResponse<DeviceV2WithConfigListResponse> listDevicesWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
public ApiResponse<PageResponse<DeviceV2WithConfigDTO>> listDevicesWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) String name,
|
@RequestParam(required = false) String name,
|
||||||
@RequestParam(required = false) String no,
|
@RequestParam(required = false) String no,
|
||||||
@@ -79,7 +80,7 @@ public class DeviceV2Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DeviceV2WithConfigListResponse response = deviceIntegrationService.listDevicesWithConfig(page, pageSize, name, no, type, isActive, scenicId);
|
PageResponse<DeviceV2WithConfigDTO> response = deviceIntegrationService.listDevicesWithConfig(page, pageSize, name, no, type, isActive, scenicId);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分页查询设备带配置信息列表失败", e);
|
log.error("分页查询设备带配置信息列表失败", e);
|
||||||
@@ -431,12 +432,12 @@ public class DeviceV2Controller {
|
|||||||
* 获取景区IPC设备列表
|
* 获取景区IPC设备列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/scenic/{scenicId}/ipc")
|
@GetMapping("/scenic/{scenicId}/ipc")
|
||||||
public ApiResponse<DeviceV2ListResponse> getScenicIpcDevices(@PathVariable Long scenicId,
|
public ApiResponse<PageResponse<DeviceV2DTO>> getScenicIpcDevices(@PathVariable Long scenicId,
|
||||||
@RequestParam(defaultValue = "1") Integer page,
|
@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
log.info("获取景区IPC设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
log.info("获取景区IPC设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
||||||
try {
|
try {
|
||||||
DeviceV2ListResponse response = deviceIntegrationService.getScenicIpcDevices(scenicId, page, pageSize);
|
PageResponse<DeviceV2DTO> response = deviceIntegrationService.getScenicIpcDevices(scenicId, page, pageSize);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取景区IPC设备列表失败, scenicId: {}", scenicId, e);
|
log.error("获取景区IPC设备列表失败, scenicId: {}", scenicId, e);
|
||||||
@@ -448,12 +449,12 @@ public class DeviceV2Controller {
|
|||||||
* 获取景区激活设备列表
|
* 获取景区激活设备列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/scenic/{scenicId}/active")
|
@GetMapping("/scenic/{scenicId}/active")
|
||||||
public ApiResponse<DeviceV2ListResponse> getScenicActiveDevices(@PathVariable Long scenicId,
|
public ApiResponse<PageResponse<DeviceV2DTO>> getScenicActiveDevices(@PathVariable Long scenicId,
|
||||||
@RequestParam(defaultValue = "1") Integer page,
|
@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
log.info("获取景区激活设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
log.info("获取景区激活设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
||||||
try {
|
try {
|
||||||
DeviceV2ListResponse response = deviceIntegrationService.getScenicActiveDevices(scenicId, page, pageSize);
|
PageResponse<DeviceV2DTO> response = deviceIntegrationService.getScenicActiveDevices(scenicId, page, pageSize);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取景区激活设备列表失败, scenicId: {}", scenicId, e);
|
log.error("获取景区激活设备列表失败, scenicId: {}", scenicId, e);
|
||||||
@@ -465,12 +466,12 @@ public class DeviceV2Controller {
|
|||||||
* 获取景区所有设备列表
|
* 获取景区所有设备列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/scenic/{scenicId}/all")
|
@GetMapping("/scenic/{scenicId}/all")
|
||||||
public ApiResponse<DeviceV2ListResponse> getScenicAllDevices(@PathVariable Long scenicId,
|
public ApiResponse<PageResponse<DeviceV2DTO>> getScenicAllDevices(@PathVariable Long scenicId,
|
||||||
@RequestParam(defaultValue = "1") Integer page,
|
@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
log.info("获取景区所有设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
log.info("获取景区所有设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize);
|
||||||
try {
|
try {
|
||||||
DeviceV2ListResponse response = deviceIntegrationService.listDevices(page, pageSize, null, null, null, null, scenicId);
|
PageResponse<DeviceV2DTO> response = deviceIntegrationService.listDevices(page, pageSize, null, null, null, null, scenicId);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取景区所有设备列表失败, scenicId: {}", scenicId, e);
|
log.error("获取景区所有设备列表失败, scenicId: {}", scenicId, e);
|
||||||
|
@@ -0,0 +1,196 @@
|
|||||||
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO;
|
||||||
|
import com.ycwl.basic.integration.render.service.RenderWorkerConfigIntegrationService;
|
||||||
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器配置管理 V2 版本控制器
|
||||||
|
* 基于 zt-render-worker 微服务标准接口实现
|
||||||
|
*
|
||||||
|
* @author Claude Code
|
||||||
|
* @date 2025-09-06
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/render/worker/config/v2")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RenderWorkerConfigV2Controller {
|
||||||
|
|
||||||
|
private final RenderWorkerConfigIntegrationService configIntegrationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器所有配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @return 工作器配置列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/{workerId}")
|
||||||
|
public ApiResponse<List<RenderWorkerConfigV2DTO>> getWorkerConfigs(@PathVariable Long workerId) {
|
||||||
|
log.info("获取渲染工作器配置列表, workerId: {}", workerId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = configIntegrationService.getWorkerConfigs(workerId);
|
||||||
|
return ApiResponse.success(configs);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取渲染工作器配置列表失败, workerId: {}", workerId, e);
|
||||||
|
return ApiResponse.fail("获取渲染工作器配置列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器平铺配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @return 平铺配置Map
|
||||||
|
*/
|
||||||
|
@GetMapping("/{workerId}/flat")
|
||||||
|
public ApiResponse<Map<String, Object>> getWorkerFlatConfig(@PathVariable Long workerId) {
|
||||||
|
log.info("获取渲染工作器平铺配置, workerId: {}", workerId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> flatConfig = configIntegrationService.getWorkerFlatConfig(workerId);
|
||||||
|
return ApiResponse.success(flatConfig);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取渲染工作器平铺配置失败, workerId: {}", workerId, e);
|
||||||
|
return ApiResponse.fail("获取渲染工作器平铺配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置键获取特定配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param configKey 配置键
|
||||||
|
* @return 配置信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/{workerId}/key/{configKey}")
|
||||||
|
public ApiResponse<RenderWorkerConfigV2DTO> getWorkerConfigByKey(@PathVariable Long workerId,
|
||||||
|
@PathVariable String configKey) {
|
||||||
|
log.info("根据配置键获取渲染工作器配置, workerId: {}, configKey: {}", workerId, configKey);
|
||||||
|
|
||||||
|
try {
|
||||||
|
RenderWorkerConfigV2DTO config = configIntegrationService.getWorkerConfigByKey(workerId, configKey);
|
||||||
|
return ApiResponse.success(config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("根据配置键获取渲染工作器配置失败, workerId: {}, configKey: {}", workerId, configKey, e);
|
||||||
|
return ApiResponse.fail("根据配置键获取渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建工作器配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param config 配置信息
|
||||||
|
* @return 创建的配置信息
|
||||||
|
*/
|
||||||
|
@PostMapping("/{workerId}")
|
||||||
|
public ApiResponse<RenderWorkerConfigV2DTO> createWorkerConfig(@PathVariable Long workerId,
|
||||||
|
@Valid @RequestBody RenderWorkerConfigV2DTO config) {
|
||||||
|
log.info("创建渲染工作器配置, workerId: {}, configKey: {}", workerId, config.getConfigKey());
|
||||||
|
|
||||||
|
try {
|
||||||
|
RenderWorkerConfigV2DTO result = configIntegrationService.createWorkerConfig(workerId, config);
|
||||||
|
return ApiResponse.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建渲染工作器配置失败, workerId: {}", workerId, e);
|
||||||
|
return ApiResponse.fail("创建渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新工作器配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param configId 配置ID
|
||||||
|
* @param updates 更新内容
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@PutMapping("/{workerId}/{configId}")
|
||||||
|
public ApiResponse<Void> updateWorkerConfig(@PathVariable Long workerId,
|
||||||
|
@PathVariable Long configId,
|
||||||
|
@Valid @RequestBody Map<String, Object> updates) {
|
||||||
|
log.info("更新渲染工作器配置, workerId: {}, configId: {}", workerId, configId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
configIntegrationService.updateWorkerConfig(workerId, configId, updates);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新渲染工作器配置失败, workerId: {}, configId: {}", workerId, configId, e);
|
||||||
|
return ApiResponse.fail("更新渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除工作器配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param configId 配置ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{workerId}/{configId}")
|
||||||
|
public ApiResponse<Void> deleteWorkerConfig(@PathVariable Long workerId,
|
||||||
|
@PathVariable Long configId) {
|
||||||
|
log.info("删除渲染工作器配置, workerId: {}, configId: {}", workerId, configId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
configIntegrationService.deleteWorkerConfig(workerId, configId);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除渲染工作器配置失败, workerId: {}, configId: {}", workerId, configId, e);
|
||||||
|
return ApiResponse.fail("删除渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新工作器配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param request 批量配置请求
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/{workerId}/batch")
|
||||||
|
public ApiResponse<Void> batchUpdateWorkerConfigs(@PathVariable Long workerId,
|
||||||
|
@Valid @RequestBody BatchRenderWorkerConfigRequest request) {
|
||||||
|
log.info("批量更新渲染工作器配置, workerId: {}, configCount: {}",
|
||||||
|
workerId, request.getConfigs() != null ? request.getConfigs().size() : 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
configIntegrationService.batchUpdateWorkerConfigs(workerId, request);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("批量更新渲染工作器配置失败, workerId: {}", workerId, e);
|
||||||
|
return ApiResponse.fail("批量更新渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量平铺更新工作器配置
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @param flatConfigs 平铺配置Map
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/{workerId}/flat-batch")
|
||||||
|
public ApiResponse<Void> batchFlatUpdateWorkerConfigs(@PathVariable Long workerId,
|
||||||
|
@Valid @RequestBody Map<String, Object> flatConfigs) {
|
||||||
|
log.info("批量平铺更新渲染工作器配置, workerId: {}, configCount: {}", workerId, flatConfigs.size());
|
||||||
|
|
||||||
|
try {
|
||||||
|
configIntegrationService.batchFlatUpdateWorkerConfigs(workerId, flatConfigs);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("批量平铺更新渲染工作器配置失败, workerId: {}", workerId, e);
|
||||||
|
return ApiResponse.fail("批量平铺更新渲染工作器配置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,61 +0,0 @@
|
|||||||
package com.ycwl.basic.controller.pc;
|
|
||||||
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery;
|
|
||||||
import com.ycwl.basic.service.pc.RenderWorkerService;
|
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author:longbinbin
|
|
||||||
* @Date:2024/12/3 14:59
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/renderWorker/v1")
|
|
||||||
// 渲染机管理
|
|
||||||
public class RenderWorkerController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RenderWorkerService renderWorkerService;
|
|
||||||
|
|
||||||
// 分页查询渲染机
|
|
||||||
@PostMapping("/page")
|
|
||||||
public ApiResponse pageQuery(@RequestBody RenderWorkerReqQuery renderWorkerReqQuery){
|
|
||||||
return renderWorkerService.pageQuery(renderWorkerReqQuery);
|
|
||||||
}
|
|
||||||
// 渲染机列表查询
|
|
||||||
@PostMapping("/list")
|
|
||||||
public ApiResponse list(@RequestBody RenderWorkerReqQuery renderWorkerReqQuery){
|
|
||||||
return renderWorkerService.list(renderWorkerReqQuery);
|
|
||||||
}
|
|
||||||
// 渲染机详情查询
|
|
||||||
@GetMapping("/detail/{id}")
|
|
||||||
public ApiResponse detail(@PathVariable Long id){
|
|
||||||
return renderWorkerService.detail(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染机新增
|
|
||||||
@PostMapping("/add")
|
|
||||||
public ApiResponse add(@RequestBody RenderWorkerEntity renderWorker){
|
|
||||||
return renderWorkerService.add(renderWorker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染机删除
|
|
||||||
@DeleteMapping("/delete/{id}")
|
|
||||||
public ApiResponse deleteById(@PathVariable Long id){
|
|
||||||
return renderWorkerService.deleteById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染机修改
|
|
||||||
@PostMapping("/update")
|
|
||||||
public ApiResponse update(@RequestBody RenderWorkerEntity renderWorker){
|
|
||||||
return renderWorkerService.update(renderWorker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染机修改状态
|
|
||||||
@PutMapping("/updateStatus/{id}")
|
|
||||||
public ApiResponse updateStatus(@PathVariable Long id) {
|
|
||||||
return renderWorkerService.updateStatus(id);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,142 @@
|
|||||||
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.CreateRenderWorkerRequest;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.RenderWorkerV2DTO;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.UpdateRenderWorkerRequest;
|
||||||
|
import com.ycwl.basic.integration.render.service.RenderWorkerIntegrationService;
|
||||||
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器管理 V2 版本控制器
|
||||||
|
* 基于 zt-render-worker 微服务标准接口实现
|
||||||
|
*
|
||||||
|
* @author Claude Code
|
||||||
|
* @date 2025-09-06
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/render/worker/v2")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RenderWorkerV2Controller {
|
||||||
|
|
||||||
|
private final RenderWorkerIntegrationService renderWorkerIntegrationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询渲染工作器列表
|
||||||
|
*
|
||||||
|
* @param page 页码,从1开始
|
||||||
|
* @param pageSize 每页大小,默认10,最大100
|
||||||
|
* @param isEnabled 是否启用(0-禁用,1-启用)
|
||||||
|
* @param name 工作器名称(模糊搜索)
|
||||||
|
* @return 分页查询结果
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
public ApiResponse<PageResponse<RenderWorkerV2DTO>> listWorkers(
|
||||||
|
@RequestParam(defaultValue = "1") Integer page,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
|
@RequestParam(required = false) Integer isEnabled,
|
||||||
|
@RequestParam(required = false) String name) {
|
||||||
|
|
||||||
|
log.info("分页查询渲染工作器列表, page: {}, pageSize: {}, isEnabled: {}, name: {}",
|
||||||
|
page, pageSize, isEnabled, name);
|
||||||
|
|
||||||
|
// 参数验证:限制pageSize最大值为100
|
||||||
|
if (pageSize > 100) {
|
||||||
|
pageSize = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
PageResponse<RenderWorkerV2DTO> result = renderWorkerIntegrationService.listWorkers(
|
||||||
|
page, pageSize, isEnabled, name);
|
||||||
|
return ApiResponse.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("分页查询渲染工作器列表失败", e);
|
||||||
|
return ApiResponse.fail("分页查询渲染工作器列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取渲染工作器详情
|
||||||
|
*
|
||||||
|
* @param id 工作器ID
|
||||||
|
* @return 工作器详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ApiResponse<RenderWorkerV2DTO> getWorker(@PathVariable Long id) {
|
||||||
|
log.info("获取渲染工作器详情, id: {}", id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
RenderWorkerV2DTO worker = renderWorkerIntegrationService.getWorker(id);
|
||||||
|
return ApiResponse.success(worker);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取渲染工作器详情失败, id: {}", id, e);
|
||||||
|
return ApiResponse.fail("获取渲染工作器详情失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建渲染工作器
|
||||||
|
*
|
||||||
|
* @param request 创建请求
|
||||||
|
* @return 创建的工作器信息
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ApiResponse<RenderWorkerV2DTO> createWorker(@Valid @RequestBody CreateRenderWorkerRequest request) {
|
||||||
|
log.info("创建渲染工作器, name: {}, key: {}, isActive: {}",
|
||||||
|
request.getName(), request.getKey(), request.getIsActive());
|
||||||
|
|
||||||
|
try {
|
||||||
|
RenderWorkerV2DTO worker = renderWorkerIntegrationService.createWorker(request);
|
||||||
|
return ApiResponse.success(worker);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建渲染工作器失败", e);
|
||||||
|
return ApiResponse.fail("创建渲染工作器失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新渲染工作器
|
||||||
|
*
|
||||||
|
* @param id 工作器ID
|
||||||
|
* @param request 更新请求
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public ApiResponse<Void> updateWorker(@PathVariable Long id,
|
||||||
|
@Valid @RequestBody UpdateRenderWorkerRequest request) {
|
||||||
|
log.info("更新渲染工作器, id: {}, name: {}, isActive: {}",
|
||||||
|
id, request.getName(), request.getIsActive());
|
||||||
|
|
||||||
|
try {
|
||||||
|
renderWorkerIntegrationService.updateWorker(id, request);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新渲染工作器失败, id: {}", id, e);
|
||||||
|
return ApiResponse.fail("更新渲染工作器失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除渲染工作器
|
||||||
|
*
|
||||||
|
* @param id 工作器ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ApiResponse<Void> deleteWorker(@PathVariable Long id) {
|
||||||
|
log.info("删除渲染工作器, id: {}", id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
renderWorkerIntegrationService.deleteWorker(id);
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除渲染工作器失败, id: {}", id, e);
|
||||||
|
return ApiResponse.fail("删除渲染工作器失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -9,9 +9,8 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterPageResponse;
|
|||||||
import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest;
|
import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse;
|
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
||||||
import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService;
|
import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService;
|
||||||
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
|
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
|
||||||
@@ -52,7 +51,7 @@ public class ScenicV2Controller {
|
|||||||
* 景区V2核心信息分页列表
|
* 景区V2核心信息分页列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public ApiResponse<ScenicV2ListResponse> listScenics(@RequestParam(defaultValue = "1") Integer page,
|
public ApiResponse<PageResponse<ScenicV2DTO>> listScenics(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) Integer status,
|
@RequestParam(required = false) Integer status,
|
||||||
@RequestParam(required = false) String name) {
|
@RequestParam(required = false) String name) {
|
||||||
@@ -64,7 +63,7 @@ public class ScenicV2Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name);
|
PageResponse<ScenicV2DTO> response = scenicIntegrationService.listScenics(page, pageSize, status, name);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分页查询景区核心信息列表失败", e);
|
log.error("分页查询景区核心信息列表失败", e);
|
||||||
@@ -76,7 +75,7 @@ public class ScenicV2Controller {
|
|||||||
* 景区V2带配置信息分页列表
|
* 景区V2带配置信息分页列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/with-config")
|
@GetMapping("/with-config")
|
||||||
public ApiResponse<ScenicV2WithConfigListResponse> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
public ApiResponse<PageResponse<ScenicV2WithConfigDTO>> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) Integer status,
|
@RequestParam(required = false) Integer status,
|
||||||
@RequestParam(required = false) String name) {
|
@RequestParam(required = false) String name) {
|
||||||
@@ -88,7 +87,7 @@ public class ScenicV2Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ScenicV2WithConfigListResponse response = scenicIntegrationService.listScenicsWithConfig(page, pageSize, status, name);
|
PageResponse<ScenicV2WithConfigDTO> response = scenicIntegrationService.listScenicsWithConfig(page, pageSize, status, name);
|
||||||
return ApiResponse.success(response);
|
return ApiResponse.success(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分页查询景区带配置信息列表失败", e);
|
log.error("分页查询景区带配置信息列表失败", e);
|
||||||
@@ -178,11 +177,11 @@ public class ScenicV2Controller {
|
|||||||
* 只支持根据状态筛选
|
* 只支持根据状态筛选
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public ApiResponse<ScenicV2ListResponse> listScenicsByStatus(@RequestParam(required = false) Integer status) {
|
public ApiResponse<PageResponse<ScenicV2DTO>> listScenicsByStatus(@RequestParam(required = false) Integer status) {
|
||||||
log.info("查询景区列表, status: {}", status);
|
log.info("查询景区列表, status: {}", status);
|
||||||
try {
|
try {
|
||||||
// 默认查询1000条数据,第1页
|
// 默认查询1000条数据,第1页
|
||||||
ScenicV2ListResponse scenics = scenicIntegrationService.listScenics(1, 1000, status, null);
|
PageResponse<ScenicV2DTO> scenics = scenicIntegrationService.listScenics(1, 1000, status, null);
|
||||||
return ApiResponse.success(scenics);
|
return ApiResponse.success(scenics);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("查询景区列表失败, status: {}", status, e);
|
log.error("查询景区列表失败, status: {}", status, e);
|
||||||
|
@@ -23,6 +23,7 @@ The integration package (`com.ycwl.basic.integration`) is responsible for extern
|
|||||||
Currently implemented:
|
Currently implemented:
|
||||||
- **Scenic Integration** (`com.ycwl.basic.integration.scenic`): ZT-Scenic microservice integration
|
- **Scenic Integration** (`com.ycwl.basic.integration.scenic`): ZT-Scenic microservice integration
|
||||||
- **Device Integration** (`com.ycwl.basic.integration.device`): ZT-Device microservice integration
|
- **Device Integration** (`com.ycwl.basic.integration.device`): ZT-Device microservice integration
|
||||||
|
- **Render Worker Integration** (`com.ycwl.basic.integration.render`): ZT-Render-Worker microservice integration
|
||||||
|
|
||||||
### Integration Pattern
|
### Integration Pattern
|
||||||
|
|
||||||
@@ -226,10 +227,12 @@ fallbackService.clearAllFallbackCache("zt-scenic");
|
|||||||
#### Feign Clients
|
#### Feign Clients
|
||||||
- **DeviceV2Client**: Main device operations (CRUD, filtering, listing)
|
- **DeviceV2Client**: Main device operations (CRUD, filtering, listing)
|
||||||
- **DeviceConfigV2Client**: Device configuration management
|
- **DeviceConfigV2Client**: Device configuration management
|
||||||
|
- **DefaultConfigClient**: Default configuration management
|
||||||
|
|
||||||
#### Services
|
#### Services
|
||||||
- **DeviceIntegrationService**: High-level device operations (with automatic fallback)
|
- **DeviceIntegrationService**: High-level device operations (with automatic fallback)
|
||||||
- **DeviceConfigIntegrationService**: Device configuration management (with automatic fallback)
|
- **DeviceConfigIntegrationService**: Device configuration management (with automatic fallback)
|
||||||
|
- **DefaultConfigIntegrationService**: Default configuration management (with automatic fallback)
|
||||||
|
|
||||||
#### Configuration
|
#### Configuration
|
||||||
```yaml
|
```yaml
|
||||||
@@ -241,6 +244,13 @@ integration:
|
|||||||
readTimeout: 10000
|
readTimeout: 10000
|
||||||
retryEnabled: false
|
retryEnabled: false
|
||||||
maxRetries: 3
|
maxRetries: 3
|
||||||
|
render:
|
||||||
|
enabled: true
|
||||||
|
serviceName: zt-render-worker
|
||||||
|
connectTimeout: 5000
|
||||||
|
readTimeout: 10000
|
||||||
|
retryEnabled: false
|
||||||
|
maxRetries: 3
|
||||||
```
|
```
|
||||||
|
|
||||||
### Usage Examples
|
### Usage Examples
|
||||||
@@ -369,6 +379,355 @@ fallbackService.clearFallbackCache("zt-device", "device:1001");
|
|||||||
fallbackService.clearAllFallbackCache("zt-device");
|
fallbackService.clearAllFallbackCache("zt-device");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Default Configuration Management (ZT-Device Microservice)
|
||||||
|
|
||||||
|
### Key Components
|
||||||
|
|
||||||
|
#### Default Configuration API
|
||||||
|
The zt-device microservice provides a comprehensive default configuration management API at `/api/device/config/v2/defaults` that allows:
|
||||||
|
- Creating and managing default configuration templates
|
||||||
|
- Batch operations with conflict detection
|
||||||
|
- Configuration type validation and enforcement
|
||||||
|
- Usage tracking and analytics
|
||||||
|
|
||||||
|
#### Feign Client
|
||||||
|
- **DefaultConfigClient**: Default configuration management operations
|
||||||
|
|
||||||
|
#### Service
|
||||||
|
- **DefaultConfigIntegrationService**: High-level default configuration operations (with automatic fallback for queries)
|
||||||
|
|
||||||
|
### Usage Examples
|
||||||
|
|
||||||
|
#### Basic Default Configuration Operations (with Automatic Fallback)
|
||||||
|
```java
|
||||||
|
@Autowired
|
||||||
|
private DefaultConfigIntegrationService defaultConfigService;
|
||||||
|
|
||||||
|
// Get default configuration list (automatically falls back to cache on failure)
|
||||||
|
PageResponse<DefaultConfigResponse> configList = defaultConfigService.listDefaultConfigs(1, 10);
|
||||||
|
log.info("Default configs: total={}, current page={}",
|
||||||
|
configList.getData().getTotal(), configList.getData().getList().size());
|
||||||
|
|
||||||
|
// Get specific default configuration (automatically falls back to cache on failure)
|
||||||
|
DefaultConfigResponse config = defaultConfigService.getDefaultConfig("resolution");
|
||||||
|
if (config != null) {
|
||||||
|
log.info("Default resolution: {}", config.getConfigValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new default configuration (direct operation, fails immediately on error)
|
||||||
|
DefaultConfigRequest newConfig = new DefaultConfigRequest();
|
||||||
|
newConfig.setConfigKey("bitrate");
|
||||||
|
newConfig.setConfigValue("2000000");
|
||||||
|
newConfig.setConfigType("int");
|
||||||
|
newConfig.setDescription("Default video bitrate in bps");
|
||||||
|
boolean created = defaultConfigService.createDefaultConfig(newConfig);
|
||||||
|
|
||||||
|
// Update default configuration with conflict detection (direct operation)
|
||||||
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
updates.put("configValue", "4000000");
|
||||||
|
updates.put("description", "Updated default bitrate - high quality");
|
||||||
|
DefaultConfigConflict conflict = defaultConfigService.updateDefaultConfig("bitrate", updates);
|
||||||
|
|
||||||
|
if (conflict != null) {
|
||||||
|
log.warn("Configuration update conflict detected:");
|
||||||
|
log.warn(" Key: {}, Type: {}, Affected devices: {}",
|
||||||
|
conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount());
|
||||||
|
log.warn(" Current type: {}, Proposed type: {}",
|
||||||
|
conflict.getCurrentType(), conflict.getProposedType());
|
||||||
|
|
||||||
|
// Handle conflict - show affected device IDs
|
||||||
|
if (conflict.getConflictDevices() != null) {
|
||||||
|
log.warn(" Conflicted device IDs: {}", conflict.getConflictDevices());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info("Configuration updated successfully without conflicts");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete default configuration (direct operation, fails immediately on error)
|
||||||
|
boolean deleted = defaultConfigService.deleteDefaultConfig("bitrate");
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Batch Default Configuration Operations
|
||||||
|
```java
|
||||||
|
// Using Builder Pattern for batch operations
|
||||||
|
BatchDefaultConfigRequest batchRequest = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addVideoConfig("1920x1080", 30, "H265") // Add video configuration group
|
||||||
|
.addNetworkConfig("192.168.1.100", 554, "RTSP") // Add network configuration group
|
||||||
|
.addConfig("recording_enabled", "true", "bool", "Enable recording by default")
|
||||||
|
.addConfig("storage_retention", "30", "int", "Storage retention in days")
|
||||||
|
.addConfig("quality_profile", "high", "string", "Default video quality profile")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Execute batch update (direct operation, no fallback)
|
||||||
|
BatchDefaultConfigResponse result = defaultConfigService.batchUpdateDefaultConfigs(batchRequest);
|
||||||
|
|
||||||
|
// Process batch results
|
||||||
|
log.info("Batch operation completed: {} success, {} failed", result.getSuccess(), result.getFailed());
|
||||||
|
|
||||||
|
// Handle conflicts
|
||||||
|
if (result.getConflicts() != null && !result.getConflicts().isEmpty()) {
|
||||||
|
log.warn("Configuration conflicts detected:");
|
||||||
|
for (DefaultConfigConflict conflict : result.getConflicts()) {
|
||||||
|
log.warn(" Key: {}, Type: {}, Devices affected: {}",
|
||||||
|
conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Review processed items
|
||||||
|
if (result.getProcessedItems() != null) {
|
||||||
|
result.getProcessedItems().forEach(item -> {
|
||||||
|
if ("success".equals(item.getStatus())) {
|
||||||
|
log.info("✅ {} {} successfully (type: {})",
|
||||||
|
item.getConfigKey(), item.getAction(), item.getFinalType());
|
||||||
|
} else {
|
||||||
|
log.warn("❌ {} failed: {}", item.getConfigKey(), item.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle errors
|
||||||
|
if (result.getErrors() != null && !result.getErrors().isEmpty()) {
|
||||||
|
result.getErrors().forEach(error -> log.error("Batch operation error: {}", error));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Device Type Specific Default Configuration Patterns
|
||||||
|
```java
|
||||||
|
// Create IPC camera default configurations
|
||||||
|
BatchDefaultConfigRequest ipcDefaults = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addVideoConfig("1920x1080", 25, "H264") // Standard HD resolution
|
||||||
|
.addConfig("night_vision", "true", "bool", "Enable night vision")
|
||||||
|
.addConfig("motion_detection", "true", "bool", "Enable motion detection")
|
||||||
|
.addConfig("stream_profile", "main", "string", "Default stream profile")
|
||||||
|
.addConfig("ptz_enabled", "false", "bool", "PTZ control enabled")
|
||||||
|
.addConfig("audio_enabled", "true", "bool", "Audio recording enabled")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create NVR default configurations
|
||||||
|
BatchDefaultConfigRequest nvrDefaults = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addConfig("max_channels", "16", "int", "Maximum supported channels")
|
||||||
|
.addConfig("storage_mode", "continuous", "string", "Recording storage mode")
|
||||||
|
.addConfig("backup_enabled", "true", "bool", "Enable automatic backup")
|
||||||
|
.addConfig("raid_level", "5", "int", "Default RAID level")
|
||||||
|
.addConfig("disk_quota", "80", "int", "Disk usage quota percentage")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Apply device-type-specific defaults
|
||||||
|
BatchDefaultConfigResponse ipcResult = defaultConfigService.batchUpdateDefaultConfigs(ipcDefaults);
|
||||||
|
BatchDefaultConfigResponse nvrResult = defaultConfigService.batchUpdateDefaultConfigs(nvrDefaults);
|
||||||
|
|
||||||
|
log.info("IPC defaults: {} success, {} failed", ipcResult.getSuccess(), ipcResult.getFailed());
|
||||||
|
log.info("NVR defaults: {} success, {} failed", nvrResult.getSuccess(), nvrResult.getFailed());
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Configuration Validation and Management Patterns
|
||||||
|
```java
|
||||||
|
// Validate system configuration completeness
|
||||||
|
PageResponse<DefaultConfigResponse> allDefaults = defaultConfigService.listDefaultConfigs(1, 100);
|
||||||
|
|
||||||
|
// Check for required default configurations
|
||||||
|
String[] requiredDefaults = {
|
||||||
|
"resolution", "frameRate", "codec", "bitrate",
|
||||||
|
"protocol", "port", "username", "password"
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<String, Boolean> configStatus = new HashMap<>();
|
||||||
|
for (String required : requiredDefaults) {
|
||||||
|
boolean exists = allDefaults.getData().getList().stream()
|
||||||
|
.anyMatch(config -> required.equals(config.getConfigKey()));
|
||||||
|
configStatus.put(required, exists);
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
log.warn("Missing required default configuration: {}", required);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate configuration completeness report
|
||||||
|
long totalConfigs = allDefaults.getData().getTotal();
|
||||||
|
long completeConfigs = configStatus.values().stream().mapToLong(exists -> exists ? 1 : 0).sum();
|
||||||
|
double completeness = (double) completeConfigs / requiredDefaults.length * 100;
|
||||||
|
|
||||||
|
log.info("Configuration completeness: {:.1f}% ({}/{} required configs present)",
|
||||||
|
completeness, completeConfigs, requiredDefaults.length);
|
||||||
|
log.info("Total default configurations in system: {}", totalConfigs);
|
||||||
|
|
||||||
|
// Analyze configuration type distribution
|
||||||
|
Map<String, Long> typeDistribution = allDefaults.getData().getList().stream()
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
DefaultConfigResponse::getConfigType,
|
||||||
|
Collectors.counting()
|
||||||
|
));
|
||||||
|
|
||||||
|
log.info("Configuration type distribution: {}", typeDistribution);
|
||||||
|
|
||||||
|
// Find most and least used configurations
|
||||||
|
DefaultConfigResponse mostUsed = allDefaults.getData().getList().stream()
|
||||||
|
.max(Comparator.comparing(DefaultConfigResponse::getUsageCount))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
DefaultConfigResponse leastUsed = allDefaults.getData().getList().stream()
|
||||||
|
.min(Comparator.comparing(DefaultConfigResponse::getUsageCount))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (mostUsed != null) {
|
||||||
|
log.info("Most used default config: {} (used {} times)",
|
||||||
|
mostUsed.getConfigKey(), mostUsed.getUsageCount());
|
||||||
|
}
|
||||||
|
if (leastUsed != null) {
|
||||||
|
log.info("Least used default config: {} (used {} times)",
|
||||||
|
leastUsed.getConfigKey(), leastUsed.getUsageCount());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Advanced Batch Configuration with Error Handling
|
||||||
|
```java
|
||||||
|
// Complex batch operation with comprehensive error handling
|
||||||
|
try {
|
||||||
|
BatchDefaultConfigRequest complexBatch = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addVideoConfig("3840x2160", 60, "H265") // 4K configuration
|
||||||
|
.addConfig("hdr_enabled", "true", "bool", "HDR video support")
|
||||||
|
.addConfig("ai_analysis", "enabled", "string", "AI analysis features")
|
||||||
|
.addConfig("edge_processing", "true", "bool", "Edge computing enabled")
|
||||||
|
.addConfig("cloud_sync", "auto", "string", "Cloud synchronization mode")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
BatchDefaultConfigResponse result = defaultConfigService.batchUpdateDefaultConfigs(complexBatch);
|
||||||
|
|
||||||
|
// Detailed result analysis
|
||||||
|
if (result.getSuccess() == complexBatch.getConfigs().size()) {
|
||||||
|
log.info("✅ All {} configurations processed successfully", result.getSuccess());
|
||||||
|
} else if (result.getSuccess() > 0) {
|
||||||
|
log.warn("⚠️ Partial success: {} succeeded, {} failed", result.getSuccess(), result.getFailed());
|
||||||
|
|
||||||
|
// Analyze what succeeded vs failed
|
||||||
|
if (result.getProcessedItems() != null) {
|
||||||
|
Map<String, Long> statusCounts = result.getProcessedItems().stream()
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
ProcessedConfigItem::getStatus,
|
||||||
|
Collectors.counting()
|
||||||
|
));
|
||||||
|
log.info("Processing breakdown: {}", statusCounts);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("❌ All configurations failed to process");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle different types of conflicts
|
||||||
|
if (result.getConflicts() != null) {
|
||||||
|
Map<String, List<DefaultConfigConflict>> conflictsByType = result.getConflicts().stream()
|
||||||
|
.collect(Collectors.groupingBy(DefaultConfigConflict::getConflictType));
|
||||||
|
|
||||||
|
conflictsByType.forEach((conflictType, conflicts) -> {
|
||||||
|
log.warn("Conflict type '{}' affects {} configurations:", conflictType, conflicts.size());
|
||||||
|
conflicts.forEach(conflict ->
|
||||||
|
log.warn(" {} affects {} devices", conflict.getConfigKey(), conflict.getDeviceCount())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Batch default configuration operation failed", e);
|
||||||
|
// Implement retry logic or fallback behavior as needed
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Fallback Cache Management for Default Configurations
|
||||||
|
```java
|
||||||
|
@Autowired
|
||||||
|
private IntegrationFallbackService fallbackService;
|
||||||
|
|
||||||
|
// Check fallback cache status for default configurations
|
||||||
|
boolean hasDefaultListCache = fallbackService.hasFallbackCache("zt-device", "defaults:list:1:10");
|
||||||
|
boolean hasSpecificConfigCache = fallbackService.hasFallbackCache("zt-device", "defaults:config:resolution");
|
||||||
|
|
||||||
|
// Get cache statistics
|
||||||
|
IntegrationFallbackService.FallbackCacheStats stats = fallbackService.getFallbackCacheStats("zt-device");
|
||||||
|
log.info("Default config fallback cache: {} items, TTL: {} days",
|
||||||
|
stats.getTotalCacheCount(), stats.getFallbackTtlDays());
|
||||||
|
|
||||||
|
// Clear specific default configuration cache
|
||||||
|
fallbackService.clearFallbackCache("zt-device", "defaults:config:resolution");
|
||||||
|
|
||||||
|
// Clear all default configuration caches
|
||||||
|
fallbackService.clearAllFallbackCache("zt-device");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Default Configuration Types and Common Keys
|
||||||
|
|
||||||
|
#### Video Configuration Defaults
|
||||||
|
- `resolution`: Video resolution ("1920x1080", "3840x2160", "1280x720")
|
||||||
|
- `frameRate`: Video frame rate (integer: 15, 25, 30, 60)
|
||||||
|
- `codec`: Video codec ("H264", "H265", "MJPEG")
|
||||||
|
- `bitrate`: Video bitrate in bps (integer)
|
||||||
|
- `quality`: Video quality level ("low", "medium", "high", "ultra")
|
||||||
|
|
||||||
|
#### Network Configuration Defaults
|
||||||
|
- `protocol`: Network protocol ("RTSP", "HTTP", "ONVIF")
|
||||||
|
- `port`: Network port (integer: 554, 80, 8080)
|
||||||
|
- `timeout`: Connection timeout in seconds (integer)
|
||||||
|
- `retry_count`: Maximum retry attempts (integer)
|
||||||
|
|
||||||
|
#### Authentication Defaults
|
||||||
|
- `username`: Default username (string)
|
||||||
|
- `password`: Default password (string)
|
||||||
|
- `auth_method`: Authentication method ("basic", "digest", "none")
|
||||||
|
|
||||||
|
#### Storage and Recording Defaults
|
||||||
|
- `storage_path`: Default storage path (string)
|
||||||
|
- `recording_enabled`: Enable recording (boolean)
|
||||||
|
- `retention_days`: Storage retention period (integer)
|
||||||
|
- `max_file_size`: Maximum file size in MB (integer)
|
||||||
|
|
||||||
|
#### Feature Control Defaults
|
||||||
|
- `motion_detection`: Enable motion detection (boolean)
|
||||||
|
- `night_vision`: Enable night vision (boolean)
|
||||||
|
- `audio_enabled`: Enable audio recording (boolean)
|
||||||
|
- `ptz_enabled`: Enable PTZ control (boolean)
|
||||||
|
- `ai_analysis`: AI analysis features ("enabled", "disabled", "auto")
|
||||||
|
|
||||||
|
### Error Handling and Responses
|
||||||
|
|
||||||
|
#### HTTP Status Codes
|
||||||
|
- **200 OK**: Configuration retrieved/updated successfully
|
||||||
|
- **201 Created**: New configuration created successfully
|
||||||
|
- **202 Accepted**: Operation completed with conflicts (check response for details)
|
||||||
|
- **400 Bad Request**: Invalid request parameters or validation errors
|
||||||
|
- **404 Not Found**: Configuration key not found
|
||||||
|
- **409 Conflict**: Configuration conflicts prevent operation (includes conflict details)
|
||||||
|
|
||||||
|
#### Conflict Resolution
|
||||||
|
When updating default configurations that are actively used by devices, the API performs conflict detection:
|
||||||
|
|
||||||
|
1. **Type Conflicts**: Changing configuration type when devices use different types
|
||||||
|
2. **Value Validation**: Ensuring new values are compatible with existing device configurations
|
||||||
|
3. **Dependency Conflicts**: Checking for configuration dependencies and relationships
|
||||||
|
|
||||||
|
The response includes detailed conflict information to help resolve issues:
|
||||||
|
```java
|
||||||
|
// Example conflict handling
|
||||||
|
DefaultConfigConflict conflict = updateResult;
|
||||||
|
if (conflict != null) {
|
||||||
|
switch (conflict.getConflictType()) {
|
||||||
|
case "TYPE_MISMATCH":
|
||||||
|
log.warn("Type conflict: {} devices using '{}' type, proposed '{}'type",
|
||||||
|
conflict.getDeviceCount(), conflict.getCurrentType(), conflict.getProposedType());
|
||||||
|
// Handle type conversion or device updates
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "VALUE_RANGE":
|
||||||
|
log.warn("Value range conflict for key '{}' affects {} devices",
|
||||||
|
conflict.getConfigKey(), conflict.getDeviceCount());
|
||||||
|
// Handle value range adjustments
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "DEPENDENCY":
|
||||||
|
log.warn("Dependency conflict detected for '{}'", conflict.getConfigKey());
|
||||||
|
// Handle dependency resolution
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Enhanced Batch Configuration API
|
### Enhanced Batch Configuration API
|
||||||
|
|
||||||
Device Integration now supports an enhanced batch configuration API that provides detailed processing results and supports default configuration rules.
|
Device Integration now supports an enhanced batch configuration API that provides detailed processing results and supports default configuration rules.
|
||||||
@@ -424,6 +783,23 @@ Each processed item includes:
|
|||||||
- **IPC**: IP Camera devices for video monitoring
|
- **IPC**: IP Camera devices for video monitoring
|
||||||
- **CUSTOM**: Custom device types for sensors, controllers, etc.
|
- **CUSTOM**: Custom device types for sensors, controllers, etc.
|
||||||
|
|
||||||
|
### Testing Default Configuration Integration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run default configuration integration tests
|
||||||
|
mvn test -Dtest=DefaultConfigIntegrationServiceTest
|
||||||
|
|
||||||
|
# Run all device integration tests (including default configs)
|
||||||
|
mvn test -Dtest="com.ycwl.basic.integration.device.*Test"
|
||||||
|
|
||||||
|
# Enable example runner in application-dev.yml
|
||||||
|
integration:
|
||||||
|
device:
|
||||||
|
example:
|
||||||
|
default-config:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
### Common Configuration Keys
|
### Common Configuration Keys
|
||||||
- `ip_address`: Device IP address
|
- `ip_address`: Device IP address
|
||||||
- `resolution`: Video resolution (e.g., "1920x1080", "3840x2160")
|
- `resolution`: Video resolution (e.g., "1920x1080", "3840x2160")
|
||||||
@@ -535,6 +911,11 @@ integration:
|
|||||||
ttlDays: 5 # Custom TTL for device (shorter due to dynamic data)
|
ttlDays: 5 # Custom TTL for device (shorter due to dynamic data)
|
||||||
# cachePrefix: "device:fallback:" # Optional custom prefix
|
# cachePrefix: "device:fallback:" # Optional custom prefix
|
||||||
|
|
||||||
|
render:
|
||||||
|
enabled: true # Enable fallback for render worker service
|
||||||
|
ttlDays: 7 # Custom TTL for render worker (medium due to stable worker data)
|
||||||
|
# cachePrefix: "render:fallback:" # Optional custom prefix
|
||||||
|
|
||||||
# Service configurations
|
# Service configurations
|
||||||
scenic:
|
scenic:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -587,6 +968,205 @@ class ScenicIntegrationServiceTest {
|
|||||||
### Integration Testing
|
### Integration Testing
|
||||||
Use `@SpringBootTest` with test profiles and mock external services.
|
Use `@SpringBootTest` with test profiles and mock external services.
|
||||||
|
|
||||||
|
## Render Worker Integration (ZT-Render-Worker Microservice)
|
||||||
|
|
||||||
|
### Key Components
|
||||||
|
|
||||||
|
#### Feign Clients
|
||||||
|
- **RenderWorkerV2Client**: Main render worker operations (CRUD, listing)
|
||||||
|
- **RenderWorkerConfigV2Client**: Render worker configuration management
|
||||||
|
|
||||||
|
#### Services
|
||||||
|
- **RenderWorkerIntegrationService**: High-level render worker operations (with automatic fallback)
|
||||||
|
- **RenderWorkerConfigIntegrationService**: Configuration management (with automatic fallback)
|
||||||
|
|
||||||
|
#### Configuration
|
||||||
|
```yaml
|
||||||
|
integration:
|
||||||
|
render:
|
||||||
|
enabled: true
|
||||||
|
serviceName: zt-render-worker
|
||||||
|
connectTimeout: 5000
|
||||||
|
readTimeout: 10000
|
||||||
|
retryEnabled: false
|
||||||
|
maxRetries: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage Examples
|
||||||
|
|
||||||
|
#### Basic Render Worker Operations (with Automatic Fallback)
|
||||||
|
```java
|
||||||
|
@Autowired
|
||||||
|
private RenderWorkerIntegrationService renderWorkerService;
|
||||||
|
|
||||||
|
// Get render worker basic info (automatically falls back to cache on failure)
|
||||||
|
RenderWorkerV2DTO worker = renderWorkerService.getWorker(workerId);
|
||||||
|
|
||||||
|
// Get render worker with configuration (automatically falls back to cache on failure)
|
||||||
|
RenderWorkerV2WithConfigDTO workerWithConfig = renderWorkerService.getWorkerWithConfig(workerId);
|
||||||
|
|
||||||
|
// Get render worker by key (automatically falls back to cache on failure)
|
||||||
|
RenderWorkerV2DTO workerByKey = renderWorkerService.getWorkerByKey("video-renderer-001");
|
||||||
|
|
||||||
|
// Get render worker with config by key (automatically falls back to cache on failure)
|
||||||
|
RenderWorkerV2WithConfigDTO workerWithConfigByKey = renderWorkerService.getWorkerWithConfigByKey("video-renderer-001");
|
||||||
|
|
||||||
|
// Create new render worker (direct operation, fails immediately on error)
|
||||||
|
CreateRenderWorkerRequest request = new CreateRenderWorkerRequest();
|
||||||
|
request.setName("Video Renderer");
|
||||||
|
request.setKey("video-renderer-001");
|
||||||
|
request.setIsActive(1);
|
||||||
|
RenderWorkerV2DTO newWorker = renderWorkerService.createWorker(request);
|
||||||
|
|
||||||
|
// Update render worker (direct operation, fails immediately on error)
|
||||||
|
UpdateRenderWorkerRequest updateRequest = new UpdateRenderWorkerRequest();
|
||||||
|
updateRequest.setName("Updated Video Renderer");
|
||||||
|
renderWorkerService.updateWorker(workerId, updateRequest);
|
||||||
|
|
||||||
|
// Delete render worker (direct operation, fails immediately on error)
|
||||||
|
renderWorkerService.deleteWorker(workerId);
|
||||||
|
|
||||||
|
// List render workers (no fallback for list operations)
|
||||||
|
List<RenderWorkerV2DTO> workers = renderWorkerService.listWorkers(1, 10, 1, null);
|
||||||
|
|
||||||
|
// List render workers with config (no fallback for list operations)
|
||||||
|
List<RenderWorkerV2WithConfigDTO> workersWithConfig =
|
||||||
|
renderWorkerService.listWorkersWithConfig(1, 10, 1, null);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Configuration Management (with Automatic Fallback)
|
||||||
|
```java
|
||||||
|
@Autowired
|
||||||
|
private RenderWorkerConfigIntegrationService configService;
|
||||||
|
|
||||||
|
// Get worker configurations (with fallback)
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = configService.getWorkerConfigs(workerId);
|
||||||
|
|
||||||
|
// Get flat configuration (automatically falls back to cache on failure)
|
||||||
|
Map<String, Object> flatConfig = configService.getWorkerFlatConfig(workerId);
|
||||||
|
|
||||||
|
// Get specific configuration by key (with fallback)
|
||||||
|
RenderWorkerConfigV2DTO config = configService.getWorkerConfigByKey(workerId, "render_quality");
|
||||||
|
|
||||||
|
// Create configuration (direct operation, fails immediately on error)
|
||||||
|
RenderWorkerConfigV2DTO newConfig = new RenderWorkerConfigV2DTO();
|
||||||
|
newConfig.setConfigKey("max_concurrent_tasks");
|
||||||
|
newConfig.setConfigValue("4");
|
||||||
|
newConfig.setConfigType("int");
|
||||||
|
newConfig.setDescription("Maximum concurrent render tasks");
|
||||||
|
newConfig.setIsActive(1);
|
||||||
|
RenderWorkerConfigV2DTO created = configService.createWorkerConfig(workerId, newConfig);
|
||||||
|
|
||||||
|
// Update configuration (direct operation, fails immediately on error)
|
||||||
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
updates.put("configValue", "8");
|
||||||
|
configService.updateWorkerConfig(workerId, configId, updates);
|
||||||
|
|
||||||
|
// Delete configuration (direct operation, fails immediately on error)
|
||||||
|
configService.deleteWorkerConfig(workerId, configId);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Enhanced Batch Configuration API
|
||||||
|
```java
|
||||||
|
// Using Builder Pattern for batch configuration
|
||||||
|
BatchRenderWorkerConfigRequest request = configService.createBatchConfigBuilder()
|
||||||
|
.addRenderConfig("high", "mp4", "1920x1080") // Render settings
|
||||||
|
.addPerformanceConfig(8, 3600) // Performance settings
|
||||||
|
.addConfig("output_path", "/data/renders", "string", "Output directory")
|
||||||
|
.addConfig("enable_gpu", "true", "bool", "Enable GPU acceleration")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Batch update configurations (direct operation, fails immediately on error)
|
||||||
|
configService.batchUpdateWorkerConfigs(workerId, request);
|
||||||
|
|
||||||
|
// Batch flat update configurations (direct operation, fails immediately on error)
|
||||||
|
Map<String, Object> flatUpdates = new HashMap<>();
|
||||||
|
flatUpdates.put("render_quality", "ultra");
|
||||||
|
flatUpdates.put("max_concurrent_tasks", 12);
|
||||||
|
flatUpdates.put("enable_preview", true);
|
||||||
|
configService.batchFlatUpdateWorkerConfigs(workerId, flatUpdates);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Render Worker Management Patterns
|
||||||
|
```java
|
||||||
|
// Create and configure render worker in one operation
|
||||||
|
CreateRenderWorkerRequest workerRequest = new CreateRenderWorkerRequest();
|
||||||
|
workerRequest.setName("4K Video Renderer");
|
||||||
|
workerRequest.setKey("4k-video-renderer");
|
||||||
|
RenderWorkerV2DTO worker = renderWorkerService.createWorker(workerRequest);
|
||||||
|
|
||||||
|
// Configure the worker for 4K video rendering
|
||||||
|
BatchRenderWorkerConfigRequest config = configService.createBatchConfigBuilder()
|
||||||
|
.addRenderConfig("ultra", "mp4", "3840x2160")
|
||||||
|
.addPerformanceConfig(4, 7200) // 4 concurrent tasks, 2 hour timeout
|
||||||
|
.addConfig("gpu_memory_limit", "8192", "int", "GPU memory limit in MB")
|
||||||
|
.addConfig("codec", "h265", "string", "Video codec")
|
||||||
|
.addConfig("bitrate", "50000", "int", "Video bitrate in kbps")
|
||||||
|
.build();
|
||||||
|
configService.batchUpdateWorkerConfigs(worker.getId(), config);
|
||||||
|
|
||||||
|
// Monitor worker configuration completeness (with automatic fallback)
|
||||||
|
Map<String, Object> workerConfig = configService.getWorkerFlatConfig(worker.getId());
|
||||||
|
boolean hasRenderConfig = workerConfig.containsKey("render_quality");
|
||||||
|
boolean hasPerformanceConfig = workerConfig.containsKey("max_concurrent_tasks");
|
||||||
|
// log configuration status...
|
||||||
|
|
||||||
|
// Get all active workers for monitoring
|
||||||
|
List<RenderWorkerV2WithConfigDTO> activeWorkers =
|
||||||
|
renderWorkerService.listWorkersWithConfig(1, 100, 1, null);
|
||||||
|
|
||||||
|
// Check worker health and configuration
|
||||||
|
for (RenderWorkerV2WithConfigDTO activeWorker : activeWorkers) {
|
||||||
|
Map<String, Object> config = activeWorker.getConfig();
|
||||||
|
boolean isConfigured = config.containsKey("render_quality") &&
|
||||||
|
config.containsKey("max_concurrent_tasks");
|
||||||
|
// log worker status...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Fallback Cache Management for Render Workers
|
||||||
|
```java
|
||||||
|
@Autowired
|
||||||
|
private IntegrationFallbackService fallbackService;
|
||||||
|
|
||||||
|
// Check fallback cache status
|
||||||
|
boolean hasWorkerCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:1001");
|
||||||
|
boolean hasWorkerByKeyCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:key:video-renderer-001");
|
||||||
|
boolean hasConfigCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:flat:config:1001");
|
||||||
|
boolean hasConfigByKeyCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:key:config:video-renderer-001");
|
||||||
|
|
||||||
|
// Get cache statistics
|
||||||
|
IntegrationFallbackService.FallbackCacheStats stats =
|
||||||
|
fallbackService.getFallbackCacheStats("zt-render-worker");
|
||||||
|
log.info("Render worker fallback cache: {} items, TTL: {} days",
|
||||||
|
stats.getTotalCacheCount(), stats.getFallbackTtlDays());
|
||||||
|
|
||||||
|
// Clear specific cache
|
||||||
|
fallbackService.clearFallbackCache("zt-render-worker", "worker:1001");
|
||||||
|
|
||||||
|
// Clear all render worker caches
|
||||||
|
fallbackService.clearAllFallbackCache("zt-render-worker");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Render Worker Types and Configuration
|
||||||
|
|
||||||
|
#### Common Configuration Keys
|
||||||
|
- `render_quality`: Render quality level ("low", "medium", "high", "ultra")
|
||||||
|
- `render_format`: Output format ("mp4", "avi", "mov", "webm")
|
||||||
|
- `render_resolution`: Video resolution ("1920x1080", "3840x2160", "1280x720")
|
||||||
|
- `max_concurrent_tasks`: Maximum concurrent render tasks (integer)
|
||||||
|
- `task_timeout`: Task timeout in seconds (integer)
|
||||||
|
- `output_path`: Render output directory path (string)
|
||||||
|
- `enable_gpu`: Enable GPU acceleration (boolean)
|
||||||
|
- `gpu_memory_limit`: GPU memory limit in MB (integer)
|
||||||
|
- `codec`: Video codec ("h264", "h265", "vp9")
|
||||||
|
- `bitrate`: Video bitrate in kbps (integer)
|
||||||
|
- `enable_preview`: Enable preview generation (boolean)
|
||||||
|
|
||||||
|
#### Worker Status
|
||||||
|
- **Active (isActive=1)**: Worker is available for tasks
|
||||||
|
- **Inactive (isActive=0)**: Worker is disabled
|
||||||
|
|
||||||
## Common Development Tasks
|
## Common Development Tasks
|
||||||
|
|
||||||
### Running Integration Tests
|
### Running Integration Tests
|
||||||
@@ -600,6 +1180,10 @@ mvn test -Dtest="com.ycwl.basic.integration.*Test"
|
|||||||
# Run device integration tests
|
# Run device integration tests
|
||||||
mvn test -Dtest=DeviceIntegrationServiceTest
|
mvn test -Dtest=DeviceIntegrationServiceTest
|
||||||
mvn test -Dtest="com.ycwl.basic.integration.device.*Test"
|
mvn test -Dtest="com.ycwl.basic.integration.device.*Test"
|
||||||
|
|
||||||
|
# Run render worker integration tests
|
||||||
|
mvn test -Dtest=RenderWorkerIntegrationServiceTest
|
||||||
|
mvn test -Dtest="com.ycwl.basic.integration.render.*Test"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adding New DTOs
|
### Adding New DTOs
|
||||||
|
@@ -26,6 +26,11 @@ public class IntegrationProperties {
|
|||||||
*/
|
*/
|
||||||
private DeviceConfig device = new DeviceConfig();
|
private DeviceConfig device = new DeviceConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器服务配置
|
||||||
|
*/
|
||||||
|
private RenderWorkerConfig render = new RenderWorkerConfig();
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class ScenicConfig {
|
public static class ScenicConfig {
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +103,32 @@ public class IntegrationProperties {
|
|||||||
*/
|
*/
|
||||||
private ServiceFallbackConfig scenic = new ServiceFallbackConfig();
|
private ServiceFallbackConfig scenic = new ServiceFallbackConfig();
|
||||||
private ServiceFallbackConfig device = new ServiceFallbackConfig();
|
private ServiceFallbackConfig device = new ServiceFallbackConfig();
|
||||||
|
private ServiceFallbackConfig render = new ServiceFallbackConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RenderWorkerConfig {
|
||||||
|
/**
|
||||||
|
* 是否启用渲染工作器服务集成
|
||||||
|
*/
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
private String serviceName = "zt-render-worker";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时配置(毫秒)
|
||||||
|
*/
|
||||||
|
private int connectTimeout = 5000;
|
||||||
|
private int readTimeout = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重试配置
|
||||||
|
*/
|
||||||
|
private boolean retryEnabled = false;
|
||||||
|
private int maxRetries = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
package com.ycwl.basic.integration.common.manager;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器配置管理器
|
||||||
|
* 基于通用ConfigManager实现渲染工作器配置的管理功能
|
||||||
|
*/
|
||||||
|
public class RenderWorkerConfigManager extends ConfigManager<RenderWorkerConfigV2DTO> {
|
||||||
|
|
||||||
|
public RenderWorkerConfigManager(List<RenderWorkerConfigV2DTO> configs) {
|
||||||
|
super(configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getConfigKey(RenderWorkerConfigV2DTO config) {
|
||||||
|
return config != null ? config.getConfigKey() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getConfigValue(RenderWorkerConfigV2DTO config) {
|
||||||
|
return config != null ? config.getConfigValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取渲染工作器配置类型
|
||||||
|
*/
|
||||||
|
public String getConfigType(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getConfigType() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取渲染工作器配置描述
|
||||||
|
*/
|
||||||
|
public String getConfigDescription(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getDescription() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取渲染工作器配置ID
|
||||||
|
*/
|
||||||
|
public Long getConfigId(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器ID
|
||||||
|
*/
|
||||||
|
public Long getWorkerId(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getWorkerId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查配置是否启用
|
||||||
|
*/
|
||||||
|
public boolean isActive(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null && config.getIsActive() != null && config.getIsActive() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置的创建时间
|
||||||
|
*/
|
||||||
|
public String getCreateTime(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getCreateTime() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置的更新时间
|
||||||
|
*/
|
||||||
|
public String getUpdateTime(String key) {
|
||||||
|
RenderWorkerConfigV2DTO config = findConfigByKey(key);
|
||||||
|
return config != null ? config.getUpdateTime() : null;
|
||||||
|
}
|
||||||
|
}
|
@@ -12,29 +12,33 @@ import lombok.AllArgsConstructor;
|
|||||||
public class CommonResponse<T> {
|
public class CommonResponse<T> {
|
||||||
private Integer code;
|
private Integer code;
|
||||||
private String message;
|
private String message;
|
||||||
|
private Boolean success;
|
||||||
private T data;
|
private T data;
|
||||||
|
|
||||||
public static <T> CommonResponse<T> success() {
|
public static <T> CommonResponse<T> success() {
|
||||||
return new CommonResponse<>(200, "OK", null);
|
return new CommonResponse<>(200, "OK", true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CommonResponse<T> success(T data) {
|
public static <T> CommonResponse<T> success(T data) {
|
||||||
return new CommonResponse<>(200, "OK", data);
|
return new CommonResponse<>(200, "OK", true, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CommonResponse<T> success(String message, T data) {
|
public static <T> CommonResponse<T> success(String message, T data) {
|
||||||
return new CommonResponse<>(200, message, data);
|
return new CommonResponse<>(200, message, true, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CommonResponse<T> error(Integer code, String message) {
|
public static <T> CommonResponse<T> error(Integer code, String message) {
|
||||||
return new CommonResponse<>(code, message, null);
|
return new CommonResponse<>(code, message, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CommonResponse<T> error(String message) {
|
public static <T> CommonResponse<T> error(String message) {
|
||||||
return new CommonResponse<>(5000, message, null);
|
return new CommonResponse<>(5000, message, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSuccess() {
|
public boolean isSuccess() {
|
||||||
return code != null && code == 200;
|
if (success == null) { // compatible
|
||||||
|
return code != null && code == 200;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
package com.ycwl.basic.integration.device.client;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.device.dto.defaults.*;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认配置管理 Feign 客户端
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "zt-device", contextId = "device-default-config", path = "/api/device/config/v2/defaults")
|
||||||
|
public interface DefaultConfigClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认配置列表
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
CommonResponse<PageResponse<DefaultConfigResponse>> listDefaultConfigs(@RequestParam(value = "page", defaultValue = "1") int page,
|
||||||
|
@RequestParam(value = "pageSize", defaultValue = "10") int pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置键获取默认配置
|
||||||
|
*/
|
||||||
|
@GetMapping("/{configKey}")
|
||||||
|
CommonResponse<DefaultConfigResponse> getDefaultConfig(@PathVariable("configKey") String configKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认配置
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
CommonResponse<String> createDefaultConfig(@RequestBody DefaultConfigRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新默认配置
|
||||||
|
*/
|
||||||
|
@PutMapping("/{configKey}")
|
||||||
|
CommonResponse<Map<String, Object>> updateDefaultConfig(@PathVariable("configKey") String configKey,
|
||||||
|
@RequestBody Map<String, Object> updates);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除默认配置
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{configKey}")
|
||||||
|
CommonResponse<String> deleteDefaultConfig(@PathVariable("configKey") String configKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新默认配置
|
||||||
|
*/
|
||||||
|
@PostMapping("/batch")
|
||||||
|
CommonResponse<BatchDefaultConfigResponse> batchUpdateDefaultConfigs(@RequestBody BatchDefaultConfigRequest request);
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.integration.device.client;
|
package com.ycwl.basic.integration.device.client;
|
||||||
|
|
||||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.device.dto.device.*;
|
import com.ycwl.basic.integration.device.dto.device.*;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -55,7 +56,7 @@ public interface DeviceV2Client {
|
|||||||
* 分页获取设备列表(核心信息)
|
* 分页获取设备列表(核心信息)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
CommonResponse<DeviceV2ListResponse> listDevices(
|
CommonResponse<PageResponse<DeviceV2DTO>> listDevices(
|
||||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(value = "name", required = false) String name,
|
@RequestParam(value = "name", required = false) String name,
|
||||||
@@ -68,7 +69,7 @@ public interface DeviceV2Client {
|
|||||||
* 分页获取设备列表(含配置)
|
* 分页获取设备列表(含配置)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/with-config")
|
@GetMapping("/with-config")
|
||||||
CommonResponse<DeviceV2WithConfigListResponse> listDevicesWithConfig(
|
CommonResponse<PageResponse<DeviceV2WithConfigDTO>> listDevicesWithConfig(
|
||||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(value = "name", required = false) String name,
|
@RequestParam(value = "name", required = false) String name,
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
package com.ycwl.basic.integration.device.dto.defaults;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量默认配置操作请求模型
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BatchDefaultConfigRequest {
|
||||||
|
|
||||||
|
@NotEmpty(message = "配置列表不能为空")
|
||||||
|
@Valid
|
||||||
|
private List<DefaultConfigRequest> configs;
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ycwl.basic.integration.device.dto.defaults;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.device.dto.config.ProcessedConfigItem;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量默认配置操作响应模型
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BatchDefaultConfigResponse {
|
||||||
|
|
||||||
|
private Integer success;
|
||||||
|
|
||||||
|
private Integer failed;
|
||||||
|
|
||||||
|
private List<DefaultConfigConflict> conflicts;
|
||||||
|
|
||||||
|
private List<ProcessedConfigItem> processedItems;
|
||||||
|
|
||||||
|
private List<String> errors;
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
package com.ycwl.basic.integration.device.dto.defaults;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 冲突信息模型
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DefaultConfigConflict {
|
||||||
|
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
private String conflictType;
|
||||||
|
|
||||||
|
private Integer deviceCount;
|
||||||
|
|
||||||
|
private String currentType;
|
||||||
|
|
||||||
|
private String proposedType;
|
||||||
|
|
||||||
|
private List<Long> conflictDevices;
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
package com.ycwl.basic.integration.device.dto.defaults;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认配置请求模型
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class DefaultConfigRequest {
|
||||||
|
|
||||||
|
@NotBlank(message = "配置键不能为空")
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
@NotBlank(message = "配置值不能为空")
|
||||||
|
private String configValue;
|
||||||
|
|
||||||
|
@NotBlank(message = "配置类型不能为空")
|
||||||
|
private String configType;
|
||||||
|
|
||||||
|
@NotBlank(message = "配置描述不能为空")
|
||||||
|
private String description;
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package com.ycwl.basic.integration.device.dto.defaults;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认配置响应模型
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DefaultConfigResponse {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
private String configValue;
|
||||||
|
|
||||||
|
private String configType;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Integer isActive;
|
||||||
|
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
private String updateTime;
|
||||||
|
|
||||||
|
private Integer usageCount;
|
||||||
|
}
|
@@ -1,13 +0,0 @@
|
|||||||
package com.ycwl.basic.integration.device.dto.device;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DeviceV2ListResponse {
|
|
||||||
private List<DeviceV2DTO> list;
|
|
||||||
private Integer total;
|
|
||||||
private Integer page;
|
|
||||||
private Integer pageSize;
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
package com.ycwl.basic.integration.device.dto.device;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DeviceV2WithConfigListResponse {
|
|
||||||
private List<DeviceV2WithConfigDTO> list;
|
|
||||||
private Integer total;
|
|
||||||
private Integer page;
|
|
||||||
private Integer pageSize;
|
|
||||||
}
|
|
@@ -17,7 +17,7 @@ public class FilterDevicesByConfigsResponse {
|
|||||||
/**
|
/**
|
||||||
* 总数
|
* 总数
|
||||||
*/
|
*/
|
||||||
private String total;
|
private Integer total;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页码
|
* 页码
|
||||||
|
@@ -0,0 +1,275 @@
|
|||||||
|
package com.ycwl.basic.integration.device.example;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.device.dto.defaults.*;
|
||||||
|
import com.ycwl.basic.integration.device.service.DeviceDefaultConfigIntegrationService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认配置集成服务使用示例
|
||||||
|
*
|
||||||
|
* 通过在 application.yml 中设置 integration.device.example.default-config.enabled=true 来启用
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@ConditionalOnProperty(name = "integration.device.example.default-config.enabled", havingValue = "true")
|
||||||
|
public class DefaultConfigIntegrationExample implements CommandLineRunner {
|
||||||
|
|
||||||
|
private final DeviceDefaultConfigIntegrationService defaultConfigService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
log.info("=== 默认配置集成服务使用示例 ===");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 基础查询操作示例(支持自动 Fallback)
|
||||||
|
basicQueryExamples();
|
||||||
|
|
||||||
|
// 2. 配置管理操作示例(直接操作)
|
||||||
|
configManagementExamples();
|
||||||
|
|
||||||
|
// 3. 批量操作示例
|
||||||
|
batchOperationExamples();
|
||||||
|
|
||||||
|
// 4. 高级使用模式示例
|
||||||
|
advancedUsageExamples();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("默认配置集成示例执行失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础查询操作示例(支持自动 Fallback)
|
||||||
|
*/
|
||||||
|
private void basicQueryExamples() {
|
||||||
|
log.info("--- 基础查询操作示例(支持自动 Fallback)---");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取默认配置列表(自动缓存,服务不可用时返回缓存数据)
|
||||||
|
PageResponse<DefaultConfigResponse> configList = defaultConfigService.listDefaultConfigs(1, 10);
|
||||||
|
log.info("默认配置列表: 总数={}, 当前页配置数={}",
|
||||||
|
configList.getTotal(), configList.getList().size());
|
||||||
|
|
||||||
|
// 显示配置详情
|
||||||
|
for (DefaultConfigResponse config : configList.getList()) {
|
||||||
|
log.info("配置详情: key={}, value={}, type={}, description={}",
|
||||||
|
config.getConfigKey(), config.getConfigValue(),
|
||||||
|
config.getConfigType(), config.getDescription());
|
||||||
|
|
||||||
|
// 获取单个配置详情(自动缓存,服务不可用时返回缓存数据)
|
||||||
|
DefaultConfigResponse detailConfig = defaultConfigService.getDefaultConfig(config.getConfigKey());
|
||||||
|
if (detailConfig != null) {
|
||||||
|
log.info("配置详情获取成功: usageCount={}, isActive={}",
|
||||||
|
detailConfig.getUsageCount(), detailConfig.getIsActive());
|
||||||
|
}
|
||||||
|
break; // 只展示第一个
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("基础查询操作失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置管理操作示例(直接操作)
|
||||||
|
*/
|
||||||
|
private void configManagementExamples() {
|
||||||
|
log.info("--- 配置管理操作示例(直接操作)---");
|
||||||
|
|
||||||
|
String testConfigKey = "example_test_config";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 创建默认配置(直接操作,失败时立即报错)
|
||||||
|
DefaultConfigRequest createRequest = new DefaultConfigRequest();
|
||||||
|
createRequest.setConfigKey(testConfigKey);
|
||||||
|
createRequest.setConfigValue("1920x1080");
|
||||||
|
createRequest.setConfigType("string");
|
||||||
|
createRequest.setDescription("示例测试配置 - 默认分辨率");
|
||||||
|
|
||||||
|
boolean createResult = defaultConfigService.createDefaultConfig(createRequest);
|
||||||
|
log.info("创建默认配置结果: {}", createResult ? "成功" : "失败");
|
||||||
|
|
||||||
|
// 2. 更新默认配置(直接操作,可能返回冲突信息)
|
||||||
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
updates.put("configValue", "3840x2160");
|
||||||
|
updates.put("description", "更新后的默认分辨率 - 4K");
|
||||||
|
|
||||||
|
DefaultConfigConflict conflict = defaultConfigService.updateDefaultConfig(testConfigKey, updates);
|
||||||
|
if (conflict != null) {
|
||||||
|
log.warn("更新配置存在冲突: configKey={}, conflictType={}, deviceCount={}",
|
||||||
|
conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount());
|
||||||
|
} else {
|
||||||
|
log.info("配置更新成功,无冲突");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证更新结果
|
||||||
|
DefaultConfigResponse updatedConfig = defaultConfigService.getDefaultConfig(testConfigKey);
|
||||||
|
if (updatedConfig != null) {
|
||||||
|
log.info("更新后配置值: {}", updatedConfig.getConfigValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 删除测试配置(直接操作)
|
||||||
|
boolean deleteResult = defaultConfigService.deleteDefaultConfig(testConfigKey);
|
||||||
|
log.info("删除默认配置结果: {}", deleteResult ? "成功" : "失败");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("配置管理操作失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量操作示例
|
||||||
|
*/
|
||||||
|
private void batchOperationExamples() {
|
||||||
|
log.info("--- 批量操作示例 ---");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 使用构建器模式创建批量配置
|
||||||
|
BatchDefaultConfigRequest batchRequest = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addVideoConfig("1920x1080", 30, "H264") // 添加视频配置组
|
||||||
|
.addNetworkConfig("192.168.1.100", 554, "RTSP") // 添加网络配置组
|
||||||
|
.addConfig("recording_enabled", "true", "bool", "是否启用录制")
|
||||||
|
.addConfig("storage_path", "/data/recordings", "string", "录制存储路径")
|
||||||
|
.addConfig("max_file_size", "1024", "int", "最大文件大小(MB)")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.info("准备批量创建 {} 个默认配置", batchRequest.getConfigs().size());
|
||||||
|
|
||||||
|
// 2. 执行批量更新(直接操作)
|
||||||
|
BatchDefaultConfigResponse batchResult = defaultConfigService.batchUpdateDefaultConfigs(batchRequest);
|
||||||
|
|
||||||
|
// 3. 处理批量结果
|
||||||
|
log.info("批量操作结果: 成功={}, 失败={}", batchResult.getSuccess(), batchResult.getFailed());
|
||||||
|
|
||||||
|
if (batchResult.getConflicts() != null && !batchResult.getConflicts().isEmpty()) {
|
||||||
|
log.warn("发现 {} 个配置冲突:", batchResult.getConflicts().size());
|
||||||
|
for (DefaultConfigConflict conflict : batchResult.getConflicts()) {
|
||||||
|
log.warn("冲突配置: key={}, type={}, deviceCount={}",
|
||||||
|
conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batchResult.getProcessedItems() != null) {
|
||||||
|
log.info("处理详情:");
|
||||||
|
batchResult.getProcessedItems().forEach(item ->
|
||||||
|
log.info(" 配置 {}: status={}, action={}, finalType={}",
|
||||||
|
item.getConfigKey(), item.getStatus(), item.getAction(), item.getFinalType())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batchResult.getErrors() != null && !batchResult.getErrors().isEmpty()) {
|
||||||
|
log.error("批量操作错误:");
|
||||||
|
batchResult.getErrors().forEach(error -> log.error(" {}", error));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("批量操作失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高级使用模式示例
|
||||||
|
*/
|
||||||
|
private void advancedUsageExamples() {
|
||||||
|
log.info("--- 高级使用模式示例 ---");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 设备类型特定的默认配置模式
|
||||||
|
createDeviceTypeSpecificConfigs();
|
||||||
|
|
||||||
|
// 2. 配置验证和完整性检查模式
|
||||||
|
validateConfigCompleteness();
|
||||||
|
|
||||||
|
// 3. 配置迁移和批量更新模式
|
||||||
|
configMigrationPattern();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("高级使用模式示例失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建设备类型特定的默认配置
|
||||||
|
*/
|
||||||
|
private void createDeviceTypeSpecificConfigs() {
|
||||||
|
log.info("创建设备类型特定的默认配置...");
|
||||||
|
|
||||||
|
// IPC摄像头默认配置
|
||||||
|
BatchDefaultConfigRequest ipcDefaults = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addVideoConfig("1920x1080", 25, "H264")
|
||||||
|
.addConfig("night_vision", "true", "bool", "夜视功能")
|
||||||
|
.addConfig("motion_detection", "true", "bool", "移动检测")
|
||||||
|
.addConfig("stream_profile", "main", "string", "码流类型")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// NVR设备默认配置
|
||||||
|
BatchDefaultConfigRequest nvrDefaults = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addConfig("max_channels", "16", "int", "最大通道数")
|
||||||
|
.addConfig("storage_mode", "continuous", "string", "存储模式")
|
||||||
|
.addConfig("backup_enabled", "true", "bool", "备份启用")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.info("IPC默认配置项数: {}, NVR默认配置项数: {}",
|
||||||
|
ipcDefaults.getConfigs().size(), nvrDefaults.getConfigs().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置验证和完整性检查
|
||||||
|
*/
|
||||||
|
private void validateConfigCompleteness() {
|
||||||
|
log.info("验证配置完整性...");
|
||||||
|
|
||||||
|
// 获取所有默认配置
|
||||||
|
PageResponse<DefaultConfigResponse> allConfigs = defaultConfigService.listDefaultConfigs(1, 100);
|
||||||
|
|
||||||
|
// 检查必需的基础配置是否存在
|
||||||
|
String[] requiredConfigs = {"resolution", "frameRate", "codec", "protocol"};
|
||||||
|
for (String requiredConfig : requiredConfigs) {
|
||||||
|
boolean exists = allConfigs.getList().stream()
|
||||||
|
.anyMatch(config -> requiredConfig.equals(config.getConfigKey()));
|
||||||
|
log.info("必需配置 {} 存在: {}", requiredConfig, exists ? "✓" : "✗");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计配置类型分布
|
||||||
|
Map<String, Long> typeDistribution = new HashMap<>();
|
||||||
|
allConfigs.getList().forEach(config ->
|
||||||
|
typeDistribution.merge(config.getConfigType(), 1L, Long::sum)
|
||||||
|
);
|
||||||
|
|
||||||
|
log.info("配置类型分布: {}", typeDistribution);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置迁移和批量更新模式
|
||||||
|
*/
|
||||||
|
private void configMigrationPattern() {
|
||||||
|
log.info("配置迁移模式示例...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 获取需要升级的配置
|
||||||
|
PageResponse<DefaultConfigResponse> oldConfigs = defaultConfigService.listDefaultConfigs(1, 50);
|
||||||
|
|
||||||
|
// 2. 创建升级配置批次
|
||||||
|
BatchDefaultConfigRequest upgradeRequest = defaultConfigService.createBatchConfigBuilder()
|
||||||
|
.addConfig("api_version", "v2", "string", "API版本")
|
||||||
|
.addConfig("security_mode", "enhanced", "string", "安全模式")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 3. 执行批量升级
|
||||||
|
BatchDefaultConfigResponse upgradeResult = defaultConfigService.batchUpdateDefaultConfigs(upgradeRequest);
|
||||||
|
log.info("配置升级结果: 成功={}, 失败={}", upgradeResult.getSuccess(), upgradeResult.getFailed());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("配置迁移示例执行失败(这是正常的,因为是示例代码)", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.integration.device.example;
|
package com.ycwl.basic.integration.device.example;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.device.dto.device.*;
|
import com.ycwl.basic.integration.device.dto.device.*;
|
||||||
import com.ycwl.basic.integration.device.dto.config.*;
|
import com.ycwl.basic.integration.device.dto.config.*;
|
||||||
import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
|
import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
|
||||||
@@ -46,7 +47,7 @@ public class DeviceIntegrationExample {
|
|||||||
log.info("获取设备配置: {}", deviceWithConfig.getName());
|
log.info("获取设备配置: {}", deviceWithConfig.getName());
|
||||||
|
|
||||||
// 分页查询景区设备列表
|
// 分页查询景区设备列表
|
||||||
DeviceV2ListResponse deviceList = deviceService.getScenicIpcDevices(1001L, 1, 10);
|
PageResponse<DeviceV2DTO> deviceList = deviceService.getScenicIpcDevices(1001L, 1, 10);
|
||||||
log.info("景区设备列表: 总数={}", deviceList.getTotal());
|
log.info("景区设备列表: 总数={}", deviceList.getTotal());
|
||||||
|
|
||||||
// 启用设备
|
// 启用设备
|
||||||
@@ -80,7 +81,7 @@ public class DeviceIntegrationExample {
|
|||||||
log.info("更新摄像头1排序为1(置顶)");
|
log.info("更新摄像头1排序为1(置顶)");
|
||||||
|
|
||||||
// 获取排序后的设备列表
|
// 获取排序后的设备列表
|
||||||
DeviceV2ListResponse sortedList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId);
|
PageResponse<DeviceV2DTO> sortedList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId);
|
||||||
log.info("排序后的设备列表:");
|
log.info("排序后的设备列表:");
|
||||||
for (DeviceV2DTO device : sortedList.getList()) {
|
for (DeviceV2DTO device : sortedList.getList()) {
|
||||||
log.info(" - {}: 排序={}, 类型={}", device.getName(), device.getSort(), device.getType());
|
log.info(" - {}: 排序={}, 类型={}", device.getName(), device.getSort(), device.getType());
|
||||||
@@ -147,7 +148,7 @@ public class DeviceIntegrationExample {
|
|||||||
log.info("将普通摄像头置顶(排序值: 1)");
|
log.info("将普通摄像头置顶(排序值: 1)");
|
||||||
|
|
||||||
// 查看最终排序结果
|
// 查看最终排序结果
|
||||||
DeviceV2ListResponse finalList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId);
|
PageResponse<DeviceV2DTO> finalList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId);
|
||||||
log.info("最终排序结果:");
|
log.info("最终排序结果:");
|
||||||
for (DeviceV2DTO device : finalList.getList()) {
|
for (DeviceV2DTO device : finalList.getList()) {
|
||||||
log.info(" - {}: 排序={}", device.getName(), device.getSort());
|
log.info(" - {}: 排序={}", device.getName(), device.getSort());
|
||||||
|
@@ -0,0 +1,218 @@
|
|||||||
|
package com.ycwl.basic.integration.device.service;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.exception.IntegrationException;
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
|
import com.ycwl.basic.integration.device.client.DefaultConfigClient;
|
||||||
|
import com.ycwl.basic.integration.device.dto.defaults.*;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认配置集成服务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DeviceDefaultConfigIntegrationService {
|
||||||
|
|
||||||
|
private final DefaultConfigClient defaultConfigClient;
|
||||||
|
private final IntegrationFallbackService fallbackService;
|
||||||
|
|
||||||
|
private static final String SERVICE_NAME = "zt-device";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认配置列表(支持 Fallback)
|
||||||
|
*/
|
||||||
|
public PageResponse<DefaultConfigResponse> listDefaultConfigs(int page, int pageSize) {
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"defaults:list:" + page + ":" + pageSize,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<PageResponse<DefaultConfigResponse>> response = defaultConfigClient.listDefaultConfigs(page, pageSize);
|
||||||
|
return handleResponse(response, "获取默认配置列表失败");
|
||||||
|
},
|
||||||
|
PageResponse.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置键获取默认配置(支持 Fallback)
|
||||||
|
*/
|
||||||
|
public DefaultConfigResponse getDefaultConfig(String configKey) {
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"defaults:config:" + configKey,
|
||||||
|
() -> {
|
||||||
|
log.info("获取默认配置, configKey: {}", configKey);
|
||||||
|
CommonResponse<DefaultConfigResponse> response = defaultConfigClient.getDefaultConfig(configKey);
|
||||||
|
return handleResponse(response, "获取默认配置失败");
|
||||||
|
},
|
||||||
|
DefaultConfigResponse.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认配置(直接操作,不支持 Fallback)
|
||||||
|
*/
|
||||||
|
public boolean createDefaultConfig(DefaultConfigRequest request) {
|
||||||
|
log.info("创建默认配置, configKey: {}", request.getConfigKey());
|
||||||
|
CommonResponse<String> response = defaultConfigClient.createDefaultConfig(request);
|
||||||
|
String result = handleResponse(response, "创建默认配置失败");
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新默认配置(直接操作,不支持 Fallback)
|
||||||
|
*/
|
||||||
|
public DefaultConfigConflict updateDefaultConfig(String configKey, Map<String, Object> updates) {
|
||||||
|
log.info("更新默认配置, configKey: {}, updates: {}", configKey, updates);
|
||||||
|
CommonResponse<Map<String, Object>> response = defaultConfigClient.updateDefaultConfig(configKey, updates);
|
||||||
|
Map<String, Object> result = handleResponse(response, "更新默认配置失败");
|
||||||
|
|
||||||
|
// 检查是否有冲突信息
|
||||||
|
if (result != null && result.containsKey("conflict")) {
|
||||||
|
Object conflictObj = result.get("conflict");
|
||||||
|
if (conflictObj instanceof Map) {
|
||||||
|
// 将Map转换为DefaultConfigConflict对象
|
||||||
|
return mapToDefaultConfigConflict((Map<String, Object>) conflictObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除默认配置(直接操作,不支持 Fallback)
|
||||||
|
*/
|
||||||
|
public boolean deleteDefaultConfig(String configKey) {
|
||||||
|
log.info("删除默认配置, configKey: {}", configKey);
|
||||||
|
CommonResponse<String> response = defaultConfigClient.deleteDefaultConfig(configKey);
|
||||||
|
String result = handleResponse(response, "删除默认配置失败");
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新默认配置(直接操作,不支持 Fallback)
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigResponse batchUpdateDefaultConfigs(BatchDefaultConfigRequest request) {
|
||||||
|
log.info("批量更新默认配置, configs count: {}", request.getConfigs().size());
|
||||||
|
CommonResponse<BatchDefaultConfigResponse> response = defaultConfigClient.batchUpdateDefaultConfigs(request);
|
||||||
|
return handleResponse(response, "批量更新默认配置失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建批量配置请求构建器
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigRequestBuilder createBatchConfigBuilder() {
|
||||||
|
return new BatchDefaultConfigRequestBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量配置请求构建器
|
||||||
|
*/
|
||||||
|
public static class BatchDefaultConfigRequestBuilder {
|
||||||
|
private final BatchDefaultConfigRequest request = new BatchDefaultConfigRequest();
|
||||||
|
|
||||||
|
public BatchDefaultConfigRequestBuilder() {
|
||||||
|
request.setConfigs(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加配置项
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigRequestBuilder addConfig(String configKey, String configValue,
|
||||||
|
String configType, String description) {
|
||||||
|
DefaultConfigRequest item = new DefaultConfigRequest();
|
||||||
|
item.setConfigKey(configKey);
|
||||||
|
item.setConfigValue(configValue);
|
||||||
|
item.setConfigType(configType);
|
||||||
|
item.setDescription(description);
|
||||||
|
request.getConfigs().add(item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加视频配置
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigRequestBuilder addVideoConfig(String resolution, Integer frameRate, String codec) {
|
||||||
|
addConfig("resolution", resolution, "string", "视频分辨率");
|
||||||
|
addConfig("frameRate", frameRate.toString(), "int", "视频帧率");
|
||||||
|
addConfig("codec", codec, "string", "视频编码格式");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加网络配置
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigRequestBuilder addNetworkConfig(String ipAddress, Integer port, String protocol) {
|
||||||
|
addConfig("ipAddress", ipAddress, "string", "IP地址");
|
||||||
|
addConfig("port", port.toString(), "int", "端口号");
|
||||||
|
addConfig("protocol", protocol, "string", "网络协议");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求对象
|
||||||
|
*/
|
||||||
|
public BatchDefaultConfigRequest build() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Map转换为DefaultConfigConflict对象
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private DefaultConfigConflict mapToDefaultConfigConflict(Map<String, Object> map) {
|
||||||
|
DefaultConfigConflict conflict = new DefaultConfigConflict();
|
||||||
|
|
||||||
|
if (map.containsKey("configKey")) {
|
||||||
|
conflict.setConfigKey((String) map.get("configKey"));
|
||||||
|
}
|
||||||
|
if (map.containsKey("conflictType")) {
|
||||||
|
conflict.setConflictType((String) map.get("conflictType"));
|
||||||
|
}
|
||||||
|
if (map.containsKey("deviceCount")) {
|
||||||
|
Object deviceCount = map.get("deviceCount");
|
||||||
|
if (deviceCount instanceof Number) {
|
||||||
|
conflict.setDeviceCount(((Number) deviceCount).intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (map.containsKey("currentType")) {
|
||||||
|
conflict.setCurrentType((String) map.get("currentType"));
|
||||||
|
}
|
||||||
|
if (map.containsKey("proposedType")) {
|
||||||
|
conflict.setProposedType((String) map.get("proposedType"));
|
||||||
|
}
|
||||||
|
if (map.containsKey("conflictDevices")) {
|
||||||
|
Object conflictDevices = map.get("conflictDevices");
|
||||||
|
if (conflictDevices instanceof Iterable) {
|
||||||
|
conflict.setConflictDevices(new ArrayList<>());
|
||||||
|
for (Object deviceId : (Iterable<?>) conflictDevices) {
|
||||||
|
if (deviceId instanceof Number) {
|
||||||
|
conflict.getConflictDevices().add(((Number) deviceId).longValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conflict;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
|
||||||
|
if (response == null || !response.isSuccess()) {
|
||||||
|
String msg = response != null && response.getMessage() != null
|
||||||
|
? response.getMessage()
|
||||||
|
: errorMessage;
|
||||||
|
Integer code = response != null ? response.getCode() : 5000;
|
||||||
|
throw new IntegrationException(code, msg, SERVICE_NAME);
|
||||||
|
}
|
||||||
|
return response.getData();
|
||||||
|
}
|
||||||
|
}
|
@@ -4,6 +4,7 @@ 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;
|
||||||
import com.ycwl.basic.integration.device.client.DeviceV2Client;
|
import com.ycwl.basic.integration.device.client.DeviceV2Client;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.device.dto.device.*;
|
import com.ycwl.basic.integration.device.dto.device.*;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -91,20 +92,20 @@ public class DeviceIntegrationService {
|
|||||||
handleResponse(response, "删除设备失败");
|
handleResponse(response, "删除设备失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceV2ListResponse listDevices(Integer page, Integer pageSize, String name, String no,
|
public PageResponse<DeviceV2DTO> listDevices(Integer page, Integer pageSize, String name, String no,
|
||||||
String type, Integer isActive, Long scenicId) {
|
String type, Integer isActive, Long scenicId) {
|
||||||
log.debug("分页查询设备列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
log.debug("分页查询设备列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
||||||
page, pageSize, name, no, type, isActive, scenicId);
|
page, pageSize, name, no, type, isActive, scenicId);
|
||||||
CommonResponse<DeviceV2ListResponse> response = deviceV2Client.listDevices(
|
CommonResponse<PageResponse<DeviceV2DTO>> response = deviceV2Client.listDevices(
|
||||||
page, pageSize, name, no, type, isActive, scenicId);
|
page, pageSize, name, no, type, isActive, scenicId);
|
||||||
return handleResponse(response, "分页查询设备列表失败");
|
return handleResponse(response, "分页查询设备列表失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceV2WithConfigListResponse listDevicesWithConfig(Integer page, Integer pageSize, String name, String no,
|
public PageResponse<DeviceV2WithConfigDTO> listDevicesWithConfig(Integer page, Integer pageSize, String name, String no,
|
||||||
String type, Integer isActive, Long scenicId) {
|
String type, Integer isActive, Long scenicId) {
|
||||||
log.debug("分页查询设备带配置列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
log.debug("分页查询设备带配置列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
||||||
page, pageSize, name, no, type, isActive, scenicId);
|
page, pageSize, name, no, type, isActive, scenicId);
|
||||||
CommonResponse<DeviceV2WithConfigListResponse> response = deviceV2Client.listDevicesWithConfig(
|
CommonResponse<PageResponse<DeviceV2WithConfigDTO>> response = deviceV2Client.listDevicesWithConfig(
|
||||||
page, pageSize, name, no, type, isActive, scenicId);
|
page, pageSize, name, no, type, isActive, scenicId);
|
||||||
return handleResponse(response, "分页查询设备带配置列表失败");
|
return handleResponse(response, "分页查询设备带配置列表失败");
|
||||||
}
|
}
|
||||||
@@ -196,14 +197,14 @@ public class DeviceIntegrationService {
|
|||||||
/**
|
/**
|
||||||
* 获取景区的IPC设备列表
|
* 获取景区的IPC设备列表
|
||||||
*/
|
*/
|
||||||
public DeviceV2ListResponse getScenicIpcDevices(Long scenicId, Integer page, Integer pageSize) {
|
public PageResponse<DeviceV2DTO> getScenicIpcDevices(Long scenicId, Integer page, Integer pageSize) {
|
||||||
return listDevices(page, pageSize, null, null, "IPC", 1, scenicId);
|
return listDevices(page, pageSize, null, null, "IPC", 1, scenicId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取景区的所有激活设备
|
* 获取景区的所有激活设备
|
||||||
*/
|
*/
|
||||||
public DeviceV2ListResponse getScenicActiveDevices(Long scenicId, Integer page, Integer pageSize) {
|
public PageResponse<DeviceV2DTO> getScenicActiveDevices(Long scenicId, Integer page, Integer pageSize) {
|
||||||
return listDevices(page, pageSize, null, null, null, 1, scenicId);
|
return listDevices(page, pageSize, null, null, null, 1, scenicId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
package com.ycwl.basic.integration.render.client;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器配置V2客户端
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "zt-render-worker", contextId = "render-worker-config-v2", path = "/api/render/worker/config/v2")
|
||||||
|
public interface RenderWorkerConfigV2Client {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器所有配置
|
||||||
|
*/
|
||||||
|
@GetMapping("/{workerId}")
|
||||||
|
CommonResponse<List<RenderWorkerConfigV2DTO>> getWorkerConfigs(@PathVariable("workerId") Long workerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置键获取特定配置
|
||||||
|
*/
|
||||||
|
@GetMapping("/{workerId}/key/{configKey}")
|
||||||
|
CommonResponse<RenderWorkerConfigV2DTO> getWorkerConfigByKey(@PathVariable("workerId") Long workerId,
|
||||||
|
@PathVariable("configKey") String configKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建配置
|
||||||
|
*/
|
||||||
|
@PostMapping("/{workerId}")
|
||||||
|
CommonResponse<RenderWorkerConfigV2DTO> createWorkerConfig(@PathVariable("workerId") Long workerId,
|
||||||
|
@RequestBody RenderWorkerConfigV2DTO config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
*/
|
||||||
|
@PutMapping("/{workerId}/{id}")
|
||||||
|
CommonResponse<Void> updateWorkerConfig(@PathVariable("workerId") Long workerId,
|
||||||
|
@PathVariable("id") Long id,
|
||||||
|
@RequestBody Map<String, Object> updates);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{workerId}/{id}")
|
||||||
|
CommonResponse<Void> deleteWorkerConfig(@PathVariable("workerId") Long workerId,
|
||||||
|
@PathVariable("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新配置
|
||||||
|
*/
|
||||||
|
@PostMapping("/{workerId}/batch")
|
||||||
|
CommonResponse<Void> batchUpdateWorkerConfigs(@PathVariable("workerId") Long workerId,
|
||||||
|
@RequestBody BatchRenderWorkerConfigRequest request);
|
||||||
|
}
|
@@ -0,0 +1,76 @@
|
|||||||
|
package com.ycwl.basic.integration.render.client;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.*;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器V2客户端
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "zt-render-worker", contextId = "render-worker-v2", path = "/api/render/worker/v2")
|
||||||
|
public interface RenderWorkerV2Client {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器核心信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
CommonResponse<RenderWorkerV2DTO> getWorker(@PathVariable("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器含配置信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/{id}/with-config")
|
||||||
|
CommonResponse<RenderWorkerV2WithConfigDTO> getWorkerWithConfig(@PathVariable("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建工作器
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
CommonResponse<RenderWorkerV2DTO> createWorker(@RequestBody CreateRenderWorkerRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新工作器
|
||||||
|
*/
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
CommonResponse<Void> updateWorker(@PathVariable("id") Long id,
|
||||||
|
@RequestBody UpdateRenderWorkerRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除工作器
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
CommonResponse<Void> deleteWorker(@PathVariable("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询工作器列表(核心信息)
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
CommonResponse<PageResponse<RenderWorkerV2DTO>> listWorkers(@RequestParam(defaultValue = "1") Integer page,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
|
@RequestParam(required = false) Integer isEnabled,
|
||||||
|
@RequestParam(required = false) String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询工作器列表(含配置信息)
|
||||||
|
*/
|
||||||
|
@GetMapping("/with-config")
|
||||||
|
CommonResponse<PageResponse<RenderWorkerV2WithConfigDTO>> listWorkersWithConfig(
|
||||||
|
@RequestParam(defaultValue = "1") Integer page,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
|
@RequestParam(required = false) Integer isEnabled,
|
||||||
|
@RequestParam(required = false) String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取工作器核心信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/key/{key}")
|
||||||
|
CommonResponse<RenderWorkerV2DTO> getWorkerByKey(@PathVariable("key") String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取工作器完整信息(含配置)
|
||||||
|
*/
|
||||||
|
@GetMapping("/key/{key}/with-config")
|
||||||
|
CommonResponse<RenderWorkerV2WithConfigDTO> getWorkerWithConfigByKey(@PathVariable("key") String key);
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
package com.ycwl.basic.integration.render.config;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.config.IntegrationProperties;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器集成配置
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(prefix = "integration.render", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RenderWorkerIntegrationConfig {
|
||||||
|
|
||||||
|
private final IntegrationProperties integrationProperties;
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新渲染工作器配置请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BatchRenderWorkerConfigRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置列表
|
||||||
|
*/
|
||||||
|
private List<RenderWorkerConfigV2DTO> configs;
|
||||||
|
}
|
@@ -0,0 +1,63 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器配置DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RenderWorkerConfigV2DTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器ID
|
||||||
|
*/
|
||||||
|
@JsonProperty("workerId")
|
||||||
|
private Long workerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置键
|
||||||
|
*/
|
||||||
|
@JsonProperty("configKey")
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置值
|
||||||
|
*/
|
||||||
|
@JsonProperty("configValue")
|
||||||
|
private String configValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置类型 (string/int/float/bool/json)
|
||||||
|
*/
|
||||||
|
@JsonProperty("configType")
|
||||||
|
private String configType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 (0-禁用,1-启用)
|
||||||
|
*/
|
||||||
|
@JsonProperty("isActive")
|
||||||
|
private Integer isActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("createTime")
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("updateTime")
|
||||||
|
private String updateTime;
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.worker;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建渲染工作器请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateRenderWorkerRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器名称
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "工作器名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器标识
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "工作器标识不能为空")
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 (0-禁用,1-启用)
|
||||||
|
*/
|
||||||
|
@JsonProperty("isActive")
|
||||||
|
private Integer isActive = 1;
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.worker;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器核心信息DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RenderWorkerV2DTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器标识
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 (0-禁用,1-启用)
|
||||||
|
*/
|
||||||
|
@JsonProperty("isActive")
|
||||||
|
private Integer isActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("createTime")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("updateTime")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
@@ -0,0 +1,55 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.worker;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带配置的渲染工作器DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RenderWorkerV2WithConfigDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器标识
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 (0-禁用,1-启用)
|
||||||
|
*/
|
||||||
|
@JsonProperty("isActive")
|
||||||
|
private Integer isActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("createTime")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("updateTime")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态配置信息
|
||||||
|
*/
|
||||||
|
private Map<String, Object> config;
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
package com.ycwl.basic.integration.render.dto.worker;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新渲染工作器请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UpdateRenderWorkerRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作器标识
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 (0-禁用,1-启用)
|
||||||
|
*/
|
||||||
|
@JsonProperty("isActive")
|
||||||
|
private Integer isActive;
|
||||||
|
}
|
@@ -0,0 +1,287 @@
|
|||||||
|
package com.ycwl.basic.integration.render.service;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.exception.IntegrationException;
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
|
import com.ycwl.basic.integration.render.client.RenderWorkerConfigV2Client;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器配置集成服务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RenderWorkerConfigIntegrationService {
|
||||||
|
|
||||||
|
private final RenderWorkerConfigV2Client renderWorkerConfigV2Client;
|
||||||
|
private final IntegrationFallbackService fallbackService;
|
||||||
|
|
||||||
|
private static final String SERVICE_NAME = "zt-render-worker";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器所有配置(带降级)
|
||||||
|
*/
|
||||||
|
public List<RenderWorkerConfigV2DTO> getWorkerConfigs(Long workerId) {
|
||||||
|
log.info("获取渲染工作器配置列表, workerId: {}", workerId);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:configs:" + workerId,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<List<RenderWorkerConfigV2DTO>> response =
|
||||||
|
renderWorkerConfigV2Client.getWorkerConfigs(workerId);
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = handleResponse(response, "获取渲染工作器配置列表失败");
|
||||||
|
return configs != null ? configs : Collections.emptyList();
|
||||||
|
},
|
||||||
|
List.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置键获取特定配置(带降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerConfigV2DTO getWorkerConfigByKey(Long workerId, String configKey) {
|
||||||
|
log.info("根据配置键获取渲染工作器配置, workerId: {}, configKey: {}", workerId, configKey);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:config:" + workerId + ":" + configKey,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<RenderWorkerConfigV2DTO> response =
|
||||||
|
renderWorkerConfigV2Client.getWorkerConfigByKey(workerId, configKey);
|
||||||
|
return handleResponse(response, "根据配置键获取渲染工作器配置失败");
|
||||||
|
},
|
||||||
|
RenderWorkerConfigV2DTO.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器平铺配置(带降级)
|
||||||
|
*/
|
||||||
|
public Map<String, Object> getWorkerFlatConfig(Long workerId) {
|
||||||
|
log.info("获取渲染工作器平铺配置, workerId: {}", workerId);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:flat:config:" + workerId,
|
||||||
|
() -> {
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = getWorkerConfigsInternal(workerId);
|
||||||
|
return flattenConfigs(configs);
|
||||||
|
},
|
||||||
|
Map.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建配置(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerConfigV2DTO createWorkerConfig(Long workerId, RenderWorkerConfigV2DTO config) {
|
||||||
|
log.info("创建渲染工作器配置, workerId: {}, configKey: {}", workerId, config.getConfigKey());
|
||||||
|
CommonResponse<RenderWorkerConfigV2DTO> response =
|
||||||
|
renderWorkerConfigV2Client.createWorkerConfig(workerId, config);
|
||||||
|
return handleResponse(response, "创建渲染工作器配置失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void updateWorkerConfig(Long workerId, Long configId, Map<String, Object> updates) {
|
||||||
|
log.info("更新渲染工作器配置, workerId: {}, configId: {}", workerId, configId);
|
||||||
|
CommonResponse<Void> response =
|
||||||
|
renderWorkerConfigV2Client.updateWorkerConfig(workerId, configId, updates);
|
||||||
|
handleVoidResponse(response, "更新渲染工作器配置失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void deleteWorkerConfig(Long workerId, Long configId) {
|
||||||
|
log.info("删除渲染工作器配置, workerId: {}, configId: {}", workerId, configId);
|
||||||
|
CommonResponse<Void> response =
|
||||||
|
renderWorkerConfigV2Client.deleteWorkerConfig(workerId, configId);
|
||||||
|
handleVoidResponse(response, "删除渲染工作器配置失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新配置(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void batchUpdateWorkerConfigs(Long workerId, BatchRenderWorkerConfigRequest request) {
|
||||||
|
log.info("批量更新渲染工作器配置, workerId: {}, configCount: {}",
|
||||||
|
workerId, request.getConfigs() != null ? request.getConfigs().size() : 0);
|
||||||
|
CommonResponse<Void> response =
|
||||||
|
renderWorkerConfigV2Client.batchUpdateWorkerConfigs(workerId, request);
|
||||||
|
handleVoidResponse(response, "批量更新渲染工作器配置失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量平铺更新配置(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void batchFlatUpdateWorkerConfigs(Long workerId, Map<String, Object> flatConfigs) {
|
||||||
|
log.info("批量平铺更新渲染工作器配置, workerId: {}, configCount: {}",
|
||||||
|
workerId, flatConfigs.size());
|
||||||
|
|
||||||
|
BatchRenderWorkerConfigRequest request = new BatchRenderWorkerConfigRequest();
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = flatConfigs.entrySet().stream()
|
||||||
|
.map(entry -> {
|
||||||
|
RenderWorkerConfigV2DTO config = new RenderWorkerConfigV2DTO();
|
||||||
|
config.setConfigKey(entry.getKey());
|
||||||
|
config.setConfigValue(String.valueOf(entry.getValue()));
|
||||||
|
config.setConfigType(determineConfigType(entry.getValue()));
|
||||||
|
config.setIsActive(1);
|
||||||
|
return config;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
request.setConfigs(configs);
|
||||||
|
batchUpdateWorkerConfigs(workerId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建批量配置构建器
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder createBatchConfigBuilder() {
|
||||||
|
return new BatchConfigBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部获取配置方法(不使用降级)
|
||||||
|
*/
|
||||||
|
private List<RenderWorkerConfigV2DTO> getWorkerConfigsInternal(Long workerId) {
|
||||||
|
CommonResponse<List<RenderWorkerConfigV2DTO>> response =
|
||||||
|
renderWorkerConfigV2Client.getWorkerConfigs(workerId);
|
||||||
|
List<RenderWorkerConfigV2DTO> configs = handleResponse(response, "获取渲染工作器配置列表失败");
|
||||||
|
return configs != null ? configs : Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将配置列表转换为平铺Map
|
||||||
|
*/
|
||||||
|
private Map<String, Object> flattenConfigs(List<RenderWorkerConfigV2DTO> configs) {
|
||||||
|
Map<String, Object> flatConfig = new HashMap<>();
|
||||||
|
for (RenderWorkerConfigV2DTO config : configs) {
|
||||||
|
if (config.getIsActive() == 1) {
|
||||||
|
Object value = convertConfigValue(config.getConfigValue(), config.getConfigType());
|
||||||
|
flatConfig.put(config.getConfigKey(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flatConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置类型转换配置值
|
||||||
|
*/
|
||||||
|
private Object convertConfigValue(String configValue, String configType) {
|
||||||
|
if (configValue == null) return null;
|
||||||
|
|
||||||
|
return switch (configType) {
|
||||||
|
case "int" -> Integer.parseInt(configValue);
|
||||||
|
case "float" -> Double.parseDouble(configValue);
|
||||||
|
case "bool" -> Boolean.parseBoolean(configValue);
|
||||||
|
case "json" -> configValue; // 保持JSON字符串格式
|
||||||
|
default -> configValue; // string类型或其他
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动判断配置类型
|
||||||
|
*/
|
||||||
|
private String determineConfigType(Object value) {
|
||||||
|
if (value instanceof Integer) return "int";
|
||||||
|
if (value instanceof Double || value instanceof Float) return "float";
|
||||||
|
if (value instanceof Boolean) return "bool";
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理通用响应
|
||||||
|
*/
|
||||||
|
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
|
||||||
|
if (response == null || !response.getSuccess()) {
|
||||||
|
String msg = response != null && response.getMessage() != null ?
|
||||||
|
response.getMessage() : errorMessage;
|
||||||
|
Integer code = response != null ? response.getCode() : 5000;
|
||||||
|
throw new IntegrationException(code, msg, SERVICE_NAME);
|
||||||
|
}
|
||||||
|
return response.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理空响应
|
||||||
|
*/
|
||||||
|
private void handleVoidResponse(CommonResponse<Void> response, String errorMessage) {
|
||||||
|
if (response == null || !response.getSuccess()) {
|
||||||
|
String msg = response != null && response.getMessage() != null ?
|
||||||
|
response.getMessage() : errorMessage;
|
||||||
|
Integer code = response != null ? response.getCode() : 5000;
|
||||||
|
throw new IntegrationException(code, msg, SERVICE_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量配置构建器
|
||||||
|
*/
|
||||||
|
public static class BatchConfigBuilder {
|
||||||
|
private final List<RenderWorkerConfigV2DTO> configs = new java.util.ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加配置项
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder addConfig(String key, String value) {
|
||||||
|
return addConfig(key, value, "string", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加配置项(指定类型)
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder addConfig(String key, String value, String type) {
|
||||||
|
return addConfig(key, value, type, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加配置项(完整)
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder addConfig(String key, String value, String type, String description) {
|
||||||
|
RenderWorkerConfigV2DTO config = new RenderWorkerConfigV2DTO();
|
||||||
|
config.setConfigKey(key);
|
||||||
|
config.setConfigValue(value);
|
||||||
|
config.setConfigType(type);
|
||||||
|
config.setDescription(description);
|
||||||
|
config.setIsActive(1);
|
||||||
|
configs.add(config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加渲染配置
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder addRenderConfig(String quality, String format, String resolution) {
|
||||||
|
return addConfig("render_quality", quality, "string", "渲染质量")
|
||||||
|
.addConfig("render_format", format, "string", "渲染格式")
|
||||||
|
.addConfig("render_resolution", resolution, "string", "渲染分辨率");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加性能配置
|
||||||
|
*/
|
||||||
|
public BatchConfigBuilder addPerformanceConfig(Integer maxTasks, Integer timeout) {
|
||||||
|
return addConfig("max_concurrent_tasks", String.valueOf(maxTasks), "int", "最大并发任务数")
|
||||||
|
.addConfig("task_timeout", String.valueOf(timeout), "int", "任务超时时间(秒)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建批量配置请求
|
||||||
|
*/
|
||||||
|
public BatchRenderWorkerConfigRequest build() {
|
||||||
|
BatchRenderWorkerConfigRequest request = new BatchRenderWorkerConfigRequest();
|
||||||
|
request.setConfigs(configs);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,168 @@
|
|||||||
|
package com.ycwl.basic.integration.render.service;
|
||||||
|
|
||||||
|
import com.ycwl.basic.integration.common.exception.IntegrationException;
|
||||||
|
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
|
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
|
||||||
|
import com.ycwl.basic.integration.render.client.RenderWorkerV2Client;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.*;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染工作器集成服务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RenderWorkerIntegrationService {
|
||||||
|
|
||||||
|
private final RenderWorkerV2Client renderWorkerV2Client;
|
||||||
|
private final IntegrationFallbackService fallbackService;
|
||||||
|
|
||||||
|
private static final String SERVICE_NAME = "zt-render-worker";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器核心信息(带降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerV2DTO getWorker(Long id) {
|
||||||
|
log.info("获取渲染工作器信息, id: {}", id);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:" + id,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<RenderWorkerV2DTO> response = renderWorkerV2Client.getWorker(id);
|
||||||
|
return handleResponse(response, "获取渲染工作器信息失败");
|
||||||
|
},
|
||||||
|
RenderWorkerV2DTO.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作器详细信息(含配置)(带降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerV2WithConfigDTO getWorkerWithConfig(Long id) {
|
||||||
|
log.info("获取渲染工作器详细信息, id: {}", id);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:config:" + id,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<RenderWorkerV2WithConfigDTO> response = renderWorkerV2Client.getWorkerWithConfig(id);
|
||||||
|
return handleResponse(response, "获取渲染工作器详细信息失败");
|
||||||
|
},
|
||||||
|
RenderWorkerV2WithConfigDTO.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建工作器(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerV2DTO createWorker(CreateRenderWorkerRequest request) {
|
||||||
|
log.info("创建渲染工作器, name: {}, key: {}", request.getName(), request.getKey());
|
||||||
|
CommonResponse<RenderWorkerV2DTO> response = renderWorkerV2Client.createWorker(request);
|
||||||
|
return handleResponse(response, "创建渲染工作器失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新工作器(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void updateWorker(Long id, UpdateRenderWorkerRequest request) {
|
||||||
|
log.info("更新渲染工作器, id: {}, name: {}", id, request.getName());
|
||||||
|
CommonResponse<Void> response = renderWorkerV2Client.updateWorker(id, request);
|
||||||
|
handleVoidResponse(response, "更新渲染工作器失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除工作器(直接调用,不降级)
|
||||||
|
*/
|
||||||
|
public void deleteWorker(Long id) {
|
||||||
|
log.info("删除渲染工作器, id: {}", id);
|
||||||
|
CommonResponse<Void> response = renderWorkerV2Client.deleteWorker(id);
|
||||||
|
handleVoidResponse(response, "删除渲染工作器失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询工作器列表(核心信息)(不降级)
|
||||||
|
*/
|
||||||
|
public PageResponse<RenderWorkerV2DTO> listWorkers(Integer page, Integer pageSize, Integer isEnabled, String name) {
|
||||||
|
log.info("分页查询渲染工作器列表, page: {}, pageSize: {}, isEnabled: {}, name: {}",
|
||||||
|
page, pageSize, isEnabled, name);
|
||||||
|
CommonResponse<PageResponse<RenderWorkerV2DTO>> response =
|
||||||
|
renderWorkerV2Client.listWorkers(page, pageSize, isEnabled, name);
|
||||||
|
return handleResponse(response, "查询渲染工作器列表失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询工作器列表(含配置信息)(不降级)
|
||||||
|
*/
|
||||||
|
public PageResponse<RenderWorkerV2WithConfigDTO> listWorkersWithConfig(Integer page, Integer pageSize,
|
||||||
|
Integer isEnabled, String name) {
|
||||||
|
log.info("分页查询渲染工作器列表(含配置), page: {}, pageSize: {}, isEnabled: {}, name: {}",
|
||||||
|
page, pageSize, isEnabled, name);
|
||||||
|
CommonResponse<PageResponse<RenderWorkerV2WithConfigDTO>> response =
|
||||||
|
renderWorkerV2Client.listWorkersWithConfig(page, pageSize, isEnabled, name);
|
||||||
|
return handleResponse(response, "查询渲染工作器列表(含配置)失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取工作器核心信息(带降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerV2DTO getWorkerByKey(String key) {
|
||||||
|
log.info("根据key获取渲染工作器信息, key: {}", key);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:key:" + key,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<RenderWorkerV2DTO> response = renderWorkerV2Client.getWorkerByKey(key);
|
||||||
|
return handleResponse(response, "根据key获取渲染工作器信息失败");
|
||||||
|
},
|
||||||
|
RenderWorkerV2DTO.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取工作器详细信息(含配置)(带降级)
|
||||||
|
*/
|
||||||
|
public RenderWorkerV2WithConfigDTO getWorkerWithConfigByKey(String key) {
|
||||||
|
log.info("根据key获取渲染工作器详细信息, key: {}", key);
|
||||||
|
return fallbackService.executeWithFallback(
|
||||||
|
SERVICE_NAME,
|
||||||
|
"worker:key:config:" + key,
|
||||||
|
() -> {
|
||||||
|
CommonResponse<RenderWorkerV2WithConfigDTO> response = renderWorkerV2Client.getWorkerWithConfigByKey(key);
|
||||||
|
return handleResponse(response, "根据key获取渲染工作器详细信息失败");
|
||||||
|
},
|
||||||
|
RenderWorkerV2WithConfigDTO.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理通用响应
|
||||||
|
*/
|
||||||
|
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
|
||||||
|
if (response == null || !response.getSuccess()) {
|
||||||
|
String msg = response != null && response.getMessage() != null ?
|
||||||
|
response.getMessage() : errorMessage;
|
||||||
|
Integer code = response != null ? response.getCode() : 5000;
|
||||||
|
throw new IntegrationException(code, msg, SERVICE_NAME);
|
||||||
|
}
|
||||||
|
return response.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理空响应
|
||||||
|
*/
|
||||||
|
private void handleVoidResponse(CommonResponse<Void> response, String errorMessage) {
|
||||||
|
if (response == null || !response.getSuccess()) {
|
||||||
|
String msg = response != null && response.getMessage() != null ?
|
||||||
|
response.getMessage() : errorMessage;
|
||||||
|
Integer code = response != null ? response.getCode() : 5000;
|
||||||
|
throw new IntegrationException(code, msg, SERVICE_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -6,8 +6,7 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest;
|
|||||||
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse;
|
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -38,13 +37,13 @@ public interface ScenicV2Client {
|
|||||||
CommonResponse<ScenicFilterPageResponse> filterScenics(@RequestBody ScenicFilterRequest request);
|
CommonResponse<ScenicFilterPageResponse> filterScenics(@RequestBody ScenicFilterRequest request);
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
CommonResponse<ScenicV2ListResponse> listScenics(@RequestParam(defaultValue = "1") Integer page,
|
CommonResponse<PageResponse<ScenicV2DTO>> listScenics(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) Integer status,
|
@RequestParam(required = false) Integer status,
|
||||||
@RequestParam(required = false) String name);
|
@RequestParam(required = false) String name);
|
||||||
|
|
||||||
@GetMapping("/with-config")
|
@GetMapping("/with-config")
|
||||||
CommonResponse<ScenicV2WithConfigListResponse> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
CommonResponse<PageResponse<ScenicV2WithConfigDTO>> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(required = false) Integer status,
|
@RequestParam(required = false) Integer status,
|
||||||
@RequestParam(required = false) String name);
|
@RequestParam(required = false) String name);
|
||||||
|
@@ -1,21 +0,0 @@
|
|||||||
package com.ycwl.basic.integration.scenic.dto.scenic;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ScenicV2ListResponse {
|
|
||||||
@JsonProperty("list")
|
|
||||||
private List<ScenicV2DTO> list;
|
|
||||||
|
|
||||||
@JsonProperty("total")
|
|
||||||
private Integer total;
|
|
||||||
|
|
||||||
@JsonProperty("page")
|
|
||||||
private Integer page;
|
|
||||||
|
|
||||||
@JsonProperty("pageSize")
|
|
||||||
private Integer pageSize;
|
|
||||||
}
|
|
@@ -1,21 +0,0 @@
|
|||||||
package com.ycwl.basic.integration.scenic.dto.scenic;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ScenicV2WithConfigListResponse {
|
|
||||||
@JsonProperty("list")
|
|
||||||
private List<ScenicV2WithConfigDTO> list;
|
|
||||||
|
|
||||||
@JsonProperty("total")
|
|
||||||
private Integer total;
|
|
||||||
|
|
||||||
@JsonProperty("page")
|
|
||||||
private Integer page;
|
|
||||||
|
|
||||||
@JsonProperty("pageSize")
|
|
||||||
private Integer pageSize;
|
|
||||||
}
|
|
@@ -13,7 +13,7 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DefaultConfigIntegrationService {
|
public class ScenicDefaultConfigIntegrationService {
|
||||||
|
|
||||||
private final DefaultConfigClient defaultConfigClient;
|
private final DefaultConfigClient defaultConfigClient;
|
||||||
|
|
@@ -10,8 +10,7 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest;
|
|||||||
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse;
|
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -93,15 +92,15 @@ public class ScenicIntegrationService {
|
|||||||
return handleResponse(response, "筛选景区失败");
|
return handleResponse(response, "筛选景区失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScenicV2ListResponse listScenics(Integer page, Integer pageSize, Integer status, String name) {
|
public PageResponse<ScenicV2DTO> listScenics(Integer page, Integer pageSize, Integer status, String name) {
|
||||||
log.debug("分页查询景区列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name);
|
log.debug("分页查询景区列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name);
|
||||||
CommonResponse<ScenicV2ListResponse> response = scenicV2Client.listScenics(page, pageSize, status, name);
|
CommonResponse<PageResponse<ScenicV2DTO>> response = scenicV2Client.listScenics(page, pageSize, status, name);
|
||||||
return handleResponse(response, "分页查询景区列表失败");
|
return handleResponse(response, "分页查询景区列表失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScenicV2WithConfigListResponse listScenicsWithConfig(Integer page, Integer pageSize, Integer status, String name) {
|
public PageResponse<ScenicV2WithConfigDTO> listScenicsWithConfig(Integer page, Integer pageSize, Integer status, String name) {
|
||||||
log.debug("分页查询景区带配置列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name);
|
log.debug("分页查询景区带配置列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name);
|
||||||
CommonResponse<ScenicV2WithConfigListResponse> response = scenicV2Client.listScenicsWithConfig(page, pageSize, status, name);
|
CommonResponse<PageResponse<ScenicV2WithConfigDTO>> response = scenicV2Client.listScenicsWithConfig(page, pageSize, status, name);
|
||||||
return handleResponse(response, "分页查询景区带配置列表失败");
|
return handleResponse(response, "分页查询景区带配置列表失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
package com.ycwl.basic.mapper;
|
|
||||||
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author:longbinbin
|
|
||||||
* @Date:2024/11/29 17:22
|
|
||||||
* 渲染机管理表
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface RenderWorkerMapper {
|
|
||||||
List<RenderWorkerEntity> list(RenderWorkerReqQuery renderWorkerReqQuery);
|
|
||||||
RenderWorkerEntity getById(Long id);
|
|
||||||
int add(RenderWorkerEntity renderWorker);
|
|
||||||
int deleteById(Long id);
|
|
||||||
int update(RenderWorkerEntity renderWorker);
|
|
||||||
int updateStatus(Long id);
|
|
||||||
|
|
||||||
RenderWorkerEntity findByAccessKey(String accessKey);
|
|
||||||
|
|
||||||
int updateHost(Long id, RenderWorkerEntity status);
|
|
||||||
}
|
|
@@ -14,50 +14,16 @@ import java.util.Date;
|
|||||||
* 渲染机管理表
|
* 渲染机管理表
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("render_worker")
|
|
||||||
public class RenderWorkerEntity {
|
public class RenderWorkerEntity {
|
||||||
@TableId
|
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 渲染机名称
|
* 渲染机名称
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 系统
|
|
||||||
*/
|
|
||||||
private String platform;
|
|
||||||
/**
|
|
||||||
* 运行环境
|
|
||||||
*/
|
|
||||||
private String runtimeVersion;
|
|
||||||
/**
|
|
||||||
* 版本
|
|
||||||
*/
|
|
||||||
private String version;
|
|
||||||
/**
|
/**
|
||||||
* 访问秘钥
|
* 访问秘钥
|
||||||
*/
|
*/
|
||||||
private String accessKey;
|
private String accessKey;
|
||||||
/**
|
|
||||||
* cpu数量
|
|
||||||
*/
|
|
||||||
private Integer cpuCount;
|
|
||||||
/**
|
|
||||||
* cpu使用率
|
|
||||||
*/
|
|
||||||
private BigDecimal cpuUsage;
|
|
||||||
/**
|
|
||||||
* 内存总量,MB
|
|
||||||
*/
|
|
||||||
private BigDecimal memoryTotal;
|
|
||||||
/**
|
|
||||||
* 内存余量,MB
|
|
||||||
*/
|
|
||||||
private BigDecimal memoryAvailable;
|
|
||||||
/**
|
|
||||||
* 支持的功能,逗号隔开
|
|
||||||
*/
|
|
||||||
private String supportFeature;
|
|
||||||
/**
|
/**
|
||||||
* 是否仅用于指定景区,空或0不适用,否则为景区ID
|
* 是否仅用于指定景区,空或0不适用,否则为景区ID
|
||||||
*/
|
*/
|
||||||
@@ -66,24 +32,10 @@ public class RenderWorkerEntity {
|
|||||||
* 是否仅用于测试,0不是,1是
|
* 是否仅用于测试,0不是,1是
|
||||||
*/
|
*/
|
||||||
private Integer testOnly;
|
private Integer testOnly;
|
||||||
/**
|
|
||||||
* 是否在线,0不在,1在
|
|
||||||
*/
|
|
||||||
private Integer online;
|
|
||||||
/**
|
/**
|
||||||
* 状态,0禁用,1启用
|
* 状态,0禁用,1启用
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
private Date createAt;
|
private Date createAt;
|
||||||
private Date updateAt;
|
private Date updateAt;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储类型
|
|
||||||
*/
|
|
||||||
private StorageType storeType;
|
|
||||||
/**
|
|
||||||
* 存储配置
|
|
||||||
*/
|
|
||||||
private String storeConfigJson;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,50 +1,50 @@
|
|||||||
package com.ycwl.basic.repository;
|
package com.ycwl.basic.repository;
|
||||||
|
|
||||||
import com.ycwl.basic.utils.JacksonUtil;
|
import com.ycwl.basic.utils.JacksonUtil;
|
||||||
import com.ycwl.basic.mapper.RenderWorkerMapper;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
||||||
import com.ycwl.basic.model.task.req.ClientStatusReqVo;
|
import com.ycwl.basic.model.task.req.ClientStatusReqVo;
|
||||||
|
import com.ycwl.basic.integration.render.dto.worker.RenderWorkerV2DTO;
|
||||||
|
import com.ycwl.basic.integration.render.service.RenderWorkerIntegrationService;
|
||||||
|
import com.ycwl.basic.integration.render.service.RenderWorkerConfigIntegrationService;
|
||||||
|
import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO;
|
||||||
|
import com.ycwl.basic.integration.common.manager.RenderWorkerConfigManager;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
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 java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class RenderWorkerRepository {
|
public class RenderWorkerRepository {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, String> redisTemplate;
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
public static final String RENDER_WORKER_CACHE_KEY = "render_worker:%s";
|
|
||||||
public static final String RENDER_WORKER_STATUS_CACHE_KEY = "render_worker:host_status:%s";
|
public static final String RENDER_WORKER_STATUS_CACHE_KEY = "render_worker:host_status:%s";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RenderWorkerMapper mapper;
|
private RenderWorkerIntegrationService renderWorkerIntegrationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RenderWorkerConfigIntegrationService renderWorkerConfigIntegrationService;
|
||||||
|
|
||||||
public RenderWorkerEntity getWorkerByAccessKey(String accessKey) {
|
public RenderWorkerEntity getWorkerByAccessKey(String accessKey) {
|
||||||
String key = String.format(RENDER_WORKER_CACHE_KEY, accessKey);
|
RenderWorkerV2DTO workerDTO = renderWorkerIntegrationService.getWorkerByKey(accessKey);
|
||||||
if (redisTemplate.hasKey(key)) {
|
if (workerDTO == null) {
|
||||||
return JacksonUtil.parseObject(redisTemplate.opsForValue().get(key), RenderWorkerEntity.class);
|
return null;
|
||||||
}
|
|
||||||
RenderWorkerEntity renderWorker = mapper.findByAccessKey(accessKey);
|
|
||||||
if (renderWorker != null) {
|
|
||||||
redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS);
|
|
||||||
redisTemplate.opsForValue().set(String.format(RENDER_WORKER_CACHE_KEY, renderWorker.getId()), JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS);
|
|
||||||
}
|
}
|
||||||
|
RenderWorkerEntity renderWorker = convertToEntity(workerDTO);
|
||||||
return renderWorker;
|
return renderWorker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderWorkerEntity getWorker(Long id) {
|
public RenderWorkerEntity getWorker(Long id) {
|
||||||
String key = String.format(RENDER_WORKER_CACHE_KEY, id);
|
RenderWorkerV2DTO workerDTO = renderWorkerIntegrationService.getWorker(id);
|
||||||
if (redisTemplate.hasKey(key)) {
|
if (workerDTO == null) {
|
||||||
return JacksonUtil.parseObject(redisTemplate.opsForValue().get(key), RenderWorkerEntity.class);
|
return null;
|
||||||
}
|
|
||||||
RenderWorkerEntity renderWorker = mapper.getById(id);
|
|
||||||
if (renderWorker != null) {
|
|
||||||
redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS);
|
|
||||||
redisTemplate.opsForValue().set(String.format(RENDER_WORKER_CACHE_KEY, renderWorker.getAccessKey()), JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS);
|
|
||||||
}
|
}
|
||||||
|
RenderWorkerEntity renderWorker = convertToEntity(workerDTO);
|
||||||
return renderWorker;
|
return renderWorker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,21 +54,6 @@ public class RenderWorkerRepository {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
status.setUpdateAt(new Date());
|
status.setUpdateAt(new Date());
|
||||||
RenderWorkerEntity worker = new RenderWorkerEntity();
|
|
||||||
worker.setCpuCount(status.getCpu_count());
|
|
||||||
worker.setCpuUsage(status.getCpu_usage());
|
|
||||||
// 上报的是字节,存储的是兆
|
|
||||||
worker.setMemoryAvailable(status.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
worker.setMemoryTotal(status.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
|
|
||||||
worker.setPlatform(status.getPlatform());
|
|
||||||
worker.setRuntimeVersion(status.getRuntime_version());
|
|
||||||
worker.setSupportFeature(String.join(",", status.getSupport_feature()));
|
|
||||||
worker.setVersion(status.getVersion());
|
|
||||||
worker.setUpdateAt(status.getUpdateAt());
|
|
||||||
if (!redisTemplate.hasKey(key)) {
|
|
||||||
mapper.updateHost(id, worker);
|
|
||||||
}
|
|
||||||
redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(status), 1, TimeUnit.HOURS);
|
redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(status), 1, TimeUnit.HOURS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +66,34 @@ public class RenderWorkerRepository {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearCache(Long id) {
|
private RenderWorkerEntity convertToEntity(RenderWorkerV2DTO dto) {
|
||||||
RenderWorkerEntity worker = getWorker(id);
|
if (dto == null) {
|
||||||
redisTemplate.delete(String.format(RENDER_WORKER_CACHE_KEY, id));
|
return null;
|
||||||
if (worker != null) {
|
|
||||||
redisTemplate.delete(String.format(RENDER_WORKER_CACHE_KEY, worker.getAccessKey()));
|
|
||||||
}
|
}
|
||||||
redisTemplate.delete(String.format(RENDER_WORKER_STATUS_CACHE_KEY, id));
|
RenderWorkerEntity entity = new RenderWorkerEntity();
|
||||||
|
entity.setId(dto.getId());
|
||||||
|
entity.setName(dto.getName());
|
||||||
|
entity.setAccessKey(dto.getKey());
|
||||||
|
entity.setStatus(dto.getIsActive());
|
||||||
|
entity.setCreateAt(dto.getCreateTime());
|
||||||
|
entity.setUpdateAt(dto.getUpdateTime());
|
||||||
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取渲染工作器配置管理器
|
||||||
|
*
|
||||||
|
* @param workerId 工作器ID
|
||||||
|
* @return RenderWorkerConfigManager实例,如果获取失败返回null
|
||||||
|
*/
|
||||||
|
public RenderWorkerConfigManager getWorkerConfigManager(Long workerId) {
|
||||||
|
try {
|
||||||
|
List<RenderWorkerConfigV2DTO> configList = renderWorkerConfigIntegrationService.getWorkerConfigs(workerId);
|
||||||
|
return new RenderWorkerConfigManager(configList);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取渲染工作器配置管理器失败, workerId: {}", workerId, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ package com.ycwl.basic.repository;
|
|||||||
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||||
import com.ycwl.basic.integration.common.util.ConfigValueUtil;
|
import com.ycwl.basic.integration.common.util.ConfigValueUtil;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
|
||||||
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
|
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
|
||||||
import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService;
|
import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService;
|
||||||
@@ -212,7 +212,7 @@ public class ScenicRepository {
|
|||||||
String name = scenicReqQuery.getName();
|
String name = scenicReqQuery.getName();
|
||||||
|
|
||||||
// 调用 zt-scenic 服务的 list 方法
|
// 调用 zt-scenic 服务的 list 方法
|
||||||
ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name);
|
PageResponse<ScenicV2DTO> response = scenicIntegrationService.listScenics(page, pageSize, status, name);
|
||||||
|
|
||||||
// 将 ScenicV2DTO 列表转换为 ScenicEntity 列表
|
// 将 ScenicV2DTO 列表转换为 ScenicEntity 列表
|
||||||
if (response != null && response.getList() != null) {
|
if (response != null && response.getList() != null) {
|
||||||
|
@@ -5,7 +5,8 @@ import com.github.pagehelper.PageInfo;
|
|||||||
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
|
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
|
||||||
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
|
||||||
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
||||||
import com.ycwl.basic.integration.device.dto.device.DeviceV2ListResponse;
|
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
|
||||||
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.mapper.ExtraDeviceMapper;
|
import com.ycwl.basic.mapper.ExtraDeviceMapper;
|
||||||
import com.ycwl.basic.mapper.ScenicAccountMapper;
|
import com.ycwl.basic.mapper.ScenicAccountMapper;
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
@@ -86,7 +87,7 @@ public class AppScenicServiceImpl implements AppScenicService {
|
|||||||
public ApiResponse<ScenicDeviceCountVO> deviceCountByScenicId(Long scenicId) {
|
public ApiResponse<ScenicDeviceCountVO> deviceCountByScenicId(Long scenicId) {
|
||||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||||
// 通过zt-device服务获取设备统计
|
// 通过zt-device服务获取设备统计
|
||||||
DeviceV2ListResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(scenicId, 1, 1000);
|
PageResponse<DeviceV2DTO> deviceListResponse = deviceIntegrationService.getScenicActiveDevices(scenicId, 1, 1000);
|
||||||
ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO();
|
ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO();
|
||||||
if (deviceListResponse != null && deviceListResponse.getList() != null) {
|
if (deviceListResponse != null && deviceListResponse.getList() != null) {
|
||||||
scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size());
|
scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size());
|
||||||
@@ -120,7 +121,7 @@ public class AppScenicServiceImpl implements AppScenicService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 通过zt-device服务获取设备统计
|
// 通过zt-device服务获取设备统计
|
||||||
DeviceV2ListResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(id, 1, 1000);
|
PageResponse<DeviceV2DTO> deviceListResponse = deviceIntegrationService.getScenicActiveDevices(id, 1, 1000);
|
||||||
ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO();
|
ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO();
|
||||||
if (deviceListResponse != null && deviceListResponse.getList() != null) {
|
if (deviceListResponse != null && deviceListResponse.getList() != null) {
|
||||||
scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size());
|
scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size());
|
||||||
@@ -276,7 +277,7 @@ public class AppScenicServiceImpl implements AppScenicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<List<DeviceRespVO>> getDevices(Long scenicId) {
|
public ApiResponse<List<DeviceRespVO>> getDevices(Long scenicId) {
|
||||||
DeviceV2ListResponse deviceV2ListResponse = deviceIntegrationService.listDevices(1, 1000, null, null, null, 1, scenicId);
|
PageResponse<DeviceV2DTO> deviceV2ListResponse = deviceIntegrationService.listDevices(1, 1000, null, null, null, 1, scenicId);
|
||||||
List<DeviceRespVO> deviceRespVOList = deviceV2ListResponse.getList().stream().map(device -> {
|
List<DeviceRespVO> deviceRespVOList = deviceV2ListResponse.getList().stream().map(device -> {
|
||||||
DeviceRespVO deviceRespVO = new DeviceRespVO();
|
DeviceRespVO deviceRespVO = new DeviceRespVO();
|
||||||
deviceRespVO.setId(device.getId());
|
deviceRespVO.setId(device.getId());
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
package com.ycwl.basic.service.pc;
|
|
||||||
|
|
||||||
import com.github.pagehelper.PageInfo;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery;
|
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author:longbinbin
|
|
||||||
* @Date:2024/12/3 15:07
|
|
||||||
*/
|
|
||||||
public interface RenderWorkerService {
|
|
||||||
ApiResponse<PageInfo<RenderWorkerEntity>> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery);
|
|
||||||
ApiResponse<List<RenderWorkerEntity>> list(RenderWorkerReqQuery renderWorkerReqQuery);
|
|
||||||
ApiResponse<RenderWorkerEntity> detail(Long id);
|
|
||||||
ApiResponse<Integer> add(RenderWorkerEntity renderWorker);
|
|
||||||
ApiResponse<Integer> deleteById(Long id);
|
|
||||||
ApiResponse<Integer> update(RenderWorkerEntity renderWorker);
|
|
||||||
ApiResponse<Integer> updateStatus(Long id);
|
|
||||||
}
|
|
@@ -1,139 +0,0 @@
|
|||||||
package com.ycwl.basic.service.pc.impl;
|
|
||||||
|
|
||||||
import com.github.pagehelper.PageHelper;
|
|
||||||
import com.github.pagehelper.PageInfo;
|
|
||||||
import com.ycwl.basic.mapper.RenderWorkerMapper;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
|
|
||||||
import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery;
|
|
||||||
import com.ycwl.basic.model.task.req.ClientStatusReqVo;
|
|
||||||
import com.ycwl.basic.repository.RenderWorkerRepository;
|
|
||||||
import com.ycwl.basic.service.pc.RenderWorkerService;
|
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author:longbinbin
|
|
||||||
* @Date:2024/12/3 15:09
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class RenderWorkerServiceImpl implements RenderWorkerService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RenderWorkerMapper renderWorkerMapper;
|
|
||||||
@Autowired
|
|
||||||
private RenderWorkerRepository renderWorkerRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<PageInfo<RenderWorkerEntity>> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery) {
|
|
||||||
PageHelper.startPage(renderWorkerReqQuery.getPageNum(), renderWorkerReqQuery.getPageSize());
|
|
||||||
List<RenderWorkerEntity> list = renderWorkerMapper.list(renderWorkerReqQuery);
|
|
||||||
list.forEach(worker -> {
|
|
||||||
ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId());
|
|
||||||
if (clientStatus == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
worker.setCpuCount(clientStatus.getCpu_count());
|
|
||||||
worker.setCpuUsage(clientStatus.getCpu_usage());
|
|
||||||
// 上报的是字节,存储的是兆
|
|
||||||
worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
|
|
||||||
worker.setPlatform(clientStatus.getPlatform());
|
|
||||||
worker.setRuntimeVersion(clientStatus.getRuntime_version());
|
|
||||||
worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature()));
|
|
||||||
worker.setVersion(clientStatus.getVersion());
|
|
||||||
worker.setUpdateAt(clientStatus.getUpdateAt());
|
|
||||||
});
|
|
||||||
PageInfo<RenderWorkerEntity> pageInfo = new PageInfo<>(list);
|
|
||||||
return ApiResponse.success(pageInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<List<RenderWorkerEntity>> list(RenderWorkerReqQuery renderWorkerReqQuery) {
|
|
||||||
List<RenderWorkerEntity> list = renderWorkerMapper.list(renderWorkerReqQuery);
|
|
||||||
list.forEach(worker -> {
|
|
||||||
ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId());
|
|
||||||
if (clientStatus == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
worker.setCpuCount(clientStatus.getCpu_count());
|
|
||||||
worker.setCpuUsage(clientStatus.getCpu_usage());
|
|
||||||
// 上报的是字节,存储的是兆
|
|
||||||
worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
|
|
||||||
worker.setPlatform(clientStatus.getPlatform());
|
|
||||||
worker.setRuntimeVersion(clientStatus.getRuntime_version());
|
|
||||||
worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature()));
|
|
||||||
worker.setVersion(clientStatus.getVersion());
|
|
||||||
worker.setUpdateAt(clientStatus.getUpdateAt());
|
|
||||||
});
|
|
||||||
return ApiResponse.success(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<RenderWorkerEntity> detail(Long id) {
|
|
||||||
RenderWorkerEntity worker = renderWorkerMapper.getById(id);
|
|
||||||
|
|
||||||
ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId());
|
|
||||||
if (clientStatus != null) {
|
|
||||||
worker.setCpuCount(clientStatus.getCpu_count());
|
|
||||||
worker.setCpuUsage(clientStatus.getCpu_usage());
|
|
||||||
// 上报的是字节,存储的是兆
|
|
||||||
worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING));
|
|
||||||
|
|
||||||
worker.setPlatform(clientStatus.getPlatform());
|
|
||||||
worker.setRuntimeVersion(clientStatus.getRuntime_version());
|
|
||||||
worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature()));
|
|
||||||
worker.setVersion(clientStatus.getVersion());
|
|
||||||
worker.setUpdateAt(clientStatus.getUpdateAt());
|
|
||||||
}
|
|
||||||
return ApiResponse.success(worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<Integer> add(RenderWorkerEntity renderWorker) {
|
|
||||||
renderWorker.setId(SnowFlakeUtil.getLongId());
|
|
||||||
if (StringUtils.isEmpty(renderWorker.getAccessKey())) {
|
|
||||||
renderWorker.setAccessKey(SnowFlakeUtil.getId());
|
|
||||||
}
|
|
||||||
renderWorker.setStatus(0);
|
|
||||||
int add = renderWorkerMapper.add(renderWorker);
|
|
||||||
if (add == 0) {
|
|
||||||
return ApiResponse.fail("渲染机添加失败");
|
|
||||||
}else {
|
|
||||||
return ApiResponse.success(add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<Integer> deleteById(Long id) {
|
|
||||||
renderWorkerRepository.clearCache(id);
|
|
||||||
return ApiResponse.success(renderWorkerMapper.deleteById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<Integer> update(RenderWorkerEntity renderWorker) {
|
|
||||||
renderWorkerRepository.clearCache(renderWorker.getId());
|
|
||||||
int update = renderWorkerMapper.update(renderWorker);
|
|
||||||
if (update == 0) {
|
|
||||||
return ApiResponse.fail("渲染机修改失败");
|
|
||||||
}else {
|
|
||||||
return ApiResponse.success(update);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResponse<Integer> updateStatus(Long id) {
|
|
||||||
renderWorkerRepository.clearCache(id);
|
|
||||||
return ApiResponse.success(renderWorkerMapper.updateStatus(id));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -2,7 +2,8 @@ package com.ycwl.basic.service.task.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.crypto.digest.MD5;
|
import cn.hutool.crypto.digest.MD5;
|
||||||
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
|
import com.ycwl.basic.integration.common.manager.RenderWorkerConfigManager;
|
||||||
|
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
|
||||||
import com.ycwl.basic.utils.JacksonUtil;
|
import com.ycwl.basic.utils.JacksonUtil;
|
||||||
import com.ycwl.basic.biz.OrderBiz;
|
import com.ycwl.basic.biz.OrderBiz;
|
||||||
import com.ycwl.basic.biz.TaskStatusBiz;
|
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||||
@@ -12,7 +13,6 @@ import com.ycwl.basic.constant.TaskConstant;
|
|||||||
import com.ycwl.basic.mapper.FaceMapper;
|
import com.ycwl.basic.mapper.FaceMapper;
|
||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.MemberMapper;
|
import com.ycwl.basic.mapper.MemberMapper;
|
||||||
import com.ycwl.basic.mapper.RenderWorkerMapper;
|
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
import com.ycwl.basic.mapper.TaskMapper;
|
import com.ycwl.basic.mapper.TaskMapper;
|
||||||
import com.ycwl.basic.mapper.TemplateMapper;
|
import com.ycwl.basic.mapper.TemplateMapper;
|
||||||
@@ -83,6 +83,8 @@ import java.util.stream.Collectors;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class TaskTaskServiceImpl implements TaskService {
|
public class TaskTaskServiceImpl implements TaskService {
|
||||||
|
private static final String WORKER_SELF_HOSTED_CACHE_KEY = "worker_self_hosted_scenic:%s";
|
||||||
|
private static final int CACHE_EXPIRE_MINUTES = 3;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskMapper taskMapper;
|
private TaskMapper taskMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -121,13 +123,40 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private VideoReUploader videoReUploader;
|
private VideoReUploader videoReUploader;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
|
|
||||||
private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
|
private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
|
||||||
String accessKey = req.getAccessKey();
|
String accessKey = req.getAccessKey();
|
||||||
if (accessKey == null) {
|
if (accessKey == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return repository.getWorkerByAccessKey(accessKey);
|
RenderWorkerEntity worker = repository.getWorkerByAccessKey(accessKey);
|
||||||
|
if (worker == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (worker.getStatus() != 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWorkerSelfHostedScenic(Long scenicId) {
|
||||||
|
String cacheKey = String.format(WORKER_SELF_HOSTED_CACHE_KEY, scenicId);
|
||||||
|
String cachedValue = redisTemplate.opsForValue().get(cacheKey);
|
||||||
|
|
||||||
|
if (cachedValue != null) {
|
||||||
|
return Boolean.parseBoolean(cachedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存中没有,查询配置
|
||||||
|
ScenicConfigManager config = scenicRepository.getScenicConfigManager(scenicId);
|
||||||
|
boolean workerSelfHostedScenic = Boolean.TRUE.equals(config.getBoolean("worker_self_hosted"));
|
||||||
|
|
||||||
|
// 缓存结果,设置30分钟过期
|
||||||
|
redisTemplate.opsForValue().set(cacheKey, String.valueOf(workerSelfHostedScenic), CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES);
|
||||||
|
|
||||||
|
return workerSelfHostedScenic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -136,7 +165,6 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
if (worker == null) {
|
if (worker == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
worker.setOnline(1);
|
|
||||||
worker.setName(null);
|
worker.setName(null);
|
||||||
worker.setStatus(null);
|
worker.setStatus(null);
|
||||||
// get status
|
// get status
|
||||||
@@ -162,21 +190,25 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
} else {
|
} else {
|
||||||
updTemplateList = templateRepository.getAllEnabledTemplateList();
|
updTemplateList = templateRepository.getAllEnabledTemplateList();
|
||||||
}
|
}
|
||||||
|
RenderWorkerConfigManager configManager = repository.getWorkerConfigManager(worker.getId());
|
||||||
try {
|
try {
|
||||||
if (lock.tryLock(2, TimeUnit.SECONDS)) {
|
if (lock.tryLock(2, TimeUnit.SECONDS)) {
|
||||||
try {
|
try {
|
||||||
List<TaskRespVO> taskList;
|
List<TaskRespVO> taskList;
|
||||||
if (worker.getScenicOnly() != null) {
|
if (Strings.isNotBlank(configManager.getString("scenic_only"))) {
|
||||||
taskList = taskMapper.selectNotRunningByScenicList(worker.getScenicOnly());
|
taskList = taskMapper.selectNotRunningByScenicList(configManager.getString("scenic_only"));
|
||||||
} else {
|
} else {
|
||||||
taskList = taskMapper.selectNotRunning();
|
var _taskList = taskMapper.selectNotRunning();
|
||||||
|
taskList = _taskList.stream().filter(task -> {
|
||||||
|
boolean workerSelfHostedScenic = isWorkerSelfHostedScenic(task.getScenicId());
|
||||||
|
return !workerSelfHostedScenic;
|
||||||
|
}).limit(1).toList();
|
||||||
}
|
}
|
||||||
resp.setTasks(taskList);
|
resp.setTasks(taskList);
|
||||||
resp.setTemplates(updTemplateList);
|
resp.setTemplates(updTemplateList);
|
||||||
taskList.forEach(task -> {
|
taskList.forEach(task -> {
|
||||||
taskMapper.assignToWorker(task.getId(), worker.getId());
|
taskMapper.assignToWorker(task.getId(), worker.getId());
|
||||||
videoTaskRepository.clearTaskCache(task.getId());
|
videoTaskRepository.clearTaskCache(task.getId());
|
||||||
repository.clearCache(worker.getId());
|
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@@ -551,10 +583,11 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
if (worker == null) {
|
if (worker == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
RenderWorkerConfigManager config = repository.getWorkerConfigManager(worker.getId());
|
||||||
IStorageAdapter adapter;
|
IStorageAdapter adapter;
|
||||||
try {
|
try {
|
||||||
adapter = StorageFactory.get(worker.getStoreType());
|
adapter = StorageFactory.get(config.getString("store_type"));
|
||||||
adapter.loadConfig(JacksonUtil.parseObject(worker.getStoreConfigJson(), Map.class));
|
adapter.loadConfig(config.getObject("store_config_json", Map.class));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
|
adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import com.ycwl.basic.device.DeviceFactory;
|
|||||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||||
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
|
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
|
||||||
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
||||||
import com.ycwl.basic.integration.device.dto.device.DeviceV2ListResponse;
|
import com.ycwl.basic.integration.common.response.PageResponse;
|
||||||
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
|
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||||
@@ -37,9 +37,8 @@ public class VideoPieceCleaner {
|
|||||||
public void clean() {
|
public void clean() {
|
||||||
log.info("开始删除视频文件");
|
log.info("开始删除视频文件");
|
||||||
// 通过zt-device服务获取所有激活设备
|
// 通过zt-device服务获取所有激活设备
|
||||||
DeviceV2ListResponse deviceListResponse = deviceIntegrationService.listDevices(1, 10000, null, null, null, 1, null);
|
PageResponse<DeviceV2DTO> deviceListResponse = deviceIntegrationService.listDevices(1, 10000, null, null, null, 1, null);
|
||||||
List<DeviceEntity> deviceList;
|
if (deviceListResponse == null || deviceListResponse.getList() == null) {
|
||||||
if (deviceListResponse == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (DeviceV2DTO device : deviceListResponse.getList()) {
|
for (DeviceV2DTO device : deviceListResponse.getList()) {
|
||||||
|
@@ -1,142 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.ycwl.basic.mapper.RenderWorkerMapper">
|
|
||||||
<insert id="add">
|
|
||||||
insert into render_worker(id, `name`, platform, runtime_version, version, access_key,
|
|
||||||
cpu_count, cpu_usage, memory_total, memory_available, support_feature, scenic_only, test_only, `online`, `status`)
|
|
||||||
VALUES (#{id}, #{name}, #{platform}, #{runtimeVersion}, #{version}, #{accessKey},
|
|
||||||
#{cpuCount}, #{cpuUsage}, #{memoryTotal}, #{memoryAvailable}, #{supportFeature}, #{scenicOnly}, #{testOnly}, #{online}, #{status})
|
|
||||||
|
|
||||||
</insert>
|
|
||||||
<update id="update">
|
|
||||||
update render_worker
|
|
||||||
<set>
|
|
||||||
<if test="name!= null and name!= ''">
|
|
||||||
name = #{name},
|
|
||||||
</if>
|
|
||||||
<if test="platform!= null and platform!= ''">
|
|
||||||
platform = #{platform},
|
|
||||||
</if>
|
|
||||||
<if test="runtimeVersion!= null and runtimeVersion!= ''">
|
|
||||||
runtime_version = #{runtimeVersion},
|
|
||||||
</if>
|
|
||||||
<if test="version!= null and version!= ''">
|
|
||||||
version = #{version},
|
|
||||||
</if>
|
|
||||||
<if test="accessKey!= null and accessKey!= ''">
|
|
||||||
access_key = #{accessKey},
|
|
||||||
</if>
|
|
||||||
<if test="cpuCount!= null">
|
|
||||||
cpu_count = #{cpuCount},
|
|
||||||
</if>
|
|
||||||
<if test="cpuUsage!= null">
|
|
||||||
cpu_usage = #{cpuUsage},
|
|
||||||
</if>
|
|
||||||
<if test="memoryTotal!= null">
|
|
||||||
memory_total = #{memoryTotal},
|
|
||||||
</if>
|
|
||||||
<if test="memoryAvailable!= null">
|
|
||||||
memory_available = #{memoryAvailable},
|
|
||||||
</if>
|
|
||||||
<if test="supportFeature!= null">
|
|
||||||
support_feature = #{supportFeature},
|
|
||||||
</if>
|
|
||||||
<if test="scenicOnly!= null">
|
|
||||||
scenic_only = #{scenicOnly},
|
|
||||||
</if>
|
|
||||||
<if test="testOnly!= null">
|
|
||||||
test_only = #{testOnly},
|
|
||||||
</if>
|
|
||||||
<if test="online!= null">
|
|
||||||
`online` = #{online},
|
|
||||||
</if>
|
|
||||||
</set>
|
|
||||||
where id = #{id}
|
|
||||||
</update>
|
|
||||||
<update id="updateStatus">
|
|
||||||
update render_worker
|
|
||||||
set status = (CASE
|
|
||||||
status
|
|
||||||
WHEN 1 THEN
|
|
||||||
0
|
|
||||||
WHEN 0 THEN
|
|
||||||
1
|
|
||||||
ELSE null
|
|
||||||
END)
|
|
||||||
where id = #{id}
|
|
||||||
</update>
|
|
||||||
<update id="updateHost">
|
|
||||||
update render_worker
|
|
||||||
set platform = #{status.platform},
|
|
||||||
runtime_version = #{status.runtimeVersion},
|
|
||||||
version = #{status.version},
|
|
||||||
cpu_count = #{status.cpuCount},
|
|
||||||
cpu_usage = #{status.cpuUsage},
|
|
||||||
memory_total = #{status.memoryTotal},
|
|
||||||
memory_available = #{status.memoryAvailable},
|
|
||||||
support_feature = #{status.supportFeature},
|
|
||||||
update_at = #{status.updateAt}
|
|
||||||
where id = #{id}
|
|
||||||
</update>
|
|
||||||
<delete id="deleteById">
|
|
||||||
delete from render_worker where id = #{id}
|
|
||||||
</delete>
|
|
||||||
|
|
||||||
<select id="list" resultType="com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity">
|
|
||||||
select id, `name`, platform, runtime_version, version, access_key,
|
|
||||||
cpu_count, cpu_usage, memory_total, memory_available, support_feature, scenic_only, test_only, `online`, `status`, create_at, update_at
|
|
||||||
from render_worker
|
|
||||||
<where>
|
|
||||||
<if test="name!= null and name!= ''">
|
|
||||||
and `name` like concat('%', #{name}, '%')
|
|
||||||
</if>
|
|
||||||
<if test="platform!= null and platform!= ''">
|
|
||||||
and platform like concat('%', #{platform}, '%')
|
|
||||||
</if>
|
|
||||||
<if test="runtimeVersion!= null and runtimeVersion!= ''">
|
|
||||||
and runtime_version like concat('%', #{runtimeVersion}, '%')
|
|
||||||
</if>
|
|
||||||
<if test="version!= null and version!= ''">
|
|
||||||
and version like concat('%', #{version}, '%')
|
|
||||||
</if>
|
|
||||||
<if test="cpuCount!= null">
|
|
||||||
and cpu_count = #{cpuCount}
|
|
||||||
</if>
|
|
||||||
<if test="cpuUsage!= null">
|
|
||||||
and cpu_usage = #{cpuUsage}
|
|
||||||
</if>
|
|
||||||
<if test="supportFeature!= null">
|
|
||||||
and support_feature like concat('%',#{supportFeature},'%')
|
|
||||||
</if>
|
|
||||||
<if test="scenicOnly!= null">
|
|
||||||
and scenic_only = #{scenicOnly}
|
|
||||||
</if>
|
|
||||||
<if test="testOnly!= null">
|
|
||||||
and test_only = #{testOnly}
|
|
||||||
</if>
|
|
||||||
<if test="online!= null">
|
|
||||||
and `online` = #{online}
|
|
||||||
</if>
|
|
||||||
<if test="status!= null">
|
|
||||||
and `status` = #{status}
|
|
||||||
</if>
|
|
||||||
<if test="startTime!=null">
|
|
||||||
and create_at >= #{startTime}
|
|
||||||
</if>
|
|
||||||
<if test="endTime!=null">
|
|
||||||
and create_at <= #{endTime}
|
|
||||||
</if>
|
|
||||||
</where>
|
|
||||||
</select>
|
|
||||||
<select id="getById" resultType="com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity">
|
|
||||||
select id, `name`, platform, runtime_version, version, access_key,
|
|
||||||
cpu_count, cpu_usage, memory_total, memory_available, support_feature, scenic_only, test_only, `online`, `status`, create_at, update_at
|
|
||||||
from render_worker
|
|
||||||
where id = #{id}
|
|
||||||
</select>
|
|
||||||
<select id="findByAccessKey" resultType="com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity">
|
|
||||||
select id, `name`, scenic_only, test_only, `online`, `status`, create_at, update_at, store_type, store_config_json
|
|
||||||
from render_worker
|
|
||||||
where access_key = #{accessKey} and status = 1
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
@@ -84,14 +84,6 @@
|
|||||||
from task
|
from task
|
||||||
where status = 0
|
where status = 0
|
||||||
and worker_id is null
|
and worker_id is null
|
||||||
and NOT EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM render_worker rw
|
|
||||||
WHERE
|
|
||||||
rw.status = 1
|
|
||||||
AND FIND_IN_SET(task.scenic_id, rw.scenic_only) > 0 -- 检查scenic_id是否在逗号分隔的字符串中
|
|
||||||
)
|
|
||||||
limit 1
|
|
||||||
</select>
|
</select>
|
||||||
<select id="selectAllNotRunning" resultType="com.ycwl.basic.model.pc.task.entity.TaskEntity">
|
<select id="selectAllNotRunning" resultType="com.ycwl.basic.model.pc.task.entity.TaskEntity">
|
||||||
select *
|
select *
|
||||||
|
Reference in New Issue
Block a user