docs: simplify jt808 mileage runtime state

This commit is contained in:
lingniu
2026-07-01 13:29:08 +08:00
parent 97ea77ed27
commit cea8ceeabe
3 changed files with 31 additions and 9 deletions

View File

@@ -6,7 +6,7 @@ The analytics app can calculate daily mileage from JT808 telemetry only. It cons
## Storage ## Storage
There is no separate JT808 daily-mileage table and no Redis mileage state. The derived value is stored as one `daily_mileage_km` metric row in the common JDBC/MySQL table `vehicle_stat_metric`; the local-day minimum and maximum GPS total mileage values are kept on that same row as calculation source columns. Runtime state: none outside `vehicle_stat_metric`. There is no separate JT808 daily-mileage table. The derived value is stored as one `daily_mileage_km` metric row in the common JDBC/MySQL table `vehicle_stat_metric`; the local-day minimum and maximum GPS total mileage values are kept on that same row as calculation source columns.
The JT808 daily-mileage value is calculated from the GPS total mileage reported in location additional information: The JT808 daily-mileage value is calculated from the GPS total mileage reported in location additional information:
@@ -29,4 +29,4 @@ MYSQL_USERNAME=<user>
MYSQL_PASSWORD=<password> MYSQL_PASSWORD=<password>
``` ```
Algorithm defaults use the Asia/Shanghai daily boundary. Restart recovery reads the same `daily_mileage_km` metric row, so no separate mileage state store is required. Algorithm defaults use the Asia/Shanghai daily boundary. Restart recovery reads the same `daily_mileage_km` metric row.

View File

@@ -32,8 +32,7 @@ is explicitly deployed.
- Store complete raw payload metadata and parsed JSON in TDengine `raw_frames`. - Store complete raw payload metadata and parsed JSON in TDengine `raw_frames`.
- Store query-friendly location rows separately from raw payload JSON. - Store query-friendly location rows separately from raw payload JSON.
- Keep derived statistics in metric tables, not protocol-specific daily tables. - Keep derived statistics in metric tables, not protocol-specific daily tables.
- Use Redis only for hot state or streaming calculation state that can be - Use Redis only for optional latest-state APIs that can be rebuilt from Kafka.
rebuilt from Kafka.
- Keep optional compatibility modules outside the production hot path. - Keep optional compatibility modules outside the production hot path.
## Non-Goals ## Non-Goals
@@ -133,9 +132,8 @@ calculation_method = JT808_TOTAL_MILEAGE_DIFF
mileage used for the subtraction stay on the same metric row as calculation mileage used for the subtraction stay on the same metric row as calculation
source columns. source columns.
There is no JT808-specific daily mileage table and no in-memory production Runtime state: none outside `vehicle_stat_metric`. There is no JT808-specific
state-store mode. Restart recovery reads the same metric row, so it does not daily mileage table. Restart recovery reads the same metric row.
require a separate Redis mileage state.
### Latest State ### Latest State
@@ -196,6 +194,5 @@ flowchart LR
- Location queries page over compact rows and reference raw records instead of - Location queries page over compact rows and reference raw records instead of
duplicating full raw JSON. duplicating full raw JSON.
- JT808 daily mileage is stored only in `vehicle_stat_metric`. - JT808 daily mileage is stored only in `vehicle_stat_metric`.
- Runtime state needed for 808 mileage is also in `vehicle_stat_metric`, with no - Runtime state needed for 808 mileage is also in `vehicle_stat_metric`.
Redis or production memory state-store mode.
- Build validation covers the active modules and their composition tests. - Build validation covers the active modules and their composition tests.

View File

@@ -35,6 +35,31 @@ class VehicleStatRepositoryContractTest {
.doesNotContain("speed integral"); .doesNotContain("speed integral");
} }
@Test
void targetArchitectureDocumentsMetricTableAsOnlyJt808MileageRuntimeState() throws IOException {
String architecture = Files.readString(repositoryRoot().resolve("docs/target-architecture.md"));
assertThat(architecture)
.contains("Runtime state: none outside `vehicle_stat_metric`")
.contains("Restart recovery reads the same metric row")
.contains("JT808 daily mileage is stored only in `vehicle_stat_metric`")
.doesNotContain("state-store")
.doesNotContain("Redis mileage state")
.doesNotContain("production memory");
}
@Test
void jt808MileageRunbookDocumentsMetricTableAsOnlyRuntimeState() throws IOException {
String runbook = Files.readString(repositoryRoot()
.resolve("docs/operations/jt808-daily-mileage-runbook.md"));
assertThat(runbook)
.contains("Runtime state: none outside `vehicle_stat_metric`")
.contains("Restart recovery reads the same `daily_mileage_km` metric row")
.doesNotContain("Redis mileage state")
.doesNotContain("state-store");
}
private static Path repositoryRoot() { private static Path repositoryRoot() {
Path path = Path.of("").toAbsolutePath(); Path path = Path.of("").toAbsolutePath();
while (path != null && !Files.exists(path.resolve("docs/superpowers/plans"))) { while (path != null && !Files.exists(path.resolve("docs/superpowers/plans"))) {