Skip to content

Commit

Permalink
fix: Drop verb client interfaces (#3110)
Browse files Browse the repository at this point in the history
Drop the `VerbClient`, `VerbClientSink`, `VerbClientSource`,
`VerbClientEmpty` interfaces. They conflict with verbs that use
primitive params and responses.

Fixes #2757
tomdaffurn authored Oct 16, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 4f9d72b commit 0a53566
Showing 10 changed files with 150 additions and 224 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package xyz.block.ftl.deployment;

public enum VerbType {
VERB,
SINK,
SOURCE,
EMPTY
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package xyz.block.ftl;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* A client for a specific verb.
*
* The sink source and empty interfaces allow for different call signatures.
*
* @param <P> The verb parameter type
* @param <R> The verb return type
* Annotation that is used to define a verb client
*/
public interface VerbClient<P, R> {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface VerbClient {

R call(P param);
String module() default "";

String name();
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -34,10 +34,6 @@
import xyz.block.ftl.TypeAlias;
import xyz.block.ftl.TypeAliasMapper;
import xyz.block.ftl.VerbClient;
import xyz.block.ftl.VerbClientDefinition;
import xyz.block.ftl.VerbClientEmpty;
import xyz.block.ftl.VerbClientSink;
import xyz.block.ftl.VerbClientSource;
import xyz.block.ftl.deployment.JVMCodeGenerator;
import xyz.block.ftl.v1.schema.Data;
import xyz.block.ftl.v1.schema.Enum;
@@ -280,36 +276,31 @@ protected void generateVerb(Module module, Verb verb, String packageName, Map<De
Map<DeclRef, String> nativeTypeAliasMap, Path outputDir)
throws IOException {
TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(className(verb.getName()) + CLIENT)
.addAnnotation(AnnotationSpec.builder(VerbClientDefinition.class)
.addAnnotation(AnnotationSpec.builder(VerbClient.class)
.addMember("name", "\"" + verb.getName() + "\"")
.addMember("module", "\"" + module.getName() + "\"")
.build())
.addModifiers(Modifier.PUBLIC);
.addModifiers(Modifier.PUBLIC)
.addJavadoc("A client for the $L.$L verb", module.getName(), verb.getName());
var comments = String.join("\n", verb.getCommentsList());
if (verb.getRequest().hasUnit() && verb.getResponse().hasUnit()) {
typeBuilder.addSuperinterface(ClassName.get(VerbClientEmpty.class))
typeBuilder.addMethod(MethodSpec.methodBuilder("call")
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).build())
.addJavadoc(comments);
} else if (verb.getRequest().hasUnit()) {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(ClassName.get(VerbClientSource.class),
toJavaTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap, true)));
typeBuilder.addMethod(MethodSpec.methodBuilder("call")
.returns(toAnnotatedJavaTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap))
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
.addJavadoc(comments)
.build());
} else if (verb.getResponse().hasUnit()) {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(ClassName.get(VerbClientSink.class),
toJavaTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap, true)));
typeBuilder.addMethod(MethodSpec.methodBuilder("call")
.returns(TypeName.VOID)
.addParameter(toAnnotatedJavaTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap), "value")
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
.addJavadoc(comments)
.build());
} else {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(ClassName.get(VerbClient.class),
toJavaTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap, true),
toJavaTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap, true)));
typeBuilder.addMethod(MethodSpec.methodBuilder("call")
.returns(toAnnotatedJavaTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap))
.addParameter(toAnnotatedJavaTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap), "value")
@@ -318,7 +309,8 @@ protected void generateVerb(Module module, Verb verb, String packageName, Map<De
.build());
}

JavaFile javaFile = JavaFile.builder(packageName, typeBuilder.build()).build();
TypeSpec client = typeBuilder.build();
JavaFile javaFile = JavaFile.builder(packageName, client).build();
javaFile.writeTo(outputDir);
}

Original file line number Diff line number Diff line change
@@ -26,10 +26,6 @@
import xyz.block.ftl.TypeAlias;
import xyz.block.ftl.TypeAliasMapper;
import xyz.block.ftl.VerbClient;
import xyz.block.ftl.VerbClientDefinition;
import xyz.block.ftl.VerbClientEmpty;
import xyz.block.ftl.VerbClientSink;
import xyz.block.ftl.VerbClientSource;
import xyz.block.ftl.deployment.JVMCodeGenerator;
import xyz.block.ftl.v1.schema.Data;
import xyz.block.ftl.v1.schema.Enum;
@@ -158,47 +154,41 @@ protected void generateVerb(Module module, Verb verb, String packageName, Map<De
throws IOException {
String thisType = className(verb.getName()) + CLIENT;
TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(thisType)
.addAnnotation(AnnotationSpec.builder(VerbClientDefinition.class)
.addAnnotation(AnnotationSpec.builder(VerbClient.class)
.addMember("name=\"" + verb.getName() + "\"")
.addMember("module=\"" + module.getName() + "\"")
.build())
.addModifiers(KModifier.PUBLIC);
.addModifiers(KModifier.PUBLIC)
.addKdoc("A client for the %L.%L verb", module.getName(), verb.getName());
String comments = String.join("\n", verb.getCommentsList());
if (verb.getRequest().hasUnit() && verb.getResponse().hasUnit()) {
typeBuilder.addSuperinterface(className(VerbClientEmpty.class), CodeBlock.of(""))
.addKdoc(comments);
typeBuilder.addFunction(FunSpec.builder("call")
.addModifiers(KModifier.ABSTRACT, KModifier.PUBLIC)
.addKdoc(comments)
.build());
} else if (verb.getRequest().hasUnit()) {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(className(VerbClientSource.class),
toKotlinTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap)), CodeBlock.of(""));
typeBuilder.addFunction(FunSpec.builder("call")
.returns(toKotlinTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap))
.addModifiers(KModifier.PUBLIC, KModifier.OVERRIDE, KModifier.ABSTRACT)
.addModifiers(KModifier.PUBLIC, KModifier.ABSTRACT)
.addKdoc(comments)
.build());
} else if (verb.getResponse().hasUnit()) {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(className(VerbClientSink.class),
toKotlinTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap)), CodeBlock.of(""));
typeBuilder.addFunction(FunSpec.builder("call")
.addModifiers(KModifier.OVERRIDE, KModifier.ABSTRACT)
.addModifiers(KModifier.ABSTRACT)
.addParameter("value", toKotlinTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap))
.addKdoc(comments)
.build());
} else {
typeBuilder.addSuperinterface(ParameterizedTypeName.get(className(VerbClient.class),
toKotlinTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap),
toKotlinTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap)), CodeBlock.of(""));
typeBuilder.addFunction(FunSpec.builder("call")
.returns(toKotlinTypeName(verb.getResponse(), typeAliasMap, nativeTypeAliasMap))
.addParameter("value", toKotlinTypeName(verb.getRequest(), typeAliasMap, nativeTypeAliasMap))
.addModifiers(KModifier.PUBLIC, KModifier.OVERRIDE, KModifier.ABSTRACT)
.addModifiers(KModifier.PUBLIC, KModifier.ABSTRACT)
.addKdoc(comments)
.build());
}

FileSpec javaFile = FileSpec.builder(packageName, thisType)
.addType(typeBuilder.build())
.build();

javaFile.writeTo(outputDir);
}

10 changes: 10 additions & 0 deletions jvm-runtime/testdata/go/gomodule/server.go
Original file line number Diff line number Diff line change
@@ -309,3 +309,13 @@ func TypeEnumVerb(ctx context.Context, val AnimalWrapper) (AnimalWrapper, error)
//func MixedEnumVerb(ctx context.Context, val Mixed) (Mixed, error) {
// return val, nil
//}

//ftl:verb export
func PrimitiveResponseVerb(ctx context.Context, val string) (int, error) {
return 1, nil
}

//ftl:verb export
func PrimitiveParamVerb(ctx context.Context, val int) (string, error) {
return "", nil
}

0 comments on commit 0a53566

Please sign in to comment.