From f38841208a5935394a062ce7fdc6f09de55b6a66 Mon Sep 17 00:00:00 2001 From: rsynek Date: Wed, 17 Jun 2026 12:26:42 +0200 Subject: [PATCH] fix: Revert "feat: Add effective map location to metadata events (#2321)" This reverts commit 71f89e11 --- .../definition/api/domain/Metadata.java | 14 ---- .../service/definition/internal/Headers.java | 2 - .../internal/MapEnrichmentContext.java | 22 ------ .../internal/platform/EnvironmentVars.java | 12 --- .../client/api/TravelTimeMatrixEnricher.java | 8 +- .../maps/service/client/impl/CacheItem.java | 2 +- .../client/impl/MapServiceClientImpl.java | 24 ++---- .../api/TravelTimeMatrixEnricherTest.java | 34 -------- .../TravelTimeAndDistanceWithMetadata.java | 7 +- .../TravelTimeAndDistanceMatrixResponse.java | 7 +- .../DistanceGetUpdateResponseTransformer.java | 77 +------------------ .../HaversineDistanceResponseTransformer.java | 4 - .../service/worker/impl/SolverWorker.java | 19 ----- 13 files changed, 12 insertions(+), 220 deletions(-) diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/domain/Metadata.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/api/domain/Metadata.java index 30238de19bc..ab15ae63911 100644 --- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/domain/Metadata.java +++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/api/domain/Metadata.java @@ -70,11 +70,6 @@ public final class Metadata implements Status { @JsonInclude(JsonInclude.Include.NON_EMPTY) private String failureMessage; - @Schema(nullable = true, - description = "The map-service region resolved when location is auto-select.") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private String resolvedMapLocation; - public Metadata() { this((String) null); } @@ -107,7 +102,6 @@ public Metadata(Metadata metadata) { this.parentId = metadata.parentId; this.originId = metadata.originId; this.failureMessage = metadata.failureMessage; - this.resolvedMapLocation = metadata.resolvedMapLocation; } public String getId() { @@ -266,14 +260,6 @@ public void setFailureMessage(String failureMessage) { this.failureMessage = failureMessage; } - public String getResolvedMapLocation() { - return resolvedMapLocation; - } - - public void setResolvedMapLocation(String resolvedMapLocation) { - this.resolvedMapLocation = resolvedMapLocation; - } - @Override public void solvingStarted() { if (solverStatus != SolvingStatus.DATASET_COMPUTED diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java index d83e1332070..a945be40dba 100644 --- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java +++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java @@ -6,8 +6,6 @@ public class Headers { public static final String X_MAPS_PROVIDER_HEADER = "X-TF-MAPS-PROVIDER"; - public static final String X_MAPS_LOCATION_HEADER = "X-TF-MAPS-LOCATION"; - public static final String X_MAPS_CACHE_ID = "X-TF-MAPS-CACHE-ID"; public static final String X_MAPS_RESPONSE_CHUNK_BYTES = "X-TF-MAPS-CHUNK-BYTES"; diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/MapEnrichmentContext.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/MapEnrichmentContext.java index 308aada4be7..e69de29bb2d 100644 --- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/MapEnrichmentContext.java +++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/MapEnrichmentContext.java @@ -1,22 +0,0 @@ -package ai.timefold.solver.service.definition.internal; - -import jakarta.enterprise.context.ApplicationScoped; - -/** - * Side-channel used by the maps enricher to publish the resolved map-service location to the - * SolverWorker, which then writes it onto the dataset's {@code Metadata} so it propagates through - * insight events. - */ -@ApplicationScoped -public class MapEnrichmentContext { - - private String resolvedMapLocation; - - public void setResolvedMapLocation(String location) { - this.resolvedMapLocation = location; - } - - public String getResolvedMapLocation() { - return this.resolvedMapLocation; - } -} diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/platform/EnvironmentVars.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/platform/EnvironmentVars.java index 28f07a91a3d..39395c53515 100644 --- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/platform/EnvironmentVars.java +++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/platform/EnvironmentVars.java @@ -32,18 +32,6 @@ public class EnvironmentVars { */ public static final String ENV_TIMEFOLD_TENANT_NAME = "AI_TIMEFOLD_TENANT_NAME"; - /** - * Configured map-service location: either a concrete region (e.g. {@code us-georgia}) or the - * sentinel {@link #MAP_SERVICE_LOCATION_AUTO_SELECT} for runtime region resolution. - */ - public static final String ENV_TIMEFOLD_PLATFORM_MAP_SERVICE_LOCATION = "AI_TIMEFOLD_PLATFORM_MAP_SERVICE_LOCATION"; - - /** - * Sentinel value for {@link #ENV_TIMEFOLD_PLATFORM_MAP_SERVICE_LOCATION}: tells the maps-service - * to auto-select the region at request time based on the locations being routed. - */ - public static final String MAP_SERVICE_LOCATION_AUTO_SELECT = "auto-select"; - /** * Kubernetes API specific environment variables that are set based on execution information like pod and node */ diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricher.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricher.java index 158a4e8e806..b29b68b80b1 100644 --- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricher.java +++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricher.java @@ -8,7 +8,6 @@ import jakarta.inject.Inject; import ai.timefold.solver.service.definition.api.enrichment.SolverModelEnricher; -import ai.timefold.solver.service.definition.internal.MapEnrichmentContext; import ai.timefold.solver.service.definition.internal.error.ErrorCodes; import ai.timefold.solver.service.definition.internal.error.TimefoldRuntimeException; import ai.timefold.solver.service.maps.api.model.Location; @@ -31,14 +30,10 @@ public class TravelTimeMatrixEnricher implements SolverModelEnricher enrich(LocationsAwareSolverModel solverMo location.setDistanceMatrix(travelTimeAndDistance.travelTimeAndDistance().distance()); }); solverModel.setLocationsNotInMap(convertIdxToLocations(travelTimeAndDistance.locationsNotInMapIdx(), locations)); - mapEnrichmentContext.setResolvedMapLocation(travelTimeAndDistance.resolvedMapLocation()); return solverModel; } diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/CacheItem.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/CacheItem.java index aa1ecdf71dd..e441a74e487 100644 --- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/CacheItem.java +++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/CacheItem.java @@ -6,6 +6,6 @@ import ai.timefold.solver.service.maps.service.integration.internal.model.TravelTimeAndDistance; public record CacheItem(TravelTimeAndDistance travelTimeAndDistance, List locations, String hash, - List locationsOutOfMap, String resolvedMapLocation) { + List locationsOutOfMap) { } diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java index 2e460aa5244..d974d9eac1d 100644 --- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java +++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java @@ -4,7 +4,6 @@ import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_INVALIDATE_MATRIX_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_CHUNK_BYTES; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_NOT_IN_MAP; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATION_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_MATRIX_HASH_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_PROVIDER_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_RESPONSE_CHUNK_BYTES; @@ -136,9 +135,8 @@ public TravelTimeAndDistanceWithMetadata getTravelTimeAndDistance(List // If there are no updates, return from cache LOGGER.info("Distance matrix in cache is up-to-date, returning from cache"); assertLocationsAreInCache(locations); - CacheItem cached = travelTimeAndDistanceSingleItemCache.get(); - return new TravelTimeAndDistanceWithMetadata(cached.travelTimeAndDistance(), - cached.locationsOutOfMap(), cached.resolvedMapLocation()); + return new TravelTimeAndDistanceWithMetadata(travelTimeAndDistanceSingleItemCache.get().travelTimeAndDistance(), + travelTimeAndDistanceSingleItemCache.get().locationsOutOfMap()); } else { // If there are updates, process them and update cache LOGGER.info("Distance matrix in cache is not up-to-date, processing updates"); @@ -207,8 +205,7 @@ private TravelTimeAndDistanceWithMetadata getFromCacheOrRequest(List l if (travelTimeAndDistanceSingleItemCache.isInCache(id)) { LOGGER.info("Distance matrix without location set name in cache, returning from cache"); CacheItem cacheItem = travelTimeAndDistanceSingleItemCache.get(); - return new TravelTimeAndDistanceWithMetadata(cacheItem.travelTimeAndDistance(), cacheItem.locationsOutOfMap(), - cacheItem.resolvedMapLocation()); + return new TravelTimeAndDistanceWithMetadata(cacheItem.travelTimeAndDistance(), cacheItem.locationsOutOfMap()); } // If it does not exist, request from maps-service and store by hash of locations @@ -240,7 +237,6 @@ private TravelTimeAndDistanceWithMetadata getAndStoreInCache(List loca private TravelTimeAndDistanceWithMetadata processResponseAndStoreInCache(Response response, String localCacheId) { String matrixHash = response.getHeaderString(X_MAPS_MATRIX_HASH_HEADER); String provider = response.getHeaderString(X_MAPS_PROVIDER_HEADER); - String resolvedMapLocation = response.getHeaderString(X_MAPS_LOCATION_HEADER); String tenant = response.getHeaderString(X_TENANT_ID_HEADER); String cacheId = response.getHeaderString(X_MAPS_CACHE_ID); String locationsNotInMapString = response.getHeaderString(X_MAPS_LOCATIONS_NOT_IN_MAP); @@ -260,13 +256,11 @@ private TravelTimeAndDistanceWithMetadata processResponseAndStoreInCache(Respons throw new IllegalArgumentException("No provider found to convert travel time and distance response."); } - TravelTimeAndDistanceWithMetadata raw = + TravelTimeAndDistanceWithMetadata travelTimeAndDistance = convertResponse(provider, chunkBytes, responseLocations, data, locationsNotInMap); - TravelTimeAndDistanceWithMetadata travelTimeAndDistance = new TravelTimeAndDistanceWithMetadata( - raw.travelTimeAndDistance(), raw.locationsNotInMapIdx(), resolvedMapLocation); travelTimeAndDistanceSingleItemCache.put(localCacheId, new CacheItem(travelTimeAndDistance.travelTimeAndDistance(), responseLocations, matrixHash, - locationsNotInMap, resolvedMapLocation)); + locationsNotInMap)); return travelTimeAndDistance; } catch (IllegalDistanceResponseException e) { @@ -281,7 +275,6 @@ private TravelTimeAndDistanceWithMetadata processResponseAndStoreInCache(Respons private TravelTimeAndDistanceWithMetadata processUpdateAndStoreInCache(Response response, String locationSetName) { String matrixHash = response.getHeaderString(X_MAPS_MATRIX_HASH_HEADER); String provider = response.getHeaderString(X_MAPS_PROVIDER_HEADER); - String resolvedMapLocation = response.getHeaderString(X_MAPS_LOCATION_HEADER); String tenant = response.getHeaderString(X_TENANT_ID_HEADER); String cacheId = response.getHeaderString(X_MAPS_CACHE_ID); String locationsNotInMapString = response.getHeaderString(X_MAPS_LOCATIONS_NOT_IN_MAP); @@ -301,18 +294,15 @@ private TravelTimeAndDistanceWithMetadata processUpdateAndStoreInCache(Response throw new IllegalArgumentException("No provider found to convert travel time and distance update."); } - TravelTimeAndDistanceWithMetadata raw = + TravelTimeAndDistanceWithMetadata travelTimeAndDistance = convertUpdate(provider, chunkBytes, responseLocations, data, cacheItem.locationsOutOfMap(), locationsNotInMap); - String effectiveMapLocation = resolvedMapLocation != null ? resolvedMapLocation : cacheItem.resolvedMapLocation(); - TravelTimeAndDistanceWithMetadata travelTimeAndDistance = new TravelTimeAndDistanceWithMetadata( - raw.travelTimeAndDistance(), raw.locationsNotInMapIdx(), effectiveMapLocation); List newLocations = Stream.concat(cacheItem.locations().stream(), responseLocations.stream()).toList(); if (locationSetName != null && matrixHash != null) { travelTimeAndDistanceSingleItemCache.put(locationSetName, new CacheItem(travelTimeAndDistance.travelTimeAndDistance(), newLocations, matrixHash, - locationsNotInMap, effectiveMapLocation)); + locationsNotInMap)); } return travelTimeAndDistance; diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricherTest.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricherTest.java index 70c5d8ffa25..ec07b480e05 100644 --- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricherTest.java +++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/api/TravelTimeMatrixEnricherTest.java @@ -1,12 +1,10 @@ package ai.timefold.solver.service.maps.service.client.api; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import jakarta.inject.Inject; -import ai.timefold.solver.service.definition.internal.MapEnrichmentContext; import ai.timefold.solver.service.maps.api.model.Location; import ai.timefold.solver.service.maps.api.model.travel.TravelDistance; import ai.timefold.solver.service.maps.api.model.travel.TravelTime; @@ -14,8 +12,6 @@ import ai.timefold.solver.service.maps.service.client.util.SampleModel; import ai.timefold.solver.service.maps.service.integration.api.LocationsAwareSolverModel; import ai.timefold.solver.service.maps.service.test.api.MapServiceApiWiremockExtensions; -import ai.timefold.solver.service.maps.service.test.impl.DistanceGetUpdateResponseTransformer; -import ai.timefold.solver.service.maps.service.test.impl.HaversineDistanceResponseTransformer; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @@ -32,9 +28,6 @@ public class TravelTimeMatrixEnricherTest { @Inject TravelTimeMatrixEnricher enricher; - @Inject - MapEnrichmentContext mapEnrichmentContext; - @Test void testRemoteConnectionWithMapServer() { Location l1 = new Location(0, 0); @@ -48,8 +41,6 @@ void testRemoteConnectionWithMapServer() { Assertions.assertThat(enrich.getLocations().getFirst().getTravelTimeTo(l2)).isEqualTo(TravelTime.of(11322L)); Assertions.assertThat(enrich.getLocations().getFirst().getDistanceTo(l2)).isEqualTo(TravelDistance.of(157249L)); Assertions.assertThat(enrich.getLocationsNotInMap()).isEmpty(); - Assertions.assertThat(mapEnrichmentContext.getResolvedMapLocation()) - .isEqualTo(HaversineDistanceResponseTransformer.RESOLVED_MAP_LOCATION); } @Test @@ -106,8 +97,6 @@ void testDistanceMatrixWithUpdates() { Assertions.assertThat(enrich.getLocations().get(1).getDistanceTo(l1)).isEqualTo(TravelDistance.of(157249L)); Assertions.assertThat(enrich.getLocations().get(2).getDistanceTo(l4)).isEqualTo(TravelDistance.of(157178L)); Assertions.assertThat(enrich.getLocationsNotInMap()).isEmpty(); - Assertions.assertThat(mapEnrichmentContext.getResolvedMapLocation()) - .isEqualTo(HaversineDistanceResponseTransformer.RESOLVED_MAP_LOCATION); } @Test @@ -164,27 +153,4 @@ void testDistanceMatrixWithLocationsOutOfMap() { Assertions.assertThat(enrich.getLocations().get(2).getDistanceTo(l4)).isEqualTo(TravelDistance.ZERO); } - @Test - void updatePathFallsBackToCachedMapLocationWhenHeaderIsMissing() { - // First enrich populates the cache for "with-updates" via the POST full-matrix path, - // which emits X_MAPS_LOCATION_HEADER and cache stores resolvedMapLocation="us-georgia". - SampleModel seed = new SampleModel(DistanceGetUpdateResponseTransformer.UPDATE_AWARE_LOCATION_SET_NAME, - DistanceGetUpdateResponseTransformer.UPDATE_OLD_LOCATIONS); - enricher.enrich(seed); - Assertions.assertThat(mapEnrichmentContext.getResolvedMapLocation()) - .isEqualTo(HaversineDistanceResponseTransformer.RESOLVED_MAP_LOCATION); - - // Second enrich adds a new location and cache hit triggers the GET-update path. - // The transformer returns a 200 update WITHOUT X_MAPS_LOCATION_HEADER, so - // processUpdateAndStoreInCache must fall back to the value stored in the CacheItem. - List withNewLocation = new ArrayList<>(DistanceGetUpdateResponseTransformer.UPDATE_OLD_LOCATIONS); - withNewLocation.addAll(DistanceGetUpdateResponseTransformer.UPDATE_NEW_LOCATIONS); - SampleModel updated = new SampleModel(DistanceGetUpdateResponseTransformer.UPDATE_AWARE_LOCATION_SET_NAME, - withNewLocation); - enricher.enrich(updated); - - Assertions.assertThat(mapEnrichmentContext.getResolvedMapLocation()) - .isEqualTo(HaversineDistanceResponseTransformer.RESOLVED_MAP_LOCATION); - } - } diff --git a/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/model/TravelTimeAndDistanceWithMetadata.java b/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/model/TravelTimeAndDistanceWithMetadata.java index 7df4476e36f..8d346d7eb33 100644 --- a/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/model/TravelTimeAndDistanceWithMetadata.java +++ b/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/model/TravelTimeAndDistanceWithMetadata.java @@ -3,10 +3,5 @@ import java.util.List; public record TravelTimeAndDistanceWithMetadata(TravelTimeAndDistance travelTimeAndDistance, - List locationsNotInMapIdx, String resolvedMapLocation) { - - public TravelTimeAndDistanceWithMetadata(TravelTimeAndDistance travelTimeAndDistance, - List locationsNotInMapIdx) { - this(travelTimeAndDistance, locationsNotInMapIdx, null); - } + List locationsNotInMapIdx) { } diff --git a/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/provider/TravelTimeAndDistanceMatrixResponse.java b/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/provider/TravelTimeAndDistanceMatrixResponse.java index 6d98be827d4..78f63ef19fb 100644 --- a/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/provider/TravelTimeAndDistanceMatrixResponse.java +++ b/service/maps/service-integration/src/main/java/ai/timefold/solver/service/maps/service/integration/internal/provider/TravelTimeAndDistanceMatrixResponse.java @@ -3,10 +3,5 @@ import java.io.InputStream; import java.util.List; -public record TravelTimeAndDistanceMatrixResponse(InputStream response, List locationsOutOfMapIndexes, - String resolvedMapLocation) { - - public TravelTimeAndDistanceMatrixResponse(InputStream response, List locationsOutOfMapIndexes) { - this(response, locationsOutOfMapIndexes, null); - } +public record TravelTimeAndDistanceMatrixResponse(InputStream response, List locationsOutOfMapIndexes) { } diff --git a/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/DistanceGetUpdateResponseTransformer.java b/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/DistanceGetUpdateResponseTransformer.java index 9b71cdc4e1d..5693f95327d 100644 --- a/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/DistanceGetUpdateResponseTransformer.java +++ b/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/DistanceGetUpdateResponseTransformer.java @@ -1,20 +1,5 @@ package ai.timefold.solver.service.maps.service.test.impl; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_CHUNK_BYTES; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_MATRIX_HASH_HEADER; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_PROVIDER_HEADER; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_RESPONSE_CHUNK_BYTES; - -import java.io.ByteArrayInputStream; -import java.io.SequenceInputStream; -import java.util.Collections; -import java.util.List; - -import ai.timefold.solver.service.maps.api.model.Location; -import ai.timefold.solver.service.maps.haversine.impl.HaversineTravelTimeAndDistanceMatrixProvider; -import ai.timefold.solver.service.maps.service.integration.internal.model.TravelTimeAndDistance; - -import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.extension.ResponseDefinitionTransformerV2; import com.github.tomakehurst.wiremock.http.ResponseDefinition; @@ -24,70 +9,10 @@ public class DistanceGetUpdateResponseTransformer implements ResponseDefinitionT public static String TRANSFORMER_NAME = "distance-get-update-response-transformer"; - /** - * Location-set name that opts a test into a real (non-410) update response. The test must seed the cache - * with {@link #UPDATE_OLD_LOCATIONS} on a first enrich, then add {@link #UPDATE_NEW_LOCATIONS} on a second. - * Used to drive the {@code processUpdateAndStoreInCache} path, which is otherwise unreachable via wiremock. - */ - public static final String UPDATE_AWARE_LOCATION_SET_NAME = "with-updates"; - public static final List UPDATE_OLD_LOCATIONS = List.of(new Location(0, 0), new Location(1, 1)); - public static final List UPDATE_NEW_LOCATIONS = List.of(new Location(2, 2)); - - private final ObjectMapper objectMapper = new ObjectMapper(); - private final HaversineTravelTimeAndDistanceMatrixProvider provider = - new HaversineTravelTimeAndDistanceMatrixProvider(objectMapper); - @Override public ResponseDefinition transform(ServeEvent serveEvent) { - String options = serveEvent.getRequest().queryParameter("options").firstValue(); - String matrixHash = serveEvent.getRequest().queryParameter("matrix-hash").firstValue(); - // "00" is the client's sentinel for "no cached hash yet"; it returns 410 so it falls back to POST. - // For any other hash on the opt-in location set, deliver a real chunked update. - if (!isUpdateAware(options) || "00".equals(matrixHash)) { - return new ResponseDefinitionBuilder().withStatus(410).build(); - } - try { - return buildUpdateResponse(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private boolean isUpdateAware(String options) { - if (options == null) { - return false; - } - for (String entry : options.split(",")) { - String[] kv = entry.split(":"); - if (kv.length == 2 && "locationSetName".equals(kv[0].trim()) - && UPDATE_AWARE_LOCATION_SET_NAME.equals(kv[1].trim())) { - return true; - } - } - return false; - } - - private ResponseDefinition buildUpdateResponse() throws Exception { - // One matrix chunk (old × new) is enough to drive processUpdateAndStoreInCache. The test only - // checks the resolvedMapLocation header fallback, not the joined matrix contents. - TravelTimeAndDistance oldXNew = objectMapper.readValue( - provider.calculateTravelTimeAndDistance(UPDATE_OLD_LOCATIONS, UPDATE_NEW_LOCATIONS, - Collections.emptyMap()).response(), - TravelTimeAndDistance.class); - - byte[] newLocationsBytes = objectMapper.writeValueAsBytes(UPDATE_NEW_LOCATIONS); - byte[] matrixBytes = objectMapper.writeValueAsBytes(oldXNew); - return new ResponseDefinitionBuilder() - .withHeader("Content-Type", "application/json") - .withHeader(X_MAPS_PROVIDER_HEADER, provider.getProvider()) - // Intentionally NO X_MAPS_LOCATION_HEADER: drives the cache-fallback branch. - .withHeader(X_MAPS_MATRIX_HASH_HEADER, "hash2") - .withHeader(X_MAPS_RESPONSE_CHUNK_BYTES, String.valueOf(matrixBytes.length)) - .withHeader(X_MAPS_LOCATIONS_CHUNK_BYTES, newLocationsBytes.length + ",0") - .withStatus(200) - .withBody(new SequenceInputStream(new ByteArrayInputStream(newLocationsBytes), - new ByteArrayInputStream(matrixBytes)).readAllBytes()) + .withStatus(410) .build(); } diff --git a/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/HaversineDistanceResponseTransformer.java b/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/HaversineDistanceResponseTransformer.java index 4b8d8f2ee33..de05e0408a2 100644 --- a/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/HaversineDistanceResponseTransformer.java +++ b/service/maps/service-test/src/main/java/ai/timefold/solver/service/maps/service/test/impl/HaversineDistanceResponseTransformer.java @@ -2,7 +2,6 @@ import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_CHUNK_BYTES; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_NOT_IN_MAP; -import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATION_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_MATRIX_HASH_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_PROVIDER_HEADER; import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_RESPONSE_CHUNK_BYTES; @@ -29,7 +28,6 @@ public class HaversineDistanceResponseTransformer implements ResponseDefinitionTransformerV2 { public static String TRANSFORMER_NAME = "haversine-distance-response-transformer"; - public static final String RESOLVED_MAP_LOCATION = "us-georgia"; private static final List locationsOutOfMap = List.of(new Location(-90, -90)); private final ObjectMapper objectMapper = new ObjectMapper(); private final HaversineTravelTimeAndDistanceMatrixProvider provider = @@ -65,7 +63,6 @@ public ResponseDefinition transform(ServeEvent serveEvent) { return new ResponseDefinitionBuilder() .withHeader("Content-Type", "application/json") .withHeader(X_MAPS_PROVIDER_HEADER, provider.getProvider()) - .withHeader(X_MAPS_LOCATION_HEADER, RESOLVED_MAP_LOCATION) .withHeader(X_MAPS_MATRIX_HASH_HEADER, "hash") .withHeader(X_MAPS_LOCATIONS_CHUNK_BYTES, metadataChunkBytes.stream().map(Object::toString).collect(Collectors.joining(","))) @@ -107,7 +104,6 @@ public ResponseDefinition transform(ServeEvent serveEvent) { return new ResponseDefinitionBuilder() .withHeader("Content-Type", "application/json") .withHeader(X_MAPS_PROVIDER_HEADER, provider.getProvider()) - .withHeader(X_MAPS_LOCATION_HEADER, RESOLVED_MAP_LOCATION) .withHeader(X_MAPS_RESPONSE_CHUNK_BYTES, response.chunkBytes().stream().map(Object::toString).collect(Collectors.joining(","))) .withHeader(X_MAPS_MATRIX_HASH_HEADER, "hash") diff --git a/service/worker/src/main/java/ai/timefold/solver/service/worker/impl/SolverWorker.java b/service/worker/src/main/java/ai/timefold/solver/service/worker/impl/SolverWorker.java index 0f8b0ca1257..883870a66da 100644 --- a/service/worker/src/main/java/ai/timefold/solver/service/worker/impl/SolverWorker.java +++ b/service/worker/src/main/java/ai/timefold/solver/service/worker/impl/SolverWorker.java @@ -49,7 +49,6 @@ import ai.timefold.solver.service.definition.api.validation.ModelValidator; import ai.timefold.solver.service.definition.api.validation.ValidationBuilder; import ai.timefold.solver.service.definition.api.validation.dto.ValidationResult; -import ai.timefold.solver.service.definition.internal.MapEnrichmentContext; import ai.timefold.solver.service.definition.internal.error.ErrorCodes; import ai.timefold.solver.service.definition.internal.error.ItemNotFoundException; import ai.timefold.solver.service.definition.internal.error.TimefoldRuntimeException; @@ -118,8 +117,6 @@ public class SolverWorker { private final SolverModelEnrichmentDirectorService enrichmentDirectorService; - private final MapEnrichmentContext mapEnrichmentContext; - private final TerminationService terminationService; private final Emitter datasetValidatedEventEmitter; @@ -174,7 +171,6 @@ public SolverWorker(@ConfigProperty(name = "timefold.application.name") Optional ModelConvertorBase modelConvertor, SolverModelEnricherService enricherService, SolverModelEnrichmentDirectorService enrichmentDirectorService, - MapEnrichmentContext mapEnrichmentContext, TerminationService terminationService, ShutdownExecutor shutdownExecutor, ShutdownOnTerminate shutdownOnTerminate, @@ -201,7 +197,6 @@ public SolverWorker(@ConfigProperty(name = "timefold.application.name") Optional this.modelConvertor = (ModelConvertor) modelConvertor; this.enricherService = enricherService; this.enrichmentDirectorService = enrichmentDirectorService; - this.mapEnrichmentContext = mapEnrichmentContext; this.terminationService = terminationService; this.shutdownExecutor = shutdownExecutor; this.shutdownOnTerminate = shutdownOnTerminate; @@ -352,7 +347,6 @@ private void computeOutputs(String id) { var modelConfig = Configuration.getSafeModelConfig(configuration); var solverModel = createSolverModel(modelInput, modelConfig); - applyResolvedMapLocation(metadata); solutionManager.update(solverModel); // Store the updated solution @@ -568,7 +562,6 @@ protected SolverModel notifyOnStart(String id, ModelInput modelInput, ModelOutpu var metadata = storageService.getMetadata(id); var solverModel = createSolverModel(modelInput, modelConfig, modelOutput); - applyResolvedMapLocation(metadata); if (metadata.getSolverStatus() == SolvingStatus.DATASET_COMPUTED || metadata.getSolverStatus() == SolvingStatus.SOLVING_SCHEDULED) { metadata.solvingStarted(); @@ -618,18 +611,6 @@ private SolverModel enrichModel(SolverModel solverModel) { : enricherService.enrich(solverModel); } - private void applyResolvedMapLocation(Metadata metadata) { - var resolved = mapEnrichmentContext.getResolvedMapLocation(); - if (resolved == null || metadata == null) { - return; - } - metadata.setResolvedMapLocation(resolved); - var configuredLocation = System.getenv(EnvironmentVars.ENV_TIMEFOLD_PLATFORM_MAP_SERVICE_LOCATION); - if (EnvironmentVars.MAP_SERVICE_LOCATION_AUTO_SELECT.equalsIgnoreCase(configuredLocation)) { - LOGGER.info("Auto-select map resolved to '{}' for dataset {}.", resolved, metadata.getId()); - } - } - protected void notifyOnInit(String id, SolverModel solverModel, boolean isTerminatedEarly, EventProducerId eventProducerId) { LOGGER.debug("Notify run init for id {}", id);