refactor: simplify history and mileage runtime
This commit is contained in:
@@ -98,10 +98,23 @@ class MavenModuleProfileTest {
|
|||||||
.doesNotContain("Spring Boot 3.4.x");
|
.doesNotContain("Spring Boot 3.4.x");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void duckDbDriverDoesNotLeakFromCompatibilityStoreIntoProductionApps() throws Exception {
|
||||||
|
Document eventFileStorePom = modulePom("modules/sinks/event-file-store/pom.xml");
|
||||||
|
|
||||||
|
assertThat(dependencyOptional(eventFileStorePom, "org.duckdb", "duckdb_jdbc"))
|
||||||
|
.as("event-file-store is a compatibility path; DuckDB must not be transitive")
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private static Document rootPom() throws Exception {
|
private static Document rootPom() throws Exception {
|
||||||
|
return modulePom("pom.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Document modulePom(String path) throws Exception {
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||||
return factory.newDocumentBuilder().parse(Files.newInputStream(repositoryRoot().resolve("pom.xml")));
|
return factory.newDocumentBuilder().parse(Files.newInputStream(repositoryRoot().resolve(path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String projectProperty(Document pom, String name) {
|
private static String projectProperty(Document pom, String name) {
|
||||||
@@ -150,6 +163,29 @@ class MavenModuleProfileTest {
|
|||||||
return List.copyOf(out);
|
return List.copyOf(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean dependencyOptional(Document pom, String groupId, String artifactId) {
|
||||||
|
Element dependencies = firstDirectChild(pom.getDocumentElement(), "dependencies");
|
||||||
|
if (dependencies == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NodeList children = dependencies.getChildNodes();
|
||||||
|
for (int i = 0; i < children.getLength(); i++) {
|
||||||
|
if (!(children.item(i) instanceof Element dependency) || !"dependency".equals(dependency.getTagName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Element currentGroupId = firstDirectChild(dependency, "groupId");
|
||||||
|
Element currentArtifactId = firstDirectChild(dependency, "artifactId");
|
||||||
|
if (currentGroupId != null
|
||||||
|
&& currentArtifactId != null
|
||||||
|
&& groupId.equals(currentGroupId.getTextContent().trim())
|
||||||
|
&& artifactId.equals(currentArtifactId.getTextContent().trim())) {
|
||||||
|
Element optional = firstDirectChild(dependency, "optional");
|
||||||
|
return optional != null && Boolean.parseBoolean(optional.getTextContent().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static Element firstDirectChild(Element parent, String tagName) {
|
private static Element firstDirectChild(Element parent, String tagName) {
|
||||||
NodeList children = parent.getChildNodes();
|
NodeList children = parent.getChildNodes();
|
||||||
for (int i = 0; i < children.getLength(); i++) {
|
for (int i = 0; i < children.getLength(); i++) {
|
||||||
|
|||||||
@@ -57,8 +57,7 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
|
|||||||
String normalizedVin = clean(vin);
|
String normalizedVin = clean(vin);
|
||||||
Date date = Date.valueOf(statDate);
|
Date date = Date.valueOf(statDate);
|
||||||
String strategy = DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF.name();
|
String strategy = DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF.name();
|
||||||
DailyMileageState existingState = findDailyMileageState(normalizedVin, date)
|
DailyMileageState existingState = findDailyMileageState(normalizedVin, date).orElse(null);
|
||||||
.orElseGet(() -> legacyDailyMileageState(normalizedVin, date).orElse(null));
|
|
||||||
double firstTotalMileage = existingState == null || !Double.isFinite(existingState.firstTotalMileageKm())
|
double firstTotalMileage = existingState == null || !Double.isFinite(existingState.firstTotalMileageKm())
|
||||||
? totalMileageKm
|
? totalMileageKm
|
||||||
: existingState.firstTotalMileageKm();
|
: existingState.firstTotalMileageKm();
|
||||||
@@ -90,29 +89,6 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
|
|||||||
.findFirst();
|
.findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<DailyMileageState> legacyDailyMileageState(String vin, Date statDate) {
|
|
||||||
OptionalDouble start = findMetric(vin, statDate, DAILY_MILEAGE_START_TOTAL_KEY);
|
|
||||||
OptionalDouble latest = findMetric(vin, statDate, DAILY_MILEAGE_LATEST_TOTAL_KEY);
|
|
||||||
if (start.isEmpty() || latest.isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
return Optional.of(new DailyMileageState(start.getAsDouble(), latest.getAsDouble()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private OptionalDouble findMetric(String vin, Date statDate, String metricKey) {
|
|
||||||
List<Double> rows = jdbcTemplate.query("""
|
|
||||||
SELECT metric_value
|
|
||||||
FROM vehicle_stat_metric
|
|
||||||
WHERE vin = ? AND stat_date = ? AND metric_key = ?
|
|
||||||
""", (rs, rowNum) -> rs.getBigDecimal("metric_value") == null
|
|
||||||
? Double.NaN
|
|
||||||
: rs.getBigDecimal("metric_value").doubleValue(), vin, statDate, metricKey);
|
|
||||||
if (rows.isEmpty() || !Double.isFinite(rows.getFirst())) {
|
|
||||||
return OptionalDouble.empty();
|
|
||||||
}
|
|
||||||
return OptionalDouble.of(rows.getFirst());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void upsertDailyMileageMetric(String vin, Date statDate, double value, String unit, String strategy,
|
private void upsertDailyMileageMetric(String vin, Date statDate, double value, String unit, String strategy,
|
||||||
double firstTotalMileageKm, double latestTotalMileageKm) {
|
double firstTotalMileageKm, double latestTotalMileageKm) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -115,6 +115,37 @@ class JdbcVehicleStatMetricRepositoryTest {
|
|||||||
""", Double.class)).isEqualTo(9.5);
|
""", Double.class)).isEqualTo(9.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void ignoresLegacySplitMileageStateMetricsWhenRecordingNewGpsTotalMileage() {
|
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
|
||||||
|
"jdbc:h2:mem:vehicle_stat_metric_ignore_legacy_state;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1",
|
||||||
|
"sa",
|
||||||
|
""));
|
||||||
|
JdbcVehicleStatMetricRepository repository = new JdbcVehicleStatMetricRepository(jdbcTemplate);
|
||||||
|
jdbcTemplate.update("""
|
||||||
|
INSERT INTO vehicle_stat_metric
|
||||||
|
(vin, stat_date, metric_key, metric_value, metric_unit, calculation_method)
|
||||||
|
VALUES
|
||||||
|
('VIN001', DATE '2026-07-01', 'daily_mileage_start_total_km', 100.0, 'km', 'JT808_TOTAL_MILEAGE_DIFF'),
|
||||||
|
('VIN001', DATE '2026-07-01', 'daily_mileage_latest_total_km', 105.0, 'km', 'JT808_TOTAL_MILEAGE_DIFF')
|
||||||
|
""");
|
||||||
|
|
||||||
|
VehicleDailyStatResult result = repository.recordDailyMileageSample(
|
||||||
|
"VIN001", LocalDate.of(2026, 7, 1), 110.0).orElseThrow();
|
||||||
|
|
||||||
|
assertThat(result.dailyMileageKm()).hasValue(0.0);
|
||||||
|
assertThat(jdbcTemplate.queryForObject("""
|
||||||
|
SELECT first_total_mileage_km
|
||||||
|
FROM vehicle_stat_metric
|
||||||
|
WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_km'
|
||||||
|
""", Double.class)).isEqualTo(110.0);
|
||||||
|
assertThat(jdbcTemplate.queryForObject("""
|
||||||
|
SELECT latest_total_mileage_km
|
||||||
|
FROM vehicle_stat_metric
|
||||||
|
WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_km'
|
||||||
|
""", Double.class)).isEqualTo(110.0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void readsLegacyCalculationMethodAsTotalMileageDifference() {
|
void readsLegacyCalculationMethodAsTotalMileageDifference() {
|
||||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.duckdb</groupId>
|
<groupId>org.duckdb</groupId>
|
||||||
<artifactId>duckdb_jdbc</artifactId>
|
<artifactId>duckdb_jdbc</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
|||||||
Reference in New Issue
Block a user