Skip to content

Commit

Permalink
feat: use export annotation (#1117)
Browse files Browse the repository at this point in the history
- Go: Replaces `ftl:verb` and `ftl:enum` with `ftl:export`, removes
`ftl:module <name>` annotation
- Kotlin: Replaces `@Verb` with `@Export`
- Updates runtime schema extractors to pull standalone data decls
annotated with `export`

Design here: https://hackmd.io/i5COidF3SEynCab8VcJwng

fixes #1114
  • Loading branch information
worstell authored Mar 22, 2024
1 parent 638a238 commit 6712969
Show file tree
Hide file tree
Showing 41 changed files with 458 additions and 472 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
uses: cashapp/activate-hermit@v1
- name: Build Cache
uses: ./.github/actions/build-cache
- name: Build Kotlin
run: just build-kt-runtime
- name: Docker Compose
run: docker compose up -d --wait
- name: Test
Expand Down
16 changes: 7 additions & 9 deletions buildengine/build_go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ func TestGenerateGoModule(t *testing.T) {
}
expected := `// Code generated by FTL. DO NOT EDIT.
//ftl:module other
package other
import (
Expand All @@ -73,15 +72,15 @@ import (
var _ = context.Background
//ftl:enum
//ftl:export
type Color string
const (
Red Color = "Red"
Blue Color = "Blue"
Green Color = "Green"
)
//ftl:enum
//ftl:export
type ColorInt int
const (
RedInt ColorInt = 0
Expand All @@ -95,28 +94,28 @@ type EchoRequest struct {
type EchoResponse struct {
}
//ftl:verb
//ftl:export
func Echo(context.Context, EchoRequest) (EchoResponse, error) {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.Call()")
}
type SinkReq struct {
}
//ftl:verb
//ftl:export
func Sink(context.Context, SinkReq) error {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.CallSink()")
}
type SourceResp struct {
}
//ftl:verb
//ftl:export
func Source(context.Context) (SourceResp, error) {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.CallSource()")
}
//ftl:verb
//ftl:export
func Nothing(context.Context) error {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.CallEmpty()")
}
Expand Down Expand Up @@ -151,7 +150,6 @@ func TestMetadataImportsExcluded(t *testing.T) {
}
expected := `// Code generated by FTL. DO NOT EDIT.
//ftl:module test
package test
import (
Expand All @@ -166,7 +164,7 @@ type Req struct {
type Resp struct {
}
//ftl:verb
//ftl:export
func Call(context.Context, Req) (Resp, error) {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.Call()")
}
Expand Down
8 changes: 7 additions & 1 deletion buildengine/build_kotlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,14 @@ var scaffoldFuncs = scaffolder.FuncMap{
imports := sets.NewSet[string]()
_ = schema.VisitExcludingMetadataChildren(m, func(n schema.Node, next func() error) error {
switch n.(type) {
case *schema.Data:
imports.Add("xyz.block.ftl.Export")

case *schema.Enum:
imports.Add("xyz.block.ftl.Export")

case *schema.Verb:
imports.Append("xyz.block.ftl.Context", "xyz.block.ftl.Ignore", "xyz.block.ftl.Verb")
imports.Append("xyz.block.ftl.Context", "xyz.block.ftl.Ignore", "xyz.block.ftl.Export")

case *schema.Time:
imports.Add("java.time.OffsetDateTime")
Expand Down
28 changes: 20 additions & 8 deletions buildengine/build_kotlin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,18 +114,22 @@ func TestGenerateAllTypes(t *testing.T) {
package ftl.test
import java.time.OffsetDateTime
import xyz.block.ftl.Export
@Export
data class ParamTestData<T>(
val t: T,
)
@Export
data class TestRequest(
val field: Long,
)
/**
* Response comments
*/
@Export
data class TestResponse(
val int: Long,
val float: Float,
Expand Down Expand Up @@ -193,17 +197,18 @@ func TestGenerateAllVerbs(t *testing.T) {
package ftl.test
import xyz.block.ftl.Context
import xyz.block.ftl.Export
import xyz.block.ftl.Ignore
import xyz.block.ftl.Verb
@Export
data class Request(
val data: Long,
)
/**
* TestVerb comments
*/
@Verb
@Export
@Ignore
fun testVerb(context: Context, req: Request): ftl.builtin.Empty = throw
NotImplementedError("Verb stubs should not be called directly, instead use context.call(::testVerb, ...)")
Expand Down Expand Up @@ -233,9 +238,12 @@ func TestGenerateBuiltins(t *testing.T) {
*/
package ftl.builtin
import xyz.block.ftl.Export
/**
* HTTP request structure used for HTTP ingress verbs.
*/
@Export
data class HttpRequest<Body>(
val method: String,
val path: String,
Expand All @@ -248,13 +256,15 @@ data class HttpRequest<Body>(
/**
* HTTP response structure used for HTTP ingress verbs.
*/
@Export
data class HttpResponse<Body, Error>(
val status: Long,
val headers: Map<String, List<String>>,
val body: Body? = null,
val error: Error? = null,
)
@Export
class Empty
`
bctx := buildContext{
Expand Down Expand Up @@ -293,10 +303,10 @@ func TestGenerateEmptyRefs(t *testing.T) {
package ftl.test
import xyz.block.ftl.Context
import xyz.block.ftl.Export
import xyz.block.ftl.Ignore
import xyz.block.ftl.Verb
@Verb
@Export
@Ignore
fun emptyVerb(context: Context, req: ftl.builtin.Empty): ftl.builtin.Empty = throw
NotImplementedError("Verb stubs should not be called directly, instead use context.call(::emptyVerb, ...)")
Expand Down Expand Up @@ -355,26 +365,28 @@ func TestGenerateSourcesAndSinks(t *testing.T) {
package ftl.test
import xyz.block.ftl.Context
import xyz.block.ftl.Export
import xyz.block.ftl.Ignore
import xyz.block.ftl.Verb
@Export
data class SinkReq(
val data: Long,
)
@Verb
@Export
@Ignore
fun sink(context: Context, req: SinkReq): Unit = throw
NotImplementedError("Verb stubs should not be called directly, instead use context.callSink(::sink, ...)")
@Export
data class SourceResp(
val data: Long,
)
@Verb
@Export
@Ignore
fun source(context: Context): SourceResp = throw
NotImplementedError("Verb stubs should not be called directly, instead use context.callSource(::source, ...)")
@Verb
@Export
@Ignore
fun nothing(context: Context): Unit = throw
NotImplementedError("Verb stubs should not be called directly, instead use context.callEmpty(::nothing, ...)")
Expand Down
3 changes: 1 addition & 2 deletions buildengine/testdata/projects/alpha/alpha.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ftl:module alpha
package alpha

import (
Expand All @@ -18,7 +17,7 @@ type EchoResponse struct {
Message string `json:"message"`
}

//ftl:verb
//ftl:export
func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
ftl.Call(ctx, other.Echo, other.EchoRequest{})
return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name.Default("anonymous"))}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package ftl.alpha
import ftl.builtin.Empty
import ftl.other.Other
import xyz.block.ftl.Context
import xyz.block.ftl.Verb
import xyz.block.ftl.Export

data class EchoRequest(val name: String?)
data class EchoResponse(val message: String)

@Verb
@Export
fun echo(context: Context, req: EchoRequest): EchoResponse {
val other = Other()
return EchoResponse(message = "Hello, ${req.name ?: "anonymous"}!.")
Expand Down
5 changes: 2 additions & 3 deletions buildengine/testdata/projects/another/another.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ftl:module another
package another

import (
Expand All @@ -16,7 +15,7 @@ type EchoResponse struct {
Message string `json:"message"`
}

//ftl:verb
//ftl:export
func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name.Default("anonymous"))}, nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package ftl.echo

import xyz.block.ftl.Context
import xyz.block.ftl.Method
import xyz.block.ftl.Verb
import xyz.block.ftl.Export

data class EchoRequest(val name: String? = "anonymous")
data class EchoResponse(val message: String)

@Verb
@Export
fun echo(context: Context, req: EchoRequest): EchoResponse {
return EchoResponse(message = "Hello, ${req.name}!")
}
2 changes: 1 addition & 1 deletion buildengine/testdata/projects/external/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type ExternalResponse struct {

// External returns the current month as an external type.
//
//ftl:verb
//ftl:export
func Time(ctx context.Context, req ExternalRequest) (ExternalResponse, error) {
return ExternalResponse{Month: time.Now().Month()}, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ftl.externalkotlin

import com.google.type.DayOfWeek
import xyz.block.ftl.Context
import xyz.block.ftl.Verb
import xyz.block.ftl.Export
import xyz.block.ftl.v1.schema.Optional

class InvalidInput(val field: String) : Exception()
Expand All @@ -11,7 +11,7 @@ data class ExternalRequest(val name: String?, val dayOfWeek: DayOfWeek)
data class ExternalResponse(val message: String)

@Throws(InvalidInput::class)
@Verb
@Export
fun external(context: Context, req: ExternalRequest): ExternalResponse {
return ExternalResponse(message = "Hello, ${req.name ?: "anonymous"}!")
}
5 changes: 2 additions & 3 deletions buildengine/testdata/projects/other/other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ftl:module other
package other

import (
Expand All @@ -16,7 +15,7 @@ type EchoResponse struct {
Message string `json:"message"`
}

//ftl:verb
//ftl:export
func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name.Default("anonymous"))}, nil
}
}
4 changes: 1 addition & 3 deletions examples/go/echo/echo.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// This is the echo module.
//
//ftl:module echo
package echo

import (
Expand All @@ -25,7 +23,7 @@ type EchoResponse struct {

// Echo returns a greeting with the current time.
//
//ftl:verb
//ftl:export
func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
tresp, err := ftl.Call(ctx, time.Time, time.TimeRequest{})
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions examples/go/time/time.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//ftl:module time
package time

import (
Expand All @@ -13,7 +12,7 @@ type TimeResponse struct {

// Time returns the current time.
//
//ftl:verb
//ftl:export
func Time(ctx context.Context, req TimeRequest) (TimeResponse, error) {
return TimeResponse{Time: time.Now()}, nil
}
4 changes: 2 additions & 2 deletions examples/kotlin/echo/src/main/kotlin/ftl/echo/Echo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package ftl.echo
import ftl.builtin.Empty
import ftl.time.time
import xyz.block.ftl.Context
import xyz.block.ftl.Verb
import xyz.block.ftl.Export

class InvalidInput(val field: String) : Exception()

data class EchoRequest(val name: String?)
data class EchoResponse(val message: String)

@Throws(InvalidInput::class)
@Verb
@Export
fun echo(context: Context, req: EchoRequest): EchoResponse {
val response = context.call(::time, Empty())
return EchoResponse(message = "Hello, ${req.name ?: "anonymous"}! The time is ${response.time}.")
Expand Down
4 changes: 2 additions & 2 deletions examples/kotlin/time/src/main/kotlin/ftl/time/Time.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package ftl.time

import ftl.builtin.Empty
import xyz.block.ftl.Context
import xyz.block.ftl.Verb
import xyz.block.ftl.Export
import java.time.OffsetDateTime

data class TimeResponse(val time: OffsetDateTime)

@Verb
@Export
fun time(context: Context, req: Empty): TimeResponse {
return TimeResponse(time = OffsetDateTime.now())
}
Loading

0 comments on commit 6712969

Please sign in to comment.