diff --git a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java index 326f0adc..f91e48b1 100644 --- a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java +++ b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java @@ -94,6 +94,18 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl children = new ArrayList<>(); } + /** + * 物料成本查询结果: + * SUCCESS - 首次(池化连接)查询成功; + * SUCCESS_AFTER_RECONNECT - 首次失败,重试时切换新连接后成功; + * FAILED - 重试后仍失败(按现有逻辑置 0,不阻断后续流程)。 + */ + private enum CostQueryResult { + SUCCESS, + SUCCESS_AFTER_RECONNECT, + FAILED + } + // ========================================================================= // 公开方法:两阶段执行 // ========================================================================= @@ -277,15 +289,27 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl> futures = needCostComponents.stream() .map(component -> CompletableFuture.runAsync(() -> { Server conn = null; + CostQueryResult costQueryResult = CostQueryResult.FAILED; try { conn = connectionPool.take(); - getFinalPartCost(component, conn, costCache); + costQueryResult = getFinalPartCost(component, conn, ifsConFactory, costCache); } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.warn("[BOM_PROCESS] 并行成本查询线程被中断 - PartNo: {}", component.getComponentPart()); } finally { if (conn != null) { - connectionPool.offer(conn); + if (costQueryResult == CostQueryResult.SUCCESS) { + connectionPool.offer(conn); + } else { + // 连接在本次查询中出现异常迹象(或最终失败),替换为新连接,避免“坏连接”反复影响后续组件 + try { + connectionPool.offer(ifsConFactory.get()); + } catch (Exception ex) { + log.warn("[BOM_PROCESS] IFS连接替换失败,回退复用原连接 - PartNo: {}, Error: {}", + component.getComponentPart(), ex.getMessage()); + connectionPool.offer(conn); + } + } } } }, IFS_COST_EXECUTOR)) @@ -825,7 +849,10 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl costCache) { + private CostQueryResult getFinalPartCost(QuoteDetailBom component, + Server ifsServer, + Supplier ifsConFactory, + Map costCache) { final int MAX_RETRY_COUNT = 2; final long RETRY_INTERVAL_MS = 500; @@ -839,7 +866,7 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl