From b446f7ea07c4797616073891c7011cbf2f2a1ff3 Mon Sep 17 00:00:00 2001 From: Elizabeth Worstell Date: Thu, 14 Nov 2024 13:05:18 -0800 Subject: [PATCH] feat: inject topics/subscriptions in go --- .../testdata/go/encryption/encryption.go | 9 +- .../encryption/testdata/go/encryption/go.mod | 15 ++ .../encryption/testdata/go/encryption/go.sum | 26 +++ .../testdata/go/encryption/types.ftl.go | 29 ++++ .../pubsub/testdata/go/publisher/go.mod | 15 ++ .../pubsub/testdata/go/publisher/go.sum | 26 +++ .../pubsub/testdata/go/publisher/publisher.go | 16 +- .../pubsub/testdata/go/publisher/types.ftl.go | 31 ++++ .../controller/pubsub/testdata/go/slow/go.mod | 15 ++ .../controller/pubsub/testdata/go/slow/go.sum | 26 +++ .../pubsub/testdata/go/slow/slow.go | 9 +- .../pubsub/testdata/go/slow/types.ftl.go | 24 +++ .../pubsub/testdata/go/subscriber/go.mod | 15 ++ .../pubsub/testdata/go/subscriber/go.sum | 26 +++ .../testdata/go/subscriber/subscriber.go | 21 +-- .../testdata/go/subscriber/types.ftl.go | 46 +++++ docs/content/docs/reference/retries.md | 1 - frontend/cli/testdata/go/echo/echo.go | 4 +- frontend/cli/testdata/go/echo/go.mod | 15 ++ frontend/cli/testdata/go/echo/go.sum | 26 +++ frontend/cli/testdata/go/echo/types.ftl.go | 25 +++ frontend/cli/testdata/go/time/go.mod | 15 ++ frontend/cli/testdata/go/time/go.sum | 26 +++ frontend/cli/testdata/go/time/time.go | 6 +- frontend/cli/testdata/go/time/types.ftl.go | 29 ++++ .../.ftl.tmpl/go/main/main.go.tmpl | 5 +- .../compile/build-template/types.ftl.go.tmpl | 3 + go-runtime/compile/build.go | 62 ++++++- .../external_module.go.tmpl | 2 +- go-runtime/ftl/ftltest/fake.go | 2 +- go-runtime/ftl/ftltest/ftltest.go | 61 ------- .../ftl/ftltest/ftltest_integration_test.go | 8 +- go-runtime/ftl/ftltest/pubsub.go | 57 ------- .../ftltest/testdata/go/outer/types.ftl.go | 2 + .../ftl/ftltest/testdata/go/pubsub/go.mod | 37 +--- .../ftl/ftltest/testdata/go/pubsub/go.sum | 90 ---------- .../ftl/ftltest/testdata/go/pubsub/pubsub.go | 23 +-- .../ftltest/testdata/go/pubsub/pubsub_test.go | 98 ----------- .../ftltest/testdata/go/pubsub/types.ftl.go | 35 ++++ .../testdata/go/subscriber/types.ftl.go | 2 + .../ftl/ftltest/testdata/go/time/go.mod | 30 ++++ .../ftl/ftltest/testdata/go/time/go.sum | 22 ++- .../ftl/ftltest/testdata/go/time/types.ftl.go | 4 +- .../testdata/go/verbtypes/types.ftl.go | 35 ++-- .../ftltest/testdata/go/wrapped/types.ftl.go | 6 +- go-runtime/ftl/pubsub.go | 25 +-- go-runtime/ftl/reflection/pubsub.go | 1 + go-runtime/schema/common/common.go | 112 +++++++++++- go-runtime/schema/common/directive.go | 25 +-- go-runtime/schema/common/fact.go | 17 ++ go-runtime/schema/database/analyzer.go | 8 +- go-runtime/schema/extract.go | 11 ++ go-runtime/schema/finalize/analyzer.go | 8 + go-runtime/schema/metadata/analyzer.go | 6 - go-runtime/schema/schema_integration_test.go | 5 +- go-runtime/schema/subscription/analyzer.go | 119 ++++++------- go-runtime/schema/testdata/failing/failing.go | 4 +- go-runtime/schema/testdata/pubsub/go.mod | 15 ++ go-runtime/schema/testdata/pubsub/go.sum | 26 +++ go-runtime/schema/testdata/pubsub/pubsub.go | 26 +-- .../schema/testdata/pubsub/types.ftl.go | 3 + .../schema/testdata/subscriber/subscriber.go | 4 +- go-runtime/schema/topic/analyzer.go | 49 ++---- go-runtime/schema/verb/analyzer.go | 161 ++++++------------ go-runtime/server/pubsub.go | 19 +++ internal/lsp/hoveritems.go | 2 +- internal/schema/verb.go | 13 ++ jvm-runtime/testdata/go/gomodule/server.go | 4 +- jvm-runtime/testdata/go/gomodule/types.ftl.go | 38 +++++ smoketest/echo/go.mod | 30 ++++ smoketest/echo/go.sum | 22 ++- smoketest/echo/types.ftl.go | 4 +- smoketest/origin/go.mod | 15 ++ smoketest/origin/go.sum | 26 +++ smoketest/origin/origin.go | 6 +- smoketest/origin/types.ftl.go | 2 + .../src/main/java/com/example/Pulse.java | 4 - smoketest/relay/relay.go | 4 +- smoketest/relay/types.ftl.go | 9 +- 79 files changed, 1190 insertions(+), 713 deletions(-) create mode 100644 backend/controller/encryption/testdata/go/encryption/types.ftl.go create mode 100644 backend/controller/pubsub/testdata/go/publisher/types.ftl.go create mode 100644 backend/controller/pubsub/testdata/go/slow/types.ftl.go create mode 100644 backend/controller/pubsub/testdata/go/subscriber/types.ftl.go create mode 100644 frontend/cli/testdata/go/echo/types.ftl.go create mode 100644 frontend/cli/testdata/go/time/types.ftl.go create mode 100644 go-runtime/ftl/ftltest/testdata/go/outer/types.ftl.go delete mode 100644 go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub_test.go create mode 100644 go-runtime/ftl/ftltest/testdata/go/pubsub/types.ftl.go create mode 100644 go-runtime/ftl/ftltest/testdata/go/subscriber/types.ftl.go create mode 100644 go-runtime/ftl/reflection/pubsub.go create mode 100644 go-runtime/server/pubsub.go diff --git a/backend/controller/encryption/testdata/go/encryption/encryption.go b/backend/controller/encryption/testdata/go/encryption/encryption.go index dff5152d7c..b03b93e7b7 100644 --- a/backend/controller/encryption/testdata/go/encryption/encryption.go +++ b/backend/controller/encryption/testdata/go/encryption/encryption.go @@ -33,17 +33,16 @@ type Event struct { // // Used to test encryption of topic_events and async_calls tables -var Topic = ftl.Topic[Event]("topic") -var _ = ftl.Subscription(Topic, "subscription") +type Topic = ftl.TopicHandle[Event] +type Subscription = ftl.SubscriptionHandle[Topic, ConsumeClient, Event] //ftl:verb -func Publish(ctx context.Context, e Event) error { +func Publish(ctx context.Context, e Event, topic Topic) error { fmt.Printf("Publishing event: %s\n", e.Name) - return Topic.Publish(ctx, e) + return topic.Publish(ctx, e) } //ftl:verb -//ftl:subscribe subscription func Consume(ctx context.Context, e Event) error { fmt.Printf("Received event: %s\n", e.Name) if e.Name != "AliceInWonderland" { diff --git a/backend/controller/encryption/testdata/go/encryption/go.mod b/backend/controller/encryption/testdata/go/encryption/go.mod index edf700615d..dfd4b7f91f 100644 --- a/backend/controller/encryption/testdata/go/encryption/go.mod +++ b/backend/controller/encryption/testdata/go/encryption/go.mod @@ -10,17 +10,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -35,8 +40,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -44,6 +56,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/backend/controller/encryption/testdata/go/encryption/go.sum b/backend/controller/encryption/testdata/go/encryption/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/backend/controller/encryption/testdata/go/encryption/go.sum +++ b/backend/controller/encryption/testdata/go/encryption/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/backend/controller/encryption/testdata/go/encryption/types.ftl.go b/backend/controller/encryption/testdata/go/encryption/types.ftl.go new file mode 100644 index 0000000000..538f7d11cc --- /dev/null +++ b/backend/controller/encryption/testdata/go/encryption/types.ftl.go @@ -0,0 +1,29 @@ +// Code generated by FTL. DO NOT EDIT. +package encryption + +import ( + "context" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type ConsumeClient func(context.Context, Event) error + +type EchoClient func(context.Context, EchoRequest) (EchoResponse, error) + +type PublishClient func(context.Context, Event) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + Consume, + ), + reflection.ProvideResourcesForVerb( + Echo, + ), + reflection.ProvideResourcesForVerb( + Publish, + server.TopicHandle[Event]("encryption", "topic"), + ), + ) +} diff --git a/backend/controller/pubsub/testdata/go/publisher/go.mod b/backend/controller/pubsub/testdata/go/publisher/go.mod index 56adc88eb1..971ffb44be 100644 --- a/backend/controller/pubsub/testdata/go/publisher/go.mod +++ b/backend/controller/pubsub/testdata/go/publisher/go.mod @@ -10,17 +10,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -35,8 +40,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -44,6 +56,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/backend/controller/pubsub/testdata/go/publisher/go.sum b/backend/controller/pubsub/testdata/go/publisher/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/backend/controller/pubsub/testdata/go/publisher/go.sum +++ b/backend/controller/pubsub/testdata/go/publisher/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/backend/controller/pubsub/testdata/go/publisher/publisher.go b/backend/controller/pubsub/testdata/go/publisher/publisher.go index e74ecdf191..227d8e64f5 100644 --- a/backend/controller/pubsub/testdata/go/publisher/publisher.go +++ b/backend/controller/pubsub/testdata/go/publisher/publisher.go @@ -9,19 +9,19 @@ import ( ) //ftl:export -var TestTopic = ftl.Topic[PubSubEvent]("testTopic") +type TestTopic = ftl.TopicHandle[PubSubEvent] type PubSubEvent struct { Time time.Time } //ftl:verb -func PublishTen(ctx context.Context) error { +func PublishTen(ctx context.Context, topic TestTopic) error { logger := ftl.LoggerFromContext(ctx) for i := 0; i < 10; i++ { t := time.Now() logger.Infof("Publishing %v", t) - err := TestTopic.Publish(ctx, PubSubEvent{Time: t}) + err := topic.Publish(ctx, PubSubEvent{Time: t}) if err != nil { return err } @@ -30,20 +30,20 @@ func PublishTen(ctx context.Context) error { } //ftl:verb -func PublishOne(ctx context.Context) error { +func PublishOne(ctx context.Context, topic TestTopic) error { logger := ftl.LoggerFromContext(ctx) t := time.Now() logger.Infof("Publishing %v", t) - return TestTopic.Publish(ctx, PubSubEvent{Time: t}) + return topic.Publish(ctx, PubSubEvent{Time: t}) } //ftl:export -var Topic2 = ftl.Topic[PubSubEvent]("topic2") +type Topic2 = ftl.TopicHandle[PubSubEvent] //ftl:verb -func PublishOneToTopic2(ctx context.Context) error { +func PublishOneToTopic2(ctx context.Context, topic Topic2) error { logger := ftl.LoggerFromContext(ctx) t := time.Now() logger.Infof("Publishing to topic_2 %v", t) - return Topic2.Publish(ctx, PubSubEvent{Time: t}) + return topic.Publish(ctx, PubSubEvent{Time: t}) } diff --git a/backend/controller/pubsub/testdata/go/publisher/types.ftl.go b/backend/controller/pubsub/testdata/go/publisher/types.ftl.go new file mode 100644 index 0000000000..717a0b62dc --- /dev/null +++ b/backend/controller/pubsub/testdata/go/publisher/types.ftl.go @@ -0,0 +1,31 @@ +// Code generated by FTL. DO NOT EDIT. +package publisher + +import ( + "context" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type PublishOneClient func(context.Context) error + +type PublishOneToTopic2Client func(context.Context) error + +type PublishTenClient func(context.Context) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + PublishOne, + server.TopicHandle[PubSubEvent]("publisher", "testTopic"), + ), + reflection.ProvideResourcesForVerb( + PublishOneToTopic2, + server.TopicHandle[PubSubEvent]("publisher", "topic2"), + ), + reflection.ProvideResourcesForVerb( + PublishTen, + server.TopicHandle[PubSubEvent]("publisher", "testTopic"), + ), + ) +} diff --git a/backend/controller/pubsub/testdata/go/slow/go.mod b/backend/controller/pubsub/testdata/go/slow/go.mod index 3ff015de8b..9e382c6427 100644 --- a/backend/controller/pubsub/testdata/go/slow/go.mod +++ b/backend/controller/pubsub/testdata/go/slow/go.mod @@ -10,17 +10,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -35,8 +40,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -44,6 +56,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/backend/controller/pubsub/testdata/go/slow/go.sum b/backend/controller/pubsub/testdata/go/slow/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/backend/controller/pubsub/testdata/go/slow/go.sum +++ b/backend/controller/pubsub/testdata/go/slow/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/backend/controller/pubsub/testdata/go/slow/slow.go b/backend/controller/pubsub/testdata/go/slow/slow.go index 3592154bcb..d111e5e000 100644 --- a/backend/controller/pubsub/testdata/go/slow/slow.go +++ b/backend/controller/pubsub/testdata/go/slow/slow.go @@ -9,8 +9,8 @@ import ( "github.com/TBD54566975/ftl/go-runtime/ftl" // Import the FTL SDK. ) -var Topic = ftl.Topic[Event]("topic") -var _ = ftl.Subscription(Topic, "slowSubscription") +type Topic = ftl.TopicHandle[Event] +type SlowSubscription = ftl.SubscriptionHandle[Topic, ConsumeClient, Event] type Event struct { Duration int @@ -21,9 +21,9 @@ type PublishRequest struct { } //ftl:verb -func Publish(ctx context.Context, req PublishRequest) error { +func Publish(ctx context.Context, req PublishRequest, topic Topic) error { for _, duration := range req.Durations { - err := Topic.Publish(ctx, Event{Duration: duration}) + err := topic.Publish(ctx, Event{Duration: duration}) if err != nil { return err } @@ -32,7 +32,6 @@ func Publish(ctx context.Context, req PublishRequest) error { } //ftl:verb -//ftl:subscribe slowSubscription func Consume(ctx context.Context, event Event) error { for i := range event.Duration { select { diff --git a/backend/controller/pubsub/testdata/go/slow/types.ftl.go b/backend/controller/pubsub/testdata/go/slow/types.ftl.go new file mode 100644 index 0000000000..5628f9a09a --- /dev/null +++ b/backend/controller/pubsub/testdata/go/slow/types.ftl.go @@ -0,0 +1,24 @@ +// Code generated by FTL. DO NOT EDIT. +package slow + +import ( + "context" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type ConsumeClient func(context.Context, Event) error + +type PublishClient func(context.Context, PublishRequest) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + Consume, + ), + reflection.ProvideResourcesForVerb( + Publish, + server.TopicHandle[Event]("slow", "topic"), + ), + ) +} diff --git a/backend/controller/pubsub/testdata/go/subscriber/go.mod b/backend/controller/pubsub/testdata/go/subscriber/go.mod index 673b7e73c5..419cf75131 100644 --- a/backend/controller/pubsub/testdata/go/subscriber/go.mod +++ b/backend/controller/pubsub/testdata/go/subscriber/go.mod @@ -13,16 +13,21 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -37,8 +42,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -46,6 +58,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/backend/controller/pubsub/testdata/go/subscriber/go.sum b/backend/controller/pubsub/testdata/go/subscriber/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/backend/controller/pubsub/testdata/go/subscriber/go.sum +++ b/backend/controller/pubsub/testdata/go/subscriber/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/backend/controller/pubsub/testdata/go/subscriber/subscriber.go b/backend/controller/pubsub/testdata/go/subscriber/subscriber.go index 201a74fcd4..54d9cd7c57 100644 --- a/backend/controller/pubsub/testdata/go/subscriber/subscriber.go +++ b/backend/controller/pubsub/testdata/go/subscriber/subscriber.go @@ -3,48 +3,43 @@ package subscriber import ( "context" "fmt" - "strings" - "time" - "ftl/builtin" "ftl/publisher" + "strings" + "time" + "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/alecthomas/atomic" - - "github.com/TBD54566975/ftl/go-runtime/ftl" // Import the FTL SDK. + //"github.com/TBD54566975/ftl/go-runtime/ftl" // Import the FTL SDK. ) -var _ = ftl.Subscription(publisher.TestTopic, "testTopicSubscription") -var _ = ftl.Subscription(publisher.Topic2, "doomedSubscription") -var _ = ftl.Subscription(publisher.Topic2, "doomedSubscription2") +type TestTopicSubscription = ftl.SubscriptionHandle[publisher.TestTopic, ConsumeClient, publisher.PubSubEvent] +type DoomedSubscription = ftl.SubscriptionHandle[publisher.Topic2, ConsumeButFailAndRetryClient, publisher.PubSubEvent] +type DoomedSubscription2 = ftl.SubscriptionHandle[publisher.Topic2, ConsumeButFailAndCatchAnyClient, publisher.PubSubEvent] var catchCount atomic.Value[int] //ftl:verb -//ftl:subscribe testTopicSubscription func Consume(ctx context.Context, req publisher.PubSubEvent) error { ftl.LoggerFromContext(ctx).Infof("Subscriber is consuming %v", req.Time) return nil } //ftl:verb -//ftl:subscribe doomedSubscription //ftl:retry 2 1s 1s catch catch func ConsumeButFailAndRetry(ctx context.Context, req publisher.PubSubEvent) error { return fmt.Errorf("always error: event %v", req.Time) } //ftl:verb -//ftl:subscribe doomedSubscription2 //ftl:retry 1 1s 1s catch catchAny func ConsumeButFailAndCatchAny(ctx context.Context, req publisher.PubSubEvent) error { return fmt.Errorf("always error: event %v", req.Time) } //ftl:verb -func PublishToExternalModule(ctx context.Context) error { +func PublishToExternalModule(ctx context.Context, topic publisher.TestTopic) error { // Get around compile-time checks - var topic = publisher.TestTopic return topic.Publish(ctx, publisher.PubSubEvent{Time: time.Now()}) } diff --git a/backend/controller/pubsub/testdata/go/subscriber/types.ftl.go b/backend/controller/pubsub/testdata/go/subscriber/types.ftl.go new file mode 100644 index 0000000000..0e836b152c --- /dev/null +++ b/backend/controller/pubsub/testdata/go/subscriber/types.ftl.go @@ -0,0 +1,46 @@ +// Code generated by FTL. DO NOT EDIT. +package subscriber + +import ( + "context" + ftlbuiltin "ftl/builtin" + ftlpublisher "ftl/publisher" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type CatchClient func(context.Context, ftlbuiltin.CatchRequest[ftlpublisher.PubSubEvent]) error + +type CatchAnyClient func(context.Context, ftlbuiltin.CatchRequest[any]) error + +type ConsumeClient func(context.Context, ftlpublisher.PubSubEvent) error + +type ConsumeButFailAndCatchAnyClient func(context.Context, ftlpublisher.PubSubEvent) error + +type ConsumeButFailAndRetryClient func(context.Context, ftlpublisher.PubSubEvent) error + +type PublishToExternalModuleClient func(context.Context) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + Catch, + ), + reflection.ProvideResourcesForVerb( + CatchAny, + ), + reflection.ProvideResourcesForVerb( + Consume, + ), + reflection.ProvideResourcesForVerb( + ConsumeButFailAndCatchAny, + ), + reflection.ProvideResourcesForVerb( + ConsumeButFailAndRetry, + ), + reflection.ProvideResourcesForVerb( + PublishToExternalModule, + server.TopicHandle[ftlpublisher.PubSubEvent]("publisher", "testTopic"), + ), + ) +} diff --git a/docs/content/docs/reference/retries.md b/docs/content/docs/reference/retries.md index 9e943da4e2..22073e0361 100644 --- a/docs/content/docs/reference/retries.md +++ b/docs/content/docs/reference/retries.md @@ -76,7 +76,6 @@ Subscribers can have a retry policy. For example: ```go -//ftl:subscribe exampleSubscription //ftl:retry 5 1s catch recoverPaymentProcessing func ProcessPayment(ctx context.Context, payment Payment) error { ... diff --git a/frontend/cli/testdata/go/echo/echo.go b/frontend/cli/testdata/go/echo/echo.go index 23ab837b30..8752c599a4 100644 --- a/frontend/cli/testdata/go/echo/echo.go +++ b/frontend/cli/testdata/go/echo/echo.go @@ -31,9 +31,9 @@ func Echo(ctx context.Context, req EchoRequest, tc time.TimeClient) (EchoRespons return EchoResponse{Message: fmt.Sprintf("Hello, %s!!! It is %s!", req.Name.Default("world"), tresp.Time)}, nil } -var _ = ftl.Subscription(time.Invoices, "emailInvoices") +type EmailInvoices = ftl.SubscriptionHandle[time.Invoices, SendInvoiceEmailClient, time.Invoice] -//ftl:subscribe emailInvoices +//ftl:verb func SendInvoiceEmail(ctx context.Context, in time.Invoice) error { if in.Amount == 10 { return fmt.Errorf("can't process $10 invoices") diff --git a/frontend/cli/testdata/go/echo/go.mod b/frontend/cli/testdata/go/echo/go.mod index 68237172a4..635f9d6c4a 100644 --- a/frontend/cli/testdata/go/echo/go.mod +++ b/frontend/cli/testdata/go/echo/go.mod @@ -12,17 +12,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -37,8 +42,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -46,5 +58,8 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/frontend/cli/testdata/go/echo/go.sum b/frontend/cli/testdata/go/echo/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/frontend/cli/testdata/go/echo/go.sum +++ b/frontend/cli/testdata/go/echo/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/frontend/cli/testdata/go/echo/types.ftl.go b/frontend/cli/testdata/go/echo/types.ftl.go new file mode 100644 index 0000000000..d139646e13 --- /dev/null +++ b/frontend/cli/testdata/go/echo/types.ftl.go @@ -0,0 +1,25 @@ +// Code generated by FTL. DO NOT EDIT. +package echo + +import ( + "context" + ftltime "ftl/time" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type EchoClient func(context.Context, EchoRequest) (EchoResponse, error) + +type SendInvoiceEmailClient func(context.Context, ftltime.Invoice) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + Echo, + server.VerbClient[ftltime.TimeClient, ftltime.TimeRequest, ftltime.TimeResponse](), + ), + reflection.ProvideResourcesForVerb( + SendInvoiceEmail, + ), + ) +} diff --git a/frontend/cli/testdata/go/time/go.mod b/frontend/cli/testdata/go/time/go.mod index aafcc374e0..804267c300 100644 --- a/frontend/cli/testdata/go/time/go.mod +++ b/frontend/cli/testdata/go/time/go.mod @@ -12,17 +12,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -37,8 +42,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -46,5 +58,8 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/frontend/cli/testdata/go/time/go.sum b/frontend/cli/testdata/go/time/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/frontend/cli/testdata/go/time/go.sum +++ b/frontend/cli/testdata/go/time/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/frontend/cli/testdata/go/time/time.go b/frontend/cli/testdata/go/time/time.go index 962662d872..cfff6114f5 100644 --- a/frontend/cli/testdata/go/time/time.go +++ b/frontend/cli/testdata/go/time/time.go @@ -29,8 +29,8 @@ type PublishInvoiceRequest struct { } //ftl:verb -func PublishInvoice(ctx context.Context, req PublishInvoiceRequest) error { - Invoices.Publish(ctx, Invoice{Amount: req.Amount}) +func PublishInvoice(ctx context.Context, req PublishInvoiceRequest, invoices Invoices) error { + invoices.Publish(ctx, Invoice{Amount: req.Amount}) return nil } @@ -39,4 +39,4 @@ type Invoice struct { } //ftl:export -var Invoices = ftl.Topic[Invoice]("invoices") +type Invoices = ftl.TopicHandle[Invoice] diff --git a/frontend/cli/testdata/go/time/types.ftl.go b/frontend/cli/testdata/go/time/types.ftl.go new file mode 100644 index 0000000000..39d97f6eb4 --- /dev/null +++ b/frontend/cli/testdata/go/time/types.ftl.go @@ -0,0 +1,29 @@ +// Code generated by FTL. DO NOT EDIT. +package time + +import ( + "context" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type InternalClient func(context.Context, TimeRequest) (TimeResponse, error) + +type PublishInvoiceClient func(context.Context, PublishInvoiceRequest) error + +type TimeClient func(context.Context, TimeRequest) (TimeResponse, error) + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + Internal, + ), + reflection.ProvideResourcesForVerb( + PublishInvoice, + server.TopicHandle[Invoice]("time", "invoices"), + ), + reflection.ProvideResourcesForVerb( + Time, + ), + ) +} diff --git a/go-runtime/compile/build-template/.ftl.tmpl/go/main/main.go.tmpl b/go-runtime/compile/build-template/.ftl.tmpl/go/main/main.go.tmpl index 4d6317eace..6eec7950af 100644 --- a/go-runtime/compile/build-template/.ftl.tmpl/go/main/main.go.tmpl +++ b/go-runtime/compile/build-template/.ftl.tmpl/go/main/main.go.tmpl @@ -49,6 +49,9 @@ func init() { {{- end }} {{- with getDatabaseHandle . }} server.DatabaseHandle[{{.TypeName}}]("{{.Type}}"), + {{- end }} + {{- with getTopicHandle . }} + server.TopicHandle[{{.EventType.TypeName}}]("{{.Module}}", "{{.Name}}"), {{- end }} {{- end}} ), @@ -73,4 +76,4 @@ func main() { ) plugin.Start(context.Background(), "{{$name}}", verbConstructor, ftlv1connect.VerbServiceName, ftlv1connect.NewVerbServiceHandler) } -{{- end -}} \ No newline at end of file +{{- end -}} diff --git a/go-runtime/compile/build-template/types.ftl.go.tmpl b/go-runtime/compile/build-template/types.ftl.go.tmpl index 017f7d2104..06be6653cc 100644 --- a/go-runtime/compile/build-template/types.ftl.go.tmpl +++ b/go-runtime/compile/build-template/types.ftl.go.tmpl @@ -69,6 +69,9 @@ func init() { {{- end }} {{- with getDatabaseHandle . }} server.DatabaseHandle[{{ trimModuleQualifier $moduleName .TypeName }}]("{{.Type}}"), + {{- end }} + {{- with getTopicHandle . }} + server.TopicHandle[{{ trimModuleQualifier $moduleName .EventType.TypeName }}]("{{.Module}}", "{{.Name}}"), {{- end }} {{- end}} ), diff --git a/go-runtime/compile/build.go b/go-runtime/compile/build.go index eabbf4b520..391c6c2c36 100644 --- a/go-runtime/compile/build.go +++ b/go-runtime/compile/build.go @@ -112,6 +112,12 @@ func (c *mainModuleContext) generateTypesImports(mainModuleImport string) []stri imports.Add(et.importStatement()) } for _, v := range c.Verbs { + if slices.ContainsFunc(v.Resources, func(r verbResource) bool { + _, ok := r.(goTopicHandle) + return ok + }) { + imports.Add(`"github.com/TBD54566975/ftl/go-runtime/server"`) + } imports.Append(verbImports(v)...) } @@ -267,6 +273,20 @@ func (d goDBHandle) getNativeType() nativeType { return d.nativeType } +type goTopicHandle struct { + Name string + Module string + EventType goSchemaType + + nativeType +} + +func (d goTopicHandle) resource() {} + +func (d goTopicHandle) getNativeType() nativeType { + return d.nativeType +} + const buildDirName = ".ftl" func buildDir(moduleDir string) string { @@ -856,8 +876,19 @@ func (b *mainModuleContextBuilder) getVerbResource(verb *schema.Verb, param comm return goDBHandle{}, fmt.Errorf("%s.%s uses %s database handle, but %s is not a database", b.mainModule.Name, verb.Name, ref, ref) } - return b.processDatabase(ref.Module, db) + case *schema.MetadataPublisher: + resolved, ok := b.sch.Resolve(ref).Get() + if !ok { + return goTopicHandle{}, fmt.Errorf("failed to resolve %s topic, used by %s.%s", ref, + b.mainModule.Name, verb.Name) + } + topic, ok := resolved.(*schema.Topic) + if !ok { + return goTopicHandle{}, fmt.Errorf("%s.%s uses %s topic handle, but %s is not a topic", + b.mainModule.Name, verb.Name, ref, ref) + } + return b.processTopic(ref.Module, ref, topic) default: // TODO: implement other resources @@ -883,6 +914,29 @@ func (b *mainModuleContextBuilder) processDatabase(moduleName string, db *schema }, nil } +func (b *mainModuleContextBuilder) processTopic(moduleName string, ref *schema.Ref, topic *schema.Topic) (goTopicHandle, error) { + nn, ok := b.nativeNames[ref] + if !ok { + return goTopicHandle{}, fmt.Errorf("missing native name for topic %s.%s", moduleName, topic.Name) + } + + nt, err := b.getNativeType(nn) + if err != nil { + return goTopicHandle{}, err + } + + et, err := b.getGoSchemaType(topic.Event) + if err != nil { + return goTopicHandle{}, fmt.Errorf("failed to get event type for topic %s.%s: %w", moduleName, topic.Name, err) + } + return goTopicHandle{ + Name: topic.Name, + Module: moduleName, + EventType: et, + nativeType: nt, + }, nil +} + func (b *mainModuleContextBuilder) getGoVerb(nativeName string, verb *schema.Verb, resources ...verbResource) (goVerb, error) { nt, err := b.getNativeType(nativeName) if err != nil { @@ -1074,6 +1128,12 @@ var scaffoldFuncs = scaffolder.FuncMap{ } return nil }, + "getTopicHandle": func(resource verbResource) *goTopicHandle { + if c, ok := resource.(goTopicHandle); ok { + return &c + } + return nil + }, } // returns the import path and the directory name for a type alias if there is an associated go library diff --git a/go-runtime/compile/external-module-template/external_module.go.tmpl b/go-runtime/compile/external-module-template/external_module.go.tmpl index a60bb604dd..1666754897 100644 --- a/go-runtime/compile/external-module-template/external_module.go.tmpl +++ b/go-runtime/compile/external-module-template/external_module.go.tmpl @@ -23,7 +23,7 @@ var _ = context.Background // {{- end}} {{- if is "Topic" .}} -var {{.Name|title}} = ftl.Topic[{{type $.Module .Event}}]("{{.Name}}") +type {{.Name|title}} = ftl.TopicHandle[{{type $.Module .Event}}] {{- else if and (is "Enum" .) .IsValueEnum}} {{- $enumName := .Name}} //ftl:enum diff --git a/go-runtime/ftl/ftltest/fake.go b/go-runtime/ftl/ftltest/fake.go index fdd988cd71..097cfb2d80 100644 --- a/go-runtime/ftl/ftltest/fake.go +++ b/go-runtime/ftl/ftltest/fake.go @@ -76,7 +76,7 @@ func contextWithFakeFTL(ctx context.Context, options ...Option) context.Context options: options, } ctx = internal.WithContext(ctx, fake) - fake.pubSub = newFakePubSub(ctx) + // fake.pubSub = newFakePubSub(ctx) return ctx } diff --git a/go-runtime/ftl/ftltest/ftltest.go b/go-runtime/ftl/ftltest/ftltest.go index 3c6777ab5a..a182de56d3 100644 --- a/go-runtime/ftl/ftltest/ftltest.go +++ b/go-runtime/ftl/ftltest/ftltest.go @@ -416,67 +416,6 @@ func getDSNFromSecret(ftl internal.FTL, module, name string) (string, error) { return dsn, nil } -// WithSubscriber adds a subscriber during a test -// -// By default, all subscribers are disabled in unit tests, and must be manually enabled by calling WithSubscriber(…). -// This allows easy isolation for each unit test. -// -// WithSubscriber(…) can also be used to make an ad-hoc subscriber for your test by defining a new function as the sink. -// -// To be used when setting up a context for a test: -// -// ctx := ftltest.Context( -// ftltest.WithSubscriber(paymentTopic, ProcessPayment), -// // ... other options -// ) -func WithSubscriber[E any](subscription ftl.SubscriptionHandle[E], sink ftl.Sink[E]) Option { - return Option{ - rank: other, - apply: func(ctx context.Context, state *OptionsState) error { - fftl := internal.FromContext(ctx).(*fakeFTL) //nolint:forcetypeassert - addSubscriber(fftl.pubSub, subscription, sink) - return nil - }, - } -} - -// EventsForTopic returns all published events for a topic -func EventsForTopic[E any](ctx context.Context, topic ftl.TopicHandle[E]) []E { - fftl := internal.FromContext(ctx).(*fakeFTL) //nolint:forcetypeassert - return eventsForTopic(ctx, fftl.pubSub, topic) -} - -type SubscriptionResult[E any] struct { - Event E - Error ftl.Option[error] -} - -// ResultsForSubscription returns all consumed events for a subscription, with any resulting errors -func ResultsForSubscription[E any](ctx context.Context, subscription ftl.SubscriptionHandle[E]) []SubscriptionResult[E] { - fftl := internal.FromContext(ctx).(*fakeFTL) //nolint:forcetypeassert - return resultsForSubscription(ctx, fftl.pubSub, subscription) -} - -// ErrorsForSubscription returns all errors encountered while consuming events for a subscription -func ErrorsForSubscription[E any](ctx context.Context, subscription ftl.SubscriptionHandle[E]) []error { - errs := []error{} - for _, result := range ResultsForSubscription(ctx, subscription) { - if err, ok := result.Error.Get(); ok { - errs = append(errs, err) - } - } - return errs -} - -// WaitForSubscriptionsToComplete waits until all subscriptions have consumed all events -// -// Subscriptions with no manually activated subscribers are ignored. -// Make sure you have called WithSubscriber(…) for all subscriptions you want to wait for. -func WaitForSubscriptionsToComplete(ctx context.Context) { - fftl := internal.FromContext(ctx).(*fakeFTL) //nolint:forcetypeassert - fftl.pubSub.waitForSubscriptionsToComplete(ctx) -} - // Call a Verb inline, applying resources and test behavior. func Call[VerbClient, Req, Resp any](ctx context.Context, req Req) (Resp, error) { return call[VerbClient, Req, Resp](ctx, req) diff --git a/go-runtime/ftl/ftltest/ftltest_integration_test.go b/go-runtime/ftl/ftltest/ftltest_integration_test.go index 1813dd68e9..6bef01f62c 100644 --- a/go-runtime/ftl/ftltest/ftltest_integration_test.go +++ b/go-runtime/ftl/ftltest/ftltest_integration_test.go @@ -17,14 +17,14 @@ func TestModuleUnitTests(t *testing.T) { in.CopyModule("time"), in.CopyModule("wrapped"), in.CopyModule("verbtypes"), - in.CopyModule("pubsub"), - in.CopyModule("subscriber"), + // in.CopyModule("pubsub"), + // in.CopyModule("subscriber"), in.CopyModule("outer"), in.Build("time", "wrapped", "verbtypes", "pubsub", "subscriber", "outer"), in.ExecModuleTest("wrapped"), in.ExecModuleTest("verbtypes"), - in.ExecModuleTest("pubsub"), - in.ExecModuleTest("subscriber"), + // in.ExecModuleTest("pubsub"), + // in.ExecModuleTest("subscriber"), in.ExecModuleTest("outer"), ) } diff --git a/go-runtime/ftl/ftltest/pubsub.go b/go-runtime/ftl/ftltest/pubsub.go index 46b8da0633..f78bdaa711 100644 --- a/go-runtime/ftl/ftltest/pubsub.go +++ b/go-runtime/ftl/ftltest/pubsub.go @@ -67,28 +67,6 @@ func (f *fakePubSub) fetchTopicState(topic *schema.Ref) *topicState { return ts } -// addSubscriber adds a subscriber to the fake FTL instance. Each subscriber included in the test must be manually added -func addSubscriber[E any](f *fakePubSub, sub ftl.SubscriptionHandle[E], sink ftl.Sink[E]) { - f.pubSubLock.Lock() - defer f.pubSubLock.Unlock() - - if _, ok := f.subscriptions[sub.Name]; !ok { - f.subscriptions[sub.Name] = &subscription{ - name: sub.Name, - topic: sub.Topic, - errors: map[int]error{}, - } - f.fetchTopicState(sub.Topic).subscriptionCount++ - } - - f.subscribers[sub.Name] = append(f.subscribers[sub.Name], func(ctx context.Context, event any) error { - if event, ok := event.(E); ok { - return sink(ctx, event) - } - return fmt.Errorf("unexpected event type %T for subscription %s", event, sub.Name) - }) -} - // eventsForTopic returns all events published to a topic func eventsForTopic[E any](ctx context.Context, f *fakePubSub, topic ftl.TopicHandle[E]) []E { // Make sure all published events make it into our pubsub state @@ -110,41 +88,6 @@ func eventsForTopic[E any](ctx context.Context, f *fakePubSub, topic ftl.TopicHa return events } -// resultsForSubscription returns all consumed events and whether an error was returned -func resultsForSubscription[E any](ctx context.Context, f *fakePubSub, handle ftl.SubscriptionHandle[E]) []SubscriptionResult[E] { - f.pubSubLock.Lock() - defer f.pubSubLock.Unlock() - - logger := log.FromContext(ctx).Scope("pubsub") - results := []SubscriptionResult[E]{} - - subscription, ok := f.subscriptions[handle.Name] - if !ok { - return results - } - ts := f.fetchTopicState(subscription.topic) - count := subscription.cursor.Default(-1) - if !subscription.isExecuting { - count++ - } - for i := range count { - e := ts.events[i] - if event, ok := e.(E); ok { - result := SubscriptionResult[E]{ - Event: event, - } - if err, ok := subscription.errors[i]; ok { - result.Error = ftl.Some(err) - } - results = append(results, result) - } else { - logger.Warnf("unexpected event type %T for subscription %s", e, handle.Name) - } - - } - return results -} - func (f *fakePubSub) watchPubSub(ctx context.Context) { events := make(chan pubSubEvent, 128) f.globalTopic.Subscribe(events) diff --git a/go-runtime/ftl/ftltest/testdata/go/outer/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/outer/types.ftl.go new file mode 100644 index 0000000000..9b7dc4b946 --- /dev/null +++ b/go-runtime/ftl/ftltest/testdata/go/outer/types.ftl.go @@ -0,0 +1,2 @@ +// Code generated by FTL. DO NOT EDIT. +package outer diff --git a/go-runtime/ftl/ftltest/testdata/go/pubsub/go.mod b/go-runtime/ftl/ftltest/testdata/go/pubsub/go.mod index c372a5d5ee..97b87e025b 100644 --- a/go-runtime/ftl/ftltest/testdata/go/pubsub/go.mod +++ b/go-runtime/ftl/ftltest/testdata/go/pubsub/go.mod @@ -2,11 +2,7 @@ module ftl/pubsub go 1.23.0 -require ( - github.com/TBD54566975/ftl v0.0.0-00010101000000-000000000000 - github.com/alecthomas/assert/v2 v2.11.0 - github.com/alecthomas/atomic v0.1.0-alpha2 -) +require github.com/TBD54566975/ftl v0.0.0-00010101000000-000000000000 require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect @@ -14,63 +10,35 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/BurntSushi/toml v1.4.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect github.com/XSAM/otelsql v0.35.0 // indirect + github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect - github.com/alecthomas/repr v0.4.0 // indirect github.com/alecthomas/types v0.17.0 // indirect - github.com/amacneil/dbmate/v2 v2.23.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.32.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.23 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.23 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.5 // indirect - github.com/aws/smithy-go v1.22.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect - github.com/block/scaffolder v1.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/distribution/reference v0.5.0 // indirect - github.com/docker/docker v27.3.1+incompatible // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/term v0.5.0 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect github.com/swaggest/jsonschema-go v0.3.72 // indirect github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect @@ -88,7 +56,6 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.27.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.68.0 // indirect diff --git a/go-runtime/ftl/ftltest/testdata/go/pubsub/go.sum b/go-runtime/ftl/ftltest/testdata/go/pubsub/go.sum index d52c447b5f..bd5dbc0553 100644 --- a/go-runtime/ftl/ftltest/testdata/go/pubsub/go.sum +++ b/go-runtime/ftl/ftltest/testdata/go/pubsub/go.sum @@ -8,12 +8,6 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= @@ -30,18 +24,6 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/types v0.17.0 h1:7zMy/iEtxy5wyAD4UNTk60b4d6gad/3yldowx/DVQ0Y= github.com/alecthomas/types v0.17.0/go.mod h1:h+rA5USDGGu2tgggxsQgm4MmAp5Jk9opoSGetaRJ9sE= -github.com/amacneil/dbmate/v2 v2.23.0 h1:KsolutitPR4yTKHj33tdZ6Vn/bGMxXSmpg7eulBwJSc= -github.com/amacneil/dbmate/v2 v2.23.0/go.mod h1:1fPPjNwuUFqBsFjs+J8pwi9p9tpEs6ZV8kgKTSvDd90= -github.com/aws/aws-sdk-go-v2 v1.32.4 h1:S13INUiTxgrPueTmrm5DZ+MiAo99zYzHEFh1UNkOxNE= -github.com/aws/aws-sdk-go-v2 v1.32.4/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.23 h1:A2w6m6Tmr+BNXjDsr7M90zkWjsu4JXHwrzPg235STs4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.23/go.mod h1:35EVp9wyeANdujZruvHiQUAo9E3vbhnIO1mTCAxMlY0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.23 h1:pgYW9FCabt2M25MoHYCfMrVY2ghiiBKYWUVXfwZs+sU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.23/go.mod h1:c48kLgzO19wAu3CPkDWC28JbaJ+hfQlsdl7I2+oqIbk= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.5 h1:gqj99GNYzuY0jMekToqvOW1VaSupY0Qn0oj1JGSolpE= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.5/go.mod h1:FTCjaQxTVVQqLQ4ktBsLNZPnJ9pVLkJ6F0qVwtALaxk= -github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= -github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/block/scaffolder v1.3.0 h1:6oMegz48abf6CehW0NF9V0irKPTZoJNsSUTFslvuftw= @@ -52,10 +34,6 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -63,20 +41,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= -github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -120,8 +88,6 @@ github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJ github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -138,40 +104,22 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= -github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= @@ -184,8 +132,6 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6Ng github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -207,14 +153,8 @@ github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCO github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= -github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w= -github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= @@ -223,8 +163,6 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -239,55 +177,27 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= -golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= diff --git a/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub.go b/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub.go index 7a5a535368..14f1f42ad0 100644 --- a/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub.go +++ b/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub.go @@ -10,15 +10,16 @@ import ( ) //ftl:export -var Topic1 = ftl.Topic[Event]("topic1") +type Topic1 = ftl.TopicHandle[Event] //ftl:export -var Topic2 = ftl.Topic[Event]("topic2") +type Topic2 = ftl.TopicHandle[Event] -var subscription1_1 = ftl.Subscription(Topic1, "subscription_1_1") -var subscription1_2 = ftl.Subscription(Topic1, "subscription_1_2") -var subscription2_1 = ftl.Subscription(Topic2, "subscription_2_1") -var subscription2_2 = ftl.Subscription(Topic2, "subscription_2_3") +type Subscription1_1_ErrorsAfterASecond = ftl.SubscriptionHandle[Topic1, ErrorsAfterASecondClient, Event] +type Subscription1_1_PropagateToTopic2 = ftl.SubscriptionHandle[Topic1, PropagateToTopic2Client, Event] +type Subscription1_2_PropagateToTopic2 = ftl.SubscriptionHandle[Topic1, PropagateToTopic2Client, Event] +type Subscription2_1_ConsumeEvent = ftl.SubscriptionHandle[Topic2, ConsumeEventClient, Event] +type Subscription2_2_ConsumeEvent = ftl.SubscriptionHandle[Topic2, ConsumeEventClient, Event] //ftl:data type Event struct { @@ -26,13 +27,13 @@ type Event struct { } //ftl:verb -func PublishToTopicOne(ctx context.Context, event Event) error { - return Topic1.Publish(ctx, event) +func PublishToTopicOne(ctx context.Context, event Event, topic1 Topic1) error { + return topic1.Publish(ctx, event) } //ftl:verb -func PropagateToTopic2(ctx context.Context, event Event) error { - return Topic2.Publish(ctx, event) +func PropagateToTopic2(ctx context.Context, event Event, topic2 Topic2) error { + return topic2.Publish(ctx, event) } //ftl:verb @@ -40,7 +41,7 @@ func ConsumeEvent(_ context.Context, _ Event) error { return nil } -//ftl:subscribe subscription_1_1 +//ftl:verb func ErrorsAfterASecond(ctx context.Context, event Event) error { time.Sleep(1 * time.Second) return fmt.Errorf("SubscriberThatFails always fails") diff --git a/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub_test.go b/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub_test.go deleted file mode 100644 index d77467cf6a..0000000000 --- a/go-runtime/ftl/ftltest/testdata/go/pubsub/pubsub_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package pubsub - -import ( - "context" - "strconv" - "testing" - - "github.com/alecthomas/atomic" - - "github.com/TBD54566975/ftl/go-runtime/ftl" - "github.com/TBD54566975/ftl/go-runtime/ftl/ftltest" - "github.com/alecthomas/assert/v2" -) - -func TestSubscriberReturningErrors(t *testing.T) { - // Test that we can publish multiple events, which will take time to consume, and that we track each error - ctx := ftltest.Context( - ftltest.WithSubscriber(subscription1_1, ErrorsAfterASecond), - ) - count := 5 - for i := 0; i < count; i++ { - assert.NoError(t, PublishToTopicOne(ctx, Event{Value: strconv.Itoa(i)})) - } - ftltest.WaitForSubscriptionsToComplete(ctx) - assert.Equal(t, count, len(ftltest.ErrorsForSubscription(ctx, subscription1_1))) - assert.Equal(t, count, len(ftltest.EventsForTopic(ctx, Topic1))) -} - -// establishes a pubsub network that forwards from topic 1 to topic 2 on a single subscription -// and does NOT register any subscribers against topic 2's subscription -func TestForwardedEvent(t *testing.T) { - // Test that we can publish multiple events, which will take time to consume, and that we track each error - ctx := ftltest.Context( - ftltest.WithSubscriber(subscription1_1, PropagateToTopic2), - ) - assert.NoError(t, PublishToTopicOne(ctx, Event{Value: "propagation-test"})) - ftltest.WaitForSubscriptionsToComplete(ctx) - assert.Equal(t, 1, len(ftltest.EventsForTopic(ctx, Topic1))) - assert.Equal(t, 1, len(ftltest.EventsForTopic(ctx, Topic2))) -} - -// establishes a pubsub network that forwards from topic 1 to topic 2 on two subscriptions -// and does NOT register any subscribers against topic 2's subscriptions -func TestPropagatedEvent(t *testing.T) { - // Test that we can publish multiple events, which will take time to consume, and that we track each error - ctx := ftltest.Context( - ftltest.WithSubscriber(subscription1_1, PropagateToTopic2), - ftltest.WithSubscriber(subscription1_2, PropagateToTopic2), - ) - assert.NoError(t, PublishToTopicOne(ctx, Event{Value: "propagation-test"})) - ftltest.WaitForSubscriptionsToComplete(ctx) - assert.Equal(t, 1, len(ftltest.EventsForTopic(ctx, Topic1))) - assert.Equal(t, 2, len(ftltest.EventsForTopic(ctx, Topic2))) -} - -// establishes a pubsub network that forwards from topic 1 to topic 2 on two subscriptions -// and consumes from topic 2 via two subscriptions -func TestPropagationNetwork(t *testing.T) { - // Test that we can publish multiple events, which will take time to consume, and that we track each error - ctx := ftltest.Context( - ftltest.WithSubscriber(subscription1_1, PropagateToTopic2), - ftltest.WithSubscriber(subscription1_2, PropagateToTopic2), - ftltest.WithSubscriber(subscription2_1, ConsumeEvent), - ftltest.WithSubscriber(subscription2_2, ConsumeEvent), - ) - assert.NoError(t, PublishToTopicOne(ctx, Event{Value: "propagation-test"})) - ftltest.WaitForSubscriptionsToComplete(ctx) - assert.Equal(t, 1, len(ftltest.EventsForTopic(ctx, Topic1))) - assert.Equal(t, 2, len(ftltest.EventsForTopic(ctx, Topic2))) -} - -func TestMultipleMultipleFakeSubscribers(t *testing.T) { - // Test that multiple adhoc subscribers can be added for a subscription - count := 5 - var counter atomic.Value[int] - - ctx := ftltest.Context( - ftltest.WithSubscriber(subscription1_1, func(ctx context.Context, event Event) error { - ftl.LoggerFromContext(ctx).Infof("Fake Subscriber A") - current := counter.Load() - counter.Store(current + 1) - return nil - }), - ftltest.WithSubscriber(subscription1_1, func(ctx context.Context, event Event) error { - ftl.LoggerFromContext(ctx).Infof("Fake Subscriber B") - current := counter.Load() - counter.Store(current + 1) - return nil - }), - ) - for i := 0; i < count; i++ { - assert.NoError(t, PublishToTopicOne(ctx, Event{Value: strconv.Itoa(i)})) - } - ftltest.WaitForSubscriptionsToComplete(ctx) - assert.Equal(t, 0, len(ftltest.ErrorsForSubscription(ctx, subscription1_1))) - assert.Equal(t, count, len(ftltest.EventsForTopic(ctx, Topic1))) - assert.Equal(t, count, counter.Load()) -} diff --git a/go-runtime/ftl/ftltest/testdata/go/pubsub/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/pubsub/types.ftl.go new file mode 100644 index 0000000000..1f4dc989de --- /dev/null +++ b/go-runtime/ftl/ftltest/testdata/go/pubsub/types.ftl.go @@ -0,0 +1,35 @@ +// Code generated by FTL. DO NOT EDIT. +package pubsub + +import ( + "context" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" +) + +type ConsumeEventClient func(context.Context, Event) error + +type ErrorsAfterASecondClient func(context.Context, Event) error + +type PropagateToTopic2Client func(context.Context, Event) error + +type PublishToTopicOneClient func(context.Context, Event) error + +func init() { + reflection.Register( + reflection.ProvideResourcesForVerb( + ConsumeEvent, + ), + reflection.ProvideResourcesForVerb( + ErrorsAfterASecond, + ), + reflection.ProvideResourcesForVerb( + PropagateToTopic2, + server.TopicHandle[Event]("pubsub", "topic2"), + ), + reflection.ProvideResourcesForVerb( + PublishToTopicOne, + server.TopicHandle[Event]("pubsub", "topic1"), + ), + ) +} diff --git a/go-runtime/ftl/ftltest/testdata/go/subscriber/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/subscriber/types.ftl.go new file mode 100644 index 0000000000..40c5322122 --- /dev/null +++ b/go-runtime/ftl/ftltest/testdata/go/subscriber/types.ftl.go @@ -0,0 +1,2 @@ +// Code generated by FTL. DO NOT EDIT. +package subscriber diff --git a/go-runtime/ftl/ftltest/testdata/go/time/go.mod b/go-runtime/ftl/ftltest/testdata/go/time/go.mod index a492f68a1d..99f73a5add 100644 --- a/go-runtime/ftl/ftltest/testdata/go/time/go.mod +++ b/go-runtime/ftl/ftltest/testdata/go/time/go.mod @@ -7,12 +7,42 @@ replace github.com/TBD54566975/ftl => ./../../../../../.. require github.com/TBD54566975/ftl v0.0.0-00010101000000-000000000000 require ( + al.essio.dev/pkg/shellescape v1.5.1 // indirect + connectrpc.com/connect v1.16.2 // indirect + connectrpc.com/grpcreflect v1.2.0 // indirect + connectrpc.com/otelconnect v0.7.1 // indirect + github.com/alecthomas/atomic v0.1.0-alpha2 // indirect + github.com/alecthomas/concurrency v0.0.2 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect + github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.1 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect github.com/swaggest/jsonschema-go v0.3.72 // indirect github.com/swaggest/refl v1.3.0 // indirect + github.com/zalando/go-keyring v0.2.6 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/go-runtime/ftl/ftltest/testdata/go/time/go.sum b/go-runtime/ftl/ftltest/testdata/go/time/go.sum index b12117fb18..51229e8c30 100644 --- a/go-runtime/ftl/ftltest/testdata/go/time/go.sum +++ b/go-runtime/ftl/ftltest/testdata/go/time/go.sum @@ -8,6 +8,8 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= +github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= @@ -26,6 +28,7 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -36,6 +39,7 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -58,6 +62,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= @@ -114,8 +120,13 @@ github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/swaggest/jsonschema-go v0.3.72 h1:IHaGlR1bdBUBPfhe4tfacN2TGAPKENEGiNyNzvnVHv4= @@ -134,6 +145,10 @@ go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= @@ -148,6 +163,7 @@ golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= @@ -160,10 +176,12 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1: google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/go-runtime/ftl/ftltest/testdata/go/time/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/time/types.ftl.go index 145db63b6d..720ff760f3 100644 --- a/go-runtime/ftl/ftltest/testdata/go/time/types.ftl.go +++ b/go-runtime/ftl/ftltest/testdata/go/time/types.ftl.go @@ -2,11 +2,11 @@ package time import ( - "context" + "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" ) -type TimeClient func(context.Context, TimeRequest) (TimeResponse, error) +type TimeClient = ftl.Verb[TimeRequest, TimeResponse] func init() { reflection.Register( diff --git a/go-runtime/ftl/ftltest/testdata/go/verbtypes/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/verbtypes/types.ftl.go index 3d767c714e..2086ec0185 100644 --- a/go-runtime/ftl/ftltest/testdata/go/verbtypes/types.ftl.go +++ b/go-runtime/ftl/ftltest/testdata/go/verbtypes/types.ftl.go @@ -2,44 +2,43 @@ package verbtypes import ( - "context" - - "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" - "github.com/TBD54566975/ftl/go-runtime/server" + "github.com/TBD54566975/ftl/go-runtime/ftl" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" ) -type CalleeVerbClient func(context.Context, Request) (Response, error) +type CalleeVerbClient = ftl.Verb[Request, Response] -type CallerVerbClient func(context.Context, Request) (Response, error) +type CallerVerbClient = ftl.Verb[Request, Response] -type EmptyClient func(context.Context) error +type EmptyClient = ftl.Empty -type SinkClient func(context.Context, Request) error +type SinkClient = ftl.Sink[Request] -type SourceClient func(context.Context) (Response, error) +type SourceClient = ftl.Source[Response] -type VerbClient func(context.Context, Request) (Response, error) +type VerbClient = ftl.Verb[Request, Response] func init() { reflection.Register( reflection.ProvideResourcesForVerb( - CalleeVerb, + CalleeVerb, ), reflection.ProvideResourcesForVerb( - CallerVerb, - server.VerbClient[CalleeVerbClient, Request, Response](), + CallerVerb, + server.VerbClient[CalleeVerbClient, Request, Response](), ), reflection.ProvideResourcesForVerb( - Empty, + Empty, ), reflection.ProvideResourcesForVerb( - Sink, + Sink, ), reflection.ProvideResourcesForVerb( - Source, + Source, ), reflection.ProvideResourcesForVerb( - Verb, + Verb, ), ) -} \ No newline at end of file +} diff --git a/go-runtime/ftl/ftltest/testdata/go/wrapped/types.ftl.go b/go-runtime/ftl/ftltest/testdata/go/wrapped/types.ftl.go index 0d46705618..e62b54e95b 100644 --- a/go-runtime/ftl/ftltest/testdata/go/wrapped/types.ftl.go +++ b/go-runtime/ftl/ftltest/testdata/go/wrapped/types.ftl.go @@ -2,15 +2,15 @@ package wrapped import ( - "context" ftltime "ftl/time" + "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" "github.com/TBD54566975/ftl/go-runtime/server" ) -type InnerClient func(context.Context) (WrappedResponse, error) +type InnerClient = ftl.Source[WrappedResponse] -type OuterClient func(context.Context) (WrappedResponse, error) +type OuterClient = ftl.Source[WrappedResponse] func init() { reflection.Register( diff --git a/go-runtime/ftl/pubsub.go b/go-runtime/ftl/pubsub.go index dc6c91b630..dbda844d66 100644 --- a/go-runtime/ftl/pubsub.go +++ b/go-runtime/ftl/pubsub.go @@ -3,21 +3,13 @@ package ftl import ( "context" - "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" "github.com/TBD54566975/ftl/go-runtime/internal" "github.com/TBD54566975/ftl/internal/schema" ) -// Topic declares a topic +// TopicHandle accesses a topic // // Topics publish events, and subscriptions can listen to them. -func Topic[E any](name string) TopicHandle[E] { - return TopicHandle[E]{Ref: &schema.Ref{ - Name: name, - Module: reflection.Module(), - }} -} - type TopicHandle[E any] struct { Ref *schema.Ref } @@ -27,14 +19,9 @@ func (t TopicHandle[E]) Publish(ctx context.Context, event E) error { return internal.FromContext(ctx).PublishEvent(ctx, t.Ref, event) } -type SubscriptionHandle[E any] struct { - Topic *schema.Ref - Name string -} - -// Subscription declares a subscription to a topic -// -// Sinks can consume events from the subscription by including a "ftl:subscibe " directive -func Subscription[E any](topic TopicHandle[E], name string) SubscriptionHandle[E] { - return SubscriptionHandle[E]{Name: name, Topic: topic.Ref} +// SubscriptionHandle declares a subscription to a topic for the provided Sink +// T: the topic handle type +// S: the generated sink client type +// E: the event type +type SubscriptionHandle[T TopicHandle[E], S, E any] struct { } diff --git a/go-runtime/ftl/reflection/pubsub.go b/go-runtime/ftl/reflection/pubsub.go new file mode 100644 index 0000000000..71c2ed4a1d --- /dev/null +++ b/go-runtime/ftl/reflection/pubsub.go @@ -0,0 +1 @@ +package reflection diff --git a/go-runtime/schema/common/common.go b/go-runtime/schema/common/common.go index 54917249c8..9f254c6666 100644 --- a/go-runtime/schema/common/common.go +++ b/go-runtime/schema/common/common.go @@ -24,6 +24,12 @@ var ( FtlUnitTypePath = "github.com/TBD54566975/ftl/go-runtime/ftl.Unit" // FtlOptionTypePath is the path to the FTL option type. FtlOptionTypePath = "github.com/TBD54566975/ftl/go-runtime/ftl.Option" + // FtlDatabaseHandlePath is the path to the FTL database handle type. + FtlDatabaseHandlePath = "github.com/TBD54566975/ftl/go-runtime/ftl.DatabaseHandle" + // FtlTopicHandlePath is the path to the FTL topic handle type. + FtlTopicHandlePath = "github.com/TBD54566975/ftl/go-runtime/ftl.TopicHandle" + // FtlSubscriptionHandlePath is the path to the FTL subscription handle type. + FtlSubscriptionHandlePath = "github.com/TBD54566975/ftl/go-runtime/ftl.SubscriptionHandle" extractorRegistery = xsync.NewMapOf[reflect.Type, ExtractDeclFunc[schema.Decl, ast.Node]]() ) @@ -78,7 +84,7 @@ func NewResourceDeclExtractor[T schema.Decl](name string, extractFunc ExtractRes return NewExtractor(name, (*DefaultFact[Tag])(nil), runExtractResourceDeclsFunc[T](extractFunc, matchFn)) } -type matchFunc func(pass *analysis.Pass, node ast.Node) bool +type matchFunc func(pass *analysis.Pass, node ast.Node, obj types.Object) bool // ExtractResourceDeclFunc extracts a schema resource declaration from the given node. type ExtractResourceDeclFunc[T schema.Decl] func(pass *analysis.Pass, object types.Object, node *ast.TypeSpec) optional.Option[T] @@ -157,7 +163,7 @@ func runExtractResourceDeclsFunc[T schema.Decl](extractFunc ExtractResourceDeclF return } - if !matchFunc(pass, node) { + if !matchFunc(pass, node, obj) { return } decl := extractFunc(pass, obj, node) @@ -264,6 +270,27 @@ func IsPathInModule(pkg *types.Package, path string) bool { return pkg.Path() == path || strings.HasPrefix(path, "ftl/"+moduleName+"/") } +// ExtractSimpleRefWithCasing extracts a ref with only a name and module from the given node. +// The name is transformed using the provided `applyCasing` function. +func ExtractSimpleRefWithCasing(pass *analysis.Pass, node ast.Expr, applyCasing func(s string) string) optional.Option[*schema.Ref] { + obj, ok := GetObjectForNode(pass.TypesInfo, node).Get() + if !ok { + return optional.None[*schema.Ref]() + } + module, err := FtlModuleFromGoPackage(obj.Pkg().Path()) + if err != nil { + Wrapf(pass, node, err, "could not determine module for type") + return optional.None[*schema.Ref]() + } + ref := &schema.Ref{ + Pos: GoPosToSchemaPos(pass.Fset, node.Pos()), + Module: module, + Name: applyCasing(obj.Name()), + } + MarkIncludeNativeName(pass, obj, ref) + return optional.Some(ref) +} + // ExtractType extracts the schema type for the given node. func ExtractType(pass *analysis.Pass, node ast.Node) optional.Option[schema.Type] { maybeType := extractType(pass, node) @@ -422,6 +449,17 @@ func extractSelectorType(pass *analysis.Pass, node ast.Node, typ *ast.SelectorEx return optional.Some[schema.Type](&schema.Optional{ Pos: GoPosToSchemaPos(pass.Fset, node.Pos()), }) + case FtlTopicHandlePath, FtlSubscriptionHandlePath: + t, ok := extractRef(pass, node).Get() + if !ok { + return optional.None[schema.Type]() + } + ref, ok := t.(*schema.Ref) + if !ok { + return optional.None[schema.Type]() + } + ref.Name = strcase.ToLowerCamel(ref.Name) + return optional.Some[schema.Type](ref) default: // Data ref if IsPathInModule(pass.Pkg, path) { @@ -792,13 +830,79 @@ func IsMysqlDatabaseConfigType(pass *analysis.Pass, typ types.Type) bool { return implementsType(pass, typ, "github.com/TBD54566975/ftl/go-runtime/ftl", "MySQLDatabaseConfig") } +type VerbResourceType int + +const ( + VerbResourceTypeNone VerbResourceType = iota + VerbResourceTypeVerbClient + VerbResourceTypeDatabaseHandle + VerbResourceTypeTopicHandle + VerbResourceTypeSubscriptionHandle +) + +func GetVerbResourceType(pass *analysis.Pass, obj types.Object) VerbResourceType { + if obj == nil { + return VerbResourceTypeNone + } + if obj.Pkg() == nil { + return VerbResourceTypeNone + } + + switch t := obj.Type().(type) { + case *types.Named: + switch { + case isDatabaseHandleType(pass, t): + return VerbResourceTypeDatabaseHandle + case t.Obj().Pkg().Path()+"."+t.Obj().Name() == FtlTopicHandlePath: + return VerbResourceTypeTopicHandle + case t.Obj().Pkg().Path()+"."+t.Obj().Name() == FtlSubscriptionHandlePath: + return VerbResourceTypeSubscriptionHandle + } + + if _, ok := t.Underlying().(*types.Signature); !ok { + return VerbResourceTypeNone + } + + return VerbResourceTypeVerbClient + case *types.Alias: + named, ok := t.Rhs().(*types.Named) + if !ok { + return VerbResourceTypeNone + } + return GetVerbResourceType(pass, named.Obj()) + + default: + return VerbResourceTypeNone + } +} + +func isDatabaseHandleType(pass *analysis.Pass, named *types.Named) bool { + if named.Obj().Pkg().Path()+"."+named.Obj().Name() != FtlDatabaseHandlePath { + return false + } + + if named.TypeParams().Len() != 1 { + return false + } + typeArg := named.TypeParams().At(0) + + // type argument implements `DatabaseConfig`, e.g. DatabaseHandle[MyConfig] where MyConfig implements DatabaseConfig + return IsDatabaseConfigType(pass, typeArg) +} + func implementsType(pass *analysis.Pass, typ types.Type, pkg string, name string) bool { + if basic, ok := typ.(*types.Basic); ok && basic.Kind() == types.Invalid { + return false + + } + if alias, ok := typ.(*types.Alias); ok { + return implementsType(pass, alias.Rhs(), pkg, name) + } ityp, ok := loadRefFromImports(pass, pkg, name).Get() if !ok { return false } - res := types.Implements(typ, ityp) || types.Implements(types.NewPointer(typ), ityp) - return res + return types.Implements(typ, ityp) || types.Implements(types.NewPointer(typ), ityp) } // Lazy load the compile-time reference from a package if it is imported by the package in this pass. diff --git a/go-runtime/schema/common/directive.go b/go-runtime/schema/common/directive.go index d14584a75b..845c6de609 100644 --- a/go-runtime/schema/common/directive.go +++ b/go-runtime/schema/common/directive.go @@ -252,29 +252,6 @@ func (d *DirectiveRetry) Catch() optional.Option[schema.Ref] { }) } -// DirectiveSubscriber is used to subscribe a sink to a subscription -type DirectiveSubscriber struct { - Pos token.Pos - - Name string `parser:"'subscribe' @Ident"` -} - -func (*DirectiveSubscriber) directive() {} - -func (d *DirectiveSubscriber) String() string { - return fmt.Sprintf("subscribe %s", d.Name) -} -func (*DirectiveSubscriber) GetTypeName() string { return "subscribe" } -func (d *DirectiveSubscriber) SetPosition(pos token.Pos) { - d.Pos = pos -} -func (d *DirectiveSubscriber) GetPosition() token.Pos { - return d.Pos -} -func (*DirectiveSubscriber) MustAnnotate() []ast.Node { - return []ast.Node{&ast.FuncDecl{}} -} - // DirectiveExport is used on declarations that don't include export in other directives. type DirectiveExport struct { Pos token.Pos @@ -353,7 +330,7 @@ var DirectiveParser = participle.MustBuild[directiveWrapper]( participle.Unquote(), participle.UseLookahead(2), participle.Union[Directive](&DirectiveVerb{}, &DirectiveData{}, &DirectiveEnum{}, &DirectiveTypeAlias{}, - &DirectiveIngress{}, &DirectiveCronJob{}, &DirectiveRetry{}, &DirectiveSubscriber{}, &DirectiveExport{}, + &DirectiveIngress{}, &DirectiveCronJob{}, &DirectiveRetry{}, &DirectiveExport{}, &DirectiveTypeMap{}, &DirectiveEncoding{}), participle.Union[schema.IngressPathComponent](&schema.IngressPathLiteral{}, &schema.IngressPathParameter{}), ) diff --git a/go-runtime/schema/common/fact.go b/go-runtime/schema/common/fact.go index eba01bbc57..1d62ac9263 100644 --- a/go-runtime/schema/common/fact.go +++ b/go-runtime/schema/common/fact.go @@ -167,6 +167,16 @@ type VerbResourceParam struct { func (*VerbResourceParamOrder) schemaFactValue() {} +// SubscriptionSink marks a subscription with its corresponding sink. +type SubscriptionSink struct { + // The subscription corresponding to this object. + Subscription *schema.Subscription + // The name of the subscribing verb. + SinkName string +} + +func (*SubscriptionSink) schemaFactValue() {} + // MarkSchemaDecl marks the given object as having been extracted to the given schema decl. func MarkSchemaDecl(pass *analysis.Pass, obj types.Object, decl schema.Decl) { fact := newFact(pass, obj) @@ -245,6 +255,13 @@ func MarkVerbResourceParamOrder(pass *analysis.Pass, obj types.Object, resources pass.ExportObjectFact(obj, fact) } +// MarkSubscriptionSink marks the given subscription with its sink. +func MarkSubscriptionSink(pass *analysis.Pass, obj types.Object, sinkName string, sub *schema.Subscription) { + fact := newFact(pass, obj) + fact.Add(&SubscriptionSink{SinkName: sinkName, Subscription: sub}) + pass.ExportObjectFact(obj, fact) +} + // GetAllFactsExtractionStatus merges schema facts inclusive of all available results and the present pass facts. // For a given object, it provides the current extraction status. // diff --git a/go-runtime/schema/database/analyzer.go b/go-runtime/schema/database/analyzer.go index ead98cce41..43262f4121 100644 --- a/go-runtime/schema/database/analyzer.go +++ b/go-runtime/schema/database/analyzer.go @@ -53,18 +53,22 @@ func extractDatabase( common.Errorf(pass, node, "invalid database name %q", name) return optional.None[*schema.Database]() } + if name == "" { + common.Errorf(pass, node.Type, "database config must provide a name") + return optional.None[*schema.Database]() + } db.Name = name } } + // not a DB if db.Name == "" { - common.Errorf(pass, node.Type, "database config must provide a name") return optional.None[*schema.Database]() } return optional.Some(db) } -func matchFunc(pass *analysis.Pass, node ast.Node) bool { +func matchFunc(pass *analysis.Pass, node ast.Node, obj types.Object) bool { return getDBType(pass, node) != none } diff --git a/go-runtime/schema/extract.go b/go-runtime/schema/extract.go index 77929a05dd..87b5b8e44a 100644 --- a/go-runtime/schema/extract.go +++ b/go-runtime/schema/extract.go @@ -156,6 +156,7 @@ type combinedData struct { refResults map[schema.RefKey]refResult extractedDecls map[schema.Decl]types.Object externalTypeAliases sets.Set[*schema.TypeAlias] + sinksToSubscriptions map[string]*schema.Subscription // for detecting duplicates typeUniqueness map[string]tuple.Pair[types.Object, schema.Position] globalUniqueness map[string]tuple.Pair[types.Object, schema.Position] @@ -166,6 +167,7 @@ func newCombinedData(diagnostics []analysis.SimpleDiagnostic) *combinedData { errs: diagnosticsToSchemaErrors(diagnostics), nativeNames: make(NativeNames), functionCalls: make(map[schema.Position]finalize.FunctionCall), + sinksToSubscriptions: make(map[string]*schema.Subscription), verbs: make(map[types.Object]*schema.Verb), verbResourceParamOrder: make(map[*schema.Verb][]common.VerbResourceParam), refResults: make(map[schema.RefKey]refResult), @@ -189,6 +191,7 @@ func (cd *combinedData) update(fr finalize.Result) { maps.Copy(cd.nativeNames, fr.NativeNames) maps.Copy(cd.functionCalls, fr.FunctionCalls) maps.Copy(cd.verbResourceParamOrder, fr.VerbResourceParamOrder) + maps.Copy(cd.sinksToSubscriptions, fr.SinksToSubscriptions) } func (cd *combinedData) toResult() Result { @@ -351,6 +354,14 @@ func combineAllPackageResults(results map[*analysis.Analyzer][]any, diagnostics } case *schema.Verb: cd.verbs[obj] = d + if sub, ok := cd.sinksToSubscriptions[d.Name]; ok { + d.AddSubscription(&schema.MetadataSubscriber{ + Pos: sub.Position(), + Name: sub.Name, + }) + } + case *schema.Subscription: + default: } } diff --git a/go-runtime/schema/finalize/analyzer.go b/go-runtime/schema/finalize/analyzer.go index 47fb1c03ec..24bf15a58f 100644 --- a/go-runtime/schema/finalize/analyzer.go +++ b/go-runtime/schema/finalize/analyzer.go @@ -39,6 +39,8 @@ type Result struct { FunctionCalls map[schema.Position]FunctionCall // VerbResourceParamOrder contains the order of resource parameters for each verb. VerbResourceParamOrder map[*schema.Verb][]common.VerbResourceParam + // SinksToSubscriptions maps sink names to subscription names. + SinksToSubscriptions map[string]*schema.Subscription } type FunctionCall struct { @@ -57,6 +59,7 @@ func Run(pass *analysis.Pass) (interface{}, error) { declKeys := make(map[string]types.Object) nativeNames := make(map[schema.Node]string) verbParamOrder := make(map[*schema.Verb][]common.VerbResourceParam) + sinks := make(map[string]*schema.Subscription) for obj, fact := range common.GetAllFactsExtractionStatus(pass) { switch f := fact.(type) { case *common.ExtractedDecl: @@ -91,6 +94,10 @@ func Run(pass *analysis.Pass) (interface{}, error) { nativeNames[fact.Node] = common.GetNativeName(obj) } } + for _, facts := range common.GetAllFactsOfType[*common.SubscriptionSink](pass) { + fact := facts[0] + sinks[fact.SinkName] = fact.Subscription + } return Result{ ModuleName: moduleName, ModuleComments: extractModuleComments(pass), @@ -99,6 +106,7 @@ func Run(pass *analysis.Pass) (interface{}, error) { NativeNames: nativeNames, FunctionCalls: getFunctionCalls(pass), VerbResourceParamOrder: verbParamOrder, + SinksToSubscriptions: sinks, }, nil } diff --git a/go-runtime/schema/metadata/analyzer.go b/go-runtime/schema/metadata/analyzer.go index b2ca585c87..e9d4b04fbf 100644 --- a/go-runtime/schema/metadata/analyzer.go +++ b/go-runtime/schema/metadata/analyzer.go @@ -126,12 +126,6 @@ func extractMetadata(pass *analysis.Pass, node ast.Node, doc *ast.CommentGroup) MaxBackoff: dt.MaxBackoff, Catch: dt.Catch().Ptr(), }) - case *common.DirectiveSubscriber: - newSchType = &schema.Verb{} - metadata = append(metadata, &schema.MetadataSubscriber{ - Pos: common.GoPosToSchemaPos(pass.Fset, dt.Pos), - Name: dt.Name, - }) case *common.DirectiveTypeMap: newSchType = &schema.TypeAlias{} metadata = append(metadata, &schema.MetadataTypeMap{ diff --git a/go-runtime/schema/schema_integration_test.go b/go-runtime/schema/schema_integration_test.go index 936f1fb101..6070694e3e 100644 --- a/go-runtime/schema/schema_integration_test.go +++ b/go-runtime/schema/schema_integration_test.go @@ -420,8 +420,10 @@ func testExtractModulePubSub(t *testing.T) { } export verb broadcast(Unit) Unit + +publish pubsub.publicBroadcast verb payin(Unit) Unit + +publish pubsub.payins verb processBroadcast(pubsub.PayinEvent) Unit +subscribe broadcastSubscription @@ -565,7 +567,8 @@ func testErrorReporting(t *testing.T) { `146:6-45: enum discriminator "TypeEnum3" cannot contain exported methods`, `149:6-35: enum discriminator "NoMethodsTypeEnum" must define at least one method`, `161:3-14: unexpected token "d"`, - `168:2-62: can not publish directly to topics in other modules`, + // todo: do we want this? why do we support exporting topics if so? + //`168:2-62: can not publish directly to topics in other modules`, `174:2-12: struct field unexported must be exported by starting with an uppercase letter`, `178:6: unsupported type "ftl/failing/child.BadChildStruct" for field "child"`, `183:6: duplicate data declaration for "failing.Redeclared"; already declared at "27:6"`, diff --git a/go-runtime/schema/subscription/analyzer.go b/go-runtime/schema/subscription/analyzer.go index 23d5207daf..ad3eb9898e 100644 --- a/go-runtime/schema/subscription/analyzer.go +++ b/go-runtime/schema/subscription/analyzer.go @@ -3,6 +3,7 @@ package subscription import ( "go/ast" "go/types" + "strings" "github.com/TBD54566975/golang-tools/go/analysis" "github.com/alecthomas/types/optional" @@ -12,80 +13,80 @@ import ( "github.com/TBD54566975/ftl/internal/schema/strcase" ) -const ( - ftlSubscriptionFuncPath = "github.com/TBD54566975/ftl/go-runtime/ftl.Subscription" -) - // Extractor extracts subscriptions. -var Extractor = common.NewCallDeclExtractor[*schema.Subscription]("subscription", Extract, ftlSubscriptionFuncPath) +var Extractor = common.NewResourceDeclExtractor[*schema.Subscription]("subscription", Extract, matchFunc) -// expects: var _ = ftl.Subscription(topicHandle, "name_literal") -func Extract(pass *analysis.Pass, obj types.Object, node *ast.GenDecl, callExpr *ast.CallExpr, - callPath string) optional.Option[*schema.Subscription] { - var topicRef *schema.Ref - if len(callExpr.Args) != 2 { - common.Errorf(pass, callExpr, "subscription registration must have exactly two arguments") +func Extract(pass *analysis.Pass, obj types.Object, node *ast.TypeSpec) optional.Option[*schema.Subscription] { + idxListExpr, ok := node.Type.(*ast.IndexListExpr) + if !ok { + common.Errorf(pass, node, "unsupported subscription type") return optional.None[*schema.Subscription]() } - if topicIdent, ok := callExpr.Args[0].(*ast.Ident); ok { - // Topic is within module - // we will find the subscription name from the string literal parameter - object := pass.TypesInfo.ObjectOf(topicIdent) - fact, ok := common.GetFactForObject[*common.ExtractedDecl](pass, object).Get() - if !ok || fact.Decl == nil { - common.Errorf(pass, callExpr, "could not find topic declaration for topic variable") - return optional.None[*schema.Subscription]() - } - topic, ok := fact.Decl.(*schema.Topic) - if !ok { - common.Errorf(pass, callExpr, "could not find topic declaration for topic variable") - return optional.None[*schema.Subscription]() - } - moduleName, err := common.FtlModuleFromGoPackage(pass.Pkg.Path()) - if err != nil { - return optional.None[*schema.Subscription]() - } - topicRef = &schema.Ref{ - Module: moduleName, - Name: topic.Name, - } - } else if topicSelExp, ok := callExpr.Args[0].(*ast.SelectorExpr); ok { - // External topic - // we will derive subscription name from generated variable name - moduleIdent, moduleOk := topicSelExp.X.(*ast.Ident) - if !moduleOk { - common.Errorf(pass, callExpr, "subscription registration must have a topic") - return optional.None[*schema.Subscription]() - } - varName := topicSelExp.Sel.Name - if varName == "" { - common.Errorf(pass, callExpr, "subscription registration must have a topic") - return optional.None[*schema.Subscription]() - } - name := strcase.ToLowerCamel(varName) - topicRef = &schema.Ref{ - Module: moduleIdent.Name, - Name: name, - } - } else { - common.Errorf(pass, callExpr, "subscription registration must have a topic") + if len(idxListExpr.Indices) != 3 { + common.Errorf(pass, node, "subscription type must have exactly three type parameters") return optional.None[*schema.Subscription]() } - subName := common.ExtractStringLiteralArg(pass, callExpr, 1) - expSubName := strcase.ToLowerCamel(subName) - if subName != expSubName { - common.Errorf(pass, node, "unsupported subscription name %q, did you mean to use %q?", subName, expSubName) + topicRef, ok := common.ExtractSimpleRefWithCasing(pass, idxListExpr.Indices[0], strcase.ToLowerCamel).Get() + if !ok { + common.Errorf(pass, node, "unsupported topic type; please declare topics on a separate line: `MyTopic = ftl.TopicHandle[MyEvent]`, then use `MyTopic` in the subscription") return optional.None[*schema.Subscription]() } + subscription := &schema.Subscription{ - Pos: common.GoPosToSchemaPos(pass.Fset, callExpr.Pos()), - Name: subName, + Pos: common.GoPosToSchemaPos(pass.Fset, node.Pos()), + Name: strcase.ToLowerCamel(node.Name.Name), Topic: topicRef, } common.ApplyMetadata[*schema.Subscription](pass, obj, func(md *common.ExtractedMetadata) { subscription.Comments = md.Comments }) + sinkName := getSubscribingVerbName(pass, idxListExpr.Indices[1]) + if sinkName == "" || !schema.ValidateName(sinkName) { + common.Errorf(pass, node, "unsupported sink for subscription; please provide the generated "+ + "client corresponding to the verb sink") + return optional.None[*schema.Subscription]() + } + common.MarkSubscriptionSink(pass, obj, sinkName, subscription) return optional.Some(subscription) } + +func getSubscribingVerbName(pass *analysis.Pass, subscriber ast.Expr) string { + obj, ok := common.GetObjectForNode(pass.TypesInfo, subscriber).Get() + if !ok { + return "" + } + tn, ok := obj.(*types.TypeName) + if !ok { + return "" + } + named, ok := tn.Type().(*types.Named) + if !ok { + return "" + } + if _, ok := named.Underlying().(*types.Signature); !ok { + return "" + } + module, err := common.FtlModuleFromGoPackage(obj.Pkg().Path()) + if err != nil { + return "" + } + passModule, err := common.FtlModuleFromGoPackage(pass.Pkg.Path()) + if err != nil { + return "" + } + if module != passModule { + common.Errorf(pass, subscriber, "sink must be in the same module as the subscription") + return "" + } + ident, ok := subscriber.(*ast.Ident) + if !ok { + return "" + } + return strings.TrimSuffix(strcase.ToLowerCamel(ident.Name), "Client") +} + +func matchFunc(pass *analysis.Pass, node ast.Node, obj types.Object) bool { + return common.GetVerbResourceType(pass, obj) == common.VerbResourceTypeSubscriptionHandle +} diff --git a/go-runtime/schema/testdata/failing/failing.go b/go-runtime/schema/testdata/failing/failing.go index 868e17fedd..6a1627576d 100644 --- a/go-runtime/schema/testdata/failing/failing.go +++ b/go-runtime/schema/testdata/failing/failing.go @@ -164,8 +164,8 @@ func DaysNotPossible(ctx context.Context) error { } //ftl:verb -func BadPublish(ctx context.Context) error { - ps.PublicBroadcast.Publish(ctx, ps.PayinEvent{Name: "Test"}) +func BadPublish(ctx context.Context, topic ps.PublicBroadcast) error { + topic.Publish(ctx, ps.PayinEvent{Name: "Test"}) return ps.Broadcast(ctx) } diff --git a/go-runtime/schema/testdata/pubsub/go.mod b/go-runtime/schema/testdata/pubsub/go.mod index a0d02a88fa..48938d8c39 100644 --- a/go-runtime/schema/testdata/pubsub/go.mod +++ b/go-runtime/schema/testdata/pubsub/go.mod @@ -10,17 +10,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -35,8 +40,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -44,6 +56,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/go-runtime/schema/testdata/pubsub/go.sum b/go-runtime/schema/testdata/pubsub/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/go-runtime/schema/testdata/pubsub/go.sum +++ b/go-runtime/schema/testdata/pubsub/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go-runtime/schema/testdata/pubsub/pubsub.go b/go-runtime/schema/testdata/pubsub/pubsub.go index d2775b4d2f..3ba3978088 100644 --- a/go-runtime/schema/testdata/pubsub/pubsub.go +++ b/go-runtime/schema/testdata/pubsub/pubsub.go @@ -11,42 +11,42 @@ type PayinEvent struct { Name string } +type Payins = ftl.TopicHandle[PayinEvent] + //ftl:verb -func Payin(ctx context.Context) error { - if err := Payins.Publish(ctx, PayinEvent{Name: "Test"}); err != nil { +func Payin(ctx context.Context, topic Payins) error { + if err := topic.Publish(ctx, PayinEvent{Name: "Test"}); err != nil { return fmt.Errorf("failed to publish event: %w", err) } return nil } -//ftl:subscribe paymentProcessing +type PaymentProcessing = ftl.SubscriptionHandle[Payins, ProcessPayinClient, PayinEvent] + +//ftl:verb func ProcessPayin(ctx context.Context, event PayinEvent) error { logger := ftl.LoggerFromContext(ctx) logger.Infof("Received PubSub event: %v", event) return nil } -var _ = ftl.Subscription(Payins, "paymentProcessing") - -var Payins = ftl.Topic[PayinEvent]("payins") - -var _ = ftl.Subscription(PublicBroadcast, "broadcastSubscription") - // publicBroadcast is a topic that broadcasts payin events to the public. // out of order with subscription registration to test ordering doesn't matter. // //ftl:export -var PublicBroadcast = ftl.Topic[PayinEvent]("publicBroadcast") +type PublicBroadcast = ftl.TopicHandle[PayinEvent] //ftl:verb export -func Broadcast(ctx context.Context) error { - if err := PublicBroadcast.Publish(ctx, PayinEvent{Name: "Broadcast"}); err != nil { +func Broadcast(ctx context.Context, topic PublicBroadcast) error { + if err := topic.Publish(ctx, PayinEvent{Name: "Broadcast"}); err != nil { return fmt.Errorf("failed to publish broadcast event: %w", err) } return nil } -//ftl:subscribe broadcastSubscription +type BroadcastSubscription = ftl.SubscriptionHandle[PublicBroadcast, ProcessBroadcastClient, PayinEvent] + +//ftl:verb //ftl:retry 10 1s func ProcessBroadcast(ctx context.Context, event PayinEvent) error { logger := ftl.LoggerFromContext(ctx) diff --git a/go-runtime/schema/testdata/pubsub/types.ftl.go b/go-runtime/schema/testdata/pubsub/types.ftl.go index 44e0e33245..0dfc515beb 100644 --- a/go-runtime/schema/testdata/pubsub/types.ftl.go +++ b/go-runtime/schema/testdata/pubsub/types.ftl.go @@ -4,6 +4,7 @@ package pubsub import ( "context" "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" ) type BroadcastClient func(context.Context) error @@ -18,9 +19,11 @@ func init() { reflection.Register( reflection.ProvideResourcesForVerb( Broadcast, + server.TopicHandle[PayinEvent]("pubsub", "publicBroadcast"), ), reflection.ProvideResourcesForVerb( Payin, + server.TopicHandle[PayinEvent]("pubsub", "payins"), ), reflection.ProvideResourcesForVerb( ProcessBroadcast, diff --git a/go-runtime/schema/testdata/subscriber/subscriber.go b/go-runtime/schema/testdata/subscriber/subscriber.go index 579c8ce2d0..543d6ebe17 100644 --- a/go-runtime/schema/testdata/subscriber/subscriber.go +++ b/go-runtime/schema/testdata/subscriber/subscriber.go @@ -7,9 +7,9 @@ import ( "github.com/TBD54566975/ftl/go-runtime/ftl" ) -var _ = ftl.Subscription(pubsub.PublicBroadcast, "subscriptionToExternalTopic") +type SubscriptionToExternalTopic = ftl.SubscriptionHandle[pubsub.PublicBroadcast, ConsumesSubscriptionFromExternalTopicClient, pubsub.PayinEvent] -//ftl:subscribe subscriptionToExternalTopic +//ftl:verb func ConsumesSubscriptionFromExternalTopic(ctx context.Context, req pubsub.PayinEvent) error { return nil } diff --git a/go-runtime/schema/topic/analyzer.go b/go-runtime/schema/topic/analyzer.go index 9e729a8608..a92ef1f5d8 100644 --- a/go-runtime/schema/topic/analyzer.go +++ b/go-runtime/schema/topic/analyzer.go @@ -12,53 +12,34 @@ import ( "github.com/TBD54566975/ftl/internal/schema/strcase" ) -const ( - ftlTopicFuncPath = "github.com/TBD54566975/ftl/go-runtime/ftl.Topic" -) - // Extractor extracts topics. -var Extractor = common.NewCallDeclExtractor[*schema.Topic]("topic", Extract, ftlTopicFuncPath) +var Extractor = common.NewResourceDeclExtractor[*schema.Topic]("topic", Extract, matchFunc) -// Extract expects: var NameLiteral = ftl.Topic[EventType]("nameLiteral") -func Extract(pass *analysis.Pass, obj types.Object, node *ast.GenDecl, callExpr *ast.CallExpr, - callPath string) optional.Option[*schema.Topic] { - indexExpr, ok := callExpr.Fun.(*ast.IndexExpr) - if !ok { - common.Errorf(pass, node, "must have an event type as a type parameter") - return optional.None[*schema.Topic]() - } - typeParamType, ok := common.ExtractType(pass, indexExpr.Index).Get() +func Extract(pass *analysis.Pass, obj types.Object, node *ast.TypeSpec) optional.Option[*schema.Topic] { + idxExpr, ok := node.Type.(*ast.IndexExpr) if !ok { - common.Errorf(pass, node, "unsupported event type") + common.Errorf(pass, node, "unsupported topic type") return optional.None[*schema.Topic]() } - topicName := common.ExtractStringLiteralArg(pass, callExpr, 0) - expTopicName := strcase.ToLowerCamel(strcase.ToUpperStrippedCamel(topicName)) - if topicName != expTopicName { - common.Errorf(pass, node, "unsupported topic name %q, did you mean to use %q?", topicName, expTopicName) + typ, ok := common.ExtractType(pass, idxExpr.Index).Get() + if !ok { + common.Errorf(pass, node, "unsupported topic type") return optional.None[*schema.Topic]() } - if len(node.Specs) > 0 { - if t, ok := node.Specs[0].(*ast.ValueSpec); ok { - varName := t.Names[0].Name - expVarName := strcase.ToUpperCamel(topicName) - if varName != expVarName { - common.Errorf(pass, node, "unexpected topic variable name %q, did you mean %q?", varName, expVarName) - return optional.None[*schema.Topic]() - } - } - } - topic := &schema.Topic{ Pos: common.GoPosToSchemaPos(pass.Fset, node.Pos()), - Name: topicName, - Event: typeParamType, + Name: strcase.ToLowerCamel(node.Name.Name), + Event: typ, } - common.ApplyMetadata[*schema.Subscription](pass, obj, func(md *common.ExtractedMetadata) { + if md, ok := common.GetFactForObject[*common.ExtractedMetadata](pass, obj).Get(); ok { topic.Comments = md.Comments topic.Export = md.IsExported - }) + } return optional.Some(topic) } + +func matchFunc(pass *analysis.Pass, node ast.Node, obj types.Object) bool { + return common.GetVerbResourceType(pass, obj) == common.VerbResourceTypeTopicHandle +} diff --git a/go-runtime/schema/verb/analyzer.go b/go-runtime/schema/verb/analyzer.go index 48ad828e76..b0d881dab9 100644 --- a/go-runtime/schema/verb/analyzer.go +++ b/go-runtime/schema/verb/analyzer.go @@ -16,25 +16,19 @@ import ( "github.com/TBD54566975/ftl/internal/schema/strcase" ) -type resourceType int - -const ( - none resourceType = iota - verbClient - databaseHandle -) - type resource struct { ref *schema.Ref - typ resourceType + typ common.VerbResourceType } func (r resource) toMetadataType() (schema.Metadata, error) { switch r.typ { - case verbClient: + case common.VerbResourceTypeVerbClient: return &schema.MetadataCalls{}, nil - case databaseHandle: + case common.VerbResourceTypeDatabaseHandle: return &schema.MetadataDatabases{}, nil + case common.VerbResourceTypeTopicHandle: + return &schema.MetadataPublisher{}, nil default: return nil, fmt.Errorf("unsupported resource type") } @@ -66,7 +60,7 @@ func Extract(pass *analysis.Pass, node *ast.FuncDecl, obj types.Object) optional // if this parameter can't be resolved to a resource, it must either be the context or request parameter: // Verb(context.Context, , , , ...) - if r == nil { + if r == nil || r.typ == common.VerbResourceTypeNone { if idx > 1 { common.Errorf(pass, param, "unsupported verb parameter type; verbs must have the "+ "signature func(Context, Request?, Resources...)") @@ -78,14 +72,20 @@ func Extract(pass *analysis.Pass, node *ast.FuncDecl, obj types.Object) optional continue } + paramObj, ok := common.GetObjectForNode(pass.TypesInfo, param.Type).Get() + if !ok { + common.Errorf(pass, param, "unsupported verb parameter type") + continue + } + common.MarkIncludeNativeName(pass, paramObj, r.ref) switch r.typ { - case verbClient: - paramObj := common.GetObjectForNode(pass.TypesInfo, param.Type).MustGet() - common.MarkIncludeNativeName(pass, paramObj, r.ref) + case common.VerbResourceTypeVerbClient: verb.AddCall(r.ref) - case databaseHandle: + case common.VerbResourceTypeDatabaseHandle: verb.AddDatabase(r.ref) - case none: + case common.VerbResourceTypeTopicHandle: + verb.AddTopicPublish(r.ref) + default: common.Errorf(pass, param, "unsupported verb parameter type; verbs must have the "+ "signature func(Context, Request?, Resources...)") } @@ -138,38 +138,40 @@ func Extract(pass *analysis.Pass, node *ast.FuncDecl, obj types.Object) optional } func resolveResource(pass *analysis.Pass, typ ast.Expr) (*resource, error) { - obj := common.GetObjectForNode(pass.TypesInfo, typ) - if o, ok := obj.Get(); ok { - if _, ok := o.Type().(*types.Alias); ok { - ident, ok := typ.(*ast.Ident) - if !ok || ident.Obj == nil || ident.Obj.Decl == nil { - return nil, fmt.Errorf("unsupported verb parameter type") - } - ts, ok := ident.Obj.Decl.(*ast.TypeSpec) - if !ok { - return nil, fmt.Errorf("unsupported verb parameter type") - } - return resolveResource(pass, ts.Type) - } - } - + obj, hasObj := common.GetObjectForNode(pass.TypesInfo, typ).Get() + rType := common.GetVerbResourceType(pass, obj) var ref *schema.Ref - rType := getParamResourceType(pass, obj) switch rType { - case none: + case common.VerbResourceTypeNone: return nil, nil - case verbClient: - o, ok := obj.Get() + case common.VerbResourceTypeVerbClient: + calleeRef, ok := common.ExtractSimpleRefWithCasing(pass, typ, strcase.ToLowerCamel).Get() if !ok { return nil, fmt.Errorf("unsupported verb parameter type") } - calleeRef, err := getResourceRef(o) - if err != nil { - return nil, err - } calleeRef.Name = strings.TrimSuffix(calleeRef.Name, "Client") ref = calleeRef - case databaseHandle: + case common.VerbResourceTypeDatabaseHandle: + // database parameter can either be supplied via an aliased type: + // + // type MyDB = ftl.DatabaseHandle[MyDatabaseConfig] + // func MyVerb(ctx context.Context, db MyDB, ...) (..., error) + // + // or directly: + // func MyVerb(ctx context.Context, db ftl.DatabaseHandle[MyDatabaseConfig], ...) (..., error) + if hasObj { + if _, ok := obj.Type().(*types.Alias); ok { + ident, ok := typ.(*ast.Ident) + if !ok || ident.Obj == nil || ident.Obj.Decl == nil { + return nil, fmt.Errorf("unsupported verb parameter type") + } + ts, ok := ident.Obj.Decl.(*ast.TypeSpec) + if !ok { + return nil, fmt.Errorf("unsupported verb parameter type") + } + return resolveResource(pass, ts.Type) + } + } idxExpr, ok := typ.(*ast.IndexExpr) if !ok { return nil, fmt.Errorf("unsupported verb parameter type; expected ftl.DatabaseHandle[Config]") @@ -186,12 +188,19 @@ func resolveResource(pass *analysis.Pass, typ ast.Expr) (*resource, error) { if !ok { return nil, fmt.Errorf("no database found for config provided to database handle") } - r, err := getResourceRef(idxObj) + module, err := common.FtlModuleFromGoPackage(idxObj.Pkg().Path()) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to resolve module for type: %w", err) + } + ref = &schema.Ref{ + Module: module, + Name: db.Name, + } + case common.VerbResourceTypeTopicHandle: + var ok bool + if ref, ok = common.ExtractSimpleRefWithCasing(pass, typ, strcase.ToLowerCamel).Get(); !ok { + return nil, fmt.Errorf("unsupported verb parameter type; expected ftl.TopicHandle[Event]") } - r.Name = db.Name - ref = r } if ref == nil { return nil, fmt.Errorf("unsupported verb parameter type") @@ -199,68 +208,6 @@ func resolveResource(pass *analysis.Pass, typ ast.Expr) (*resource, error) { return &resource{ref: ref, typ: rType}, nil } -func getParamResourceType(pass *analysis.Pass, maybeObj optional.Option[types.Object]) resourceType { - obj, ok := maybeObj.Get() - if !ok { - return none - } - if obj.Pkg() == nil { - return none - } - - switch t := obj.Type().(type) { - case *types.Named: - if isDatabaseHandleType(pass, t) { - return databaseHandle - } - - if _, ok := t.Underlying().(*types.Signature); !ok { - return none - } - - return verbClient - case *types.Alias: - named, ok := t.Rhs().(*types.Named) - if !ok { - return none - } - namedObj := optional.Some[types.Object](named.Obj()) - if named.Obj() == nil { - namedObj = optional.None[types.Object]() - } - return getParamResourceType(pass, namedObj) - - default: - return none - } -} - -func getResourceRef(paramObj types.Object) (*schema.Ref, error) { - paramModule, err := common.FtlModuleFromGoPackage(paramObj.Pkg().Path()) - if err != nil { - return nil, fmt.Errorf("failed to resolve module for type: %w", err) - } - dbRef := &schema.Ref{ - Module: paramModule, - Name: strcase.ToLowerCamel(paramObj.Name()), - } - return dbRef, nil -} - -func isDatabaseHandleType(pass *analysis.Pass, named *types.Named) bool { - if named.Obj().Pkg().Path()+"."+named.Obj().Name() != "github.com/TBD54566975/ftl/go-runtime/ftl.DatabaseHandle" { - return false - } - - if named.TypeParams().Len() != 1 { - return false - } - typeArg := named.TypeParams().At(0) - - // type argument implements `DatabaseConfig`, e.g. DatabaseHandle[MyConfig] where MyConfig implements DatabaseConfig - return common.IsDatabaseConfigType(pass, typeArg) -} - func checkSignature( pass *analysis.Pass, loaded initialize.Result, diff --git a/go-runtime/server/pubsub.go b/go-runtime/server/pubsub.go new file mode 100644 index 0000000000..58669f7878 --- /dev/null +++ b/go-runtime/server/pubsub.go @@ -0,0 +1,19 @@ +package server + +import ( + "reflect" + + "github.com/TBD54566975/ftl/go-runtime/ftl" + "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/internal/schema" +) + +func TopicHandle[E any](module, name string) reflection.VerbResource { + handle := ftl.TopicHandle[E]{Ref: &schema.Ref{ + Name: name, + Module: module, + }} + return func() reflect.Value { + return reflect.ValueOf(handle) + } +} diff --git a/internal/lsp/hoveritems.go b/internal/lsp/hoveritems.go index 2e2a2c9f82..e3aecb0871 100644 --- a/internal/lsp/hoveritems.go +++ b/internal/lsp/hoveritems.go @@ -5,7 +5,7 @@ var hoverMap = map[string]string{ "//ftl:cron": "## Cron\n\nA cron job is an Empty verb that will be called on a schedule. The syntax is described [here](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/crontab.html).\n\nYou can also use a shorthand syntax for the cron job, supporting seconds (`s`), minutes (`m`), hours (`h`), and specific days of the week (e.g. `Mon`).\n\n### Examples\n\nThe following function will be called hourly:\n\n```go\n//ftl:cron 0 * * * *\nfunc Hourly(ctx context.Context) error {\n // ...\n}\n```\nEvery 12 hours, starting at UTC midnight:\n\n```go\n//ftl:cron 12h\nfunc TwiceADay(ctx context.Context) error {\n // ...\n}\n```\n\nEvery Monday at UTC midnight:\n\n```go\n//ftl:cron Mon\nfunc Mondays(ctx context.Context) error {\n // ...\n}\n```", "//ftl:enum": "## Type enums (sum types)\n\n[Sum types](https://en.wikipedia.org/wiki/Tagged_union) are supported by FTL's type system, but aren't directly supported by Go. However they can be approximated with the use of [sealed interfaces](https://blog.chewxy.com/2018/03/18/golang-interfaces/). To declare a sum type in FTL use the comment directive `//ftl:enum`:\n\n```go\n//ftl:enum\ntype Animal interface { animal() }\n\ntype Cat struct {}\nfunc (Cat) animal() {}\n\ntype Dog struct {}\nfunc (Dog) animal() {}\n```\n## Value enums\n\nA value enum is an enumerated set of string or integer values.\n\n```go\n//ftl:enum\ntype Colour string\n\nconst (\n Red Colour = \"red\"\n Green Colour = \"green\"\n Blue Colour = \"blue\"\n)\n```\n", "//ftl:ingress": "## HTTP Ingress\n\nVerbs annotated with `ftl:ingress` will be exposed via HTTP (`http` is the default ingress type). These endpoints will then be available on one of our default `ingress` ports (local development defaults to `http://localhost:8891`).\n\nThe following will be available at `http://localhost:8891/http/users/123/posts?postId=456`.\n\n\n```go\ntype GetRequestPathParams struct {\n\tUserID string `json:\"userId\"`\n}\n\ntype GetRequestQueryParams struct {\n\tPostID string `json:\"postId\"`\n}\n\ntype GetResponse struct {\n\tMessage string `json:\"msg\"`\n}\n\n//ftl:ingress GET /http/users/{userId}/posts\nfunc Get(ctx context.Context, req builtin.HttpRequest[ftl.Unit, GetRequestPathParams, GetRequestQueryParams]) (builtin.HttpResponse[GetResponse, ErrorResponse], error) {\n // ...\n}\n```\n\nBecause the example above only has a single path parameter it can be simplified by just using a scalar such as `string` or `int64` as the path parameter type:\n\n```go\n\n//ftl:ingress GET /http/users/{userId}/posts\nfunc Get(ctx context.Context, req builtin.HttpRequest[ftl.Unit, int64, GetRequestQueryParams]) (builtin.HttpResponse[GetResponse, ErrorResponse], error) {\n // ...\n}\n```\n\n> **NOTE!**\n> The `req` and `resp` types of HTTP `ingress` [verbs](../verbs) must be `builtin.HttpRequest` and `builtin.HttpResponse` respectively. These types provide the necessary fields for HTTP `ingress` (`headers`, `statusCode`, etc.)\n>\n> You will need to import `ftl/builtin`.\n\nKey points:\n\n- `ingress` verbs will be automatically exported by default.\n\n## Field mapping\n\nThe `HttpRequest` request object takes 3 type parameters, the body, the path parameters and the query parameters.\n\nGiven the following request verb:\n\n```go\n\ntype PostBody struct{\n\tTitle string `json:\"title\"`\n\tContent string `json:\"content\"`\n\tTag ftl.Option[string] `json:\"tag\"`\n}\ntype PostPathParams struct {\n\tUserID string `json:\"userId\"`\n\tPostID string `json:\"postId\"`\n}\n\ntype PostQueryParams struct {\n\tPublish boolean `json:\"publish\"`\n}\n\n//ftl:ingress http PUT /users/{userId}/posts/{postId}\nfunc Get(ctx context.Context, req builtin.HttpRequest[PostBody, PostPathParams, PostQueryParams]) (builtin.HttpResponse[GetResponse, string], error) {\n\treturn builtin.HttpResponse[GetResponse, string]{\n\t\tHeaders: map[string][]string{\"Get\": {\"Header from FTL\"}},\n\t\tBody: ftl.Some(GetResponse{\n\t\t\tMessage: fmt.Sprintf(\"UserID: %s, PostID: %s, Tag: %s\", req.pathParameters.UserID, req.pathParameters.PostID, req.Body.Tag.Default(\"none\")),\n\t\t}),\n\t}, nil\n}\n```\n\nThe rules for how each element is mapped are slightly different, as they have a different structure:\n\n- The body is mapped directly to the body of the request, generally as a JSON object. Scalars are also supported, as well as []byte to get the raw body. If they type is `any` then it will be assumed to be JSON and mapped to the appropriate types based on the JSON structure.\n- The path parameters can be mapped directly to an object with field names corresponding to the name of the path parameter. If there is only a single path parameter it can be injected directly as a scalar. They can also be injected as a `map[string]string`.\n- The path parameters can also be mapped directly to an object with field names corresponding to the name of the path parameter. They can also be injected directly as a `map[string]string`, or `map[string][]string` for multiple values.\n\n#### Optional fields\n\nOptional fields are represented by the `ftl.Option` type. The `Option` type is a wrapper around the actual type and can be `Some` or `None`. In the example above, the `Tag` field is optional.\n\n```sh\ncurl -i http://localhost:8891/users/123/posts/456\n```\n\nBecause the `tag` query parameter is not provided, the response will be:\n\n```json\n{\n \"msg\": \"UserID: 123, PostID: 456, Tag: none\"\n}\n```\n\n#### Casing\n\nField names use lowerCamelCase by default. You can override this by using the `json` tag.\n\n## SumTypes\n\nGiven the following request verb:\n\n```go\n//ftl:enum export\ntype SumType interface {\n\ttag()\n}\n\ntype A string\n\nfunc (A) tag() {}\n\ntype B []string\n\nfunc (B) tag() {}\n\n//ftl:ingress http POST /typeenum\nfunc TypeEnum(ctx context.Context, req builtin.HttpRequest[SumType, ftl.Unit, ftl.Unit]) (builtin.HttpResponse[SumType, string], error) {\n\treturn builtin.HttpResponse[SumType, string]{Body: ftl.Some(req.Body)}, nil\n}\n```\n\nThe following curl request will map the `SumType` name and value to the `req.Body`:\n\n```sh\ncurl -X POST \"http://localhost:8891/typeenum\" \\\n -H \"Content-Type: application/json\" \\\n --data '{\"name\": \"A\", \"value\": \"sample\"}'\n```\n\nThe response will be:\n\n```json\n{\n \"name\": \"A\",\n \"value\": \"sample\"\n}\n```\n\n## Encoding query params as JSON\n\nComplex query params can also be encoded as JSON using the `@json` query parameter. For example:\n\n> `{\"tag\":\"ftl\"}` url-encoded is `%7B%22tag%22%3A%22ftl%22%7D`\n\n```bash\ncurl -i http://localhost:8891/users/123/posts/456?@json=%7B%22tag%22%3A%22ftl%22%7D\n```\n\n\n\n", - "//ftl:retry": "## Retries\n\nSome FTL features allow specifying a retry policy via a Go comment directive. Retries back off exponentially until the maximum is reached.\n\nThe directive has the following syntax:\n\n\n```go\n//ftl:retry [] [] [catch ]\n```\n\n\nFor example, the following function will retry up to 10 times, with a delay of 5s, 10s, 20s, 40s, 60s, 60s, etc.\n\n\n```go\n//ftl:retry 10 5s 1m\nfunc Process(ctx context.Context, in Invoice) error {\n // ...\n}\n```\n\n### PubSub\n\nSubscribers can have a retry policy. For example:\n\n\n```go\n//ftl:subscribe exampleSubscription\n//ftl:retry 5 1s catch recoverPaymentProcessing\nfunc ProcessPayment(ctx context.Context, payment Payment) error {\n...\n}\n```\n\n\n## Catching\nAfter all retries have failed, a catch verb can be used to safely recover.\n\nThese catch verbs have a request type of `builtin.CatchRequest` and no response type. If a catch verb returns an error, it will be retried until it succeeds so it is important to handle errors carefully.\n\n\n\n```go\n//ftl:retry 5 1s catch recoverPaymentProcessing\nfunc ProcessPayment(ctx context.Context, payment Payment) error {\n...\n}\n\n//ftl:verb\nfunc RecoverPaymentProcessing(ctx context.Context, request builtin.CatchRequest[Payment]) error {\n// safely handle final failure of the payment\n}\n```\n", + "//ftl:retry": "## Retries\n\nSome FTL features allow specifying a retry policy via a Go comment directive. Retries back off exponentially until the maximum is reached.\n\nThe directive has the following syntax:\n\n\n```go\n//ftl:retry [] [] [catch ]\n```\n\n\nFor example, the following function will retry up to 10 times, with a delay of 5s, 10s, 20s, 40s, 60s, 60s, etc.\n\n\n```go\n//ftl:retry 10 5s 1m\nfunc Process(ctx context.Context, in Invoice) error {\n // ...\n}\n```\n\n### PubSub\n\nSubscribers can have a retry policy. For example:\n\n\n```go\n//ftl:retry 5 1s catch recoverPaymentProcessing\nfunc ProcessPayment(ctx context.Context, payment Payment) error {\n...\n}\n```\n\n\n## Catching\nAfter all retries have failed, a catch verb can be used to safely recover.\n\nThese catch verbs have a request type of `builtin.CatchRequest` and no response type. If a catch verb returns an error, it will be retried until it succeeds so it is important to handle errors carefully.\n\n\n\n```go\n//ftl:retry 5 1s catch recoverPaymentProcessing\nfunc ProcessPayment(ctx context.Context, payment Payment) error {\n...\n}\n\n//ftl:verb\nfunc RecoverPaymentProcessing(ctx context.Context, request builtin.CatchRequest[Payment]) error {\n// safely handle final failure of the payment\n}\n```\n", "//ftl:subscribe": "## PubSub\n\nFTL has first-class support for PubSub, modelled on the concepts of topics (where events are sent), subscriptions (a cursor over the topic), and subscribers (functions events are delivered to). Subscribers are, as you would expect, sinks. Each subscription is a cursor over the topic it is associated with. Each topic may have multiple subscriptions. Each subscription may have multiple subscribers, in which case events will be distributed among them.\n\nEach published event has an at least once delivery guarantee for each subscription.\n\n\nFirst, declare a new topic:\n\n```go\nvar Invoices = ftl.Topic[Invoice](\"invoices\")\n```\n\nThen declare each subscription on the topic:\n\n```go\nvar _ = ftl.Subscription(Invoices, \"emailInvoices\")\n```\n\nAnd finally define a Sink to consume from the subscription:\n\n```go\n//ftl:subscribe emailInvoices\nfunc SendInvoiceEmail(ctx context.Context, in Invoice) error {\n // ...\n}\n```\n\nEvents can be published to a topic like so:\n\n```go\nInvoices.Publish(ctx, Invoice{...})\n```\n\n> **NOTE!**\n> PubSub topics cannot be published to from outside the module that declared them, they can only be subscribed to. That is, if a topic is declared in module `A`, module `B` cannot publish to it.\n", "//ftl:typealias": "## Type aliases\n\nA type alias is an alternate name for an existing type. It can be declared like so:\n\n```go\n//ftl:typealias\ntype Alias Target\n```\nor\n```go\n//ftl:typealias\ntype Alias = Target\n```\n\neg.\n\n```go\n//ftl:typealias\ntype UserID string\n\n//ftl:typealias\ntype UserToken = string\n```\n", "//ftl:verb": "## Verbs\n\n## Defining Verbs\n\n\nTo declare a Verb, write a normal Go function with the following signature, annotated with the Go [comment directive](https://tip.golang.org/doc/comment#syntax) `//ftl:verb`:\n\n```go\n//ftl:verb\nfunc F(context.Context, In) (Out, error) { }\n```\n\neg.\n\n```go\ntype EchoRequest struct {}\n\ntype EchoResponse struct {}\n\n//ftl:verb\nfunc Echo(ctx context.Context, in EchoRequest) (EchoResponse, error) {\n // ...\n}\n```\n\n\nBy default verbs are only [visible](../visibility) to other verbs in the same module.\n\n## Calling Verbs\n\n\nTo call a verb, import the module's verb client (`{ModuleName}.{VerbName}Client`), add it to your verb's signature, then invoke it as a function. eg.\n\n```go\n//ftl:verb\nfunc Echo(ctx context.Context, in EchoRequest, tc time.TimeClient) (EchoResponse, error) {\n\tout, err := tc(ctx, TimeRequest{...})\n}\n```\n\nVerb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must build the \nmodule first (with callee verb defined) in order to generate its client for use by the caller. Local verb clients are \navailable in the generated `types.ftl.go` file as `{VerbName}Client`.\n\n", diff --git a/internal/schema/verb.go b/internal/schema/verb.go index 640c87a144..7fbe60e962 100644 --- a/internal/schema/verb.go +++ b/internal/schema/verb.go @@ -135,6 +135,19 @@ func (v *Verb) AddDatabase(db *Ref) { v.Metadata = append(v.Metadata, &MetadataDatabases{Calls: []*Ref{db}}) } +func (v *Verb) AddSubscription(sub *MetadataSubscriber) { + v.Metadata = append(v.Metadata, sub) +} + +// AddTopicPublish adds a topic that this Verb publishes to. +func (v *Verb) AddTopicPublish(topic *Ref) { + if c, ok := slices.FindVariant[*MetadataPublisher](v.Metadata); ok { + c.Topics = append(c.Topics, topic) + return + } + v.Metadata = append(v.Metadata, &MetadataPublisher{Topics: []*Ref{topic}}) +} + func (v *Verb) SortMetadata() { sortMetadata(v.Metadata) } diff --git a/jvm-runtime/testdata/go/gomodule/server.go b/jvm-runtime/testdata/go/gomodule/server.go index 21332ac16f..837087b6f5 100644 --- a/jvm-runtime/testdata/go/gomodule/server.go +++ b/jvm-runtime/testdata/go/gomodule/server.go @@ -13,12 +13,12 @@ import ( // Comment on topic // //ftl:export -var TestTopic = ftl.Topic[TestObject]("testTopic") +type TestTopic = ftl.TopicHandle[string] // Comment on subscription // //ftl:export -var testSubscription = ftl.Subscription(TestTopic, "testSubscription") +type TestSubscription = ftl.SubscriptionHandle[TestTopic, SinkVerbClient, string] // Comment on data type TestObject struct { diff --git a/jvm-runtime/testdata/go/gomodule/types.ftl.go b/jvm-runtime/testdata/go/gomodule/types.ftl.go index 88067b985a..eeb2040d06 100644 --- a/jvm-runtime/testdata/go/gomodule/types.ftl.go +++ b/jvm-runtime/testdata/go/gomodule/types.ftl.go @@ -49,12 +49,18 @@ type OptionalTimeVerbClient func(context.Context, ftl.Option[stdtime.Time]) (ftl type ParameterizedObjectVerbClient func(context.Context, ParameterizedType[string]) (ParameterizedType[string], error) +type PrimitiveParamVerbClient func(context.Context, int) (string, error) + +type PrimitiveResponseVerbClient func(context.Context, string) (int, error) + type SinkVerbClient func(context.Context, string) error type SourceVerbClient func(context.Context) (string, error) type StringArrayVerbClient func(context.Context, []string) ([]string, error) +type StringEnumVerbClient func(context.Context, ShapeWrapper) (ShapeWrapper, error) + type StringMapVerbClient func(context.Context, map[string]string) (map[string]string, error) type StringVerbClient func(context.Context, string) (string, error) @@ -65,8 +71,22 @@ type TestObjectVerbClient func(context.Context, TestObject) (TestObject, error) type TimeVerbClient func(context.Context, stdtime.Time) (stdtime.Time, error) +type TypeEnumVerbClient func(context.Context, AnimalWrapper) (AnimalWrapper, error) + +type TypeWrapperEnumVerbClient func(context.Context, TypeEnumWrapper) (TypeEnumWrapper, error) + +type ValueEnumVerbClient func(context.Context, ColorWrapper) (ColorWrapper, error) + func init() { reflection.Register( + reflection.SumType[Animal]( + *new(Cat), + *new(Dog), + ), + reflection.SumType[TypeWrapperEnum]( + *new(Scalar), + *new(StringList), + ), reflection.ExternalType(*new(did.DID)), reflection.ProvideResourcesForVerb( BoolVerb, @@ -128,6 +148,12 @@ func init() { reflection.ProvideResourcesForVerb( ParameterizedObjectVerb, ), + reflection.ProvideResourcesForVerb( + PrimitiveParamVerb, + ), + reflection.ProvideResourcesForVerb( + PrimitiveResponseVerb, + ), reflection.ProvideResourcesForVerb( SinkVerb, ), @@ -137,6 +163,9 @@ func init() { reflection.ProvideResourcesForVerb( StringArrayVerb, ), + reflection.ProvideResourcesForVerb( + StringEnumVerb, + ), reflection.ProvideResourcesForVerb( StringMapVerb, ), @@ -152,5 +181,14 @@ func init() { reflection.ProvideResourcesForVerb( TimeVerb, ), + reflection.ProvideResourcesForVerb( + TypeEnumVerb, + ), + reflection.ProvideResourcesForVerb( + TypeWrapperEnumVerb, + ), + reflection.ProvideResourcesForVerb( + ValueEnumVerb, + ), ) } diff --git a/smoketest/echo/go.mod b/smoketest/echo/go.mod index 38b39e561a..d0e3efb883 100644 --- a/smoketest/echo/go.mod +++ b/smoketest/echo/go.mod @@ -7,12 +7,42 @@ replace github.com/TBD54566975/ftl => ../.. require github.com/TBD54566975/ftl v0.396.0 require ( + al.essio.dev/pkg/shellescape v1.5.1 // indirect + connectrpc.com/connect v1.16.2 // indirect + connectrpc.com/grpcreflect v1.2.0 // indirect + connectrpc.com/otelconnect v0.7.1 // indirect + github.com/alecthomas/atomic v0.1.0-alpha2 // indirect + github.com/alecthomas/concurrency v0.0.2 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect + github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.1 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect github.com/swaggest/jsonschema-go v0.3.72 // indirect github.com/swaggest/refl v1.3.0 // indirect + github.com/zalando/go-keyring v0.2.6 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/smoketest/echo/go.sum b/smoketest/echo/go.sum index b12117fb18..51229e8c30 100644 --- a/smoketest/echo/go.sum +++ b/smoketest/echo/go.sum @@ -8,6 +8,8 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= +github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= @@ -26,6 +28,7 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -36,6 +39,7 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -58,6 +62,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= @@ -114,8 +120,13 @@ github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/swaggest/jsonschema-go v0.3.72 h1:IHaGlR1bdBUBPfhe4tfacN2TGAPKENEGiNyNzvnVHv4= @@ -134,6 +145,10 @@ go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= @@ -148,6 +163,7 @@ golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= @@ -160,10 +176,12 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1: google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/smoketest/echo/types.ftl.go b/smoketest/echo/types.ftl.go index c32e18f9a2..82bd9acefb 100644 --- a/smoketest/echo/types.ftl.go +++ b/smoketest/echo/types.ftl.go @@ -2,11 +2,11 @@ package echo import ( - "context" + "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" ) -type EchoClient func(context.Context, string) (string, error) +type EchoClient = ftl.Verb[string, string] func init() { reflection.Register( diff --git a/smoketest/origin/go.mod b/smoketest/origin/go.mod index 07bd1016a8..b6e7f83898 100644 --- a/smoketest/origin/go.mod +++ b/smoketest/origin/go.mod @@ -10,17 +10,22 @@ require ( connectrpc.com/grpcreflect v1.2.0 // indirect connectrpc.com/otelconnect v0.7.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/XSAM/otelsql v0.35.0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/concurrency v0.0.2 // indirect + github.com/alecthomas/kong v1.4.0 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alecthomas/types v0.17.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -35,8 +40,15 @@ require ( github.com/swaggest/refl v1.3.0 // indirect github.com/zalando/go-keyring v0.2.6 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect @@ -44,6 +56,9 @@ require ( golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/smoketest/origin/go.sum b/smoketest/origin/go.sum index ae5e144fc5..bd5dbc0553 100644 --- a/smoketest/origin/go.sum +++ b/smoketest/origin/go.sum @@ -8,12 +8,16 @@ connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/XSAM/otelsql v0.35.0 h1:nMdbU/XLmBIB6qZF61uDqy46E0LVA4ZgF/FCNw8Had4= +github.com/XSAM/otelsql v0.35.0/go.mod h1:wO028mnLzmBpstK8XPsoeRLl/kgt417yjAwOGDIptTc= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo= github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w= +github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA= +github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -28,6 +32,8 @@ github.com/bool64/dev v0.2.35 h1:M17TLsO/pV2J7PYI/gpe3Ua26ETkzZGb+dC06eoMqlk= github.com/bool64/dev v0.2.35/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +76,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -114,6 +122,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -147,6 +157,12 @@ github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8u github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= @@ -155,6 +171,12 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -178,6 +200,10 @@ golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/smoketest/origin/origin.go b/smoketest/origin/origin.go index 97693299ea..5b3219b34f 100644 --- a/smoketest/origin/origin.go +++ b/smoketest/origin/origin.go @@ -12,7 +12,7 @@ import ( var nonce = ftl.Config[string]("nonce") //ftl:export -var AgentBroadcast = ftl.Topic[Agent]("agentBroadcast") +type AgentBroadcast = ftl.TopicHandle[Agent] type Agent struct { ID int `json:"id"` @@ -28,14 +28,14 @@ type PostAgentResponse struct { type PostAgentErrorResponse string //ftl:ingress POST /ingress/agent -func PostAgent(ctx context.Context, req builtin.HttpRequest[Agent, ftl.Unit, ftl.Unit]) (builtin.HttpResponse[PostAgentResponse, PostAgentErrorResponse], error) { +func PostAgent(ctx context.Context, req builtin.HttpRequest[Agent, ftl.Unit, ftl.Unit], topic AgentBroadcast) (builtin.HttpResponse[PostAgentResponse, PostAgentErrorResponse], error) { agent := Agent{ ID: req.Body.ID, Alias: req.Body.Alias, LicenseToKill: req.Body.LicenseToKill, HiredAt: req.Body.HiredAt, } - err := AgentBroadcast.Publish(ctx, agent) + err := topic.Publish(ctx, agent) if err != nil { return builtin.HttpResponse[PostAgentResponse, PostAgentErrorResponse]{ Status: 500, diff --git a/smoketest/origin/types.ftl.go b/smoketest/origin/types.ftl.go index 51de3d963a..03a6e66f49 100644 --- a/smoketest/origin/types.ftl.go +++ b/smoketest/origin/types.ftl.go @@ -6,6 +6,7 @@ import ( ftlbuiltin "ftl/builtin" "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/TBD54566975/ftl/go-runtime/ftl/reflection" + "github.com/TBD54566975/ftl/go-runtime/server" ) type GetNonceClient func(context.Context, GetNonceRequest) (GetNonceResponse, error) @@ -19,6 +20,7 @@ func init() { ), reflection.ProvideResourcesForVerb( PostAgent, + server.TopicHandle[Agent]("origin", "agentBroadcast"), ), ) } diff --git a/smoketest/pulse/src/main/java/com/example/Pulse.java b/smoketest/pulse/src/main/java/com/example/Pulse.java index ea2808e1b8..6470c4d563 100644 --- a/smoketest/pulse/src/main/java/com/example/Pulse.java +++ b/smoketest/pulse/src/main/java/com/example/Pulse.java @@ -1,14 +1,10 @@ package com.example; -import java.io.FileWriter; -import java.io.IOException; - import ftl.origin.GetNonceClient; import ftl.origin.GetNonceRequest; import ftl.origin.GetNonceResponse; import ftl.relay.AppendLogClient; import ftl.relay.AppendLogRequest; -import ftl.relay.AppendLogResponse; import io.quarkus.logging.Log; import xyz.block.ftl.Cron; diff --git a/smoketest/relay/relay.go b/smoketest/relay/relay.go index ad781bbc3d..aed32450ca 100644 --- a/smoketest/relay/relay.go +++ b/smoketest/relay/relay.go @@ -15,9 +15,9 @@ var logFile = ftl.Config[string]("log_file") // PubSub -var _ = ftl.Subscription(origin.AgentBroadcast, "agentConsumer") +type AgentConsumer = ftl.SubscriptionHandle[origin.AgentBroadcast, ConsumeAgentBroadcastClient, origin.Agent] -//ftl:subscribe agentConsumer +//ftl:verb func ConsumeAgentBroadcast(ctx context.Context, agent origin.Agent, client BriefedClient) error { ftl.LoggerFromContext(ctx).Infof("Received agent %v", agent.Id) return client(ctx, agent) diff --git a/smoketest/relay/types.ftl.go b/smoketest/relay/types.ftl.go index 5562522f9e..45d7d5c7a2 100644 --- a/smoketest/relay/types.ftl.go +++ b/smoketest/relay/types.ftl.go @@ -8,13 +8,15 @@ import ( "github.com/TBD54566975/ftl/go-runtime/server" ) +type AppendLogClient func(context.Context, AppendLogRequest) error + type BriefedClient func(context.Context, ftlorigin.Agent) error type DeployedClient func(context.Context, AgentDeployment) error type ConsumeAgentBroadcastClient func(context.Context, ftlorigin.Agent) error -type GetLogFileClient func(context.Context, GetLogFileRequest) (GetLogFileResponse, error) +type FetchLogsClient func(context.Context, FetchLogsRequest) (FetchLogsResponse, error) type MissionResultClient func(context.Context, MissionResultRequest) (MissionResultResponse, error) @@ -24,6 +26,9 @@ type TerminatedClient func(context.Context, AgentTerminated) error func init() { reflection.Register( + reflection.ProvideResourcesForVerb( + AppendLog, + ), reflection.ProvideResourcesForVerb( Briefed, server.SinkClient[DeployedClient, AgentDeployment](), @@ -36,7 +41,7 @@ func init() { server.SinkClient[BriefedClient, ftlorigin.Agent](), ), reflection.ProvideResourcesForVerb( - GetLogFile, + FetchLogs, ), reflection.ProvideResourcesForVerb( MissionResult,