From 3554841fc3e09927f3245a7903f8da8d0d5528bd Mon Sep 17 00:00:00 2001 From: sladro Date: Sun, 8 Feb 2026 12:39:41 +0800 Subject: [PATCH] =?UTF-8?q?Refactor=20code=20structure=20for=20improved=20?= =?UTF-8?q?readability=20and=20maintainability=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=BA=86inout=E7=9A=84=E5=AF=B9=E9=BD=90=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdxpFlightServiceWebSocketClient.java | 77 ++++++++++++++++-- .../service/DataProcessingService.java | 2 +- .../AdxpFlightServiceWebSocketClient.class | Bin 0 -> 38514 bytes 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 tmpjarcheck/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.class diff --git a/qaup-collision/src/main/java/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.java b/qaup-collision/src/main/java/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.java index c6d4d04..6ecf681 100644 --- a/qaup-collision/src/main/java/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.java +++ b/qaup-collision/src/main/java/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.java @@ -503,6 +503,23 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler { return normalized.isEmpty() ? null : normalized.toUpperCase(); } + private static String normalizeRedisString(Object v) { + if (v == null) { + return null; + } + String s = String.valueOf(v).trim(); + if (s.isEmpty()) { + return null; + } + if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) { + s = s.substring(1, s.length() - 1).trim(); + } + if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) { + s = s.substring(1, s.length() - 1).trim(); + } + return s.isEmpty() ? null : s; + } + private static String buildBizRedisKey(String bizKey) { String normalized = normalizeBizKey(bizKey); if (normalized == null) { @@ -596,6 +613,30 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler { redisCache.setCacheMapValue(flightKey, "activeBizKeyTs", String.valueOf(nowMs)); } + private String readRunwayFromKeys(String flightKey, String bizKey, String field) { + String value = null; + if (bizKey != null) { + value = normalizeRedisString(redisCache.getCacheMapValue(bizKey, field)); + } + if ((value == null || value.isBlank()) && flightKey != null) { + value = normalizeRedisString(redisCache.getCacheMapValue(flightKey, field)); + } + return value; + } + + private String[] resolveRunwayPair(String incomingIn, String incomingOut, String existingIn, String existingOut) { + String finalIn = incomingIn != null && !incomingIn.isBlank() ? incomingIn : existingIn; + String finalOut = incomingOut != null && !incomingOut.isBlank() ? incomingOut : existingOut; + + if ((finalIn == null || finalIn.isBlank()) && finalOut != null && !finalOut.isBlank()) { + finalIn = finalOut; + } + if ((finalOut == null || finalOut.isBlank()) && finalIn != null && !finalIn.isBlank()) { + finalOut = finalIn; + } + return new String[]{finalIn, finalOut}; + } + private LocalDateTime parseBestFlightDateTimeForDfi(org.w3c.dom.Element root, String[] bizParts) { if (bizParts != null && bizParts.length >= 3) { LocalDateTime fromBiz = parseDateTimeLoose(bizParts[2]); @@ -824,12 +865,21 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler { setCommonFlightMeta(flightKey, normalizedFlightNo, arr); setCommonFlightMeta(bizRedisKey, normalizedFlightNo, arr); updateActiveBizKey(flightKey, normalizedBizKey, nowMs); - if (RunwayNum != null && !RunwayNum.isBlank()) { - // DFIE 的 RunwayNum 用于初始化跑道参数:in/out 同步赋值,再由 RUNWAY 事件按 BizKey 精确覆盖 - setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunway", RunwayNum); - setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunway", RunwayNum); + String incomingRunway = normalizeRedisString(RunwayNum); + String existingInRunway = readRunwayFromKeys(flightKey, bizRedisKey, "inRunway"); + String existingOutRunway = readRunwayFromKeys(flightKey, bizRedisKey, "outRunway"); + String[] resolvedRunways = resolveRunwayPair(incomingRunway, incomingRunway, existingInRunway, existingOutRunway); + String inRunwayToWrite = resolvedRunways[0]; + String outRunwayToWrite = resolvedRunways[1]; + if (inRunwayToWrite != null && !inRunwayToWrite.isBlank() + && outRunwayToWrite != null && !outRunwayToWrite.isBlank()) { + setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunway", inRunwayToWrite); + setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunway", outRunwayToWrite); setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunwayTs", String.valueOf(nowMs)); setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunwayTs", String.valueOf(nowMs)); + } else { + log.debug("DFIE runway skipped: both in/out are blank, flightNo={}, bizKey={}, runwayNum={}", + normalizedFlightNo, normalizedBizKey, RunwayNum); } LocalDateTime bizDateTime = parseBestFlightDateTimeForDfi(root, arr); applyDfiExpiry(flightKey, bizRedisKey, bizDateTime, nowMs, normalizedFlightNo, normalizedBizKey); @@ -873,13 +923,22 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler { setCommonFlightMeta(flightKey, normalizedFlightNo, arr); setCommonFlightMeta(bizRedisKey, normalizedFlightNo, arr); updateActiveBizKey(flightKey, normalizedBizKey, nowMs); - if (inRunway != null && !inRunway.isBlank()){ - setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunway", inRunway); + String incomingInRunway = normalizeRedisString(inRunway); + String incomingOutRunway = normalizeRedisString(outRunway); + String existingInRunway = readRunwayFromKeys(flightKey, bizRedisKey, "inRunway"); + String existingOutRunway = readRunwayFromKeys(flightKey, bizRedisKey, "outRunway"); + String[] resolvedRunways = resolveRunwayPair(incomingInRunway, incomingOutRunway, existingInRunway, existingOutRunway); + String inRunwayToWrite = resolvedRunways[0]; + String outRunwayToWrite = resolvedRunways[1]; + if (inRunwayToWrite != null && !inRunwayToWrite.isBlank() + && outRunwayToWrite != null && !outRunwayToWrite.isBlank()) { + setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunway", inRunwayToWrite); + setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunway", outRunwayToWrite); setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "inRunwayTs", String.valueOf(nowMs)); - } - if (outRunway != null && !outRunway.isBlank()){ - setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunway", outRunway); setValueOnFlightAndBizKeys(flightKey, bizRedisKey, "outRunwayTs", String.valueOf(nowMs)); + } else { + log.debug("RUNWAY skipped: both in/out are blank, flightNo={}, bizKey={}, inRunway={}, outRunway={}", + normalizedFlightNo, normalizedBizKey, inRunway, outRunway); } log.info("成功将航班RUNWAY数据存储到Redis: flightNumber={}, bizKey={}, inRunway={}, outRunway={}", normalizedFlightNo, bizKey, inRunway, outRunway); diff --git a/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java b/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java index 44c3531..d5db4f0 100644 --- a/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java +++ b/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java @@ -1049,7 +1049,7 @@ public class DataProcessingService { */ private final Map pendingRouteQueries = new ConcurrentHashMap<>(); - private static final int ROUTE_RETRY_MAX_ATTEMPTS = 2; + private static final int ROUTE_RETRY_MAX_ATTEMPTS = 20; private static final long ROUTE_RETRY_MIN_DELAY_MS = 1_000L; // 1s private static final long ROUTE_RETRY_MAX_DELAY_MS = 5_000L; // 5s diff --git a/tmpjarcheck/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.class b/tmpjarcheck/com/qaup/collision/datacollector/websocket/AdxpFlightServiceWebSocketClient.class new file mode 100644 index 0000000000000000000000000000000000000000..6100ce6c576f6015a15af7d20c2b371ff586c052 GIT binary patch literal 38514 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
4$jksQ(-FO? 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 M^e4Jg@21fI1CyUr)c^nh literal 0 HcmV?d00001