perf: reuse mqtt identity resolution

This commit is contained in:
lingniu
2026-07-01 10:12:52 +08:00
parent 418aefc189
commit 74e01acc7a
4 changed files with 126 additions and 0 deletions

View File

@@ -141,6 +141,7 @@ public final class MqttEndpointManager implements AutoCloseable {
MqttPayload parsed = profileRegistry.parse(ep.getName(), ep.getProfile(), topic, payload);
String externalDeviceId = firstNonBlank(parsed.deviceId(), parsed.vin());
IdentityResolution identity = resolveIdentity(parsed);
parsed = parsed.withIdentity(identity.identity(), identity.errorMessage());
Map<String, String> meta = new HashMap<>(4);
// metadata 同时保留外部设备号和内部 VIN便于排查绑定表错误导致的车辆归属问题。
meta.put("vin", identity.identity().vin());

View File

@@ -109,6 +109,17 @@ public final class YutongEventMapper implements EventMapper<MqttPayload> {
}
private IdentityResolution resolveIdentity(MqttPayload payload) {
if (payload.hasIdentitySnapshot()) {
VehicleIdentitySource source = VehicleIdentitySource.UNKNOWN;
try {
source = VehicleIdentitySource.valueOf(payload.identitySource());
} catch (IllegalArgumentException ignored) {
// 保守兜底,外部化的 payload 如果带了未知 source 不应影响接收主链路。
}
return new IdentityResolution(
new VehicleIdentity(payload.resolvedVin(), payload.identityResolved(), source),
payload.identityErrorMessage().isBlank() ? null : payload.identityErrorMessage());
}
String externalDeviceId = firstNonBlank(payload.deviceId(), payload.vin());
String externalVin = payload.externalVin() == null ? "" : payload.externalVin();
String phone = payload.phone() == null ? "" : payload.phone();

View File

@@ -1,6 +1,9 @@
package com.lingniu.ingest.inbound.mqtt.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;
import com.lingniu.ingest.identity.VehicleIdentity;
import com.lingniu.ingest.identity.VehicleIdentitySource;
import java.time.Instant;
@@ -15,6 +18,7 @@ import java.time.Instant;
* @param phone 外部手机号 / SIM 字段
* @param deviceId 外部设备号 / 终端 ID / IMEI 字段
* @param plateNo 外部车牌字段
* @param resolvedVin 已解析的内部 VIN供 RAW 和业务事件复用同一次身份查询
* @param deviceTime 设备上报时刻
* @param data 原始 JSON 树,供 Mapper 按 profile 提取字段
*/
@@ -27,9 +31,33 @@ public record MqttPayload(
String phone,
String deviceId,
String plateNo,
@JsonIgnore String resolvedVin,
@JsonIgnore boolean identityResolved,
@JsonIgnore String identitySource,
@JsonIgnore String identityErrorMessage,
Instant deviceTime,
JsonNode data
) {
public MqttPayload {
resolvedVin = resolvedVin == null ? "" : resolvedVin.trim();
identitySource = identitySource == null ? "" : identitySource.trim();
identityErrorMessage = identityErrorMessage == null ? "" : identityErrorMessage.trim();
}
public MqttPayload(String endpointName,
String profile,
String topic,
String vin,
String externalVin,
String phone,
String deviceId,
String plateNo,
Instant deviceTime,
JsonNode data) {
this(endpointName, profile, topic, vin, externalVin, phone, deviceId, plateNo,
"", false, "", "", deviceTime, data);
}
public MqttPayload(String endpointName,
String profile,
String topic,
@@ -38,4 +66,17 @@ public record MqttPayload(
JsonNode data) {
this(endpointName, profile, topic, vin, "", "", vin, "", deviceTime, data);
}
public MqttPayload withIdentity(VehicleIdentity identity, String errorMessage) {
VehicleIdentity safe = identity == null
? new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN)
: identity;
return new MqttPayload(endpointName, profile, topic, vin, externalVin, phone, deviceId, plateNo,
safe.vin(), safe.resolved(), safe.source().name(), errorMessage, deviceTime, data);
}
@JsonIgnore
public boolean hasIdentitySnapshot() {
return !identitySource.isBlank();
}
}