Skip to content

Commit e933876

Browse files
New executor defaults for handler runner
1 parent d48e074 commit e933876

1 file changed

Lines changed: 27 additions & 12 deletions

File tree

sdk-api/src/main/java/dev/restate/sdk/HandlerRunner.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
package dev.restate.sdk;
1010

1111
import dev.restate.common.Slice;
12-
import dev.restate.common.function.ThrowingBiConsumer;
13-
import dev.restate.common.function.ThrowingBiFunction;
14-
import dev.restate.common.function.ThrowingConsumer;
15-
import dev.restate.common.function.ThrowingFunction;
12+
import dev.restate.common.function.*;
1613
import dev.restate.sdk.common.TerminalException;
1714
import dev.restate.sdk.endpoint.definition.HandlerContext;
1815
import dev.restate.sdk.internal.ContextThreadLocal;
@@ -22,6 +19,7 @@
2219
import java.util.Objects;
2320
import java.util.concurrent.CompletableFuture;
2421
import java.util.concurrent.Executor;
22+
import java.util.concurrent.ExecutorService;
2523
import java.util.concurrent.Executors;
2624
import java.util.concurrent.atomic.AtomicReference;
2725
import org.apache.logging.log4j.LogManager;
@@ -182,25 +180,42 @@ public static <CTX extends Context> HandlerRunner<Void, Void> of(
182180
public static final class Options
183181
implements dev.restate.sdk.endpoint.definition.HandlerRunner.Options {
184182
/**
185-
* Default options will use a {@link Executors#newCachedThreadPool()} shared among all the
186-
* {@link HandlerRunner} instances.
183+
* Default options will use virtual threads on Java 21+, or fallback to {@link
184+
* Executors#newCachedThreadPool()} for Java &lt; 21. The bounded pool is shared among all {@link
185+
* HandlerRunner} instances, and is used by {@link Restate#run}/{@link Context#run} as well.
187186
*/
188-
public static final Options DEFAULT = new Options(Executors.newCachedThreadPool());
187+
public static final Options DEFAULT = new Options(createDefaultExecutor());
189188

190189
private final Executor executor;
191190

192-
/**
193-
* You can run on virtual threads by using the executor {@code
194-
* Executors.newVirtualThreadPerTaskExecutor()}.
195-
*/
196191
private Options(Executor executor) {
197192
this.executor = executor;
198193
}
199194

200-
/** Copy this options setting the given {@code executor}. */
195+
/**
196+
* Create an instance of {@link Options} with the given {@code executor}.
197+
*
198+
* <p>The given executor is used for running the handler code, and {@link Restate#run}/{@link
199+
* Context#run} as well.
200+
*/
201201
public static Options withExecutor(Executor executor) {
202202
return new Options(executor);
203203
}
204+
205+
private static ExecutorService createDefaultExecutor() {
206+
// Try to use virtual threads if available (Java 21+)
207+
try {
208+
return (ExecutorService)
209+
Executors.class.getMethod("newVirtualThreadPerTaskExecutor").invoke(null);
210+
} catch (Exception e) {
211+
LOG.debug(
212+
"Virtual threads not available, using unbounded thread pool. "
213+
+ "If you need to customize the thread pool used by your restate handlers, "
214+
+ "use HandlerRunner.Options.withExecutor() with Endpoint.bind()");
215+
216+
return Executors.newCachedThreadPool();
217+
}
218+
}
204219
}
205220

206221
static HandlerContext getHandlerContext() {

0 commit comments

Comments
 (0)