feat(iwork): 合并流程创建日志和回调日志(iwork统一用印内容)
- 将原 iwork_workflow_log.sql 重命名为 iwork_workflow_log_20260130.sql - 在数据库表中新增回调状态、重试次数、错误信息等字段 - 更新表注释为 iWork 流程日志,表明合并了创建日志和回调日志 - 修改 requestId 字段长度从 64 扩展到 128 - 新增回调相关索引配置 - 删除 IWorkCallbackLogService 相关接口及实现类 - 将 IWorkBizCallbackListener 中的日志服务替换为工作流日志服务 - 在控制器层将回调日志查询统一到工作流日志服务 - 合并 IWorkIntegrationServiceImpl 中的流程日志处理逻辑 - 移除独立的用印流程回调日志实体类 IWorkSealLogDO - 在 IWorkWorkflowLogDO 中增加回调相关字段定义 - 完善工作流日志服务接口和实现类,支持回调状态管理 - 更新流程回调处理逻辑,统一使用工作流日志表进行状态跟踪
This commit is contained in:
@@ -1,12 +1,19 @@
|
|||||||
-- iWork 流程创建日志表(达梦数据库)
|
-- iWork 流程日志表(达梦数据库)
|
||||||
|
-- 合并了流程创建日志和回调日志
|
||||||
CREATE TABLE system_iwork_workflow_log (
|
CREATE TABLE system_iwork_workflow_log (
|
||||||
id BIGINT NOT NULL,
|
id BIGINT NOT NULL,
|
||||||
request_id VARCHAR(64) NOT NULL,
|
request_id VARCHAR(128) NOT NULL,
|
||||||
workflow_id BIGINT,
|
workflow_id BIGINT,
|
||||||
business_code VARCHAR(128),
|
business_code VARCHAR(128),
|
||||||
biz_callback_key VARCHAR(255),
|
biz_callback_key VARCHAR(255),
|
||||||
raw_request VARCHAR(2000),
|
raw_request VARCHAR(2000),
|
||||||
status VARCHAR(32),
|
status VARCHAR(32),
|
||||||
|
callback_status INTEGER,
|
||||||
|
retry_count INTEGER DEFAULT 0,
|
||||||
|
max_retry INTEGER,
|
||||||
|
last_error_message VARCHAR(512),
|
||||||
|
raw_callback VARCHAR(2000),
|
||||||
|
last_callback_time TIMESTAMP,
|
||||||
creator VARCHAR(64) DEFAULT '',
|
creator VARCHAR(64) DEFAULT '',
|
||||||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
updater VARCHAR(64) DEFAULT '',
|
updater VARCHAR(64) DEFAULT '',
|
||||||
@@ -17,14 +24,20 @@ CREATE TABLE system_iwork_workflow_log (
|
|||||||
);
|
);
|
||||||
|
|
||||||
-- 添加注释
|
-- 添加注释
|
||||||
COMMENT ON TABLE system_iwork_workflow_log IS 'iWork 流程创建日志';
|
COMMENT ON TABLE system_iwork_workflow_log IS 'iWork 流程日志';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.id IS '主键';
|
COMMENT ON COLUMN system_iwork_workflow_log.id IS '主键';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.request_id IS 'iWork 返回的请求编号';
|
COMMENT ON COLUMN system_iwork_workflow_log.request_id IS 'iWork 请求编号';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.workflow_id IS '流程模板 ID';
|
COMMENT ON COLUMN system_iwork_workflow_log.workflow_id IS '流程模板 ID';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.business_code IS '业务编码';
|
COMMENT ON COLUMN system_iwork_workflow_log.business_code IS '业务编码';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.biz_callback_key IS '业务回调标识';
|
COMMENT ON COLUMN system_iwork_workflow_log.biz_callback_key IS '业务回调标识';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.raw_request IS '创建请求原始参数';
|
COMMENT ON COLUMN system_iwork_workflow_log.raw_request IS '创建请求原文';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.status IS '流程状态';
|
COMMENT ON COLUMN system_iwork_workflow_log.status IS '流程状态';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.callback_status IS '回调处理状态';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.retry_count IS '已重试次数';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.max_retry IS '最大重试次数';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.last_error_message IS '最后错误信息';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.raw_callback IS '回调原文';
|
||||||
|
COMMENT ON COLUMN system_iwork_workflow_log.last_callback_time IS '最近回调时间';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.creator IS '创建者';
|
COMMENT ON COLUMN system_iwork_workflow_log.creator IS '创建者';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.create_time IS '创建时间';
|
COMMENT ON COLUMN system_iwork_workflow_log.create_time IS '创建时间';
|
||||||
COMMENT ON COLUMN system_iwork_workflow_log.updater IS '更新者';
|
COMMENT ON COLUMN system_iwork_workflow_log.updater IS '更新者';
|
||||||
@@ -33,6 +46,8 @@ COMMENT ON COLUMN system_iwork_workflow_log.deleted IS '是否删除';
|
|||||||
COMMENT ON COLUMN system_iwork_workflow_log.tenant_id IS '租户编号';
|
COMMENT ON COLUMN system_iwork_workflow_log.tenant_id IS '租户编号';
|
||||||
|
|
||||||
-- 创建唯一索引
|
-- 创建唯一索引
|
||||||
CREATE UNIQUE INDEX uk_request_id ON system_iwork_workflow_log(request_id);
|
CREATE UNIQUE INDEX uk_iwork_workflow_log_request_id ON system_iwork_workflow_log(request_id);
|
||||||
|
|
||||||
|
|
||||||
|
-- 创建普通索引
|
||||||
|
-- CREATE INDEX idx_iwork_workflow_log_business_code ON system_iwork_workflow_log(business_code);
|
||||||
|
-- CREATE INDEX idx_iwork_workflow_log_biz_callback_key ON system_iwork_workflow_log(biz_callback_key);
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
-- iWork 用印回调日志(DM8)
|
|
||||||
-- 表:system_iwork_seal_log
|
|
||||||
-- 序列:system_iwork_seal_log_seq
|
|
||||||
|
|
||||||
-- 清理旧对象(若存在)
|
|
||||||
DROP TABLE IF EXISTS system_iwork_seal_log;
|
|
||||||
|
|
||||||
CREATE TABLE system_iwork_seal_log (
|
|
||||||
id BIGINT NOT NULL,
|
|
||||||
request_id VARCHAR(128) NOT NULL,
|
|
||||||
business_code VARCHAR(128),
|
|
||||||
biz_callback_key VARCHAR(255),
|
|
||||||
status INTEGER,
|
|
||||||
retry_count INTEGER DEFAULT 0,
|
|
||||||
max_retry INTEGER,
|
|
||||||
last_error_message VARCHAR(512),
|
|
||||||
raw_callback VARCHAR(2000),
|
|
||||||
last_callback_time DATETIME,
|
|
||||||
creator VARCHAR(64),
|
|
||||||
create_time DATETIME DEFAULT SYSDATE,
|
|
||||||
updater VARCHAR(64),
|
|
||||||
update_time DATETIME DEFAULT SYSDATE,
|
|
||||||
deleted SMALLINT DEFAULT 0 NOT NULL,
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
UNIQUE (request_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
COMMENT ON TABLE system_iwork_seal_log IS 'iWork 用印回调日志';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.id IS '主键';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.request_id IS 'iWork requestId 唯一标识';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.business_code IS '业务单号';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.biz_callback_key IS '业务回调标识';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.status IS '状态枚举';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.retry_count IS '已重试次数';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.max_retry IS '最大重试次数快照';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.last_error_message IS '最后错误信息';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.raw_callback IS '回调原文截断';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.last_callback_time IS '最近回调时间';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.creator IS '创建者';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.create_time IS '创建时间';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.updater IS '更新者';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.update_time IS '最后更新时间';
|
|
||||||
COMMENT ON COLUMN system_iwork_seal_log.deleted IS '是否删除';
|
|
||||||
@@ -229,7 +229,6 @@ zt:
|
|||||||
- system_seq_dtl
|
- system_seq_dtl
|
||||||
- system_seq_rcd
|
- system_seq_rcd
|
||||||
- system_sync_log
|
- system_sync_log
|
||||||
- system_iwork_seal_log
|
|
||||||
ignore-caches:
|
ignore-caches:
|
||||||
- user_role_ids
|
- user_role_ids
|
||||||
- permission_menu_ids
|
- permission_menu_ids
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package com.zt.plat.module.system.controller.admin.integration.iwork;
|
|||||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.framework.tenant.core.aop.TenantIgnore;
|
import com.zt.plat.framework.tenant.core.aop.TenantIgnore;
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.*;
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.*;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkCallbackLogService;
|
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncService;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -37,7 +38,7 @@ public class IWorkIntegrationController {
|
|||||||
private final IWorkIntegrationService integrationService;
|
private final IWorkIntegrationService integrationService;
|
||||||
private final IWorkOrgRestService orgRestService;
|
private final IWorkOrgRestService orgRestService;
|
||||||
private final IWorkSyncService syncService;
|
private final IWorkSyncService syncService;
|
||||||
private final IWorkCallbackLogService callbackLogService;
|
private final IWorkWorkflowLogService workflowLogService;
|
||||||
|
|
||||||
@PostMapping("/auth/register")
|
@PostMapping("/auth/register")
|
||||||
@Operation(summary = "注册 iWork 凭证,获取服务端公钥与 secret")
|
@Operation(summary = "注册 iWork 凭证,获取服务端公钥与 secret")
|
||||||
@@ -99,17 +100,17 @@ public class IWorkIntegrationController {
|
|||||||
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:iwork:log:query')")
|
@PreAuthorize("@ss.hasPermission('system:iwork:log:query')")
|
||||||
@PostMapping("/log/page")
|
@PostMapping("/log/page")
|
||||||
@Operation(summary = "iWork 回调日志分页查询")
|
@Operation(summary = "iWork 流程日志分页查询")
|
||||||
public CommonResult<com.zt.plat.framework.common.pojo.PageResult<IWorkCallbackLogRespVO>> pageLogs(@Valid @RequestBody IWorkCallbackLogPageReqVO reqVO) {
|
public CommonResult<com.zt.plat.framework.common.pojo.PageResult<IWorkCallbackLogRespVO>> pageLogs(@Valid @RequestBody IWorkCallbackLogPageReqVO reqVO) {
|
||||||
com.zt.plat.framework.common.pojo.PageResult<com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO> page = callbackLogService.page(reqVO);
|
com.zt.plat.framework.common.pojo.PageResult<IWorkWorkflowLogDO> page = workflowLogService.page(reqVO);
|
||||||
java.util.List<IWorkCallbackLogRespVO> mapped = new java.util.ArrayList<>();
|
java.util.List<IWorkCallbackLogRespVO> mapped = new java.util.ArrayList<>();
|
||||||
for (com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO log : page.getList()) {
|
for (IWorkWorkflowLogDO log : page.getList()) {
|
||||||
IWorkCallbackLogRespVO vo = new IWorkCallbackLogRespVO();
|
IWorkCallbackLogRespVO vo = new IWorkCallbackLogRespVO();
|
||||||
vo.setId(log.getId());
|
vo.setId(log.getId());
|
||||||
vo.setRequestId(log.getRequestId());
|
vo.setRequestId(log.getRequestId());
|
||||||
vo.setBusinessCode(log.getBusinessCode());
|
vo.setBusinessCode(log.getBusinessCode());
|
||||||
vo.setBizCallbackKey(log.getBizCallbackKey());
|
vo.setBizCallbackKey(log.getBizCallbackKey());
|
||||||
vo.setStatus(log.getStatus());
|
vo.setStatus(log.getCallbackStatus());
|
||||||
vo.setRetryCount(log.getRetryCount());
|
vo.setRetryCount(log.getRetryCount());
|
||||||
vo.setMaxRetry(log.getMaxRetry());
|
vo.setMaxRetry(log.getMaxRetry());
|
||||||
vo.setLastErrorMessage(log.getLastErrorMessage());
|
vo.setLastErrorMessage(log.getLastErrorMessage());
|
||||||
@@ -126,7 +127,7 @@ public class IWorkIntegrationController {
|
|||||||
@PostMapping("/log/retry")
|
@PostMapping("/log/retry")
|
||||||
@Operation(summary = "iWork 回调手工重试")
|
@Operation(summary = "iWork 回调手工重试")
|
||||||
public CommonResult<Boolean> retry(@Valid @RequestBody IWorkWorkflowVoidReqVO reqVO) {
|
public CommonResult<Boolean> retry(@Valid @RequestBody IWorkWorkflowVoidReqVO reqVO) {
|
||||||
callbackLogService.resetAndDispatch(reqVO.getRequestId());
|
workflowLogService.resetAndDispatch(reqVO.getRequestId());
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Schema(description = "iWork 流程回调请求")
|
|
||||||
@Data
|
|
||||||
public class IWorkWorkflowCallbackReqVO {
|
|
||||||
|
|
||||||
@Schema(description = "iWork requestId,唯一标识", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
@NotBlank(message = "requestId 不能为空")
|
|
||||||
private String requestId;
|
|
||||||
|
|
||||||
@Schema(description = "业务单号 (ywxtdjbh)")
|
|
||||||
private String businessCode;
|
|
||||||
|
|
||||||
@Schema(description = "业务回调标识 bizCallbackKey")
|
|
||||||
private String bizCallbackKey;
|
|
||||||
|
|
||||||
@Schema(description = "回调状态/结果码")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
@Schema(description = "原始回调文本(可截断存储)")
|
|
||||||
private String rawBody;
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package com.zt.plat.module.system.dal.dataobject.iwork;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* iWork 用印流程回调日志。
|
|
||||||
*/
|
|
||||||
@TableName("system_iwork_seal_log")
|
|
||||||
@KeySequence("system_iwork_seal_log_seq")
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class IWorkSealLogDO extends BaseDO {
|
|
||||||
|
|
||||||
@TableId(type = IdType.ASSIGN_ID)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* iWork 返回的请求编号,唯一业务标识。
|
|
||||||
*/
|
|
||||||
private String requestId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务单号(ywxtdjbh)。
|
|
||||||
*/
|
|
||||||
private String businessCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务回调标识。
|
|
||||||
*/
|
|
||||||
private String bizCallbackKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态枚举,参考 IWorkCallbackStatusEnum。
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 已执行的自动/手工重试次数。
|
|
||||||
*/
|
|
||||||
private Integer retryCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最大重试次数(快照)。
|
|
||||||
*/
|
|
||||||
private Integer maxRetry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最后一次错误信息。
|
|
||||||
*/
|
|
||||||
private String lastErrorMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回调原始负载(截断)。
|
|
||||||
*/
|
|
||||||
private String rawCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最近一次回调时间。
|
|
||||||
*/
|
|
||||||
private LocalDateTime lastCallbackTime;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,9 +9,11 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iWork 流程创建日志。
|
* iWork 流程日志。
|
||||||
* 用于记录流程创建时的关键信息,供回调时查询使用。
|
* 合并了流程创建日志和回调日志,记录完整的流程生命周期。
|
||||||
*/
|
*/
|
||||||
@TableName("system_iwork_workflow_log")
|
@TableName("system_iwork_workflow_log")
|
||||||
@KeySequence("system_iwork_workflow_log_seq")
|
@KeySequence("system_iwork_workflow_log_seq")
|
||||||
@@ -24,27 +26,27 @@ public class IWorkWorkflowLogDO extends BaseDO {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iWork 返回的请求编号,唯一业务标识。
|
* iWork 请求编号,唯一业务标识
|
||||||
*/
|
*/
|
||||||
private String requestId;
|
private String requestId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程模板 ID。
|
* 流程模板 ID
|
||||||
*/
|
*/
|
||||||
private Long workflowId;
|
private Long workflowId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务编码(用于关联业务数据)。
|
* 业务编码(用于关联业务数据)
|
||||||
*/
|
*/
|
||||||
private String businessCode;
|
private String businessCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务回调标识(用于 MQ 消息路由)。
|
* 业务回调标识(用于 MQ 消息路由)
|
||||||
*/
|
*/
|
||||||
private String bizCallbackKey;
|
private String bizCallbackKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建请求的原始参数(JSON 格式,截断存储)。
|
* 创建请求的原始参数(JSON 格式,截断存储)
|
||||||
*/
|
*/
|
||||||
private String rawRequest;
|
private String rawRequest;
|
||||||
|
|
||||||
@@ -52,4 +54,36 @@ public class IWorkWorkflowLogDO extends BaseDO {
|
|||||||
* 流程状态:CREATED-已创建, CALLBACK_RECEIVED-已收到回调, COMPLETED-已完成
|
* 流程状态:CREATED-已创建, CALLBACK_RECEIVED-已收到回调, COMPLETED-已完成
|
||||||
*/
|
*/
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
// ========== 回调相关字段 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调处理状态:1-待处理, 2-处理中, 3-成功, 4-重试中, 5-失败
|
||||||
|
*/
|
||||||
|
private Integer callbackStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已重试次数
|
||||||
|
*/
|
||||||
|
private Integer retryCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大重试次数
|
||||||
|
*/
|
||||||
|
private Integer maxRetry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后错误信息
|
||||||
|
*/
|
||||||
|
private String lastErrorMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调原文(JSON 格式,截断存储)
|
||||||
|
*/
|
||||||
|
private String rawCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近回调时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastCallbackTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.zt.plat.module.system.dal.mysql.iwork;
|
|
||||||
|
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
|
||||||
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
|
||||||
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface IWorkSealLogMapper extends BaseMapperX<IWorkSealLogDO> {
|
|
||||||
|
|
||||||
default IWorkSealLogDO selectByRequestId(String requestId) {
|
|
||||||
return selectOne(IWorkSealLogDO::getRequestId, requestId);
|
|
||||||
}
|
|
||||||
|
|
||||||
default PageResult<IWorkSealLogDO> selectPage(IWorkCallbackLogPageReqVO reqVO) {
|
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<IWorkSealLogDO>()
|
|
||||||
.eqIfPresent(IWorkSealLogDO::getRequestId, reqVO.getRequestId())
|
|
||||||
.eqIfPresent(IWorkSealLogDO::getBusinessCode, reqVO.getBusinessCode())
|
|
||||||
.eqIfPresent(IWorkSealLogDO::getBizCallbackKey, reqVO.getBizCallbackKey())
|
|
||||||
.eqIfPresent(IWorkSealLogDO::getStatus, reqVO.getStatus())
|
|
||||||
.betweenIfPresent(IWorkSealLogDO::getCreateTime, reqVO.getCreateTime())
|
|
||||||
.betweenIfPresent(IWorkSealLogDO::getLastCallbackTime, reqVO.getLastCallbackTime())
|
|
||||||
.orderByDesc(IWorkSealLogDO::getId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.zt.plat.module.system.dal.mysql.iwork;
|
package com.zt.plat.module.system.dal.mysql.iwork;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@@ -10,4 +13,15 @@ public interface IWorkWorkflowLogMapper extends BaseMapperX<IWorkWorkflowLogDO>
|
|||||||
default IWorkWorkflowLogDO selectByRequestId(String requestId) {
|
default IWorkWorkflowLogDO selectByRequestId(String requestId) {
|
||||||
return selectOne(IWorkWorkflowLogDO::getRequestId, requestId);
|
return selectOne(IWorkWorkflowLogDO::getRequestId, requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PageResult<IWorkWorkflowLogDO> selectPage(IWorkCallbackLogPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<IWorkWorkflowLogDO>()
|
||||||
|
.eqIfPresent(IWorkWorkflowLogDO::getRequestId, reqVO.getRequestId())
|
||||||
|
.eqIfPresent(IWorkWorkflowLogDO::getBusinessCode, reqVO.getBusinessCode())
|
||||||
|
.eqIfPresent(IWorkWorkflowLogDO::getBizCallbackKey, reqVO.getBizCallbackKey())
|
||||||
|
.eqIfPresent(IWorkWorkflowLogDO::getCallbackStatus, reqVO.getStatus())
|
||||||
|
.betweenIfPresent(IWorkWorkflowLogDO::getCreateTime, reqVO.getCreateTime())
|
||||||
|
.betweenIfPresent(IWorkWorkflowLogDO::getLastCallbackTime, reqVO.getLastCallbackTime())
|
||||||
|
.orderByDesc(IWorkWorkflowLogDO::getId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package com.zt.plat.module.system.mq.iwork;
|
package com.zt.plat.module.system.mq.iwork;
|
||||||
|
|
||||||
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkCallbackLogService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
|
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackResultMessage;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||||
@@ -24,7 +22,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@RocketMQMessageListener(topic = IWorkBizCallbackResultMessage.TOPIC, consumerGroup = IWorkBizCallbackResultMessage.TOPIC + "_CONSUMER")
|
@RocketMQMessageListener(topic = IWorkBizCallbackResultMessage.TOPIC, consumerGroup = IWorkBizCallbackResultMessage.TOPIC + "_CONSUMER")
|
||||||
public class IWorkBizCallbackListener implements RocketMQListener<IWorkBizCallbackResultMessage>, InitializingBean {
|
public class IWorkBizCallbackListener implements RocketMQListener<IWorkBizCallbackResultMessage>, InitializingBean {
|
||||||
|
|
||||||
private final IWorkCallbackLogService logService;
|
private final IWorkWorkflowLogService workflowLogService;
|
||||||
private final IWorkProperties properties;
|
private final IWorkProperties properties;
|
||||||
private final IWorkBizCallbackProducer producer;
|
private final IWorkBizCallbackProducer producer;
|
||||||
private ScheduledExecutorService scheduler;
|
private ScheduledExecutorService scheduler;
|
||||||
@@ -38,16 +36,16 @@ public class IWorkBizCallbackListener implements RocketMQListener<IWorkBizCallba
|
|||||||
public void onMessage(IWorkBizCallbackResultMessage message) {
|
public void onMessage(IWorkBizCallbackResultMessage message) {
|
||||||
String key = message.getBizCallbackKey();
|
String key = message.getBizCallbackKey();
|
||||||
if (message.isSuccess()) {
|
if (message.isSuccess()) {
|
||||||
logService.markSuccess(message.getRequestId());
|
workflowLogService.markCallbackSuccess(message.getRequestId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int attempt = message.getAttempt() + 1;
|
int attempt = message.getAttempt() + 1;
|
||||||
logService.incrementRetry(message.getRequestId());
|
workflowLogService.incrementRetry(message.getRequestId());
|
||||||
int maxAttempts = message.getMaxAttempts() > 0 ? message.getMaxAttempts() : properties.getCallback().getRetry().getMaxAttempts();
|
int maxAttempts = message.getMaxAttempts() > 0 ? message.getMaxAttempts() : properties.getCallback().getRetry().getMaxAttempts();
|
||||||
|
|
||||||
if (attempt < maxAttempts) {
|
if (attempt < maxAttempts) {
|
||||||
logService.markFailure(message.getRequestId(), message.getErrorMessage(), true, maxAttempts);
|
workflowLogService.markCallbackFailure(message.getRequestId(), message.getErrorMessage(), true, maxAttempts);
|
||||||
|
|
||||||
IWorkBizCallbackMessage next = IWorkBizCallbackMessage.builder()
|
IWorkBizCallbackMessage next = IWorkBizCallbackMessage.builder()
|
||||||
.requestId(message.getRequestId())
|
.requestId(message.getRequestId())
|
||||||
@@ -60,7 +58,7 @@ public class IWorkBizCallbackListener implements RocketMQListener<IWorkBizCallba
|
|||||||
int delay = properties.getCallback().getRetry().getDelaySeconds();
|
int delay = properties.getCallback().getRetry().getDelaySeconds();
|
||||||
scheduler.schedule(() -> producer.send(next), delay, TimeUnit.SECONDS);
|
scheduler.schedule(() -> producer.send(next), delay, TimeUnit.SECONDS);
|
||||||
} else {
|
} else {
|
||||||
logService.markFailure(message.getRequestId(), message.getErrorMessage(), false, maxAttempts);
|
workflowLogService.markCallbackFailure(message.getRequestId(), message.getErrorMessage(), false, maxAttempts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.zt.plat.module.system.service.integration.iwork;
|
|
||||||
|
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowCallbackReqVO;
|
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO;
|
|
||||||
|
|
||||||
public interface IWorkCallbackLogService {
|
|
||||||
|
|
||||||
IWorkSealLogDO upsertOnCallback(IWorkWorkflowCallbackReqVO reqVO, int maxRetry, String rawBody);
|
|
||||||
|
|
||||||
void markSuccess(String requestId);
|
|
||||||
|
|
||||||
void markFailure(String requestId, String error, boolean retrying, int maxRetry);
|
|
||||||
|
|
||||||
void incrementRetry(String requestId);
|
|
||||||
|
|
||||||
PageResult<IWorkSealLogDO> page(IWorkCallbackLogPageReqVO reqVO);
|
|
||||||
|
|
||||||
void resetAndDispatch(String requestId);
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.zt.plat.module.system.service.integration.iwork;
|
package com.zt.plat.module.system.service.integration.iwork;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iWork 流程创建日志 Service
|
* iWork 流程日志 Service
|
||||||
*/
|
*/
|
||||||
public interface IWorkWorkflowLogService {
|
public interface IWorkWorkflowLogService {
|
||||||
|
|
||||||
@@ -13,7 +15,7 @@ public interface IWorkWorkflowLogService {
|
|||||||
void saveWorkflowLog(IWorkWorkflowLogDO logDO);
|
void saveWorkflowLog(IWorkWorkflowLogDO logDO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 requestId 查询流程创建日志
|
* 根据 requestId 查询流程日志
|
||||||
*/
|
*/
|
||||||
IWorkWorkflowLogDO getByRequestId(String requestId);
|
IWorkWorkflowLogDO getByRequestId(String requestId);
|
||||||
|
|
||||||
@@ -21,4 +23,36 @@ public interface IWorkWorkflowLogService {
|
|||||||
* 更新流程状态
|
* 更新流程状态
|
||||||
*/
|
*/
|
||||||
void updateStatus(String requestId, String status);
|
void updateStatus(String requestId, String status);
|
||||||
|
|
||||||
|
// ========== 回调相关方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新回调信息(收到回调时调用)
|
||||||
|
*/
|
||||||
|
void updateCallback(String requestId, String rawCallback, int maxRetry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记回调成功
|
||||||
|
*/
|
||||||
|
void markCallbackSuccess(String requestId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记回调失败
|
||||||
|
*/
|
||||||
|
void markCallbackFailure(String requestId, String errorMessage, boolean retrying, int maxRetry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加重试次数
|
||||||
|
*/
|
||||||
|
void incrementRetry(String requestId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询流程日志
|
||||||
|
*/
|
||||||
|
PageResult<IWorkWorkflowLogDO> page(IWorkCallbackLogPageReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置并重新派发回调
|
||||||
|
*/
|
||||||
|
void resetAndDispatch(String requestId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
package com.zt.plat.module.system.service.integration.iwork.impl;
|
|
||||||
|
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
|
||||||
import com.zt.plat.framework.common.util.json.JsonUtils;
|
|
||||||
import com.zt.plat.framework.common.util.object.ObjectUtils;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowCallbackReqVO;
|
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO;
|
|
||||||
import com.zt.plat.module.system.dal.mysql.iwork.IWorkSealLogMapper;
|
|
||||||
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
|
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackProducer;
|
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkCallbackLogService;
|
|
||||||
import com.zt.plat.module.system.service.integration.iwork.enums.IWorkCallbackStatusEnum;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class IWorkCallbackLogServiceImpl implements IWorkCallbackLogService {
|
|
||||||
|
|
||||||
private static final int RAW_MAX = 2000;
|
|
||||||
|
|
||||||
private final IWorkSealLogMapper logMapper;
|
|
||||||
private final IWorkBizCallbackProducer producer;
|
|
||||||
private final IWorkProperties properties;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public IWorkSealLogDO upsertOnCallback(IWorkWorkflowCallbackReqVO reqVO, int maxRetry, String rawBody) {
|
|
||||||
IWorkSealLogDO existing = logMapper.selectByRequestId(reqVO.getRequestId());
|
|
||||||
IWorkSealLogDO log = Optional.ofNullable(existing).orElseGet(IWorkSealLogDO::new);
|
|
||||||
log.setRequestId(reqVO.getRequestId());
|
|
||||||
log.setBusinessCode(reqVO.getBusinessCode());
|
|
||||||
log.setBizCallbackKey(reqVO.getBizCallbackKey());
|
|
||||||
log.setStatus(IWorkCallbackStatusEnum.CALLBACK_PENDING.getStatus());
|
|
||||||
log.setRetryCount(ObjectUtils.defaultIfNull(log.getRetryCount(), 0));
|
|
||||||
log.setMaxRetry(maxRetry);
|
|
||||||
log.setRawCallback(truncate(rawBody));
|
|
||||||
log.setLastCallbackTime(LocalDateTime.now());
|
|
||||||
if (log.getId() == null) {
|
|
||||||
logMapper.insert(log);
|
|
||||||
} else {
|
|
||||||
logMapper.updateById(log);
|
|
||||||
}
|
|
||||||
return log;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void markSuccess(String requestId) {
|
|
||||||
IWorkSealLogDO log = new IWorkSealLogDO();
|
|
||||||
log.setRequestId(requestId);
|
|
||||||
log.setStatus(IWorkCallbackStatusEnum.CALLBACK_SUCCESS.getStatus());
|
|
||||||
log.setLastErrorMessage(null);
|
|
||||||
log.setLastCallbackTime(LocalDateTime.now());
|
|
||||||
logMapper.update(log, new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<IWorkSealLogDO>()
|
|
||||||
.eq(IWorkSealLogDO::getRequestId, requestId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void markFailure(String requestId, String error, boolean retrying, int maxRetry) {
|
|
||||||
IWorkSealLogDO log = new IWorkSealLogDO();
|
|
||||||
log.setRequestId(requestId);
|
|
||||||
log.setStatus(retrying ? IWorkCallbackStatusEnum.CALLBACK_RETRYING.getStatus() : IWorkCallbackStatusEnum.CALLBACK_FAILED.getStatus());
|
|
||||||
log.setLastErrorMessage(error);
|
|
||||||
log.setLastCallbackTime(LocalDateTime.now());
|
|
||||||
log.setMaxRetry(maxRetry);
|
|
||||||
logMapper.update(log, new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<IWorkSealLogDO>()
|
|
||||||
.eq(IWorkSealLogDO::getRequestId, requestId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void incrementRetry(String requestId) {
|
|
||||||
IWorkSealLogDO db = logMapper.selectByRequestId(requestId);
|
|
||||||
if (db == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IWorkSealLogDO log = new IWorkSealLogDO();
|
|
||||||
log.setId(db.getId());
|
|
||||||
log.setRetryCount(ObjectUtils.defaultIfNull(db.getRetryCount(), 0) + 1);
|
|
||||||
log.setLastCallbackTime(LocalDateTime.now());
|
|
||||||
logMapper.updateById(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<IWorkSealLogDO> page(IWorkCallbackLogPageReqVO reqVO) {
|
|
||||||
return logMapper.selectPage(reqVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetAndDispatch(String requestId) {
|
|
||||||
IWorkSealLogDO db = logMapper.selectByRequestId(requestId);
|
|
||||||
if (db == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IWorkSealLogDO log = new IWorkSealLogDO();
|
|
||||||
log.setId(db.getId());
|
|
||||||
log.setRetryCount(0);
|
|
||||||
log.setStatus(IWorkCallbackStatusEnum.CALLBACK_RETRYING.getStatus());
|
|
||||||
log.setLastCallbackTime(LocalDateTime.now());
|
|
||||||
logMapper.updateById(log);
|
|
||||||
|
|
||||||
int maxAttempts = properties.getCallback().getRetry().getMaxAttempts();
|
|
||||||
Object payload;
|
|
||||||
try {
|
|
||||||
payload = JsonUtils.parseObject(db.getRawCallback(), Object.class);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
payload = db.getRawCallback();
|
|
||||||
}
|
|
||||||
producer.send(IWorkBizCallbackMessage.builder()
|
|
||||||
.requestId(db.getRequestId())
|
|
||||||
.bizCallbackKey(db.getBizCallbackKey())
|
|
||||||
.payload(payload)
|
|
||||||
.attempt(0)
|
|
||||||
.maxAttempts(maxAttempts)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String truncate(String raw) {
|
|
||||||
if (!StringUtils.hasText(raw)) {
|
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
return raw.length() > RAW_MAX ? raw.substring(0, RAW_MAX) : raw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ import com.zt.plat.module.system.controller.admin.integration.iwork.vo.*;
|
|||||||
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
|
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackProducer;
|
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackProducer;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkCallbackLogService;
|
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||||
@@ -65,7 +64,6 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
|
|
||||||
private final FileApi fileApi;
|
private final FileApi fileApi;
|
||||||
private final BusinessFileApi businessFileApi;
|
private final BusinessFileApi businessFileApi;
|
||||||
private final IWorkCallbackLogService callbackLogService;
|
|
||||||
private final IWorkWorkflowLogService workflowLogService;
|
private final IWorkWorkflowLogService workflowLogService;
|
||||||
private final IWorkBizCallbackProducer bizCallbackProducer;
|
private final IWorkBizCallbackProducer bizCallbackProducer;
|
||||||
|
|
||||||
@@ -250,23 +248,17 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
TenantUtils.execute(tenantId, () -> attachmentIdRef.set(saveCallbackAttachment(fileUrl, reqVO.getFileName(), referenceBusinessFile)));
|
TenantUtils.execute(tenantId, () -> attachmentIdRef.set(saveCallbackAttachment(fileUrl, reqVO.getFileName(), referenceBusinessFile)));
|
||||||
Long attachmentId = attachmentIdRef.get();
|
Long attachmentId = attachmentIdRef.get();
|
||||||
|
|
||||||
// 3. 更新回调日志
|
// 3. 更新流程日志(回调信息 + 状态)
|
||||||
int maxRetry = properties.getCallback().getRetry().getMaxAttempts();
|
int maxRetry = properties.getCallback().getRetry().getMaxAttempts();
|
||||||
String rawBody = buildCallbackRawBody(reqVO);
|
String rawBody = buildCallbackRawBody(reqVO);
|
||||||
IWorkWorkflowCallbackReqVO logReqVO = buildCallbackLogReqVO(reqVO);
|
|
||||||
if (StringUtils.hasText(bizCallbackKey)) {
|
|
||||||
logReqVO.setBizCallbackKey(bizCallbackKey);
|
|
||||||
}
|
|
||||||
callbackLogService.upsertOnCallback(logReqVO, maxRetry, rawBody);
|
|
||||||
|
|
||||||
// 4. 更新流程创建日志状态
|
|
||||||
if (workflowLog != null) {
|
if (workflowLog != null) {
|
||||||
|
workflowLogService.updateCallback(reqVO.getRequestId(), rawBody, maxRetry);
|
||||||
String status = StringUtils.hasText(reqVO.getStatus()) ? reqVO.getStatus() : "CALLBACK_RECEIVED";
|
String status = StringUtils.hasText(reqVO.getStatus()) ? reqVO.getStatus() : "CALLBACK_RECEIVED";
|
||||||
workflowLogService.updateStatus(reqVO.getRequestId(), status);
|
workflowLogService.updateStatus(reqVO.getRequestId(), status);
|
||||||
log.info("[handleFileCallback] 已更新流程状态: requestId={}, status={}", reqVO.getRequestId(), status);
|
log.info("[handleFileCallback] 已更新流程日志: requestId={}, status={}", reqVO.getRequestId(), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 发送 MQ 通知业务系统(仅当 bizCallbackKey 存在时发送)
|
// 4. 发送 MQ 通知业务系统(仅当 bizCallbackKey 存在时发送)
|
||||||
if (StringUtils.hasText(bizCallbackKey)) {
|
if (StringUtils.hasText(bizCallbackKey)) {
|
||||||
IWorkBizCallbackMessage message = IWorkBizCallbackMessage.builder()
|
IWorkBizCallbackMessage message = IWorkBizCallbackMessage.builder()
|
||||||
.requestId(reqVO.getRequestId())
|
.requestId(reqVO.getRequestId())
|
||||||
@@ -286,16 +278,6 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
|
|||||||
return attachmentId;
|
return attachmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWorkWorkflowCallbackReqVO buildCallbackLogReqVO(IWorkFileCallbackReqVO reqVO) {
|
|
||||||
IWorkWorkflowCallbackReqVO logReqVO = new IWorkWorkflowCallbackReqVO();
|
|
||||||
logReqVO.setRequestId(reqVO.getRequestId());
|
|
||||||
logReqVO.setBusinessCode(reqVO.getBusinessCode());
|
|
||||||
logReqVO.setBizCallbackKey(reqVO.getBizCallbackKey());
|
|
||||||
logReqVO.setStatus(reqVO.getStatus());
|
|
||||||
logReqVO.setRawBody(reqVO.getRawBody());
|
|
||||||
return logReqVO;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildCallbackRawBody(IWorkFileCallbackReqVO reqVO) {
|
private String buildCallbackRawBody(IWorkFileCallbackReqVO reqVO) {
|
||||||
if (StringUtils.hasText(reqVO.getRawBody())) {
|
if (StringUtils.hasText(reqVO.getRawBody())) {
|
||||||
return reqVO.getRawBody();
|
return reqVO.getRawBody();
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
package com.zt.plat.module.system.service.integration.iwork.impl;
|
package com.zt.plat.module.system.service.integration.iwork.impl;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.common.util.json.JsonUtils;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkCallbackLogPageReqVO;
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||||
import com.zt.plat.module.system.dal.mysql.iwork.IWorkWorkflowLogMapper;
|
import com.zt.plat.module.system.dal.mysql.iwork.IWorkWorkflowLogMapper;
|
||||||
|
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
||||||
|
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
|
||||||
|
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackProducer;
|
||||||
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.enums.IWorkCallbackStatusEnum;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class IWorkWorkflowLogServiceImpl implements IWorkWorkflowLogService {
|
public class IWorkWorkflowLogServiceImpl implements IWorkWorkflowLogService {
|
||||||
|
|
||||||
private final IWorkWorkflowLogMapper workflowLogMapper;
|
private final IWorkWorkflowLogMapper workflowLogMapper;
|
||||||
|
private final IWorkProperties properties;
|
||||||
|
private final IWorkBizCallbackProducer bizCallbackProducer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveWorkflowLog(IWorkWorkflowLogDO logDO) {
|
public void saveWorkflowLog(IWorkWorkflowLogDO logDO) {
|
||||||
@@ -32,4 +43,105 @@ public class IWorkWorkflowLogServiceImpl implements IWorkWorkflowLogService {
|
|||||||
workflowLogMapper.updateById(update);
|
workflowLogMapper.updateById(update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 回调相关方法 ==========
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateCallback(String requestId, String rawCallback, int maxRetry) {
|
||||||
|
IWorkWorkflowLogDO existing = workflowLogMapper.selectByRequestId(requestId);
|
||||||
|
if (existing != null) {
|
||||||
|
IWorkWorkflowLogDO update = new IWorkWorkflowLogDO();
|
||||||
|
update.setId(existing.getId());
|
||||||
|
update.setCallbackStatus(IWorkCallbackStatusEnum.CALLBACK_PENDING.getStatus());
|
||||||
|
update.setRawCallback(truncate(rawCallback, 2000));
|
||||||
|
update.setMaxRetry(maxRetry);
|
||||||
|
update.setRetryCount(existing.getRetryCount() != null ? existing.getRetryCount() : 0);
|
||||||
|
update.setLastCallbackTime(LocalDateTime.now());
|
||||||
|
workflowLogMapper.updateById(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markCallbackSuccess(String requestId) {
|
||||||
|
IWorkWorkflowLogDO existing = workflowLogMapper.selectByRequestId(requestId);
|
||||||
|
if (existing != null) {
|
||||||
|
IWorkWorkflowLogDO update = new IWorkWorkflowLogDO();
|
||||||
|
update.setId(existing.getId());
|
||||||
|
update.setCallbackStatus(IWorkCallbackStatusEnum.CALLBACK_SUCCESS.getStatus());
|
||||||
|
update.setLastErrorMessage(null);
|
||||||
|
update.setLastCallbackTime(LocalDateTime.now());
|
||||||
|
workflowLogMapper.updateById(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markCallbackFailure(String requestId, String errorMessage, boolean retrying, int maxRetry) {
|
||||||
|
IWorkWorkflowLogDO existing = workflowLogMapper.selectByRequestId(requestId);
|
||||||
|
if (existing != null) {
|
||||||
|
IWorkWorkflowLogDO update = new IWorkWorkflowLogDO();
|
||||||
|
update.setId(existing.getId());
|
||||||
|
update.setCallbackStatus(retrying
|
||||||
|
? IWorkCallbackStatusEnum.CALLBACK_RETRYING.getStatus()
|
||||||
|
: IWorkCallbackStatusEnum.CALLBACK_FAILED.getStatus());
|
||||||
|
update.setLastErrorMessage(errorMessage);
|
||||||
|
update.setMaxRetry(maxRetry);
|
||||||
|
update.setLastCallbackTime(LocalDateTime.now());
|
||||||
|
workflowLogMapper.updateById(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementRetry(String requestId) {
|
||||||
|
IWorkWorkflowLogDO existing = workflowLogMapper.selectByRequestId(requestId);
|
||||||
|
if (existing != null) {
|
||||||
|
IWorkWorkflowLogDO update = new IWorkWorkflowLogDO();
|
||||||
|
update.setId(existing.getId());
|
||||||
|
update.setRetryCount((existing.getRetryCount() != null ? existing.getRetryCount() : 0) + 1);
|
||||||
|
update.setLastCallbackTime(LocalDateTime.now());
|
||||||
|
workflowLogMapper.updateById(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String truncate(String raw, int maxLen) {
|
||||||
|
if (raw == null || raw.length() <= maxLen) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
return raw.substring(0, maxLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<IWorkWorkflowLogDO> page(IWorkCallbackLogPageReqVO reqVO) {
|
||||||
|
return workflowLogMapper.selectPage(reqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetAndDispatch(String requestId) {
|
||||||
|
IWorkWorkflowLogDO existing = workflowLogMapper.selectByRequestId(requestId);
|
||||||
|
if (existing == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 重置状态
|
||||||
|
IWorkWorkflowLogDO update = new IWorkWorkflowLogDO();
|
||||||
|
update.setId(existing.getId());
|
||||||
|
update.setRetryCount(0);
|
||||||
|
update.setCallbackStatus(IWorkCallbackStatusEnum.CALLBACK_RETRYING.getStatus());
|
||||||
|
update.setLastCallbackTime(LocalDateTime.now());
|
||||||
|
workflowLogMapper.updateById(update);
|
||||||
|
|
||||||
|
// 重新派发
|
||||||
|
int maxAttempts = properties.getCallback().getRetry().getMaxAttempts();
|
||||||
|
Object payload;
|
||||||
|
try {
|
||||||
|
payload = JsonUtils.parseObject(existing.getRawCallback(), Object.class);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
payload = existing.getRawCallback();
|
||||||
|
}
|
||||||
|
bizCallbackProducer.send(IWorkBizCallbackMessage.builder()
|
||||||
|
.requestId(existing.getRequestId())
|
||||||
|
.bizCallbackKey(existing.getBizCallbackKey())
|
||||||
|
.payload(payload)
|
||||||
|
.attempt(0)
|
||||||
|
.maxAttempts(maxAttempts)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.zt.plat.module.system.service.integration.iwork.impl;
|
|
||||||
|
|
||||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowCallbackReqVO;
|
|
||||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO;
|
|
||||||
import com.zt.plat.module.system.dal.mysql.iwork.IWorkSealLogMapper;
|
|
||||||
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
|
|
||||||
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackProducer;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
class IWorkCallbackLogServiceImplTest {
|
|
||||||
|
|
||||||
private IWorkSealLogMapper mapper;
|
|
||||||
private IWorkBizCallbackProducer producer;
|
|
||||||
private IWorkProperties properties;
|
|
||||||
private IWorkCallbackLogServiceImpl service;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setup() {
|
|
||||||
mapper = mock(IWorkSealLogMapper.class);
|
|
||||||
producer = mock(IWorkBizCallbackProducer.class);
|
|
||||||
properties = new IWorkProperties();
|
|
||||||
service = new IWorkCallbackLogServiceImpl(mapper, producer, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void upsertOnCallback_shouldTruncateRaw() {
|
|
||||||
String longRaw = "x".repeat(2100);
|
|
||||||
IWorkWorkflowCallbackReqVO req = new IWorkWorkflowCallbackReqVO();
|
|
||||||
req.setRequestId("REQ-1");
|
|
||||||
req.setBizCallbackKey("key");
|
|
||||||
|
|
||||||
ArgumentCaptor<IWorkSealLogDO> captor = ArgumentCaptor.forClass(IWorkSealLogDO.class);
|
|
||||||
when(mapper.selectByRequestId("REQ-1")).thenReturn(null);
|
|
||||||
|
|
||||||
service.upsertOnCallback(req, 3, longRaw);
|
|
||||||
|
|
||||||
verify(mapper).insert(captor.capture());
|
|
||||||
IWorkSealLogDO saved = captor.getValue();
|
|
||||||
assertThat(saved.getRawCallback()).hasSize(2000);
|
|
||||||
assertThat(saved.getMaxRetry()).isEqualTo(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void incrementRetry_shouldIncreaseCount() {
|
|
||||||
IWorkSealLogDO existing = new IWorkSealLogDO();
|
|
||||||
existing.setId(1L);
|
|
||||||
existing.setRequestId("REQ-2");
|
|
||||||
existing.setRetryCount(1);
|
|
||||||
when(mapper.selectByRequestId("REQ-2")).thenReturn(existing);
|
|
||||||
|
|
||||||
service.incrementRetry("REQ-2");
|
|
||||||
|
|
||||||
ArgumentCaptor<IWorkSealLogDO> captor = ArgumentCaptor.forClass(IWorkSealLogDO.class);
|
|
||||||
verify(mapper).updateById(captor.capture());
|
|
||||||
assertThat(captor.getValue().getRetryCount()).isEqualTo(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user