Skip to content

Commit

Permalink
Allow checked exceptions in annotated services
Browse files Browse the repository at this point in the history
This contains a bytecode breaking change in Handler.of static methods, due to the changed type.
  • Loading branch information
slinkydeveloper committed Nov 18, 2024
1 parent 069a162 commit 7340fb2
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 17 deletions.
9 changes: 9 additions & 0 deletions sdk-api-gen/src/test/java/dev/restate/sdk/CodegenTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import dev.restate.sdk.core.ProtoUtils;
import dev.restate.sdk.core.TestDefinitions;
import dev.restate.sdk.core.TestDefinitions.TestSuite;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;

Expand Down Expand Up @@ -182,6 +183,14 @@ public String sharedHandler(SharedWorkflowContext context, String myInput) {
}
}

@Service
static class CheckedException {
@Handler
String greet(Context context, String request) throws IOException {
return request;
}
}

@Override
public Stream<TestDefinitions.TestDefinition> definitions() {
return Stream.of(
Expand Down
23 changes: 12 additions & 11 deletions sdk-api/src/main/java/dev/restate/sdk/HandlerRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@
package dev.restate.sdk;

import dev.restate.sdk.common.TerminalException;
import dev.restate.sdk.common.function.ThrowingBiConsumer;
import dev.restate.sdk.common.function.ThrowingBiFunction;
import dev.restate.sdk.common.function.ThrowingConsumer;
import dev.restate.sdk.common.function.ThrowingFunction;
import dev.restate.sdk.common.syscalls.HandlerSpecification;
import dev.restate.sdk.common.syscalls.SyscallCallback;
import dev.restate.sdk.common.syscalls.Syscalls;
import io.opentelemetry.context.Scope;
import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jspecify.annotations.Nullable;

/** Adapter class for {@link dev.restate.sdk.common.syscalls.HandlerRunner} to use the Java API. */
public class HandlerRunner<REQ, RES>
implements dev.restate.sdk.common.syscalls.HandlerRunner<REQ, RES, HandlerRunner.Options> {
private final BiFunction<Context, REQ, RES> runner;
private final ThrowingBiFunction<Context, REQ, RES> runner;

private static final Logger LOG = LogManager.getLogger(HandlerRunner.class);

HandlerRunner(BiFunction<? extends Context, REQ, RES> runner) {
HandlerRunner(ThrowingBiFunction<? extends Context, REQ, RES> runner) {
//noinspection unchecked
this.runner = (BiFunction<Context, REQ, RES>) runner;
this.runner = (ThrowingBiFunction<Context, REQ, RES>) runner;
}

@Override
Expand Down Expand Up @@ -106,18 +106,19 @@ public void run(
}

public static <CTX extends Context, REQ, RES> HandlerRunner<REQ, RES> of(
BiFunction<CTX, REQ, RES> runner) {
ThrowingBiFunction<CTX, REQ, RES> runner) {
return new HandlerRunner<>(runner);
}

@SuppressWarnings("unchecked")
public static <CTX extends Context, RES> HandlerRunner<Void, RES> of(Function<CTX, RES> runner) {
public static <CTX extends Context, RES> HandlerRunner<Void, RES> of(
ThrowingFunction<CTX, RES> runner) {
return new HandlerRunner<>((context, o) -> runner.apply((CTX) context));
}

@SuppressWarnings("unchecked")
public static <CTX extends Context, REQ> HandlerRunner<REQ, Void> of(
BiConsumer<CTX, REQ> runner) {
ThrowingBiConsumer<CTX, REQ> runner) {
return new HandlerRunner<>(
(context, o) -> {
runner.accept((CTX) context, o);
Expand All @@ -126,7 +127,7 @@ public static <CTX extends Context, REQ> HandlerRunner<REQ, Void> of(
}

@SuppressWarnings("unchecked")
public static <CTX extends Context> HandlerRunner<Void, Void> of(Consumer<CTX> runner) {
public static <CTX extends Context> HandlerRunner<Void, Void> of(ThrowingConsumer<CTX> runner) {
return new HandlerRunner<>(
(ctx, o) -> {
runner.accept((CTX) ctx);
Expand Down
14 changes: 10 additions & 4 deletions sdk-api/src/test/java/dev/restate/sdk/JavaBlockingTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import dev.restate.sdk.common.HandlerType;
import dev.restate.sdk.common.Serde;
import dev.restate.sdk.common.ServiceType;
import dev.restate.sdk.common.function.ThrowingBiFunction;
import dev.restate.sdk.common.syscalls.HandlerDefinition;
import dev.restate.sdk.common.syscalls.HandlerSpecification;
import dev.restate.sdk.common.syscalls.ServiceDefinition;
Expand All @@ -24,7 +25,6 @@
import dev.restate.sdk.core.TestDefinitions.TestSuite;
import dev.restate.sdk.core.TestRunner;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Stream;

public class JavaBlockingTests extends TestRunner {
Expand Down Expand Up @@ -52,7 +52,7 @@ public Stream<TestSuite> definitions() {
}

public static <T, R> TestInvocationBuilder testDefinitionForService(
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<Context, T, R> runner) {
String name, Serde<T> reqSerde, Serde<R> resSerde, ThrowingBiFunction<Context, T, R> runner) {
return TestDefinitions.testInvocation(
ServiceDefinition.of(
name,
Expand All @@ -65,7 +65,10 @@ public static <T, R> TestInvocationBuilder testDefinitionForService(
}

public static <T, R> TestInvocationBuilder testDefinitionForVirtualObject(
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<ObjectContext, T, R> runner) {
String name,
Serde<T> reqSerde,
Serde<R> resSerde,
ThrowingBiFunction<ObjectContext, T, R> runner) {
return TestDefinitions.testInvocation(
ServiceDefinition.of(
name,
Expand All @@ -78,7 +81,10 @@ public static <T, R> TestInvocationBuilder testDefinitionForVirtualObject(
}

public static <T, R> TestInvocationBuilder testDefinitionForWorkflow(
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<WorkflowContext, T, R> runner) {
String name,
Serde<T> reqSerde,
Serde<R> resSerde,
ThrowingBiFunction<WorkflowContext, T, R> runner) {
return TestDefinitions.testInvocation(
ServiceDefinition.of(
name,
Expand Down
3 changes: 1 addition & 2 deletions sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ protected TestInvocationBuilder failingSideEffectWithRetryPolicy(
Serde.VOID,
JsonSerdes.STRING,
(ctx, unused) -> {
PreviewContext.run(
ctx,
ctx.run(
retryPolicy,
() -> {
throw new IllegalStateException(reason);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
//
// This file is part of the Restate Java SDK,
// which is released under the MIT license.
//
// You can find a copy of the license in file LICENSE in the root
// directory of this repository or package, or at
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
package dev.restate.sdk.common.function;

/** Like {@link java.util.function.BiFunction} but can throw checked exceptions. */
@FunctionalInterface
public interface ThrowingBiFunction<T, U, R> {
R apply(T var1, U var2) throws Throwable;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
//
// This file is part of the Restate Java SDK,
// which is released under the MIT license.
//
// You can find a copy of the license in file LICENSE in the root
// directory of this repository or package, or at
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
package dev.restate.sdk.common.function;

import java.util.function.Consumer;

/** Like {@link Consumer} but can throw checked exceptions. */
@FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T var1) throws Throwable;
}

0 comments on commit 7340fb2

Please sign in to comment.