diff --git a/examples/src/main/java/my/restate/sdk/examples/LoanWorkflow.java b/examples/src/main/java/my/restate/sdk/examples/LoanWorkflow.java index d59ddd5a..5a6c84a9 100644 --- a/examples/src/main/java/my/restate/sdk/examples/LoanWorkflow.java +++ b/examples/src/main/java/my/restate/sdk/examples/LoanWorkflow.java @@ -103,7 +103,7 @@ public void run(WorkflowContext ctx, LoanRequest loanRequest) { LOG.info("Loan request submitted"); // 2. Ask human approval - ctx.sideEffect(() -> askHumanApproval(ctx.workflowKey())); + ctx.run(() -> askHumanApproval(ctx.workflowKey())); ctx.set(STATUS, Status.WAITING_HUMAN_APPROVAL); // 3. Wait human approval diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt index 019e60c2..8a0e3dda 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt @@ -130,10 +130,7 @@ internal class ContextImpl internal constructor(private val syscalls: Syscalls) } } - override suspend fun sideEffect( - serde: Serde, - sideEffectAction: suspend () -> T - ): T { + override suspend fun run(serde: Serde, sideEffectAction: suspend () -> T): T { val exitResult = suspendCancellableCoroutine { cont: CancellableContinuation> -> diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt index f3de91e9..c7458179 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt @@ -17,8 +17,8 @@ import kotlin.time.Duration /** * This interface exposes the Restate functionalities to Restate services. It can be used to - * interact with other Restate services, record side effects, execute timers and synchronize with - * external systems. + * interact with other Restate services, record non-deterministic closures, execute timers and + * synchronize with external systems. * * To use it within your Restate service, implement [RestateKtComponent] and get an instance with * [RestateKtComponent.restateContext]. @@ -114,9 +114,9 @@ sealed interface Context { * Errors occurring within this closure won't be propagated to the caller, unless they are * [TerminalException]. Consider the following code: * ``` - * // Bad usage of try-catch outside the side effect + * // Bad usage of try-catch outside the run * try { - * ctx.sideEffect { + * ctx.run { * throw IllegalStateException(); * }; * } catch (e: IllegalStateException) { @@ -125,9 +125,9 @@ sealed interface Context { * // following the invocation retry policy. * } * - * // Good usage of try-catch outside the side effect + * // Good usage of try-catch outside the run * try { - * ctx.sideEffect { + * ctx.run { * throw TerminalException("my error"); * }; * } catch (e: TerminalException) { @@ -135,19 +135,18 @@ sealed interface Context { * } * ``` * - * To propagate side effects failures to the side effect call-site, make sure to wrap them in - * [TerminalException]. + * To propagate failures to the run call-site, make sure to wrap them in [TerminalException]. * * @param serde the type tag of the return value, used to serialize/deserialize it. - * @param action to execute for its side effects. + * @param action closure to execute. * @param T type of the return value. - * @return value of the side effect operation. + * @return value of the run operation. */ - suspend fun sideEffect(serde: Serde, sideEffectAction: suspend () -> T): T + suspend fun run(serde: Serde, sideEffectAction: suspend () -> T): T - /** Like [sideEffect] without a return value. */ - suspend fun sideEffect(sideEffectAction: suspend () -> Unit) { - sideEffect(KtSerdes.UNIT, sideEffectAction) + /** Like [run] without a return value. */ + suspend fun run(sideEffectAction: suspend () -> Unit) { + run(KtSerdes.UNIT, sideEffectAction) } /** @@ -177,9 +176,9 @@ sealed interface Context { * * This instance is useful to generate identifiers, idempotency keys, and for uniform sampling * from a set of options. If a cryptographically secure value is needed, please generate that - * externally using [sideEffect]. + * externally using [run]. * - * You MUST NOT use this [Random] instance inside a [sideEffect]. + * You MUST NOT use this [Random] instance inside a [run]. * * @return the [Random] instance. */ @@ -234,7 +233,7 @@ class RestateRandom(seed: Long, private val syscalls: Syscalls) : Random() { private val r = Random(seed) override fun nextBits(bitCount: Int): Int { - check(!syscalls.isInsideSideEffect) { "You can't use RestateRandom inside a side effect!" } + check(!syscalls.isInsideSideEffect) { "You can't use RestateRandom inside ctx.run!" } return r.nextBits(bitCount) } diff --git a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/RandomTest.kt b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/RandomTest.kt index a11b6329..f2505fbc 100644 --- a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/RandomTest.kt +++ b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/RandomTest.kt @@ -21,7 +21,7 @@ class RandomTest : RandomTestSuite() { override fun randomInsideSideEffect(): TestInvocationBuilder = testDefinitionForService("RandomInsideSideEffect") { ctx, _: Unit -> - ctx.sideEffect { ctx.random().nextInt() } + ctx.run { ctx.random().nextInt() } throw IllegalStateException("This should not unreachable") } diff --git a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/SideEffectTest.kt b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/SideEffectTest.kt index d1b037e0..bd844f82 100644 --- a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/SideEffectTest.kt +++ b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/SideEffectTest.kt @@ -23,15 +23,15 @@ class SideEffectTest : SideEffectTestSuite() { override fun sideEffect(sideEffectOutput: String): TestInvocationBuilder = testDefinitionForService("SideEffect") { ctx, _: Unit -> - val result = ctx.sideEffect(CoreSerdes.JSON_STRING) { sideEffectOutput } + val result = ctx.run(CoreSerdes.JSON_STRING) { sideEffectOutput } "Hello $result" } override fun consecutiveSideEffect(sideEffectOutput: String): TestInvocationBuilder = testDefinitionForService("ConsecutiveSideEffect") { ctx, _: Unit -> - val firstResult = ctx.sideEffect(CoreSerdes.JSON_STRING) { sideEffectOutput } + val firstResult = ctx.run(CoreSerdes.JSON_STRING) { sideEffectOutput } val secondResult = - ctx.sideEffect(CoreSerdes.JSON_STRING) { firstResult.uppercase(Locale.getDefault()) } + ctx.run(CoreSerdes.JSON_STRING) { firstResult.uppercase(Locale.getDefault()) } "Hello $secondResult" } @@ -43,9 +43,7 @@ class SideEffectTest : SideEffectTestSuite() { Dispatchers.Unconfined + CoroutineName("CheckContextSwitchingTestCoroutine"))) { handler("run") { ctx, _: Unit -> val sideEffectCoroutine = - ctx.sideEffect(CoreSerdes.JSON_STRING) { - coroutineContext[CoroutineName]!!.name - } + ctx.run(CoreSerdes.JSON_STRING) { coroutineContext[CoroutineName]!!.name } check(sideEffectCoroutine == "CheckContextSwitchingTestCoroutine") { "Side effect thread is not running within the same coroutine context of the handler method: $sideEffectCoroutine" } @@ -56,7 +54,7 @@ class SideEffectTest : SideEffectTestSuite() { override fun sideEffectGuard(): TestInvocationBuilder = testDefinitionForService("SideEffectGuard") { ctx, _: Unit -> - ctx.sideEffect { ctx.send(GREETER_SERVICE_TARGET, KtSerdes.json(), "something") } + ctx.run { ctx.send(GREETER_SERVICE_TARGET, KtSerdes.json(), "something") } throw IllegalStateException("This point should not be reached") } } diff --git a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/StateMachineFailuresTest.kt b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/StateMachineFailuresTest.kt index fac7654d..b395f329 100644 --- a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/StateMachineFailuresTest.kt +++ b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/StateMachineFailuresTest.kt @@ -47,7 +47,7 @@ class StateMachineFailuresTest : StateMachineFailuresTestSuite() { override fun sideEffectFailure(serde: Serde): TestInvocationBuilder = testDefinitionForService("SideEffectFailure") { ctx, _: Unit -> - ctx.sideEffect(serde) { 0 } + ctx.run(serde) { 0 } "Francesco" } } diff --git a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/UserFailuresTest.kt b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/UserFailuresTest.kt index a4a06a34..6bc77151 100644 --- a/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/UserFailuresTest.kt +++ b/sdk-api-kotlin/src/test/kotlin/dev/restate/sdk/kotlin/UserFailuresTest.kt @@ -26,7 +26,7 @@ class UserFailuresTest : UserFailuresTestSuite() { ): TestInvocationBuilder = testDefinitionForService("SideEffectThrowIllegalStateException") { ctx, _: Unit -> try { - ctx.sideEffect { throw IllegalStateException("Whatever") } + ctx.run { throw IllegalStateException("Whatever") } } catch (e: Throwable) { if (e !is CancellationException && e !is TerminalException) { nonTerminalExceptionsSeen.addAndGet(1) @@ -44,7 +44,7 @@ class UserFailuresTest : UserFailuresTestSuite() { override fun sideEffectThrowTerminalException(code: Int, message: String): TestInvocationBuilder = testDefinitionForService("SideEffectThrowTerminalException") { ctx, _: Unit -> - ctx.sideEffect { throw TerminalException(code, message) } + ctx.run { throw TerminalException(code, message) } throw IllegalStateException("Not expected to reach this point") } } diff --git a/sdk-api/src/main/java/dev/restate/sdk/Context.java b/sdk-api/src/main/java/dev/restate/sdk/Context.java index 85a2a781..171b5d3e 100644 --- a/sdk-api/src/main/java/dev/restate/sdk/Context.java +++ b/sdk-api/src/main/java/dev/restate/sdk/Context.java @@ -15,8 +15,8 @@ /** * This interface exposes the Restate functionalities to Restate services. It can be used to - * interact with other Restate services, record side effects, execute timers and synchronize with - * external systems. + * interact with other Restate services, record non-deterministic closures, execute timers and + * synchronize with external systems. * *

All methods of this interface, and related interfaces, throws either {@link TerminalException} * or {@link AbortedExecutionException}, where the former can be caught and acted upon, while the @@ -109,9 +109,9 @@ default void sleep(Duration duration) { * TerminalException}. Consider the following code: * *

{@code
-   * // Bad usage of try-catch outside the side effect
+   * // Bad usage of try-catch outside the run
    * try {
-   *     ctx.sideEffect(() -> {
+   *     ctx.run(() -> {
    *         throw new IllegalStateException();
    *     });
    * } catch (IllegalStateException e) {
@@ -120,9 +120,9 @@ default void sleep(Duration duration) {
    *     // following the invocation retry policy.
    * }
    *
-   * // Good usage of try-catch outside the side effect
+   * // Good usage of try-catch outside the run
    * try {
-   *     ctx.sideEffect(() -> {
+   *     ctx.run(() -> {
    *         throw new TerminalException("my error");
    *     });
    * } catch (TerminalException e) {
@@ -130,19 +130,19 @@ default void sleep(Duration duration) {
    * }
    * }
* - * To propagate side effects failures to the side effect call-site, make sure to wrap them in - * {@link TerminalException}. + * To propagate run failures to the call-site, make sure to wrap them in {@link + * TerminalException}. * * @param serde the type tag of the return value, used to serialize/deserialize it. - * @param action to execute for its side effects. + * @param action closure to execute. * @param type of the return value. - * @return value of the side effect operation. + * @return value of the run operation. */ - T sideEffect(Serde serde, ThrowingSupplier action) throws TerminalException; + T run(Serde serde, ThrowingSupplier action) throws TerminalException; - /** Like {@link #sideEffect(Serde, ThrowingSupplier)}, but without returning a value. */ - default void sideEffect(ThrowingRunnable runnable) throws TerminalException { - sideEffect( + /** Like {@link #run(Serde, ThrowingSupplier)}, but without returning a value. */ + default void run(ThrowingRunnable runnable) throws TerminalException { + run( CoreSerdes.VOID, () -> { runnable.run(); diff --git a/sdk-api/src/main/java/dev/restate/sdk/ContextImpl.java b/sdk-api/src/main/java/dev/restate/sdk/ContextImpl.java index afd51709..1704f8f6 100644 --- a/sdk-api/src/main/java/dev/restate/sdk/ContextImpl.java +++ b/sdk-api/src/main/java/dev/restate/sdk/ContextImpl.java @@ -110,7 +110,7 @@ public void send(Target target, Serde inputSerde, T parameter, Duration d } @Override - public T sideEffect(Serde serde, ThrowingSupplier action) { + public T run(Serde serde, ThrowingSupplier action) { CompletableFuture> enterFut = new CompletableFuture<>(); syscalls.enterSideEffectBlock( new EnterSideEffectSyscallCallback() { diff --git a/sdk-api/src/main/java/dev/restate/sdk/RestateRandom.java b/sdk-api/src/main/java/dev/restate/sdk/RestateRandom.java index 4ed24ab1..074d5514 100644 --- a/sdk-api/src/main/java/dev/restate/sdk/RestateRandom.java +++ b/sdk-api/src/main/java/dev/restate/sdk/RestateRandom.java @@ -21,10 +21,9 @@ * *

This instance is useful to generate identifiers, idempotency keys, and for uniform sampling * from a set of options. If a cryptographically secure value is needed, please generate that - * externally using {@link ObjectContext#sideEffect(Serde, ThrowingSupplier)}. + * externally using {@link ObjectContext#run(Serde, ThrowingSupplier)}. * - *

You MUST NOT use this object inside a {@link ObjectContext#sideEffect(Serde, - * ThrowingSupplier)}. + *

You MUST NOT use this object inside a {@link ObjectContext#run(Serde, ThrowingSupplier)}. */ public class RestateRandom extends Random { @@ -58,7 +57,7 @@ public UUID nextUUID() { @Override protected int next(int bits) { if (this.syscalls.isInsideSideEffect()) { - throw new IllegalStateException("You can't use RestateRandom inside a side effect!"); + throw new IllegalStateException("You can't use RestateRandom inside ctx.run!"); } return super.next(bits); diff --git a/sdk-api/src/test/java/dev/restate/sdk/RandomTest.java b/sdk-api/src/test/java/dev/restate/sdk/RandomTest.java index cb9f2f8a..3a98ac85 100644 --- a/sdk-api/src/test/java/dev/restate/sdk/RandomTest.java +++ b/sdk-api/src/test/java/dev/restate/sdk/RandomTest.java @@ -31,7 +31,7 @@ protected TestInvocationBuilder randomInsideSideEffect() { CoreSerdes.VOID, CoreSerdes.JSON_INT, (ctx, unused) -> { - ctx.sideEffect(() -> ctx.random().nextInt()); + ctx.run(() -> ctx.random().nextInt()); throw new IllegalStateException("This should not unreachable"); }); } diff --git a/sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java b/sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java index 9f52ee23..38c30210 100644 --- a/sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java +++ b/sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java @@ -24,7 +24,7 @@ protected TestInvocationBuilder sideEffect(String sideEffectOutput) { CoreSerdes.VOID, CoreSerdes.JSON_STRING, (ctx, unused) -> { - String result = ctx.sideEffect(CoreSerdes.JSON_STRING, () -> sideEffectOutput); + String result = ctx.run(CoreSerdes.JSON_STRING, () -> sideEffectOutput); return "Hello " + result; }); } @@ -35,8 +35,8 @@ protected TestInvocationBuilder consecutiveSideEffect(String sideEffectOutput) { CoreSerdes.VOID, CoreSerdes.JSON_STRING, (ctx, unused) -> { - String firstResult = ctx.sideEffect(CoreSerdes.JSON_STRING, () -> sideEffectOutput); - String secondResult = ctx.sideEffect(CoreSerdes.JSON_STRING, firstResult::toUpperCase); + String firstResult = ctx.run(CoreSerdes.JSON_STRING, () -> sideEffectOutput); + String secondResult = ctx.run(CoreSerdes.JSON_STRING, firstResult::toUpperCase); return "Hello " + secondResult; }); @@ -51,7 +51,7 @@ protected TestInvocationBuilder checkContextSwitching() { String currentThread = Thread.currentThread().getName(); String sideEffectThread = - ctx.sideEffect(CoreSerdes.JSON_STRING, () -> Thread.currentThread().getName()); + ctx.run(CoreSerdes.JSON_STRING, () -> Thread.currentThread().getName()); if (!Objects.equals(currentThread, sideEffectThread)) { throw new IllegalStateException( @@ -71,7 +71,7 @@ protected TestInvocationBuilder sideEffectGuard() { CoreSerdes.VOID, CoreSerdes.JSON_STRING, (ctx, unused) -> { - ctx.sideEffect(() -> ctx.send(GREETER_SERVICE_TARGET, new byte[] {})); + ctx.run(() -> ctx.send(GREETER_SERVICE_TARGET, new byte[] {})); throw new IllegalStateException("This point should not be reached"); }); } diff --git a/sdk-api/src/test/java/dev/restate/sdk/StateMachineFailuresTest.java b/sdk-api/src/test/java/dev/restate/sdk/StateMachineFailuresTest.java index f8b31352..f8ea7f7b 100644 --- a/sdk-api/src/test/java/dev/restate/sdk/StateMachineFailuresTest.java +++ b/sdk-api/src/test/java/dev/restate/sdk/StateMachineFailuresTest.java @@ -55,7 +55,7 @@ protected TestInvocationBuilder sideEffectFailure(Serde serde) { CoreSerdes.VOID, CoreSerdes.JSON_STRING, (ctx, unused) -> { - ctx.sideEffect(serde, () -> 0); + ctx.run(serde, () -> 0); return "Francesco"; }); } diff --git a/sdk-api/src/test/java/dev/restate/sdk/UserFailuresTest.java b/sdk-api/src/test/java/dev/restate/sdk/UserFailuresTest.java index 7179c858..f0acff0d 100644 --- a/sdk-api/src/test/java/dev/restate/sdk/UserFailuresTest.java +++ b/sdk-api/src/test/java/dev/restate/sdk/UserFailuresTest.java @@ -37,7 +37,7 @@ protected TestInvocationBuilder sideEffectThrowIllegalStateException( CoreSerdes.VOID, (ctx, unused) -> { try { - ctx.sideEffect( + ctx.run( () -> { throw new IllegalStateException("Whatever"); }); @@ -72,7 +72,7 @@ protected TestInvocationBuilder sideEffectThrowTerminalException(int code, Strin CoreSerdes.VOID, CoreSerdes.VOID, (ctx, unused) -> { - ctx.sideEffect( + ctx.run( () -> { throw new TerminalException(code, message); }); diff --git a/sdk-core/src/test/java/dev/restate/sdk/core/RandomTestSuite.java b/sdk-core/src/test/java/dev/restate/sdk/core/RandomTestSuite.java index 04c24f35..18a6e9a8 100644 --- a/sdk-core/src/test/java/dev/restate/sdk/core/RandomTestSuite.java +++ b/sdk-core/src/test/java/dev/restate/sdk/core/RandomTestSuite.java @@ -38,7 +38,6 @@ public Stream definitions() { .withInput(startMessage(1).setDebugId(debugId), ProtoUtils.inputMessage()) .assertingOutput( containsOnlyExactErrorMessage( - new IllegalStateException( - "You can't use RestateRandom inside a side effect!")))); + new IllegalStateException("You can't use RestateRandom inside ctx.run!")))); } } diff --git a/sdk-http-vertx/src/test/kotlin/dev/restate/sdk/http/vertx/VertxExecutorsTest.kt b/sdk-http-vertx/src/test/kotlin/dev/restate/sdk/http/vertx/VertxExecutorsTest.kt index 7d4bc679..36230b0d 100644 --- a/sdk-http-vertx/src/test/kotlin/dev/restate/sdk/http/vertx/VertxExecutorsTest.kt +++ b/sdk-http-vertx/src/test/kotlin/dev/restate/sdk/http/vertx/VertxExecutorsTest.kt @@ -36,7 +36,7 @@ class VertxExecutorsTest : TestDefinitions.TestSuite { LOG.info("I am on the thread I am before executing side effect") check(Vertx.currentContext() == null) check(coroutineContext[CoroutineName] == nonBlockingCoroutineName) - ctx.sideEffect { + ctx.run { LOG.info("I am on the thread I am when executing side effect") check(coroutineContext[CoroutineName] == nonBlockingCoroutineName) check(Vertx.currentContext() == null) @@ -52,7 +52,7 @@ class VertxExecutorsTest : TestDefinitions.TestSuite { ): Void? { val id = Thread.currentThread().id check(Vertx.currentContext() == null) - ctx.sideEffect { + ctx.run { check(Thread.currentThread().id == id) check(Vertx.currentContext() == null) } diff --git a/sdk-workflow-api/src/main/java/dev/restate/sdk/workflow/impl/WorkflowContextImpl.java b/sdk-workflow-api/src/main/java/dev/restate/sdk/workflow/impl/WorkflowContextImpl.java index 8cff2876..6d67b694 100644 --- a/sdk-workflow-api/src/main/java/dev/restate/sdk/workflow/impl/WorkflowContextImpl.java +++ b/sdk-workflow-api/src/main/java/dev/restate/sdk/workflow/impl/WorkflowContextImpl.java @@ -209,13 +209,13 @@ public void send(Target target, Serde inputSerde, T parameter, Duration d } @Override - public T sideEffect(Serde serde, ThrowingSupplier action) throws TerminalException { - return ctx.sideEffect(serde, action); + public T run(Serde serde, ThrowingSupplier action) throws TerminalException { + return ctx.run(serde, action); } @Override - public void sideEffect(ThrowingRunnable runnable) throws TerminalException { - ctx.sideEffect(runnable); + public void run(ThrowingRunnable runnable) throws TerminalException { + ctx.run(runnable); } @Override