Bläddra i källkod

update 优化线程

ct 3 dagar sedan
förälder
incheckning
f844215220

+ 56 - 25
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -101,12 +101,31 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+
 @Slf4j
 @Component("task")
 public class Task {
+
+    /**
+     * 物流状态查询专用有界线程池,避免打满 ForkJoinPool / Redis / DB 连接池
+     */
+    private static final ExecutorService DELIVERY_STATUS_EXECUTOR = new ThreadPoolExecutor(
+            4,
+            8,
+            60L,
+            TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(200),
+            new BasicThreadFactory.Builder().namingPattern("delivery-status-%d").daemon(true).build(),
+            new ThreadPoolExecutor.CallerRunsPolicy()
+    );
     @Autowired
     private FsUserCouponMapper fsUserCouponMapper;
     @Autowired
@@ -792,25 +811,27 @@ public class Task {
         3.查询订单结果更新order,或者回滚df表*/
         //目的是查询创建成功erp的订单,应该在第三部之后改动的数据来作为查询条件;即为待收货订单and拥有deliverySn的数据;
         List<FsIntegralOrder> orders = fsIntegralOrderMapper.selectList(Wrappers.<FsIntegralOrder>lambdaQuery().eq(FsIntegralOrder::getStatus, 2).isNotNull(FsIntegralOrder::getDeliverySn));
+        if (orders == null || orders.isEmpty()) {
+            return;
+        }
         IErpOrderService erpOrderService = getErpService();
-        List<CompletableFuture<Void>> futures = new ArrayList<>();
+        List<CompletableFuture<Void>> futures = new ArrayList<>(orders.size());
         for (FsIntegralOrder order : orders) {
-            // 创建局部final变量副本
             final FsIntegralOrder currentOrder = order;
             FsStoreOrder order1 = new FsStoreOrder();
             order1.setDeliverySn(currentOrder.getDeliverySn());
             order1.setOrderCode(currentOrder.getOrderCode());
             order1.setOrderId(currentOrder.getOrderId());
-            // 异步执行,使用局部变量副本
-            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            futures.add(CompletableFuture.runAsync(() -> {
                 OrderContextHolder.setIntegralOrder(currentOrder);
                 try {
                     erpOrderService.getOrderDeliveryStatus(order1);
+                } catch (Exception e) {
+                    log.error("积分订单物流状态更新失败 orderId={}, orderCode={}", currentOrder.getOrderId(), currentOrder.getOrderCode(), e);
                 } finally {
                     OrderContextHolder.clear();
                 }
-            });
-            futures.add(future);
+            }, DELIVERY_STATUS_EXECUTOR));
         }
         CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
     }
@@ -858,12 +879,16 @@ public class Task {
         if (erpOrderService != null && erpOrderService == dfOrderService) {
             orders = fsStoreOrderMapper.selectShippedOrder();
             if (orders != null && !orders.isEmpty()) {
-                List<CompletableFuture<Void>> futures = new ArrayList<>();
+                List<CompletableFuture<Void>> futures = new ArrayList<>(orders.size());
                 for (FsStoreOrder order : orders) {
-                    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
-                        erpOrderService.getOrderDeliveryStatus(order);
-                    });
-                    futures.add(future);
+                    final FsStoreOrder currentOrder = order;
+                    futures.add(CompletableFuture.runAsync(() -> {
+                        try {
+                            erpOrderService.getOrderDeliveryStatus(currentOrder);
+                        } catch (Exception e) {
+                            log.error("商城订单物流状态更新失败 orderId={}, orderCode={}", currentOrder.getOrderId(), currentOrder.getOrderCode(), e);
+                        }
+                    }, DELIVERY_STATUS_EXECUTOR));
                 }
                 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
             }
@@ -1848,35 +1873,41 @@ public class Task {
         // 处理待收货订单
         if (integralOrders != null && !integralOrders.isEmpty()) {
             for (FsIntegralOrder order : integralOrders) {
-                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
-                    // 使用 OrderContextHolder 和局部副本
-                    OrderContextHolder.setIntegralOrder(order);
+                final FsIntegralOrder currentOrder = order;
+                futures.add(CompletableFuture.runAsync(() -> {
+                    OrderContextHolder.setIntegralOrder(currentOrder);
                     try {
-                        // 直接创建 FsStoreOrder 并调用 ERP 服务
                         FsStoreOrder storeOrder = new FsStoreOrder();
-                        storeOrder.setDeliverySn(order.getDeliverySn());
-                        storeOrder.setOrderCode(order.getOrderCode());
-                        storeOrder.setOrderId(order.getOrderId());
+                        storeOrder.setDeliverySn(currentOrder.getDeliverySn());
+                        storeOrder.setOrderCode(currentOrder.getOrderCode());
+                        storeOrder.setOrderId(currentOrder.getOrderId());
                         erpOrderService.sendExpressInfoAt9And16(storeOrder);
+                    } catch (Exception e) {
+                        log.error("积分订单定时发送物流消息失败 orderId={}", currentOrder.getOrderId(), e);
                     } finally {
                         OrderContextHolder.clear();
                     }
-                });
-                futures.add(future);
+                }, DELIVERY_STATUS_EXECUTOR));
             }
         }
 
         if (fsStoreOrders != null && !fsStoreOrders.isEmpty()) {
             for (FsStoreOrder order : fsStoreOrders) {
-                CompletableFuture<Void> future = CompletableFuture.runAsync(() ->
-                        erpOrderService.sendExpressInfoAt9And16(order)
-                );
-                futures.add(future);
+                final FsStoreOrder currentOrder = order;
+                futures.add(CompletableFuture.runAsync(() -> {
+                    try {
+                        erpOrderService.sendExpressInfoAt9And16(currentOrder);
+                    } catch (Exception e) {
+                        log.error("商城订单定时发送物流消息失败 orderId={}", currentOrder.getOrderId(), e);
+                    }
+                }, DELIVERY_STATUS_EXECUTOR));
             }
         }
 
         // 等待所有异步任务完成
-        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+        if (!futures.isEmpty()) {
+            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+        }
     }
 
 

+ 5 - 1
fs-service/src/main/java/com/fs/course/mapper/FsCourseSopAppLinkMapper.java

@@ -98,6 +98,10 @@ public interface FsCourseSopAppLinkMapper extends BaseMapper<FsCourseSopAppLink>
             "\tAND al.update_time >= NOW() ")
     Integer selectSopCountIsNotRead(@Param("userId") Long userId);
 
-    @Update("update fs_course_sop_app_link set is_read = 1 where link = #{id}")
+    /**
+     * 按 link 标记已读。务必保证表上有索引:ALTER TABLE fs_course_sop_app_link ADD INDEX idx_link (link);
+     * 无索引时全表扫描会产生数万 lock_structs,引发长事务告警。
+     */
+    @Update("update fs_course_sop_app_link set is_read = 1 where link = #{id} and (is_read is null or is_read = 0)")
     int updateFsCourseSopAppLinkByLink(@Param("id") String id);
 }

+ 1 - 1
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java

@@ -106,7 +106,7 @@ public interface FsIntegralOrderMapper extends BaseMapper<FsIntegralOrder>
             " order by o.order_id desc "+
             "</script>"})
     List<FsIntegralOrderListUVO> selectFsIntegralOrderListUVO(@Param("maps")FsIntegralOrderListUParam param);
-    @Select("select *from fs_integral_order where order_code=#{orderCode}")
+    @Select("select * from fs_integral_order where order_code=#{orderCode} order by order_id desc limit 1")
     FsIntegralOrder selectFsIntegralOrderByOrderCode(String orderCode);
 
     @Select("UPDATE fs_integral_order SET `status`=3 WHERE `status`=2 and DATE(delivery_time) < DATE_SUB(CURDATE(), INTERVAL 15 DAY)")

+ 7 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -859,7 +859,13 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         if (null==fsIntegralOrder){
             throw new ServiceException("订单不存在");
         }
-        log.info("用户:{}退款订单编号:{},退还积分{}", SecurityUtils.getLoginUser().getUser().getNickName(),fsIntegralOrder.getOrderCode(),fsIntegralOrder.getIntegral());
+        String operator = "system";
+        try {
+            operator = SecurityUtils.getLoginUser().getUser().getNickName();
+        } catch (Exception ignored) {
+            // 定时任务/异步线程无登录上下文
+        }
+        log.info("用户:{}退款订单编号:{},退还积分{}", operator, fsIntegralOrder.getOrderCode(), fsIntegralOrder.getIntegral());
         //物流退单操作
         //用户说自己去对接物流,不必校验是否发货。
 //        if (fsIntegralOrder.getStatus()!=1){

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsIntegralOrderScrmMapper.java

@@ -91,7 +91,7 @@ public interface FsIntegralOrderScrmMapper
             " order by o.order_id desc "+
             "</script>"})
     List<FsIntegralOrderListUVO> selectFsIntegralOrderListUVO(@Param("maps")FsIntegralOrderListUParam param);
-    @Select("select *from fs_integral_order where order_code=#{orderCode}")
+    @Select("select * from fs_integral_order where order_code=#{orderCode} order by order_id desc limit 1")
     FsIntegralOrderScrm selectFsIntegralOrderByOrderCode(String orderCode);
 
     @Select("UPDATE fs_integral_order SET `status`=3 WHERE `status`=2 and DATE(delivery_time) < DATE_SUB(CURDATE(), INTERVAL 15 DAY)")

+ 6 - 6
fs-service/src/main/resources/mapper/statis/ConsumptionBalanceMapper.xml

@@ -121,9 +121,9 @@
         </where>
     </select>
     <select id="queryRewardCount" resultType="java.lang.Long">
-        select count(*) from fs_course_red_packet_log rpl
-            left join fs_course_watch_log log
-            on rpl.watch_log_id=log.log_id
+        select count(rpl.log_id) from fs_course_red_packet_log rpl
+            inner join fs_course_watch_log log
+            on rpl.watch_log_id = log.log_id
         <where>
             <if test="startTime != null and endTime != null">
                 and rpl.create_time BETWEEN #{startTime} AND #{endTime}
@@ -137,9 +137,9 @@
         </where>
     </select>
     <select id="queryRewardMoney" resultType="java.math.BigDecimal">
-        select sum(rpl.amount) from fs_course_red_packet_log rpl
-        left join fs_course_watch_log log
-        on rpl.watch_log_id=log.log_id
+        select ifnull(sum(rpl.amount), 0) from fs_course_red_packet_log rpl
+        inner join fs_course_watch_log log
+        on rpl.watch_log_id = log.log_id
         <where>
             <if test="startTime != null and endTime != null">
                 and rpl.create_time BETWEEN #{startTime} AND #{endTime}