From 5910d23dd9810a387547db4c056469dd4efdeb50 Mon Sep 17 00:00:00 2001 From: lingniu Date: Wed, 1 Jul 2026 14:58:39 +0800 Subject: [PATCH] chore: remove in-memory identity store --- .../InMemoryVehicleIdentityService.java | 82 ------------------- .../InMemoryVehicleIdentityServiceTest.java | 47 ----------- .../VehicleIdentityAutoConfigurationTest.java | 12 +++ 3 files changed, 12 insertions(+), 129 deletions(-) delete mode 100644 modules/core/vehicle-identity/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java delete mode 100644 modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityServiceTest.java diff --git a/modules/core/vehicle-identity/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java b/modules/core/vehicle-identity/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java deleted file mode 100644 index ca021d8f..00000000 --- a/modules/core/vehicle-identity/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lingniu.ingest.identity; - -import com.lingniu.ingest.api.ProtocolId; - -import java.util.Locale; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public final class InMemoryVehicleIdentityService implements VehicleIdentityResolver, VehicleIdentityRegistry { - - private final ConcurrentMap phoneToVin = new ConcurrentHashMap<>(); - private final ConcurrentMap deviceIdToVin = new ConcurrentHashMap<>(); - private final ConcurrentMap plateToVin = new ConcurrentHashMap<>(); - - @Override - public void bind(VehicleIdentityBinding binding) { - if (binding == null || !binding.hasResolvedVin()) { - return; - } - if (!binding.phone().isBlank()) { - phoneToVin.put(key(binding.protocol(), binding.phone()), binding.vin()); - } - if (!binding.deviceId().isBlank()) { - deviceIdToVin.put(key(binding.protocol(), binding.deviceId()), binding.vin()); - } - if (!binding.plate().isBlank()) { - plateToVin.put(key(binding.protocol(), binding.plate()), binding.vin()); - } - } - - @Override - public VehicleIdentity resolve(VehicleIdentityLookup lookup) { - if (lookup == null) { - return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN); - } - if (!lookup.vin().isBlank()) { - // 协议报文已经携带可信 VIN 时直接采用;绑定表主要服务 JT808/MQTT/信达这类外部 ID。 - return new VehicleIdentity(lookup.vin(), true, VehicleIdentitySource.EXPLICIT_VIN); - } - // 绑定优先级:phone > deviceId > plate。顺序要稳定,否则同一车辆多外部号会产生不同内部 VIN。 - VehicleIdentity phone = resolveBound(phoneToVin, lookup.protocol(), lookup.phone(), VehicleIdentitySource.BOUND_PHONE); - if (phone != null) return phone; - - VehicleIdentity device = resolveBound(deviceIdToVin, lookup.protocol(), lookup.deviceId(), VehicleIdentitySource.BOUND_DEVICE_ID); - if (device != null) return device; - - VehicleIdentity plate = resolveBound(plateToVin, lookup.protocol(), lookup.plate(), VehicleIdentitySource.BOUND_PLATE); - if (plate != null) return plate; - - if (!lookup.deviceId().isBlank()) { - // fallback 不是已确认绑定,只用于不中断接收和冷存;metadata.identityResolved=false 会保留这个事实。 - return new VehicleIdentity(lookup.deviceId(), false, VehicleIdentitySource.FALLBACK_DEVICE_ID); - } - if (!lookup.phone().isBlank()) { - return new VehicleIdentity(lookup.phone(), false, VehicleIdentitySource.FALLBACK_PHONE); - } - if (!lookup.plate().isBlank()) { - return new VehicleIdentity(lookup.plate(), false, VehicleIdentitySource.FALLBACK_PLATE); - } - return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN); - } - - private static VehicleIdentity resolveBound(ConcurrentMap map, - ProtocolId protocol, - String externalId, - VehicleIdentitySource source) { - if (externalId == null || externalId.isBlank()) { - return null; - } - String vin = map.get(key(protocol, externalId)); - if (vin == null) { - return null; - } - return new VehicleIdentity(vin, true, source); - } - - private static String key(ProtocolId protocol, String value) { - String p = protocol == null ? "UNKNOWN" : protocol.name(); - // 绑定 key 带协议前缀,避免 JT808 phone 与 MQTT deviceId 数值相同时互相覆盖。 - return p + ":" + value.trim().toUpperCase(Locale.ROOT); - } -} diff --git a/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityServiceTest.java b/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityServiceTest.java deleted file mode 100644 index b6139703..00000000 --- a/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityServiceTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.lingniu.ingest.identity; - -import com.lingniu.ingest.api.ProtocolId; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class InMemoryVehicleIdentityServiceTest { - - private final InMemoryVehicleIdentityService service = new InMemoryVehicleIdentityService(); - - @Test - void explicitVinWinsOverExternalIdentifiers() { - VehicleIdentity identity = service.resolve(new VehicleIdentityLookup( - ProtocolId.JT808, "LNVIN000000000001", "13900000000", "DEV001", "粤B12345")); - - assertThat(identity.vin()).isEqualTo("LNVIN000000000001"); - assertThat(identity.resolved()).isTrue(); - assertThat(identity.source()).isEqualTo(VehicleIdentitySource.EXPLICIT_VIN); - } - - @Test - void resolvesBoundPhoneDeviceIdAndPlateToVin() { - service.bind(new VehicleIdentityBinding( - ProtocolId.JT808, "LNVIN000000000002", "13900000001", "DEV002", "粤B22222")); - - assertThat(service.resolve(new VehicleIdentityLookup( - ProtocolId.JT808, "", "13900000001", "", "")).vin()) - .isEqualTo("LNVIN000000000002"); - assertThat(service.resolve(new VehicleIdentityLookup( - ProtocolId.JT808, "", "", "DEV002", "")).vin()) - .isEqualTo("LNVIN000000000002"); - assertThat(service.resolve(new VehicleIdentityLookup( - ProtocolId.JT808, "", "", "", "粤B22222")).vin()) - .isEqualTo("LNVIN000000000002"); - } - - @Test - void fallsBackToStableExternalIdentifierWhenNoBindingExists() { - VehicleIdentity identity = service.resolve(new VehicleIdentityLookup( - ProtocolId.JT808, "", "13900000003", "DEV003", "粤B33333")); - - assertThat(identity.vin()).isEqualTo("DEV003"); - assertThat(identity.resolved()).isFalse(); - assertThat(identity.source()).isEqualTo(VehicleIdentitySource.FALLBACK_DEVICE_ID); - } -} diff --git a/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/config/VehicleIdentityAutoConfigurationTest.java b/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/config/VehicleIdentityAutoConfigurationTest.java index 438f6f83..ca673fa4 100644 --- a/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/config/VehicleIdentityAutoConfigurationTest.java +++ b/modules/core/vehicle-identity/src/test/java/com/lingniu/ingest/identity/config/VehicleIdentityAutoConfigurationTest.java @@ -6,6 +6,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import java.nio.file.Files; +import java.nio.file.Path; + import static org.assertj.core.api.Assertions.assertThat; class VehicleIdentityAutoConfigurationTest { @@ -69,4 +72,13 @@ class VehicleIdentityAutoConfigurationTest { .hasMessageContaining("identity.store supports only mysql") .hasMessageContaining("sqlite")); } + + @Test + void moduleDoesNotKeepAlternativeStoreImplementations() { + Path sourceRoot = Path.of("src/main/java/com/lingniu/ingest/identity"); + + assertThat(Files.exists(sourceRoot.resolve("InMemoryVehicleIdentityService.java"))) + .as("identity store is mysql-only; in-memory implementation must not be shipped") + .isFalse(); + } }