Browse Source

2026-07-01

新建报价单做出优化,获取成本异常时第二轮的重试使用新的连接池用来获取;
master
fengyuan_yang 4 weeks ago
parent
commit
e1ff6ffdb2
  1. 41
      src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java

41
src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java

@ -94,6 +94,18 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
List<BomNodeData> children = new ArrayList<>(); List<BomNodeData> children = new ArrayList<>();
} }
/**
* 物料成本查询结果
* SUCCESS - 首次池化连接查询成功
* SUCCESS_AFTER_RECONNECT - 首次失败重试时切换新连接后成功
* FAILED - 重试后仍失败按现有逻辑置 0不阻断后续流程
*/
private enum CostQueryResult {
SUCCESS,
SUCCESS_AFTER_RECONNECT,
FAILED
}
// ========================================================================= // =========================================================================
// 公开方法两阶段执行 // 公开方法两阶段执行
// ========================================================================= // =========================================================================
@ -277,17 +289,29 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
List<CompletableFuture<Void>> futures = needCostComponents.stream() List<CompletableFuture<Void>> futures = needCostComponents.stream()
.map(component -> CompletableFuture.runAsync(() -> { .map(component -> CompletableFuture.runAsync(() -> {
Server conn = null; Server conn = null;
CostQueryResult costQueryResult = CostQueryResult.FAILED;
try { try {
conn = connectionPool.take(); conn = connectionPool.take();
getFinalPartCost(component, conn, costCache);
costQueryResult = getFinalPartCost(component, conn, ifsConFactory, costCache);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
log.warn("[BOM_PROCESS] 并行成本查询线程被中断 - PartNo: {}", component.getComponentPart()); log.warn("[BOM_PROCESS] 并行成本查询线程被中断 - PartNo: {}", component.getComponentPart());
} finally { } finally {
if (conn != null) { if (conn != null) {
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); connectionPool.offer(conn);
} }
} }
}
}
}, IFS_COST_EXECUTOR)) }, IFS_COST_EXECUTOR))
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -825,7 +849,10 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
/** /**
* 获取物料成本带重试机制 * 获取物料成本带重试机制
*/ */
private void getFinalPartCost(QuoteDetailBom component, Server ifsServer, Map<String, BigDecimal> costCache) {
private CostQueryResult getFinalPartCost(QuoteDetailBom component,
Server ifsServer,
Supplier<Server> ifsConFactory,
Map<String, BigDecimal> costCache) {
final int MAX_RETRY_COUNT = 2; final int MAX_RETRY_COUNT = 2;
final long RETRY_INTERVAL_MS = 500; final long RETRY_INTERVAL_MS = 500;
@ -839,7 +866,7 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
component.setActualPrice(cachedCost); component.setActualPrice(cachedCost);
component.setQuotePrice(cachedCost); component.setQuotePrice(cachedCost);
log.info("[COST_QUERY] 从缓存读取成功 - PartNo: {}, Site: {}, UnitCost: {}", partNo, site, cachedCost); log.info("[COST_QUERY] 从缓存读取成功 - PartNo: {}, Site: {}, UnitCost: {}", partNo, site, cachedCost);
return;
return CostQueryResult.SUCCESS;
} }
log.info("[COST_QUERY] 开始查询物料成本 - PartNo: {}, Site: {}", partNo, site); log.info("[COST_QUERY] 开始查询物料成本 - PartNo: {}, Site: {}", partNo, site);
@ -855,8 +882,9 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
for (int retryCount = 1; retryCount <= MAX_RETRY_COUNT; retryCount++) { for (int retryCount = 1; retryCount <= MAX_RETRY_COUNT; retryCount++) {
try { try {
log.debug("[COST_QUERY] 第 {} 次尝试查询 - PartNo: {}", retryCount, partNo); log.debug("[COST_QUERY] 第 {} 次尝试查询 - PartNo: {}", retryCount, partNo);
map = baseSearchBean.getInventoryValueByPartNo(ifsServer, part);
// 首次查询使用连接池分配的连接重试使用新连接提升偶发连接态异常下的成功率
Server currentIfsServer = retryCount == 1 ? ifsServer : ifsConFactory.get();
map = baseSearchBean.getInventoryValueByPartNo(currentIfsServer, part);
if (Objects.equals(map.get("resultCode"), "200")) { if (Objects.equals(map.get("resultCode"), "200")) {
InventoryPartUnitCostSumVo unitCostSumVo = JSONObject.parseObject(map.get("obj"), InventoryPartUnitCostSumVo.class); InventoryPartUnitCostSumVo unitCostSumVo = JSONObject.parseObject(map.get("obj"), InventoryPartUnitCostSumVo.class);
@ -869,7 +897,7 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
log.info("[COST_QUERY] 查询成功 - PartNo: {}, Site: {}, UnitCost: {}, 尝试次数: {}", log.info("[COST_QUERY] 查询成功 - PartNo: {}, Site: {}, UnitCost: {}, 尝试次数: {}",
partNo, site, unitCost, retryCount); partNo, site, unitCost, retryCount);
success = true; success = true;
break;
return retryCount == 1 ? CostQueryResult.SUCCESS : CostQueryResult.SUCCESS_AFTER_RECONNECT;
} else { } else {
lastErrorMsg = map.get("resultMsg"); lastErrorMsg = map.get("resultMsg");
log.warn("[COST_QUERY] 第 {} 次查询失败 - PartNo: {}, Site: {}, ResultCode: {}, ErrorMsg: {}", log.warn("[COST_QUERY] 第 {} 次查询失败 - PartNo: {}, Site: {}, ResultCode: {}, ErrorMsg: {}",
@ -923,6 +951,7 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
component.setQuotePrice(BigDecimal.ZERO); component.setQuotePrice(BigDecimal.ZERO);
costCache.put(cacheKey, BigDecimal.ZERO); costCache.put(cacheKey, BigDecimal.ZERO);
} }
return CostQueryResult.FAILED;
} }
private QuoteDetailBomTree isComponentBom(QuoteDetail component) { private QuoteDetailBomTree isComponentBom(QuoteDetail component) {

Loading…
Cancel
Save