1. 优化用户部门选择部门时的支持接口

2. 完善 e 办同步接口重跑和定时重跑任务
This commit is contained in:
chenbowen
2025-09-18 21:20:43 +08:00
parent 79c1d5e6a4
commit f8c984d627
13 changed files with 404 additions and 11 deletions

View File

@@ -32,7 +32,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url> <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties> <properties>
<revision>3.0.33</revision> <revision>3.0.34</revision>
<!-- Maven 相关 --> <!-- Maven 相关 -->
<java.version>17</java.version> <java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.source>${java.version}</maven.compiler.source>

View File

@@ -0,0 +1,14 @@
-- 达梦8数据库DDL脚本
-- 为 system_dept 表添加 code 和 short_name 字段
-- 添加部门编码字段
ALTER TABLE system_dept ADD COLUMN code VARCHAR(50);
-- 添加部门简称字段
ALTER TABLE system_dept ADD COLUMN short_name VARCHAR(20);
-- 添加字段注释
COMMENT ON COLUMN system_dept.code IS '部门编码';
COMMENT ON COLUMN system_dept.short_name IS '部门简称';

View File

@@ -26,7 +26,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url> <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties> <properties>
<revision>3.0.33</revision> <revision>3.0.34</revision>
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version> <flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<!-- 统一依赖管理 --> <!-- 统一依赖管理 -->
<spring.boot.version>3.4.5</spring.boot.version> <spring.boot.version>3.4.5</spring.boot.version>

View File

@@ -13,6 +13,9 @@ public class DeptRespDTO {
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
private String name; private String name;
@Schema(description = "部门编码", example = "XXXXXXX")
private String code;
@Schema(description = "父部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "父部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long parentId; private Long parentId;

View File

@@ -105,18 +105,18 @@ public class DeptController {
@GetMapping("/top-level-list") @GetMapping("/top-level-list")
@Operation(summary = "获取顶级部门列表", description = "用于懒加载,只返回没有父部门的顶级部门") @Operation(summary = "获取顶级部门列表", description = "用于懒加载,只返回没有父部门的顶级部门")
@PreAuthorize("@ss.hasPermission('system:dept:query')") @PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<List<DeptSimpleRespVO>> getTopLevelDeptList() { public CommonResult<List<DeptRespVO>> getTopLevelDeptList() {
List<DeptDO> list = deptService.getTopLevelDeptList(); List<DeptDO> list = deptService.getTopLevelDeptList();
return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); return success(BeanUtils.toBean(list, DeptRespVO.class));
} }
@GetMapping("/children") @GetMapping("/children")
@Operation(summary = "根据父部门ID获取子部门列表", description = "用于懒加载根据父部门ID返回直接子部门") @Operation(summary = "根据父部门ID获取子部门列表", description = "用于懒加载根据父部门ID返回直接子部门")
@Parameter(name = "parentId", description = "父部门ID", required = true, example = "1024") @Parameter(name = "parentId", description = "父部门ID", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dept:query')") @PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<List<DeptSimpleRespVO>> getChildrenDeptList(@RequestParam("parentId") Long parentId) { public CommonResult<List<DeptRespVO>> getChildrenDeptList(@RequestParam("parentId") Long parentId) {
List<DeptDO> list = deptService.getDirectChildDeptList(parentId); List<DeptDO> list = deptService.getDirectChildDeptList(parentId);
return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); return success(BeanUtils.toBean(list, DeptRespVO.class));
} }
@GetMapping("/get") @GetMapping("/get")

View File

@@ -20,7 +20,6 @@ public class DeptSaveReqVO {
private Long id; private Long id;
@Schema(description = "部门编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "DEPT_001") @Schema(description = "部门编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "DEPT_001")
@NotBlank(message = "部门编码不能为空")
@Size(max = 50, message = "部门编码长度不能超过 50 个字符") @Size(max = 50, message = "部门编码长度不能超过 50 个字符")
private String code; private String code;

View File

@@ -16,6 +16,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/** /**
@@ -58,4 +60,36 @@ public class SyncLogController {
return success(success); return success(success);
} }
@PostMapping("/batch-rerun")
@Operation(summary = "根据服务类型批量重跑异常的同步接口")
@PreAuthorize("@ss.hasPermission('system:sync-log:batch-rerun')")
public CommonResult<Integer> batchRerunByServiceName(
@RequestParam("serviceName") String serviceName,
@RequestParam(value = "batchSize", defaultValue = "200") Integer batchSize) {
// 参数校验
if (batchSize > 500) {
throw new IllegalArgumentException("批次大小不能超过500");
}
Integer count = syncLogService.markForBatchRerun(serviceName, batchSize);
return success(count);
}
@GetMapping("/batch-rerun/progress")
@Operation(summary = "查询批量重跑进度")
@PreAuthorize("@ss.hasPermission('system:sync-log:query')")
public CommonResult<Map<String, Object>> getBatchRerunProgress(
@RequestParam("serviceName") String serviceName) {
Map<String, Object> progress = syncLogService.getBatchRerunProgress(serviceName);
return success(progress);
}
@PostMapping("/batch-rerun/pause")
@Operation(summary = "暂停批量重跑(将重试中状态重置为原失败状态)")
@PreAuthorize("@ss.hasPermission('system:sync-log:batch-rerun')")
public CommonResult<Integer> pauseBatchRerun(@RequestParam("serviceName") String serviceName) {
Integer count = syncLogService.pauseBatchRerun(serviceName);
return success(count);
}
} }

View File

@@ -17,7 +17,9 @@ public enum SyncLogStatusEnum {
SIGNATURE_VERIFY_FAILED(2, "签名验证失败"), SIGNATURE_VERIFY_FAILED(2, "签名验证失败"),
AUTH_FAILED(3, "认证失败"), AUTH_FAILED(3, "认证失败"),
BUSINESS_FAILED(4, "业务处理失败"), BUSINESS_FAILED(4, "业务处理失败"),
SYSTEM_ERROR(5, "系统异常"); SYSTEM_ERROR(5, "系统异常"),
RETRYING(6, "重试中"),
RETRY_FAILED(7, "重试失败");
/** /**
* 状态码 * 状态码

View File

@@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.system.job.sync;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.service.sync.SyncLogService;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 同步日志自动标记重试任务
*
* 该任务定期扫描失败状态的同步日志记录,自动标记为"重试中"状态
* 实现完全自动化的重试闭环
*
* @author ZT
*/
@Component
@Slf4j
public class SyncLogAutoMarkRetryJob {
@Resource
private SyncLogService syncLogService;
/**
* 自动标记重试任务
*
* 建议配置执行频率每5分钟执行一次
* cron表达式0 0/5 * * * ?
*
* 该任务会按服务类型自动标记失败记录为重试状态:
* 1. 优先处理SYSTEM_ERROR状态的记录
* 2. 然后处理其他失败状态的记录
* 3. 每次每种服务类型最多标记100条记录
*/
@XxlJob("syncLogAutoMarkRetryJob")
@TenantJob
public void execute() {
log.info("[syncLogAutoMarkRetryJob][开始执行同步日志自动标记重试任务]");
try {
// 定义需要处理的服务类型
String[] serviceNames = {
"OrgCreateService",
"OrgUpdateService",
"OrgDeleteService",
"UserCreateService",
"UserUpdateService",
"UserDeleteService"
};
int totalMarkedCount = 0;
// 为每种服务类型自动标记重试
for (String serviceName : serviceNames) {
try {
// 每种服务类型最多标记100条记录避免一次性处理过多
Integer markedCount = syncLogService.autoMarkForRetry(serviceName, 100);
totalMarkedCount += markedCount;
if (markedCount > 0) {
log.info("[syncLogAutoMarkRetryJob][服务类型 {} 自动标记了 {} 条记录为重试状态]",
serviceName, markedCount);
}
} catch (Exception e) {
log.error("[syncLogAutoMarkRetryJob][处理服务类型 {} 时发生异常]", serviceName, e);
}
}
if (totalMarkedCount > 0) {
log.info("[syncLogAutoMarkRetryJob][自动标记重试任务执行完成,总共标记了 {} 条记录]", totalMarkedCount);
}
} catch (Exception e) {
log.error("[syncLogAutoMarkRetryJob][自动标记重试任务执行异常]", e);
}
}
}

View File

@@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.system.job.sync;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.service.sync.SyncLogService;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 同步日志批量重跑任务
*
* 该任务定期扫描状态为"重试中"的同步日志记录,进行分批重跑处理
*
* @author ZT
*/
@Component
@Slf4j
public class SyncLogBatchRerunJob {
@Resource
private SyncLogService syncLogService;
/**
* 执行批量重跑任务
*
* 建议配置执行频率每30秒执行一次
* cron表达式0/30 * * * * ?
*/
@XxlJob("syncLogBatchRerunJob")
@TenantJob
public void execute() {
log.info("[syncLogBatchRerunJob][开始执行同步日志批量重跑任务]");
try {
// 执行批量重跑处理每次处理50条记录
int processedCount = syncLogService.processBatchRerun(50);
if (processedCount > 0) {
log.info("[syncLogBatchRerunJob][批量重跑任务执行完成,处理了 {} 条记录]", processedCount);
}
} catch (Exception e) {
log.error("[syncLogBatchRerunJob][批量重跑任务执行异常]", e);
}
}
}

View File

@@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.userdept.UserDeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.userdept.UserDeptMapper; import cn.iocoder.yudao.module.system.dal.mysql.userdept.UserDeptMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.system.enums.dept.DeptSourceEnum;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -31,8 +32,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import cn.iocoder.yudao.module.system.enums.dept.DeptSourceEnum;
/** /**
* 部门 Service 实现类 * 部门 Service 实现类
* *
@@ -172,7 +171,7 @@ public class DeptServiceImpl implements DeptService {
@VisibleForTesting @VisibleForTesting
void validateDeptCodeUnique(Long id, String code) { void validateDeptCodeUnique(Long id, String code) {
if (StrUtil.isBlank(code)) { if (StrUtil.isBlank(code)) {
throw exception(DEPT_CODE_NOT_NULL); return;
} }
DeptDO dept = deptMapper.selectByCode(code); DeptDO dept = deptMapper.selectByCode(code);
if (dept == null) { if (dept == null) {

View File

@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
import java.util.Map;
/** /**
* 同步接口日志 Service 接口 * 同步接口日志 Service 接口
* *
@@ -107,4 +109,46 @@ public interface SyncLogService {
*/ */
boolean rerunSyncLog(Long logId); boolean rerunSyncLog(Long logId);
/**
* 根据服务类型批量标记为重试状态
*
* @param serviceName 服务名称
* @param batchSize 批次大小(限制单次标记的最大数量)
* @return 标记的记录数量
*/
Integer markForBatchRerun(String serviceName, Integer batchSize);
/**
* 自动标记失败记录为重试状态由XXL-Job调用
*
* @param serviceName 服务名称
* @param batchSize 批次大小
* @return 标记的记录数量
*/
Integer autoMarkForRetry(String serviceName, Integer batchSize);
/**
* 处理批量重跑由XXL-Job调用
*
* @param batchSize 每次处理的记录数量
* @return 实际处理的记录数量
*/
int processBatchRerun(int batchSize);
/**
* 获取批量重跑进度
*
* @param serviceName 服务名称
* @return 进度信息
*/
Map<String, Object> getBatchRerunProgress(String serviceName);
/**
* 暂停批量重跑(将重试中状态重置为系统异常状态)
*
* @param serviceName 服务名称
* @return 暂停的记录数量
*/
Integer pauseBatchRerun(String serviceName);
} }

View File

@@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.sync.SyncLogMapper; import cn.iocoder.yudao.module.system.dal.mysql.sync.SyncLogMapper;
import cn.iocoder.yudao.module.system.enums.sync.SyncLogStatusEnum; import cn.iocoder.yudao.module.system.enums.sync.SyncLogStatusEnum;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -20,6 +22,11 @@ import org.springframework.validation.annotation.Validated;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 同步接口日志 Service 实现类 * 同步接口日志 Service 实现类
@@ -304,4 +311,172 @@ public class SyncLogServiceImpl implements SyncLogService {
} }
} }
@Override
public Integer markForBatchRerun(String serviceName, Integer batchSize) {
log.info("开始批量标记重试serviceName: {}, batchSize: {}", serviceName, batchSize);
// 安全检查
if (batchSize > 500) {
throw new IllegalArgumentException("批次大小不能超过500");
}
// 查询失败状态的记录(排除成功、重试中、重试失败的状态)
List<Integer> failedStatuses = Arrays.asList(
SyncLogStatusEnum.DECRYPT_FAILED.getStatus(),
SyncLogStatusEnum.SIGNATURE_VERIFY_FAILED.getStatus(),
SyncLogStatusEnum.AUTH_FAILED.getStatus(),
SyncLogStatusEnum.BUSINESS_FAILED.getStatus(),
SyncLogStatusEnum.SYSTEM_ERROR.getStatus()
);
// 使用 MyBatis-Plus 的条件构造器进行批量更新
int updateCount = syncLogMapper.update(null,
new LambdaUpdateWrapper<SyncLogDO>()
.eq(SyncLogDO::getServiceName, serviceName)
.in(SyncLogDO::getStatus, failedStatuses)
.isNotNull(SyncLogDO::getDecryptedRequest) // 只处理有解密数据的记录
.set(SyncLogDO::getStatus, SyncLogStatusEnum.RETRYING.getStatus())
.set(SyncLogDO::getErrorCode, null)
.set(SyncLogDO::getErrorMessage, null)
.set(SyncLogDO::getExceptionStack, null)
.last("LIMIT " + batchSize));
log.info("批量标记重试完成serviceName: {}, 标记数量: {}", serviceName, updateCount);
return updateCount;
}
@Override
public Integer autoMarkForRetry(String serviceName, Integer batchSize) {
log.debug("开始自动标记重试serviceName: {}, batchSize: {}", serviceName, batchSize);
// 自动标记的策略:
// 1. 优先处理"重试失败"状态的记录(给第二次机会)
// 2. 然后处理其他失败状态的记录
// 3. 排除"重试中"状态的记录(避免重复处理)
// 4. 只处理24小时前的失败记录避免处理刚刚失败的记录
List<Integer> retryableStatuses = Arrays.asList(
SyncLogStatusEnum.RETRY_FAILED.getStatus(), // 优先重试失败的记录
SyncLogStatusEnum.SYSTEM_ERROR.getStatus(), // 系统异常可能是临时问题
SyncLogStatusEnum.BUSINESS_FAILED.getStatus(), // 业务失败也可能是临时问题
SyncLogStatusEnum.AUTH_FAILED.getStatus() // 认证失败可能是临时问题
);
// 使用 MyBatis-Plus 进行批量更新
int updateCount = syncLogMapper.update(null,
new LambdaUpdateWrapper<SyncLogDO>()
.eq(SyncLogDO::getServiceName, serviceName)
.in(SyncLogDO::getStatus, retryableStatuses)
.isNotNull(SyncLogDO::getDecryptedRequest) // 只处理有解密数据的记录
.lt(SyncLogDO::getResponseTime, LocalDateTime.now().minusHours(1)) // 只处理1小时前的记录
.set(SyncLogDO::getStatus, SyncLogStatusEnum.RETRYING.getStatus())
.set(SyncLogDO::getErrorCode, null)
.set(SyncLogDO::getErrorMessage, null)
.set(SyncLogDO::getExceptionStack, null)
.last("LIMIT " + batchSize));
if (updateCount > 0) {
log.info("自动标记重试完成serviceName: {}, 标记数量: {}", serviceName, updateCount);
}
return updateCount;
}
@Override
public int processBatchRerun(int batchSize) {
// 查询状态为"重试中"的记录
List<SyncLogDO> retryingLogs = syncLogMapper.selectList(
new LambdaQueryWrapper<SyncLogDO>()
.eq(SyncLogDO::getStatus, SyncLogStatusEnum.RETRYING.getStatus())
.orderByAsc(SyncLogDO::getId)
.last("LIMIT " + batchSize));
if (retryingLogs.isEmpty()) {
return 0;
}
log.info("开始处理批量重跑,本次处理 {} 条记录", retryingLogs.size());
int successCount = 0;
int failedCount = 0;
for (SyncLogDO log : retryingLogs) {
try {
// 调用原有的重跑业务逻辑
boolean success = rerunBusinessLogic(log.getServiceName(), log.getDecryptedRequest(), log.getId());
if (success) {
successCount++;
} else {
failedCount++;
// 标记为重试失败
updateSyncLogStatus(log.getId(), SyncLogStatusEnum.RETRY_FAILED.getStatus(),
"RETRY_FAILED", "重试失败");
}
} catch (Exception e) {
failedCount++;
// 标记为重试失败
updateSyncLogStatus(log.getId(), SyncLogStatusEnum.RETRY_FAILED.getStatus(),
"RETRY_ERROR", "重试异常: " + e.getMessage());
}
}
log.info("批量重跑处理完成,成功: {}, 失败: {}", successCount, failedCount);
return retryingLogs.size();
}
@Override
public Map<String, Object> getBatchRerunProgress(String serviceName) {
// 统计各状态的记录数量
Map<Integer, Long> statusCounts = syncLogMapper.selectList(
new LambdaQueryWrapper<SyncLogDO>()
.eq(SyncLogDO::getServiceName, serviceName)
.groupBy(SyncLogDO::getStatus))
.stream()
.collect(Collectors.groupingBy(SyncLogDO::getStatus, Collectors.counting()));
Map<String, Object> progress = new HashMap<>();
progress.put("serviceName", serviceName);
progress.put("totalCount", statusCounts.values().stream().mapToLong(Long::longValue).sum());
progress.put("successCount", statusCounts.getOrDefault(SyncLogStatusEnum.SUCCESS.getStatus(), 0L));
progress.put("retryingCount", statusCounts.getOrDefault(SyncLogStatusEnum.RETRYING.getStatus(), 0L));
progress.put("retryFailedCount", statusCounts.getOrDefault(SyncLogStatusEnum.RETRY_FAILED.getStatus(), 0L));
progress.put("failedCount",
statusCounts.getOrDefault(SyncLogStatusEnum.DECRYPT_FAILED.getStatus(), 0L) +
statusCounts.getOrDefault(SyncLogStatusEnum.SIGNATURE_VERIFY_FAILED.getStatus(), 0L) +
statusCounts.getOrDefault(SyncLogStatusEnum.AUTH_FAILED.getStatus(), 0L) +
statusCounts.getOrDefault(SyncLogStatusEnum.BUSINESS_FAILED.getStatus(), 0L) +
statusCounts.getOrDefault(SyncLogStatusEnum.SYSTEM_ERROR.getStatus(), 0L));
return progress;
}
/**
* 更新同步日志状态
*/
private void updateSyncLogStatus(Long logId, Integer status, String errorCode, String errorMessage) {
SyncLogDO updateLog = new SyncLogDO();
updateLog.setId(logId);
updateLog.setStatus(status);
updateLog.setErrorCode(errorCode);
updateLog.setErrorMessage(errorMessage);
updateLog.setResponseTime(LocalDateTime.now());
updateSyncLog(updateLog);
}
@Override
public Integer pauseBatchRerun(String serviceName) {
log.info("暂停批量重跑serviceName: {}", serviceName);
// 将"重试中"状态重置为"系统异常"状态
int updateCount = syncLogMapper.update(null,
new LambdaUpdateWrapper<SyncLogDO>()
.eq(SyncLogDO::getServiceName, serviceName)
.eq(SyncLogDO::getStatus, SyncLogStatusEnum.RETRYING.getStatus())
.set(SyncLogDO::getStatus, SyncLogStatusEnum.SYSTEM_ERROR.getStatus())
.set(SyncLogDO::getErrorCode, "PAUSED")
.set(SyncLogDO::getErrorMessage, "批量重跑已暂停"));
log.info("批量重跑暂停完成serviceName: {}, 暂停数量: {}", serviceName, updateCount);
return updateCount;
}
} }