|
|
@@ -34,10 +34,7 @@ import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
import java.util.*;
|
|
|
-import java.util.concurrent.Callable;
|
|
|
-import java.util.concurrent.CountDownLatch;
|
|
|
-import java.util.concurrent.ExecutionException;
|
|
|
-import java.util.concurrent.Future;
|
|
|
+import java.util.concurrent.*;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
@@ -284,63 +281,88 @@ public class ConsumeRequestCheck {
|
|
|
*/
|
|
|
private R<ErrorInfo> executeTermValidationChain(TermConsumeValidationContext context) {
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
- List<Callable<R<ErrorInfo>>> validationTasks = new ArrayList<>();
|
|
|
-
|
|
|
- validationTasks.add(() -> validateSwipeInterval(context));
|
|
|
- validationTasks.add(() -> validateSingleLimit(context));
|
|
|
- validationTasks.add(() -> validateCardValidity(context));
|
|
|
- validationTasks.add(() -> validateCardType(context));
|
|
|
- validationTasks.add(() -> validateMealLimit(context));
|
|
|
- validationTasks.add(() -> validateDailyLimit(context));
|
|
|
-
|
|
|
+ // 创建CountDownLatch 有1个任务返回错误时就唤醒主线程 // 使用CountDownLatch跟踪任务完成
|
|
|
+ CountDownLatch latch = new CountDownLatch(1);
|
|
|
// 用于存储第一个错误结果
|
|
|
AtomicReference<R<ErrorInfo>> firstError = new AtomicReference<>(null);
|
|
|
+ // 创建验证任务列表
|
|
|
+ List<Callable<R<ErrorInfo>>> validationTasks = getTermValidationCallables(context, firstError, latch);
|
|
|
|
|
|
- // 使用CountDownLatch跟踪任务完成
|
|
|
- // CountDownLatch latch = new CountDownLatch(validationTasks.size());
|
|
|
- // AtomicBoolean cancelled = new AtomicBoolean(false);
|
|
|
+ // 所有任务的结果
|
|
|
List<Future<R<ErrorInfo>>> futures = new ArrayList<>();
|
|
|
// 提交所有任务
|
|
|
for (Callable<R<ErrorInfo>> task : validationTasks) {
|
|
|
futures.add(threadPoolTaskExecutor.submit(task));
|
|
|
}
|
|
|
- int taskIndex = 0;
|
|
|
- try {
|
|
|
- for (Future<R<ErrorInfo>> future : futures) {
|
|
|
- long starTime = System.currentTimeMillis();
|
|
|
- if (firstError.get() != null) {
|
|
|
-
|
|
|
- future.cancel(true); // 取消剩余任务
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- // R<ErrorInfo> result = future.get(VALIDATION_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
|
- R<ErrorInfo> result = future.get();
|
|
|
- // 发现错误,立即取消其他任务
|
|
|
- if (result != null && R.isError(result)) {
|
|
|
-
|
|
|
- if (firstError.compareAndSet(null, result)) {
|
|
|
- futures.forEach(f -> f.cancel(true));
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (ExecutionException e) {
|
|
|
- log.error("{}验证执行异常", getTaskName(taskIndex), e);
|
|
|
- if (firstError.compareAndSet(null, createError(TradeStatusEnum.SysError))) {
|
|
|
- futures.forEach(f -> f.cancel(true));
|
|
|
- }
|
|
|
- } finally {
|
|
|
- log.info("{}结束,耗时:{} ms", getTaskName(taskIndex), System.currentTimeMillis() - starTime);
|
|
|
- taskIndex++;
|
|
|
- }
|
|
|
- }
|
|
|
- return firstError.get() != null ? firstError.get() : R.ok();
|
|
|
|
|
|
+ // 最终执行的结果,true 为正常执行结束及latch减至了0;false 为超时
|
|
|
+ boolean finallyResult;
|
|
|
+ try {
|
|
|
+ // 阻塞主线程,等待执行结果; latch 为0时,会唤醒主线程,最多阻塞10s
|
|
|
+ finallyResult = latch.await(10, TimeUnit.SECONDS);
|
|
|
} catch (InterruptedException e) {
|
|
|
- Thread.currentThread().interrupt(); // 保留中断状态
|
|
|
- log.error("验证过程被中断", e);
|
|
|
+ log.error("executeTermValidationChain- main 被中断 :{}", e.getMessage());
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ // 取消所有任务
|
|
|
+ futures.forEach(f -> f.cancel(true));
|
|
|
+ return createError(TradeStatusEnum.SysError);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 循环取消所有任务
|
|
|
+ futures.forEach(f -> f.cancel(true));
|
|
|
+ if (!finallyResult) {
|
|
|
+ log.error("executeTermValidationChain- 执行消费终端校验链10s超时");
|
|
|
return createError(TradeStatusEnum.SysError);
|
|
|
}
|
|
|
+
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ log.info("executeTermValidationChain- 执行消费终端校验链耗时:{}ms", System.currentTimeMillis() - startTime);
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return errorInfoR;
|
|
|
+ }else {
|
|
|
+ return R.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+// int taskIndex = 0;
|
|
|
+// try {
|
|
|
+// for (Future<R<ErrorInfo>> future : futures) {
|
|
|
+// long starTime = System.currentTimeMillis();
|
|
|
+// if (firstError.get() != null) {
|
|
|
+//
|
|
|
+// future.cancel(true); // 取消剩余任务
|
|
|
+// continue;
|
|
|
+// }
|
|
|
+//
|
|
|
+// try {
|
|
|
+// // R<ErrorInfo> result = future.get(VALIDATION_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
|
+// R<ErrorInfo> result = future.get();
|
|
|
+// // 发现错误,立即取消其他任务
|
|
|
+// if (result != null && R.isError(result)) {
|
|
|
+//
|
|
|
+// if (firstError.compareAndSet(null, result)) {
|
|
|
+// futures.forEach(f -> f.cancel(true));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } catch (ExecutionException e) {
|
|
|
+// log.error("{}验证执行异常", getTaskName(taskIndex), e);
|
|
|
+// if (firstError.compareAndSet(null, createError(TradeStatusEnum.SysError))) {
|
|
|
+// futures.forEach(f -> f.cancel(true));
|
|
|
+// }
|
|
|
+// } finally {
|
|
|
+// log.info("{}结束,耗时:{} ms", getTaskName(taskIndex), System.currentTimeMillis() - starTime);
|
|
|
+// taskIndex++;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// return firstError.get() != null ? firstError.get() : R.ok();
|
|
|
+//
|
|
|
+// } catch (InterruptedException e) {
|
|
|
+// Thread.currentThread().interrupt(); // 保留中断状态
|
|
|
+// log.error("验证过程被中断", e);
|
|
|
+// return createError(TradeStatusEnum.SysError);
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
//// 创建验证任务列表
|
|
|
//List<Supplier<R<ErrorInfo>>> validationTasks = new ArrayList<>();
|
|
|
//
|
|
|
@@ -393,6 +415,100 @@ public class ConsumeRequestCheck {
|
|
|
// return commonCheck.createError(TradeStatusEnum.SysError);
|
|
|
//}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取任务列表
|
|
|
+ * @param context
|
|
|
+ * @param firstError
|
|
|
+ * @param latch
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<Callable<R<ErrorInfo>>> getTermValidationCallables(TermConsumeValidationContext context,
|
|
|
+ AtomicReference<R<ErrorInfo>> firstError, CountDownLatch latch) {
|
|
|
+ List<Callable<R<ErrorInfo>>> validationTasks = new ArrayList<>();
|
|
|
+
|
|
|
+ // 消费时间间隔验证
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateSwipeInterval(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ // 设置错误结果
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ // 单次消费限额判断
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateSingleLimit(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ // 卡有效期验证
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateCardValidity(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ // 卡类型验证
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateCardType(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ // 餐次验证
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateMealLimit(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ // 日限额验证
|
|
|
+ validationTasks.add(() -> {
|
|
|
+ R<ErrorInfo> errorInfoR = firstError.get();
|
|
|
+ if (errorInfoR != null && R.isError(errorInfoR)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ R<ErrorInfo> infoR = validateDailyLimit(context);
|
|
|
+ if (infoR != null && R.isError(infoR)) {
|
|
|
+ firstError.set(infoR);
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ return infoR;
|
|
|
+ });
|
|
|
+ return validationTasks;
|
|
|
+ }
|
|
|
+
|
|
|
//validationTasks.add(() -> validateSwipeInterval(context));
|
|
|
//validationTasks.add(() -> validateSingleLimit(context));
|
|
|
//validationTasks.add(() -> validateCardValidity(context));
|