-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: support source and sink func declarations #1070
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Good start, but you're right, the other two points need to be addressed. LMK what you come up with.
6ebb5d6
to
7945e84
Compare
go-runtime/ftl/call.go
Outdated
// SourceToRef returns the FTL reference for a Source. | ||
func SourceToRef[Resp any](source Source[Resp]) SourceRef { | ||
ref := runtime.FuncForPC(reflect.ValueOf(source).Pointer()).Name() | ||
return SourceRef(goRefToFTLRef(ref)) | ||
} | ||
|
||
// EmptyToRef returns the FTL reference for an Empty. | ||
func EmptyToRef(empty Empty) VerbRef { | ||
ref := runtime.FuncForPC(reflect.ValueOf(empty).Pointer()).Name() | ||
return goRefToFTLRef(ref) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stuff might change once we use a generic Ref
everywhere. But this is working for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@worstell says she has a change for this in flight
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome I can work with her to get her change and mine merged and updated here.
go-runtime/server/server.go
Outdated
return ftl.Unit{}, err | ||
} | ||
|
||
return handler(ftl.VerbRef{Module: ref.Module, Name: ref.Name}, verb) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is the best approach here, but it works as intended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfectly acceptable I think.
c36342b
to
24887ee
Compare
require(verb.valueParameters.size >= 1) { "$verbSourcePos Verbs must have at least one argument, ${verb.name} did not" } | ||
require(verb.valueParameters.size <= 2) { "$verbSourcePos Verbs must have at most two arguments, ${verb.name} did not" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@worstell would be good to get your 👀 on some of this kotlin
stuff if you have a moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but it would be good to add an integration test for these two cases.
go-runtime/compile/build.go
Outdated
@@ -201,6 +211,9 @@ var scaffoldFuncs = scaffolder.FuncMap{ | |||
} | |||
panic(fmt.Sprintf("unsupported value %T", v)) | |||
}, | |||
"isSink": func(v schema.Verb) string { | |||
return "wes" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOLOL
go-runtime/server/server.go
Outdated
return ftl.Unit{}, err | ||
} | ||
|
||
return handler(ftl.VerbRef{Module: ref.Module, Name: ref.Name}, verb) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfectly acceptable I think.
@@ -34,8 +34,19 @@ data class {{.Name|title}} | |||
{{- else if is "Verb" . }} | |||
{{.Comments|comment -}}@Verb | |||
@Ignore | |||
{{- if and (eq (type $ .Request) "Unit") (eq (type $ .Response) "Unit")}} | |||
fun {{.Name|lowerCamel}}(context: Context): Unit = throw |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could probably pull fun {{.Name|lowerCamel}}(context: Context
out from the if/else bodies if you wanted to DRY this a bit more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll noodle on this one a bit. It makes the template quite a bit tougher for me to read, but maybe I'm just weird :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering that too. Just leave it as-is if it's too gross.
6e12590
to
5101fb4
Compare
func TestPubSub(t *testing.T) { | ||
runForRuntimes(t, func(modulesDir string, runtime string, rd runtimeData) []test { | ||
return []test{ | ||
{name: fmt.Sprintf("PubSub%s", rd.testSuffix), assertions: assertions{ | ||
run("ftl", rd.initOpts...), | ||
scaffoldTestData(runtime, "pubsub", rd.modulePath), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these under pubsub
assuming they can be extended to support pubsub
once it's ready for integration tests.
if (verb.valueParameters.size == 2) { | ||
val reqParam = verb.valueParameters.last() | ||
require(reqParam.typeReference?.resolveType() | ||
?.let { it.toClassDescriptor().isData || it.isEmptyBuiltin() || it.isUnit() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to allow kotlin.Unit as a request type? i thought we were going to infer this from omission with the new change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh good catch! I had this in before I added the size check above and forgot to remove! Thanks for pointing this one out!
8220825
to
f2778f6
Compare
respClass.fqNameOrNull()?.asString() | ||
}" | ||
verb.createTypeBindingForReturnType(bindingContext)?.type?.let { | ||
require(it.toClassDescriptor().isData || it.isEmptyBuiltin() || it.isUnit()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, do we want to look for a null return type instead of a kotlin.Unit
return type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On this one, I think kotlin
infers the return type of Unit
if it's omitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah got it
f2778f6
to
65356c4
Compare
var requestRef = Type(unit = xyz.block.ftl.v1.schema.Unit()) | ||
if (verb.valueParameters.size > 1) { | ||
val ref = verb.valueParameters.last()?.let { | ||
val position = it.getLineAndColumn().toPosition() | ||
return@let it.typeReference?.resolveType()?.toSchemaType(position) | ||
} | ||
ref?.let { requestRef = it } | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var requestRef = Type(unit = xyz.block.ftl.v1.schema.Unit()) | |
if (verb.valueParameters.size > 1) { | |
val ref = verb.valueParameters.last()?.let { | |
val position = it.getLineAndColumn().toPosition() | |
return@let it.typeReference?.resolveType()?.toSchemaType(position) | |
} | |
ref?.let { requestRef = it } | |
} | |
val requestRef = verb.valueParameters.takeIf { it.size > 1 }?.last()?.let { | |
val position = it.getLineAndColumn().toPosition() | |
return@let it.typeReference?.resolveType()?.toSchemaType(position) | |
} ?: Type(unit = xyz.block.ftl.v1.schema.Unit()) |
var returnRef = Type(unit = xyz.block.ftl.v1.schema.Unit()) | ||
val ref = verb.createTypeBindingForReturnType(bindingContext)?.let { | ||
val position = it.psiElement.getLineAndColumn().toPosition() | ||
return@let it.type.toSchemaType(position) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var returnRef = Type(unit = xyz.block.ftl.v1.schema.Unit()) | |
val ref = verb.createTypeBindingForReturnType(bindingContext)?.let { | |
val position = it.psiElement.getLineAndColumn().toPosition() | |
return@let it.type.toSchemaType(position) | |
} | |
val returnRef = verb.createTypeBindingForReturnType(bindingContext)?.let { | |
val position = it.psiElement.getLineAndColumn().toPosition() | |
return@let it.type.toSchemaType(position) | |
} ?: Type(unit = xyz.block.ftl.v1.schema.Unit()) |
65356c4
to
3824b82
Compare
3824b82
to
632022e
Compare
Fixes #1065
SOLVED: Some things to figure out still:
These were solved by assuming anything without a req is a source, anything without a resp, is a sink, and anything without either is empty.
How to use
Handle
with these new definitions. Since the signature no longer matches theHandle
func, what should we do here? The generated code here will fail:How should we deal with the fact that the generated code doesn't match the original signature? This also leads to issues using things like
ftl.callSink
andftl.callSource
since the generated code doesn't match the signature.