diff --git a/application/src/main/java/org/opentripplanner/framework/application/OTPRequestTimeoutException.java b/application/src/main/java/org/opentripplanner/framework/application/OTPRequestTimeoutException.java index a8b0789d7c0..9d71314f153 100644 --- a/application/src/main/java/org/opentripplanner/framework/application/OTPRequestTimeoutException.java +++ b/application/src/main/java/org/opentripplanner/framework/application/OTPRequestTimeoutException.java @@ -18,10 +18,9 @@ public String getMessage() { /** * The Grizzly web server is configured with a transaction timeout and will set the interrupt - * flag on the current thread. OTP does not have many blocking operations which check the - * interrupted flag, so instead we need to do the check manually. The check has a small - * performance overhead so try to place the check in the beginning of significantly big block of - * calculations. + * flag on the current thread. OTP has few blocking operations which check the interrupted flag, + * so instead we need to do the check manually. The check has a small performance overhead, so + * try to place the check at the beginning of a significant calculations. */ public static void checkForTimeout() { // We call yield() to allow monitoring thread to interrupt current thread. If this work or not diff --git a/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorEnvironment.java b/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorEnvironment.java new file mode 100644 index 00000000000..30e3abb5b27 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorEnvironment.java @@ -0,0 +1,41 @@ +package org.opentripplanner.raptor.api.request; + +import java.util.concurrent.ExecutorService; +import javax.annotation.Nullable; + +/** + * The raptor environment provides a few hooks and integration points to the caller. The default + * implementation will work just fine, override to adjust Raptor to the calling application. + */ +public interface RaptorEnvironment { + Runnable NOOP = () -> {}; + + /** + * Use the timeout-hook to register a callback from Raptor. The hook is called periodically to + * check if a time-out is reached. The hook should then exit with an exception handled by the + * caller. Raptor does not have blocking method calls so just calling {@link Thread#interrupt()} + * will not terminate the Raptor search. + */ + default Runnable timeoutHook() { + return NOOP; + } + + /** + * Raptor has support for running a few things in parallel. If Raptor catches an + * {@link InterruptedException}, Raptor will convert the checked exception to an unchecked + * exception. The default is {@link RuntimeException}. Override this method to map + * {@link InterruptedException} to your prefered runtime exception. + */ + default RuntimeException mapInterruptedException(InterruptedException e) { + return new RuntimeException(e); + } + + /** + * Inject a thread pool into Raptor to run part of the raptor search in parallel. If no + * thread pool is provided, then Raptor runs everything in the caller thread. + */ + @Nullable + default ExecutorService threadPool() { + return null; + } +} diff --git a/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorTuningParameters.java b/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorTuningParameters.java index d80c50ed7f5..a85fc3069f6 100644 --- a/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorTuningParameters.java +++ b/application/src/main/java/org/opentripplanner/raptor/api/request/RaptorTuningParameters.java @@ -20,11 +20,6 @@ default int iterationDepartureStepInSeconds() { return 60; } - /** see {@link org.opentripplanner.standalone.config.routerconfig.TransitRoutingConfig} **/ - default int searchThreadPoolSize() { - return 0; - } - /** * Coefficients used to calculate raptor-search-window parameters dynamically from heuristics. */ diff --git a/application/src/main/java/org/opentripplanner/raptor/api/view/ArrivalView.java b/application/src/main/java/org/opentripplanner/raptor/api/view/ArrivalView.java index 862f7f17fb6..2dffbbe5733 100644 --- a/application/src/main/java/org/opentripplanner/raptor/api/view/ArrivalView.java +++ b/application/src/main/java/org/opentripplanner/raptor/api/view/ArrivalView.java @@ -10,7 +10,6 @@ import org.opentripplanner.raptor.api.model.RaptorValueFormatter; import org.opentripplanner.raptor.api.model.TransitArrival; import org.opentripplanner.raptor.spi.RaptorCostCalculator; -import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.DefaultCostCalculator; /** * The purpose of the stop-arrival-view is to provide a common interface for stop-arrivals for @@ -157,7 +156,7 @@ default String asString() { String arrival = "[" + TimeUtils.timeToStrCompact(arrivalTime()) + - cost(c1(), DefaultCostCalculator.ZERO_COST, RaptorValueFormatter::formatC1) + + cost(c1(), RaptorCostCalculator.ZERO_COST, RaptorValueFormatter::formatC1) + cost(c2(), RaptorConstants.NOT_SET, RaptorValueFormatter::formatC2) + "]"; return switch (arrivedBy()) { diff --git a/application/src/main/java/org/opentripplanner/raptor/configure/RaptorConfig.java b/application/src/main/java/org/opentripplanner/raptor/configure/RaptorConfig.java index cc488448304..380f9fe3ba5 100644 --- a/application/src/main/java/org/opentripplanner/raptor/configure/RaptorConfig.java +++ b/application/src/main/java/org/opentripplanner/raptor/configure/RaptorConfig.java @@ -1,10 +1,8 @@ package org.opentripplanner.raptor.configure; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.annotation.Nullable; -import org.opentripplanner.framework.concurrent.OtpRequestThreadFactory; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; +import org.opentripplanner.raptor.api.request.RaptorEnvironment; import org.opentripplanner.raptor.api.request.RaptorRequest; import org.opentripplanner.raptor.api.request.RaptorTuningParameters; import org.opentripplanner.raptor.rangeraptor.DefaultRangeRaptorWorker; @@ -27,26 +25,26 @@ /** * This class is responsible for creating a new search and holding application scoped Raptor state. *

- * This class should have APPLICATION scope. It manage a threadPool, and hold a reference to the - * application tuning parameters. + * This class should have APPLICATION scope. It keeps a reference to the environment and the + * tuning parameters. The environment has a thread-pool, which should be APPLICATION scope. * * @param The TripSchedule type defined by the user of the raptor API. */ public class RaptorConfig { - private final ExecutorService threadPool; + private final RaptorEnvironment environment; private final RaptorTuningParameters tuningParameters; /** The service is not final, because it depends on the request. */ private PassThroughPointsService passThroughPointsService = null; - public RaptorConfig(RaptorTuningParameters tuningParameters) { + public RaptorConfig(RaptorTuningParameters tuningParameters, RaptorEnvironment environment) { this.tuningParameters = tuningParameters; - this.threadPool = createNewThreadPool(tuningParameters.searchThreadPoolSize()); + this.environment = environment; } public static RaptorConfig defaultConfigForTest() { - return new RaptorConfig<>(new RaptorTuningParameters() {}); + return new RaptorConfig<>(new RaptorTuningParameters() {}, new RaptorEnvironment() {}); } public SearchContext context(RaptorTransitDataProvider transit, RaptorRequest request) { @@ -114,19 +112,23 @@ public Heuristics createHeuristic( } public boolean isMultiThreaded() { - return threadPool != null; + return threadPool() != null; } public ExecutorService threadPool() { - return threadPool; + return environment.threadPool(); } public void shutdown() { - if (threadPool != null) { - threadPool.shutdown(); + if (threadPool() != null) { + threadPool().shutdown(); } } + public RuntimeException mapInterruptedException(InterruptedException e) { + return environment.mapInterruptedException(e); + } + public RaptorSearchWindowCalculator searchWindowCalculator() { return new RaptorSearchWindowCalculator(tuningParameters.dynamicSearchWindowCoefficients()); } @@ -164,14 +166,8 @@ private RangeRaptor createRangeRaptor(SearchContext ctx, RangeRaptorWorker ctx.roundTracker(), ctx.calculator(), ctx.createLifeCyclePublisher(), - ctx.performanceTimers() + ctx.performanceTimers(), + environment.timeoutHook() ); } - - @Nullable - private ExecutorService createNewThreadPool(int size) { - return size > 0 - ? Executors.newFixedThreadPool(size, OtpRequestThreadFactory.of("raptor-%d")) - : null; - } } diff --git a/application/src/main/java/org/opentripplanner/raptor/rangeraptor/RangeRaptor.java b/application/src/main/java/org/opentripplanner/raptor/rangeraptor/RangeRaptor.java index 02c39f9e52c..02fb2a627e9 100644 --- a/application/src/main/java/org/opentripplanner/raptor/rangeraptor/RangeRaptor.java +++ b/application/src/main/java/org/opentripplanner/raptor/rangeraptor/RangeRaptor.java @@ -2,7 +2,6 @@ import static java.util.Objects.requireNonNull; -import org.opentripplanner.framework.application.OTPRequestTimeoutException; import org.opentripplanner.raptor.api.debug.RaptorTimers; import org.opentripplanner.raptor.api.model.RaptorConstants; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; @@ -66,6 +65,8 @@ public final class RangeRaptor implements RaptorRo private final LifeCycleEventPublisher lifeCycle; + private final Runnable timeoutHook; + private final int minNumberOfRounds; public RangeRaptor( @@ -75,7 +76,8 @@ public RangeRaptor( RoundTracker roundTracker, RaptorTransitCalculator calculator, LifeCycleEventPublisher lifeCyclePublisher, - RaptorTimers timers + RaptorTimers timers, + Runnable timeoutHook ) { this.worker = requireNonNull(worker); this.transitData = requireNonNull(transitData); @@ -85,6 +87,7 @@ public RangeRaptor( this.minNumberOfRounds = accessPaths.calculateMaxNumberOfRides(); this.roundTracker = requireNonNull(roundTracker); this.lifeCycle = requireNonNull(lifeCyclePublisher); + this.timeoutHook = requireNonNull(timeoutHook); } public RaptorRouterResult route() { @@ -165,7 +168,7 @@ private int round() { * Run the raptor search for this particular iteration departure time */ private void setupIteration(int iterationDepartureTime) { - OTPRequestTimeoutException.checkForTimeout(); + timeoutHook.run(); roundTracker.setupIteration(); lifeCycle.prepareForNextRound(round()); lifeCycle.setupIteration(iterationDepartureTime); diff --git a/application/src/main/java/org/opentripplanner/raptor/rangeraptor/support/TimeBasedBoardingSupport.java b/application/src/main/java/org/opentripplanner/raptor/rangeraptor/support/TimeBasedBoardingSupport.java index 9ecd2bbf100..2b5c4694409 100644 --- a/application/src/main/java/org/opentripplanner/raptor/rangeraptor/support/TimeBasedBoardingSupport.java +++ b/application/src/main/java/org/opentripplanner/raptor/rangeraptor/support/TimeBasedBoardingSupport.java @@ -13,7 +13,6 @@ import org.opentripplanner.raptor.spi.RaptorConstrainedBoardingSearch; import org.opentripplanner.raptor.spi.RaptorTimeTable; import org.opentripplanner.raptor.spi.RaptorTripScheduleSearch; -import org.opentripplanner.routing.algorithm.raptoradapter.transit.request.TripScheduleBoardSearch; /** * This class contains code which is shared by all time-dependent {@link RoutingStrategy}s. @@ -119,9 +118,6 @@ private int earliestBoardTime(int prevArrivalTime, int boardSlack) { return calculator.plusDuration(prevArrivalTime, boardSlack); } - /** - * Create a trip search using {@link TripScheduleBoardSearch}. - */ private RaptorTripScheduleSearch createTripSearch(RaptorTimeTable timeTable) { if (!inFirstIteration && isFirstRound(round) && !hasTimeDependentAccess) { // For the first round of every iteration(except the first) we restrict the first diff --git a/application/src/main/java/org/opentripplanner/raptor/service/RangeRaptorDynamicSearch.java b/application/src/main/java/org/opentripplanner/raptor/service/RangeRaptorDynamicSearch.java index 5353804f414..c2a174d646a 100644 --- a/application/src/main/java/org/opentripplanner/raptor/service/RangeRaptorDynamicSearch.java +++ b/application/src/main/java/org/opentripplanner/raptor/service/RangeRaptorDynamicSearch.java @@ -11,7 +11,6 @@ import java.util.concurrent.Future; import java.util.stream.Collectors; import javax.annotation.Nullable; -import org.opentripplanner.framework.application.OTPRequestTimeoutException; import org.opentripplanner.raptor.RaptorService; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; import org.opentripplanner.raptor.api.request.RaptorRequest; @@ -182,10 +181,10 @@ private void runHeuristicsInParallel() { Thread.currentThread().interrupt(); // propagate interruption to the running task. asyncResult.cancel(true); - throw new OTPRequestTimeoutException(); + throw config.mapInterruptedException(e); } catch (ExecutionException e) { - if (e.getCause() instanceof DestinationNotReachedException) { - throw new DestinationNotReachedException(); + if (e.getCause() instanceof DestinationNotReachedException dnr) { + throw dnr; } LOG.error(e.getMessage() + ". Request: " + originalRequest, e); throw new IllegalStateException( diff --git a/application/src/main/java/org/opentripplanner/raptor/service/ViaRangeRaptorDynamicSearch.java b/application/src/main/java/org/opentripplanner/raptor/service/ViaRangeRaptorDynamicSearch.java index 4476e40464f..cfd12f65b3a 100644 --- a/application/src/main/java/org/opentripplanner/raptor/service/ViaRangeRaptorDynamicSearch.java +++ b/application/src/main/java/org/opentripplanner/raptor/service/ViaRangeRaptorDynamicSearch.java @@ -11,7 +11,6 @@ import java.util.concurrent.Future; import java.util.stream.Collectors; import javax.annotation.Nullable; -import org.opentripplanner.framework.application.OTPRequestTimeoutException; import org.opentripplanner.raptor.RaptorService; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; import org.opentripplanner.raptor.api.request.RaptorRequest; @@ -182,7 +181,7 @@ private void runHeuristicsInParallel() { Thread.currentThread().interrupt(); // propagate interruption to the running task. asyncResult.cancel(true); - throw new OTPRequestTimeoutException(); + throw config.mapInterruptedException(e); } catch (ExecutionException e) { if (e.getCause() instanceof DestinationNotReachedException) { throw new DestinationNotReachedException(); diff --git a/application/src/main/java/org/opentripplanner/raptor/spi/BoardAndAlightTime.java b/application/src/main/java/org/opentripplanner/raptor/spi/BoardAndAlightTime.java index 94744f4bd61..9c0f8264511 100644 --- a/application/src/main/java/org/opentripplanner/raptor/spi/BoardAndAlightTime.java +++ b/application/src/main/java/org/opentripplanner/raptor/spi/BoardAndAlightTime.java @@ -1,7 +1,8 @@ package org.opentripplanner.raptor.spi; import java.util.Objects; -import org.opentripplanner.framework.tostring.ValueObjectToStringBuilder; +import org.opentripplanner.framework.time.DurationUtils; +import org.opentripplanner.framework.time.TimeUtils; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; /** @@ -68,19 +69,18 @@ public boolean equals(Object o) { @Override public String toString() { - return ValueObjectToStringBuilder - .of() - .addText("[") - .addObj(trip.pattern().stopIndex(boardStopPos)) - .addText(" ~ ") - .addServiceTime(boardTime()) - .addText(" ") - .addServiceTime(alightTime()) - .addText("(") - .addDurationSec(alightTime() - boardTime()) - .addText(") ~ ") - .addObj(trip.pattern().stopIndex(alightStopPos)) - .addText("]") - .toString(); + return ( + "[" + + trip.pattern().stopIndex(boardStopPos) + + " ~ " + + TimeUtils.timeToStrCompact(boardTime()) + + " " + + TimeUtils.timeToStrCompact(alightTime()) + + "(" + + DurationUtils.durationToStr(alightTime() - boardTime()) + + ") ~ " + + trip.pattern().stopIndex(alightStopPos) + + "]" + ); } } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/router/TransitRouter.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/router/TransitRouter.java index e72d8ee1427..8040c16d800 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/router/TransitRouter.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/router/TransitRouter.java @@ -288,11 +288,10 @@ private Collection fetchAccessEgresses(AccessEgre } /** - * Given a list of {@code results} shift the access ones which contain driving - * so that they only start at the time when the ride hailing vehicle can actually be there - * to pick up passengers. + * Given a list of {@code results} shift the access ones that contain driving so that they only + * start at the time when the ride hailing vehicle can actually be there to pick up passengers. *

- * If there are accesses/egresses with only walking then they remain unchanged. + * If there are accesses/egresses with only walking, then they remain unchanged. *

* This method is a good candidate to be moved to the access/egress filter chain when that has * been added. diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/TripScheduleBoardSearch.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/TripScheduleBoardSearch.java index db08dd2dada..4ec306f84b3 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/TripScheduleBoardSearch.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/TripScheduleBoardSearch.java @@ -15,7 +15,7 @@ * trips are ordered after the FIRST stop boarding times. We also assume that trips do not pass each * other; Hence trips IN SERVICE on a given day will be in order for all other stops too. *

- * The search use a binary search if the number of trip schedules is above a given threshold. A + * The search uses a binary search if the number of trip schedules is above a given threshold. A * linear search is slow when the number of schedules is very large, let say more than 300 trip * schedules. * diff --git a/application/src/main/java/org/opentripplanner/standalone/config/configure/ConfigModule.java b/application/src/main/java/org/opentripplanner/standalone/config/configure/ConfigModule.java index b7d7084f7ba..4f75f3984d5 100644 --- a/application/src/main/java/org/opentripplanner/standalone/config/configure/ConfigModule.java +++ b/application/src/main/java/org/opentripplanner/standalone/config/configure/ConfigModule.java @@ -3,12 +3,14 @@ import dagger.Module; import dagger.Provides; import jakarta.inject.Singleton; +import org.opentripplanner.raptor.api.request.RaptorEnvironment; import org.opentripplanner.raptor.configure.RaptorConfig; import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripSchedule; import org.opentripplanner.standalone.config.BuildConfig; import org.opentripplanner.standalone.config.ConfigModel; import org.opentripplanner.standalone.config.OtpConfig; import org.opentripplanner.standalone.config.RouterConfig; +import org.opentripplanner.standalone.config.routerconfig.RaptorEnvironmentFactory; /** * Map {@link ConfigModel} into more specific types like {@link BuildConfig} to simplify @@ -34,7 +36,17 @@ static RouterConfig provideRouterConfig(ConfigModel model) { @Provides @Singleton - static RaptorConfig providesRaptorConfig(ConfigModel config) { - return new RaptorConfig<>(config.routerConfig().transitTuningConfig()); + static RaptorConfig providesRaptorConfig( + RouterConfig routerConfig, + RaptorEnvironment environment + ) { + return new RaptorConfig<>(routerConfig.transitTuningConfig(), environment); + } + + @Provides + @Singleton + static RaptorEnvironment providesRaptorEnvironment(RouterConfig routerConfig) { + int searchThreadPoolSize = routerConfig.transitTuningConfig().searchThreadPoolSize(); + return RaptorEnvironmentFactory.create(searchThreadPoolSize); } } diff --git a/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/RaptorEnvironmentFactory.java b/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/RaptorEnvironmentFactory.java new file mode 100644 index 00000000000..e2cd5d6dee7 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/RaptorEnvironmentFactory.java @@ -0,0 +1,41 @@ +package org.opentripplanner.standalone.config.routerconfig; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.annotation.Nullable; +import org.opentripplanner.framework.application.OTPRequestTimeoutException; +import org.opentripplanner.framework.concurrent.OtpRequestThreadFactory; +import org.opentripplanner.raptor.api.request.RaptorEnvironment; + +/** + * Create {@link RaptorEnvironment} from config and adapt it to the OTP application. + */ +public class RaptorEnvironmentFactory { + + public static RaptorEnvironment create(final int threadPoolSize) { + return new RaptorEnvironment() { + @Override + public Runnable timeoutHook() { + return OTPRequestTimeoutException::checkForTimeout; + } + + /** + * OTP web server will interrupt all request threads in case of a timeout. In OTP + * such events should be mapped to {@link OTPRequestTimeoutException}, witch will + * later be mapped to the right API response. + */ + @Override + public RuntimeException mapInterruptedException(InterruptedException e) { + return new OTPRequestTimeoutException(); + } + + @Nullable + @Override + public ExecutorService threadPool() { + return threadPoolSize > 0 + ? Executors.newFixedThreadPool(threadPoolSize, OtpRequestThreadFactory.of("raptor-%d")) + : null; + } + }; + } +} diff --git a/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/TransitRoutingConfig.java b/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/TransitRoutingConfig.java index 34465cff27a..74dbfd4bab9 100644 --- a/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/TransitRoutingConfig.java +++ b/application/src/main/java/org/opentripplanner/standalone/config/routerconfig/TransitRoutingConfig.java @@ -112,7 +112,7 @@ public TransitRoutingConfig( no extra threads are started and the search is done in one thread. """ ) - .asInt(dft.searchThreadPoolSize()); + .asInt(0); // Dynamic Search Window this.stopBoardAlightDuringTransferCost = c @@ -244,7 +244,6 @@ public int iterationDepartureStepInSeconds() { return iterationDepartureStepInSeconds; } - @Override public int searchThreadPoolSize() { return searchThreadPoolSize; } diff --git a/application/src/test/java/org/opentripplanner/TestServerContext.java b/application/src/test/java/org/opentripplanner/TestServerContext.java index 04a222c4434..fd9d75def75 100644 --- a/application/src/test/java/org/opentripplanner/TestServerContext.java +++ b/application/src/test/java/org/opentripplanner/TestServerContext.java @@ -19,6 +19,7 @@ import org.opentripplanner.service.worldenvelope.model.WorldEnvelope; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.opentripplanner.standalone.config.RouterConfig; +import org.opentripplanner.standalone.config.routerconfig.RaptorEnvironmentFactory; import org.opentripplanner.standalone.server.DefaultServerRequestContext; import org.opentripplanner.street.model.StreetLimitationParameters; import org.opentripplanner.street.service.DefaultStreetLimitationParametersService; @@ -42,7 +43,10 @@ public static OtpServerRequestContext createServerContext( DefaultServerRequestContext context = DefaultServerRequestContext.create( routerConfig.transitTuningConfig(), routerConfig.routingRequestDefaults(), - new RaptorConfig<>(routerConfig.transitTuningConfig()), + new RaptorConfig<>( + routerConfig.transitTuningConfig(), + RaptorEnvironmentFactory.create(routerConfig.transitTuningConfig().searchThreadPoolSize()) + ), graph, new DefaultTransitService(timetableRepository), Metrics.globalRegistry, diff --git a/application/src/test/java/org/opentripplanner/transit/speed_test/SpeedTest.java b/application/src/test/java/org/opentripplanner/transit/speed_test/SpeedTest.java index 38fb11712b8..c1d0ac781f4 100644 --- a/application/src/test/java/org/opentripplanner/transit/speed_test/SpeedTest.java +++ b/application/src/test/java/org/opentripplanner/transit/speed_test/SpeedTest.java @@ -29,6 +29,7 @@ import org.opentripplanner.standalone.config.BuildConfig; import org.opentripplanner.standalone.config.ConfigModel; import org.opentripplanner.standalone.config.OtpConfigLoader; +import org.opentripplanner.standalone.config.routerconfig.RaptorEnvironmentFactory; import org.opentripplanner.standalone.config.routerconfig.VectorTileConfig; import org.opentripplanner.standalone.server.DefaultServerRequestContext; import org.opentripplanner.transit.service.DefaultTransitService; @@ -108,7 +109,10 @@ public SpeedTest( DefaultServerRequestContext.create( config.transitRoutingParams, config.request, - new RaptorConfig<>(config.transitRoutingParams), + new RaptorConfig<>( + config.transitRoutingParams, + RaptorEnvironmentFactory.create(config.transitRoutingParams.searchThreadPoolSize()) + ), graph, new DefaultTransitService(timetableRepository), timer.getRegistry(),