|
|
@@ -18,13 +18,11 @@ import org.dromara.common.core.domain.model.ErrorInfo;
|
|
|
import org.dromara.common.core.enums.CardStatusEnum;
|
|
|
import org.dromara.common.core.enums.TradeStatusEnum;
|
|
|
import org.dromara.common.core.enums.UserAccountStatusEnum;
|
|
|
-import org.dromara.common.json.utils.JsonUtils;
|
|
|
import org.dromara.common.redis.utils.RedisUtils;
|
|
|
import org.dromara.server.common.constant.ConsumeConstants;
|
|
|
import org.dromara.server.common.domain.consume.bo.ConsumptionBo;
|
|
|
import org.dromara.server.common.util.CardDateUtils;
|
|
|
import org.dromara.server.consume.business.*;
|
|
|
-import org.dromara.server.consume.cache.CardCacheManager;
|
|
|
import org.dromara.server.consume.domain.vo.XfCardLimitedVo;
|
|
|
import org.dromara.server.consume.domain.vo.XfTermVo;
|
|
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
@@ -32,14 +30,12 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.text.MessageFormat;
|
|
|
-import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.*;
|
|
|
-import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
-import java.util.function.Supplier;
|
|
|
|
|
|
/**
|
|
|
* 消费业务通用验证类
|
|
|
@@ -56,11 +52,13 @@ import java.util.function.Supplier;
|
|
|
public class CommonCheck {
|
|
|
// 异步线程执行超时时间,以毫秒为单位
|
|
|
private static final long VALIDATION_TIMEOUT = 500;
|
|
|
+ // 异步线程的任务个数
|
|
|
+ private static final int THREAD_TASK = 3;
|
|
|
|
|
|
private final BaseBusiness baseBusiness;
|
|
|
private final EmployeeBusiness employeeBusiness;
|
|
|
private final CardBusiness cardBusiness;
|
|
|
- private final ThreadPoolTaskExecutor taskExecutor;
|
|
|
+ private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
|
|
private final TermBusiness termBusiness;
|
|
|
|
|
|
//region 账户、卡片与设备验证
|
|
|
@@ -89,24 +87,26 @@ public class CommonCheck {
|
|
|
private R<ErrorInfo> executeTermValidationChain(AllowConsumeValidationContext ctx) {
|
|
|
// 创建CountDownLatch 有1个任务返回错误时就唤醒主线程 // 使用CountDownLatch跟踪任务完成
|
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
|
+ // 任务执行完也要唤醒主线程
|
|
|
+ AtomicInteger completeCount = new AtomicInteger();
|
|
|
// 用于存储第一个错误结果
|
|
|
AtomicReference<R<ErrorInfo>> firstError = new AtomicReference<>(null);
|
|
|
// 创建验证任务列表
|
|
|
- List<Callable<R<ErrorInfo>>> validationTasks = getTermValidCallables(ctx, firstError, latch);
|
|
|
+ List<Callable<R<ErrorInfo>>> validationTasks = getTermValidCallables(ctx, firstError, latch , completeCount);
|
|
|
|
|
|
// 所有任务的结果集合
|
|
|
List<Future<R<ErrorInfo>>> futures = new ArrayList<>();
|
|
|
// 提交所有任务
|
|
|
for (Callable<R<ErrorInfo>> task : validationTasks) {
|
|
|
- futures.add(taskExecutor.submit(task));
|
|
|
+ futures.add(threadPoolTaskExecutor.submit(task));
|
|
|
}
|
|
|
|
|
|
long starTime = System.currentTimeMillis();
|
|
|
// 最终执行的结果,true 为正常执行结束及latch减至了0;false 为超时
|
|
|
boolean finallyResult;
|
|
|
try {
|
|
|
- // 阻塞主线程,等待执行结果; latch 为0时,会唤醒主线程,最多阻塞10s
|
|
|
- finallyResult = latch.await(10, TimeUnit.SECONDS);
|
|
|
+ // 阻塞主线程,等待执行结果; latch 为0时,会唤醒主线程,最多阻塞5s
|
|
|
+ finallyResult = latch.await(5, TimeUnit.SECONDS);
|
|
|
} catch (InterruptedException e) {
|
|
|
log.error("executeTermValidationChain- main 被中断 :{}", e.getMessage());
|
|
|
Thread.currentThread().interrupt();
|
|
|
@@ -118,7 +118,7 @@ public class CommonCheck {
|
|
|
// 循环取消所有任务
|
|
|
futures.forEach(f -> f.cancel(true));
|
|
|
if (!finallyResult) {
|
|
|
- log.error("executeTermValidationChain- 设备、账户、参数校验10s超时");
|
|
|
+ log.error("executeTermValidationChain- 设备、账户、参数校验5s超时");
|
|
|
return createError(TradeStatusEnum.SysError);
|
|
|
}
|
|
|
|
|
|
@@ -218,52 +218,112 @@ public class CommonCheck {
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Callable<R<ErrorInfo>>> getTermValidCallables(AllowConsumeValidationContext ctx,
|
|
|
- AtomicReference<R<ErrorInfo>> firstError, CountDownLatch latch) {
|
|
|
+ AtomicReference<R<ErrorInfo>> firstError,
|
|
|
+ CountDownLatch latch,AtomicInteger completeCount) {
|
|
|
List<Callable<R<ErrorInfo>>> validationTasks = new ArrayList<>();
|
|
|
|
|
|
// 校验参数任务
|
|
|
- validationTasks.add(() -> {
|
|
|
- R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
- if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
- return null;
|
|
|
+ validationTasks.add(() -> obtainParamTask(ctx, firstError, latch, completeCount));
|
|
|
+ //消费设备校验
|
|
|
+ validationTasks.add(() -> obtainTermVTask(ctx, firstError, latch, completeCount));
|
|
|
+ //用户账户校验
|
|
|
+ validationTasks.add(() -> obtainUserTask(ctx, firstError, latch, completeCount));
|
|
|
+ return validationTasks;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户信息校验任务
|
|
|
+ * @param ctx
|
|
|
+ * @param firstError
|
|
|
+ * @param latch
|
|
|
+ * @param completeCount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private R<ErrorInfo> obtainUserTask(AllowConsumeValidationContext ctx, AtomicReference<R<ErrorInfo>> firstError, CountDownLatch latch, AtomicInteger completeCount) {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
+ latch.countDown();
|
|
|
}
|
|
|
- R<ErrorInfo> infoR = checkParam(ctx);
|
|
|
- if (infoR != null && R.isError(infoR)) {
|
|
|
- // 设置错误结果
|
|
|
- firstError.set(infoR);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = checkUserAccount(ctx);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ // 存储错误结果
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }else{
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
latch.countDown();
|
|
|
}
|
|
|
- return infoR;
|
|
|
- });
|
|
|
- //消费设备校验
|
|
|
- validationTasks.add(() -> {
|
|
|
- R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
- if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
- return null;
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取设备校验任务
|
|
|
+ * @param ctx
|
|
|
+ * @param firstError
|
|
|
+ * @param latch
|
|
|
+ * @param completeCount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private R<ErrorInfo> obtainTermVTask(AllowConsumeValidationContext ctx, AtomicReference<R<ErrorInfo>> firstError,
|
|
|
+ CountDownLatch latch, AtomicInteger completeCount) {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
+ latch.countDown();
|
|
|
}
|
|
|
- R<ErrorInfo> infoR = checkTerm(ctx);
|
|
|
- if (infoR != null && R.isError(infoR)) {
|
|
|
- // 存储错误结果
|
|
|
- firstError.set(infoR);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = checkTerm(ctx);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ // 存储错误结果
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }else{
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
latch.countDown();
|
|
|
}
|
|
|
- return infoR;
|
|
|
- });
|
|
|
- //用户账户校验
|
|
|
- validationTasks.add(() -> {
|
|
|
- R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
- if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
- return null;
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取参数校验任务
|
|
|
+ * @param ctx
|
|
|
+ * @param firstError
|
|
|
+ * @param latch
|
|
|
+ * @param completeCount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private R<ErrorInfo> obtainParamTask(AllowConsumeValidationContext ctx, AtomicReference<R<ErrorInfo>> firstError,
|
|
|
+ CountDownLatch latch, AtomicInteger completeCount) {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
+ latch.countDown();
|
|
|
}
|
|
|
- R<ErrorInfo> infoR = checkUserAccount(ctx);
|
|
|
- if (infoR != null && R.isError(infoR)) {
|
|
|
- // 存储错误结果
|
|
|
- firstError.set(infoR);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = checkParam(ctx);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ // 设置错误结果
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }else{
|
|
|
+ // 任务都结束了
|
|
|
+ if (completeCount.incrementAndGet() == THREAD_TASK) {
|
|
|
latch.countDown();
|
|
|
}
|
|
|
- return infoR;
|
|
|
- });
|
|
|
- return validationTasks;
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
}
|
|
|
|
|
|
private String getTaskName(int taskIndex) {
|
|
|
@@ -679,9 +739,9 @@ public class CommonCheck {
|
|
|
|
|
|
// if (ObjectUtil.equals(currentDateStr, consumeDateStr)) {
|
|
|
// 重置卡天当日消费数据
|
|
|
- taskExecutor.execute(() -> baseBusiness.resetCardConsumeInfo(userCardVo, mealType, consumeMoney, consumeDate));
|
|
|
+ threadPoolTaskExecutor.execute(() -> baseBusiness.resetCardConsumeInfo(userCardVo, mealType, consumeMoney, consumeDate));
|
|
|
// 重置卡片当日限制数据
|
|
|
- taskExecutor.execute(() -> baseBusiness.restCardLimitedInfo(mapCardLimited, cardLimitedVo, consumeMoney));
|
|
|
+ threadPoolTaskExecutor.execute(() -> baseBusiness.restCardLimitedInfo(mapCardLimited, cardLimitedVo, consumeMoney));
|
|
|
// 重置人员当日总卡余
|
|
|
// taskExecutor.submit(() -> baseBusiness.resetUserBalance(userId, balance));
|
|
|
// }
|