Commit 96ecd5028dbf46e48cbb18bc61ae8ef40ba720c3
1 parent
44b0346e
1. 优化支付订单回调任务,避免重复打 SQL 查询日志
2. 修复定时任务的回调,回调成功未更新状态的问题。
Showing
5 changed files
with
21 additions
and
19 deletions
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
| @@ -48,7 +48,7 @@ public class PayDemoOrderController { | @@ -48,7 +48,7 @@ public class PayDemoOrderController { | ||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | @PostMapping("/update-paid") | 50 | @PostMapping("/update-paid") |
| 51 | - @Operation(description = "更新示例订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob | 51 | + @Operation(summary = "更新示例订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob |
| 52 | @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 | 52 | @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 |
| 53 | @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 | 53 | @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 |
| 54 | public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) { | 54 | public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) { |
| @@ -58,7 +58,7 @@ public class PayDemoOrderController { | @@ -58,7 +58,7 @@ public class PayDemoOrderController { | ||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | @PutMapping("/refund") | 60 | @PutMapping("/refund") |
| 61 | - @Operation(description = "发起示例订单的退款") | 61 | + @Operation(summary = "发起示例订单的退款") |
| 62 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 62 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 63 | public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) { | 63 | public CommonResult<Boolean> refundDemoOrder(@RequestParam("id") Long id) { |
| 64 | payDemoOrderService.refundDemoOrder(id, getClientIP()); | 64 | payDemoOrderService.refundDemoOrder(id, getClientIP()); |
| @@ -66,7 +66,7 @@ public class PayDemoOrderController { | @@ -66,7 +66,7 @@ public class PayDemoOrderController { | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | @PostMapping("/update-refunded") | 68 | @PostMapping("/update-refunded") |
| 69 | - @Operation(description = "更新示例订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob | 69 | + @Operation(summary = "更新示例订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob |
| 70 | @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 | 70 | @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 |
| 71 | @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 | 71 | @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 |
| 72 | public CommonResult<Boolean> updateDemoOrderRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { | 72 | public CommonResult<Boolean> updateDemoOrderRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java
| @@ -5,5 +5,5 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -5,5 +5,5 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 | ||
| 7 | @Mapper | 7 | @Mapper |
| 8 | -public interface PayNotifyLogCoreMapper extends BaseMapperX<PayNotifyLogDO> { | 8 | +public interface PayNotifyLogMapper extends BaseMapperX<PayNotifyLogDO> { |
| 9 | } | 9 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java
| @@ -10,7 +10,7 @@ import java.time.LocalDateTime; | @@ -10,7 +10,7 @@ import java.time.LocalDateTime; | ||
| 10 | import java.util.List; | 10 | import java.util.List; |
| 11 | 11 | ||
| 12 | @Mapper | 12 | @Mapper |
| 13 | -public interface PayNotifyTaskCoreMapper extends BaseMapperX<PayNotifyTaskDO> { | 13 | +public interface PayNotifyTaskMapper extends BaseMapperX<PayNotifyTaskDO> { |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * 获得需要通知的 PayNotifyTaskDO 记录。需要满足如下条件: | 16 | * 获得需要通知的 PayNotifyTaskDO 记录。需要满足如下条件: |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
| @@ -13,8 +13,8 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | @@ -13,8 +13,8 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; | ||
| 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | 13 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; |
| 14 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 14 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 15 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 15 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 16 | -import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogCoreMapper; | ||
| 17 | -import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskCoreMapper; | 16 | +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper; |
| 17 | +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper; | ||
| 18 | import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; | 18 | import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; |
| 19 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; | 19 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; |
| 20 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | 20 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| @@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional; | @@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional; | ||
| 32 | 32 | ||
| 33 | import javax.annotation.Resource; | 33 | import javax.annotation.Resource; |
| 34 | import javax.validation.Valid; | 34 | import javax.validation.Valid; |
| 35 | +import java.time.Duration; | ||
| 35 | import java.time.LocalDateTime; | 36 | import java.time.LocalDateTime; |
| 36 | import java.util.HashMap; | 37 | import java.util.HashMap; |
| 37 | import java.util.List; | 38 | import java.util.List; |
| @@ -40,6 +41,7 @@ import java.util.Objects; | @@ -40,6 +41,7 @@ import java.util.Objects; | ||
| 40 | import java.util.concurrent.CountDownLatch; | 41 | import java.util.concurrent.CountDownLatch; |
| 41 | import java.util.concurrent.TimeUnit; | 42 | import java.util.concurrent.TimeUnit; |
| 42 | 43 | ||
| 44 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | ||
| 43 | import static cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR; | 45 | import static cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR; |
| 44 | 46 | ||
| 45 | /** | 47 | /** |
| @@ -69,9 +71,9 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -69,9 +71,9 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 69 | private PayRefundService refundService; | 71 | private PayRefundService refundService; |
| 70 | 72 | ||
| 71 | @Resource | 73 | @Resource |
| 72 | - private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper; | 74 | + private PayNotifyTaskMapper payNotifyTaskMapper; |
| 73 | @Resource | 75 | @Resource |
| 74 | - private PayNotifyLogCoreMapper payNotifyLogCoreMapper; | 76 | + private PayNotifyLogMapper payNotifyLogMapper; |
| 75 | 77 | ||
| 76 | @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) | 78 | @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) |
| 77 | private ThreadPoolTaskExecutor threadPoolTaskExecutor; | 79 | private ThreadPoolTaskExecutor threadPoolTaskExecutor; |
| @@ -101,7 +103,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -101,7 +103,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | // 执行插入 | 105 | // 执行插入 |
| 104 | - payNotifyTaskCoreMapper.insert(task); | 106 | + payNotifyTaskMapper.insert(task); |
| 105 | 107 | ||
| 106 | // 异步直接发起任务。虽然会有定时任务扫描,但是会导致延迟 | 108 | // 异步直接发起任务。虽然会有定时任务扫描,但是会导致延迟 |
| 107 | self.executeNotifyAsync(task); | 109 | self.executeNotifyAsync(task); |
| @@ -110,7 +112,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -110,7 +112,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 110 | @Override | 112 | @Override |
| 111 | public int executeNotify() throws InterruptedException { | 113 | public int executeNotify() throws InterruptedException { |
| 112 | // 获得需要通知的任务 | 114 | // 获得需要通知的任务 |
| 113 | - List<PayNotifyTaskDO> tasks = payNotifyTaskCoreMapper.selectListByNotify(); | 115 | + List<PayNotifyTaskDO> tasks = payNotifyTaskMapper.selectListByNotify(); |
| 114 | if (CollUtil.isEmpty(tasks)) { | 116 | if (CollUtil.isEmpty(tasks)) { |
| 115 | return 0; | 117 | return 0; |
| 116 | } | 118 | } |
| @@ -168,8 +170,8 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -168,8 +170,8 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 168 | payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { | 170 | payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { |
| 169 | // 校验,当前任务是否已经被通知过 | 171 | // 校验,当前任务是否已经被通知过 |
| 170 | // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 | 172 | // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 |
| 171 | - PayNotifyTaskDO dbTask = payNotifyTaskCoreMapper.selectById(task.getId()); | ||
| 172 | - if (LocalDateTimeUtils.afterNow(dbTask.getNextNotifyTime())) { | 173 | + PayNotifyTaskDO dbTask = payNotifyTaskMapper.selectById(task.getId()); |
| 174 | + if (afterNow(dbTask.getNextNotifyTime())) { | ||
| 173 | log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", | 175 | log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", |
| 174 | JsonUtils.toJsonString(dbTask)); | 176 | JsonUtils.toJsonString(dbTask)); |
| 175 | return; | 177 | return; |
| @@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 197 | // 记录 PayNotifyLog 日志 | 199 | // 记录 PayNotifyLog 日志 |
| 198 | String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : | 200 | String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : |
| 199 | JsonUtils.toJsonString(invokeResult); | 201 | JsonUtils.toJsonString(invokeResult); |
| 200 | - payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) | 202 | + payNotifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) |
| 201 | .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); | 203 | .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); |
| 202 | } | 204 | } |
| 203 | 205 | ||
| @@ -250,23 +252,22 @@ public class PayNotifyServiceImpl implements PayNotifyService { | @@ -250,23 +252,22 @@ public class PayNotifyServiceImpl implements PayNotifyService { | ||
| 250 | // 情况一:调用成功 | 252 | // 情况一:调用成功 |
| 251 | if (invokeResult != null && invokeResult.isSuccess()) { | 253 | if (invokeResult != null && invokeResult.isSuccess()) { |
| 252 | updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); | 254 | updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); |
| 255 | + payNotifyTaskMapper.updateById(updateTask); | ||
| 253 | return updateTask.getStatus(); | 256 | return updateTask.getStatus(); |
| 254 | } | 257 | } |
| 255 | // 情况二:调用失败、调用异常 | 258 | // 情况二:调用失败、调用异常 |
| 256 | // 2.1 超过最大回调次数 | 259 | // 2.1 超过最大回调次数 |
| 257 | if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { | 260 | if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { |
| 258 | updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); | 261 | updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); |
| 262 | + payNotifyTaskMapper.updateById(updateTask); | ||
| 259 | return updateTask.getStatus(); | 263 | return updateTask.getStatus(); |
| 260 | } | 264 | } |
| 261 | // 2.2 未超过最大回调次数 | 265 | // 2.2 未超过最大回调次数 |
| 262 | - updateTask.setNextNotifyTime(LocalDateTime.now().plusSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()])); | 266 | + updateTask.setNextNotifyTime(addTime(Duration.ofSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()]))); |
| 263 | updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() | 267 | updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() |
| 264 | : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); | 268 | : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); |
| 269 | + payNotifyTaskMapper.updateById(updateTask); | ||
| 265 | return updateTask.getStatus(); | 270 | return updateTask.getStatus(); |
| 266 | } | 271 | } |
| 267 | 272 | ||
| 268 | - private void processNotifySuccess(PayNotifyTaskDO task, PayNotifyTaskDO updateTask) { | ||
| 269 | - payNotifyTaskCoreMapper.updateById(updateTask); | ||
| 270 | - } | ||
| 271 | - | ||
| 272 | } | 273 | } |
yudao-server/src/main/resources/application-local.yaml
| @@ -153,6 +153,7 @@ logging: | @@ -153,6 +153,7 @@ logging: | ||
| 153 | cn.iocoder.yudao.module.infra.dal.mysql: debug | 153 | cn.iocoder.yudao.module.infra.dal.mysql: debug |
| 154 | cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info | 154 | cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info |
| 155 | cn.iocoder.yudao.module.pay.dal.mysql: debug | 155 | cn.iocoder.yudao.module.pay.dal.mysql: debug |
| 156 | + cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 JobLogMapper 的日志级别为 info | ||
| 156 | cn.iocoder.yudao.module.system.dal.mysql: debug | 157 | cn.iocoder.yudao.module.system.dal.mysql: debug |
| 157 | cn.iocoder.yudao.module.tool.dal.mysql: debug | 158 | cn.iocoder.yudao.module.tool.dal.mysql: debug |
| 158 | cn.iocoder.yudao.module.member.dal.mysql: debug | 159 | cn.iocoder.yudao.module.member.dal.mysql: debug |