Class Restate
This is the entry point for the new reflection-based API where services are defined using annotations and methods can access Restate features through static methods on this class.
Example Usage
@Service
public class Greeter {
@Handler
public String greet(String input) {
// Use Restate features via static methods
String result = Restate.run(
"external-call",
String.class,
() -> externalService.call(input)
);
return "You said hi to " + req.name + "!";
}
}
Error handling
All methods of this class throws eitherTerminalException or AbortedExecutionException, where the former can be caught and acted upon, while the latter MUST
NOT be caught, but simply propagated for clean up purposes.
Serialization and Deserialization
The methods of this class that need to serialize or deserialize payloads have an overload both acceptingClass or TypeTag. Depending on your case, you might use the Class overload for simple types, and TypeRef for generic types.
By default, Jackson Databind will be used for all serialization/deserialization. Check SerdeFactory for more details on how to customize that.
Thread safety
This class MUST NOT be accessed concurrently since it can lead to different orderings of user actions, corrupting the execution of the invocation.- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceEXPERIMENTAL API: Interface to interact with this Virtual Object/Workflow state. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic <T> Awakeable<T> Create anAwakeable, addressable throughAwakeable.id().static <T> Awakeable<T> Create anAwakeable, addressable throughAwakeable.id().static AwakeableHandleCreate a newAwakeableHandlefor the provided identifier.static InstantReturns the current time as a deterministicInstant.static InvocationHandle<Slice> invocationHandle(String invocationId) LikeinvocationHandle(String, Class), without providing a response parserstatic <R> InvocationHandle<R> invocationHandle(String invocationId, TypeTag<R> responseTypeTag) static <R> InvocationHandle<R> invocationHandle(String invocationId, Class<R> responseClazz) Get anInvocationHandlefor an already existing invocation.static Stringkey()EXPERIMENTAL APIstatic <T> DurablePromise<T> promise(DurablePromiseKey<T> key) EXPERIMENTAL API: Create aDurablePromisefor the given key.static <T> DurablePromiseHandle<T> promiseHandle(DurablePromiseKey<T> key) EXPERIMENTAL API: Create a newDurablePromiseHandlefor the provided key.static RestateRandomrandom()Returns a deterministic random.static HandlerRequestrequest()static voidrun(String name, ThrowingRunnable runnable) Likerun(String, Class, ThrowingSupplier)without output.static voidrun(String name, RetryPolicy retryPolicy, ThrowingRunnable runnable) Likerun(String, ThrowingRunnable), but without a return value and using a custom retry policy.static <T> Trun(String name, TypeTag<T> typeTag, ThrowingSupplier<T> action) Likerun(String, Class, ThrowingSupplier), but providing aTypeTag.static <T> Trun(String name, TypeTag<T> typeTag, RetryPolicy retryPolicy, ThrowingSupplier<T> action) Likerun(String, TypeTag, ThrowingSupplier), but using a custom retry policy.static <T> Trun(String name, Class<T> clazz, ThrowingSupplier<T> action) Execute a closure, recording the result value in the journal.static <T> Trun(String name, Class<T> clazz, RetryPolicy retryPolicy, ThrowingSupplier<T> action) Likerun(String, Class, ThrowingSupplier), but using a custom retry policy.static DurableFuture<Void> runAsync(String name, ThrowingRunnable runnable) LikerunAsync(String, Class, ThrowingSupplier)without output.static DurableFuture<Void> runAsync(String name, RetryPolicy retryPolicy, ThrowingRunnable runnable) LikerunAsync(String, Class, ThrowingSupplier), but without an output and using a custom retry policy.static <T> DurableFuture<T> runAsync(String name, TypeTag<T> typeTag, ThrowingSupplier<T> action) LikerunAsync(String, Class, ThrowingSupplier), but providing aTypeTag.static <T> DurableFuture<T> runAsync(String name, TypeTag<T> typeTag, RetryPolicy retryPolicy, ThrowingSupplier<T> action) LikerunAsync(String, TypeTag, ThrowingSupplier), but using a custom retry policy.static <T> DurableFuture<T> runAsync(String name, Class<T> clazz, ThrowingSupplier<T> action) Execute a closure asynchronously.static <T> DurableFuture<T> runAsync(String name, Class<T> clazz, RetryPolicy retryPolicy, ThrowingSupplier<T> action) LikerunAsync(String, Class, ThrowingSupplier), but using a custom retry policy.static <SVC> SVCEXPERIMENTAL API: Simple API to invoke a Restate service.static <SVC> ServiceHandle<SVC> serviceHandle(Class<SVC> clazz) EXPERIMENTAL API: Advanced API to invoke a Restate service with full control.static voidCauses the current execution of the function invocation to sleep for the given duration.static Restate.Statestate()EXPERIMENTAL API: Access to this Virtual Object/Workflow state.static DurableFuture<Void> Causes the start of a timer for the given duration.static <SVC> SVCvirtualObject(Class<SVC> clazz, String key) EXPERIMENTAL API: Simple API to invoke a Restate Virtual Object.static <SVC> ServiceHandle<SVC> virtualObjectHandle(Class<SVC> clazz, String key) EXPERIMENTAL API: Advanced API to invoke a Restate Virtual Object with full control.static <SVC> SVCEXPERIMENTAL API: Simple API to invoke a Restate Workflow.static <SVC> ServiceHandle<SVC> workflowHandle(Class<SVC> clazz, String key) EXPERIMENTAL API: Advanced API to invoke a Restate Workflow with full control.
-
Constructor Details
-
Restate
public Restate()
-
-
Method Details
-
request
- See Also:
-
random
Returns a deterministic random.- See Also:
-
instantNow
Returns the current time as a deterministicInstant.This method returns the current timestamp in a way that is consistent across replays. The time is captured using
run(java.lang.String, java.lang.Class<T>, dev.restate.common.function.ThrowingSupplier<T>), ensuring that the same value is returned during replay as was returned during the original execution.- Returns:
- the recorded
Instant - See Also:
-
invocationHandle
@Experimental public static <R> InvocationHandle<R> invocationHandle(String invocationId, TypeTag<R> responseTypeTag) - See Also:
-
invocationHandle
@Experimental public static <R> InvocationHandle<R> invocationHandle(String invocationId, Class<R> responseClazz) Get anInvocationHandlefor an already existing invocation. This will let you interact with a running invocation, for example to cancel it or retrieve its result.- Parameters:
invocationId- The invocation to interact with.responseClazz- The response class.- See Also:
-
invocationHandle
LikeinvocationHandle(String, Class), without providing a response parser- See Also:
-
sleep
Causes the current execution of the function invocation to sleep for the given duration.- Parameters:
duration- for which to sleep.- See Also:
-
timer
Causes the start of a timer for the given duration. You can await on the timer end by invokingDurableFuture.await().- Parameters:
name- name used for observabilityduration- for which to sleep.- See Also:
-
run
@Experimental public static <T> T run(String name, Class<T> clazz, ThrowingSupplier<T> action) throws TerminalException Execute a closure, recording the result value in the journal. The result value will be re-played in case of re-invocation (e.g. because of failure recovery or suspension point) without re-executing the closure.If the result type contains generic types, e.g. a
List<String>, you should userun(String, TypeTag, ThrowingSupplier). SeeContextfor more details about serialization and deserialization.You can name this closure using the
nameparameter. This name will be available in the observability tools.The closure should tolerate retries, that is Restate might re-execute the closure multiple times until it records a result. You can control and limit the amount of retries using
run(String, Class, RetryPolicy, ThrowingSupplier).Error handling: Errors occurring within this closure won't be propagated to the caller, unless they are
TerminalException. To propagate run failures to the call-site, make sure to wrap them inTerminalException.- Type Parameters:
T- type of the return value.- Parameters:
name- name of the side effect.clazz- the class of the return value, used to serialize/deserialize it.action- closure to execute.- Returns:
- value of the run operation.
- Throws:
TerminalException- See Also:
-
run
@Experimental public static <T> T run(String name, TypeTag<T> typeTag, RetryPolicy retryPolicy, ThrowingSupplier<T> action) throws TerminalException Likerun(String, TypeTag, ThrowingSupplier), but using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
run
@Experimental public static <T> T run(String name, Class<T> clazz, RetryPolicy retryPolicy, ThrowingSupplier<T> action) throws TerminalException Likerun(String, Class, ThrowingSupplier), but using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
run
@Experimental public static <T> T run(String name, TypeTag<T> typeTag, ThrowingSupplier<T> action) throws TerminalException Likerun(String, Class, ThrowingSupplier), but providing aTypeTag.See
Contextfor more details about serialization and deserialization.- Throws:
TerminalException- See Also:
-
run
@Experimental public static void run(String name, RetryPolicy retryPolicy, ThrowingRunnable runnable) throws TerminalException Likerun(String, ThrowingRunnable), but without a return value and using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
run
@Experimental public static void run(String name, ThrowingRunnable runnable) throws TerminalException Likerun(String, Class, ThrowingSupplier)without output.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static <T> DurableFuture<T> runAsync(String name, Class<T> clazz, ThrowingSupplier<T> action) throws TerminalException Execute a closure asynchronously. This is likerun(String, Class, ThrowingSupplier), but it returns aDurableFuturethat you can combine and select.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static <T> DurableFuture<T> runAsync(String name, TypeTag<T> typeTag, ThrowingSupplier<T> action) throws TerminalException LikerunAsync(String, Class, ThrowingSupplier), but providing aTypeTag.See
Contextfor more details about serialization and deserialization.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static <T> DurableFuture<T> runAsync(String name, Class<T> clazz, RetryPolicy retryPolicy, ThrowingSupplier<T> action) throws TerminalException LikerunAsync(String, Class, ThrowingSupplier), but using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static <T> DurableFuture<T> runAsync(String name, TypeTag<T> typeTag, RetryPolicy retryPolicy, ThrowingSupplier<T> action) throws TerminalException LikerunAsync(String, TypeTag, ThrowingSupplier), but using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static DurableFuture<Void> runAsync(String name, RetryPolicy retryPolicy, ThrowingRunnable runnable) throws TerminalException LikerunAsync(String, Class, ThrowingSupplier), but without an output and using a custom retry policy.When a retry policy is not specified, the
runwill be retried using the Restate invoker retry policy, which by default retries indefinitely.- Throws:
TerminalException- See Also:
-
runAsync
@Experimental public static DurableFuture<Void> runAsync(String name, ThrowingRunnable runnable) throws TerminalException LikerunAsync(String, Class, ThrowingSupplier)without output.- Throws:
TerminalException- See Also:
-
awakeable
Create anAwakeable, addressable throughAwakeable.id().You can use this feature to implement external asynchronous systems interactions, for example you can send a Kafka record including the
Awakeable.id(), and then let another service consume from Kafka the responses of given external system interaction by usingawakeableHandle(String).- Parameters:
clazz- the response type to use for deserializing theAwakeableresult. When using generic types, useawakeable(TypeTag)instead.- Returns:
- the
Awakeableto await on. - See Also:
-
awakeable
Create anAwakeable, addressable throughAwakeable.id().You can use this feature to implement external asynchronous systems interactions, for example you can send a Kafka record including the
Awakeable.id(), and then let another service consume from Kafka the responses of given external system interaction by usingawakeableHandle(String). -
awakeableHandle
Create a newAwakeableHandlefor the provided identifier. You can use it toAwakeableHandle.resolve(TypeTag, Object)orAwakeableHandle.reject(String)the linkedAwakeable.- See Also:
-
service
EXPERIMENTAL API: Simple API to invoke a Restate service.Create a proxy client that allows calling service methods directly and synchronously. This is the recommended approach for straightforward request-response interactions.
var greeterProxy = Restate.service(Greeter.class); GreetingResponse response = greeterProxy.greet(new Greeting("Alice"));For advanced use cases requiring asynchronous request handling, composable futures, or invocation options (such as idempotency keys), use
serviceHandle(Class)instead.- Parameters:
clazz- the service class annotated withService- Returns:
- a proxy client to invoke the service
-
serviceHandle
EXPERIMENTAL API: Advanced API to invoke a Restate service with full control.Create a handle that provides advanced invocation capabilities including:
- Composable futures for asynchronous request handling
- Invocation options such as
InvocationOptions.idempotencyKey(String) - Fire-and-forget requests via
send() - Deferred response handling
// 1. Use call() with method reference and await the result GreetingResponse response = Restate.serviceHandle(Greeter.class) .call(Greeter::greet, new Greeting("Alice")) .await(); // 2. Use send() for one-way invocation without waiting InvocationHandle<GreetingResponse> handle = Restate.serviceHandle(Greeter.class) .send(Greeter::greet, new Greeting("Alice"));For simple synchronous request-response interactions, consider using
service(Class)instead.- Parameters:
clazz- the service class annotated withService- Returns:
- a handle to invoke the service with advanced options
-
virtualObject
EXPERIMENTAL API: Simple API to invoke a Restate Virtual Object.Create a proxy client that allows calling virtual object methods directly and synchronously. This is the recommended approach for straightforward request-response interactions.
var counterProxy = Restate.virtualObject(Counter.class, "my-counter"); int count = counterProxy.increment();For advanced use cases requiring asynchronous request handling, composable futures, or invocation options (such as idempotency keys), use
virtualObjectHandle(Class, String)instead.- Parameters:
clazz- the virtual object class annotated withVirtualObjectkey- the key identifying the specific virtual object instance- Returns:
- a proxy client to invoke the virtual object
-
virtualObjectHandle
@Experimental public static <SVC> ServiceHandle<SVC> virtualObjectHandle(Class<SVC> clazz, String key) EXPERIMENTAL API: Advanced API to invoke a Restate Virtual Object with full control.Create a handle that provides advanced invocation capabilities including:
- Composable futures for asynchronous request handling
- Invocation options such as
InvocationOptions.idempotencyKey(String) - Fire-and-forget requests via
send() - Deferred response handling
// 1. Use call() with method reference and await the result int count = Restate.virtualObjectHandle(Counter.class, "my-counter") .call(Counter::increment) .await(); // 2. Use send() for one-way invocation without waiting InvocationHandle<Integer> handle = Restate.virtualObjectHandle(Counter.class, "my-counter") .send(Counter::increment);For simple synchronous request-response interactions, consider using
virtualObject(Class, String)instead.- Parameters:
clazz- the virtual object class annotated withVirtualObjectkey- the key identifying the specific virtual object instance- Returns:
- a handle to invoke the virtual object with advanced options
-
workflow
EXPERIMENTAL API: Simple API to invoke a Restate Workflow.Create a proxy client that allows calling workflow methods directly and synchronously. This is the recommended approach for straightforward request-response interactions.
var workflowProxy = Restate.workflow(OrderWorkflow.class, "order-123"); workflowProxy.start(new OrderRequest(...));For advanced use cases requiring asynchronous request handling, composable futures, or invocation options (such as idempotency keys), use
workflowHandle(Class, String)instead.- Parameters:
clazz- the workflow class annotated withWorkflowkey- the key identifying the specific workflow instance- Returns:
- a proxy client to invoke the workflow
-
workflowHandle
EXPERIMENTAL API: Advanced API to invoke a Restate Workflow with full control.Create a handle that provides advanced invocation capabilities including:
- Composable futures for asynchronous request handling
- Invocation options such as
InvocationOptions.idempotencyKey(String) - Fire-and-forget requests via
send() - Deferred response handling
// 1. Use call() with method reference and await the result Restate.workflowHandle(OrderWorkflow.class, "order-123") .call(OrderWorkflow::start, new OrderRequest(...)) .await(); // 2. Use send() for one-way invocation without waiting InvocationHandle<Void> handle = Restate.workflowHandle(OrderWorkflow.class, "order-123") .send(OrderWorkflow::start, new OrderRequest(...));For simple synchronous request-response interactions, consider using
workflow(Class, String)instead.- Parameters:
clazz- the workflow class annotated withWorkflowkey- the key identifying the specific workflow instance- Returns:
- a handle to invoke the workflow with advanced options
-
key
EXPERIMENTAL API- Returns:
- this Virtual Object/Workflow key
- Throws:
IllegalStateException- if called from a regular Service handler.
-
state
EXPERIMENTAL API: Access to this Virtual Object/Workflow state.- Returns:
Restate.Statefor this Virtual Object/Workflow- Throws:
IllegalStateException- if called from a regular Service handler.
-
promise
EXPERIMENTAL API: Create aDurablePromisefor the given key.You can use this feature to implement interaction between different workflow handlers, e.g. to send a signal from a shared handler to the workflow handler.
- Returns:
- the
DurablePromise. - Throws:
IllegalStateException- if called from a non-Workflow handler- See Also:
-
promiseHandle
EXPERIMENTAL API: Create a newDurablePromiseHandlefor the provided key. You can use it toDurablePromiseHandle.resolve(Object)orDurablePromiseHandle.reject(String)the givenDurablePromise.- Throws:
IllegalStateException- if called from a non-Workflow handler- See Also:
-