Codec Server
A simple example inspired by temporalio/samples-go/codecserver
main.go
package main
import (
"context"
"errors"
"log"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/cludden/protoc-gen-go-temporal/examples/example"
examplev1 "github.com/cludden/protoc-gen-go-temporal/gen/example/v1"
"github.com/cludden/protoc-gen-go-temporal/pkg/codec"
"github.com/cludden/protoc-gen-go-temporal/pkg/scheme"
"github.com/urfave/cli/v2"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/converter"
tlog "go.temporal.io/sdk/log"
"go.temporal.io/sdk/worker"
)
func main() {
app, err := examplev1.NewExampleCli(
examplev1.NewExampleCliOptions().
WithClient(func(cmd *cli.Context) (client.Client, error) {
return client.Dial(client.Options{
DataConverter: converter.NewCompositeDataConverter(
converter.NewNilPayloadConverter(),
converter.NewByteSlicePayloadConverter(),
converter.NewProtoPayloadConverter(),
),
Logger: tlog.NewStructuredLogger(slog.Default()),
})
}).
WithWorker(func(cmd *cli.Context, c client.Client) (worker.Worker, error) {
w := worker.New(c, examplev1.ExampleTaskQueue, worker.Options{})
examplev1.RegisterExampleActivities(w, &example.Activities{})
examplev1.RegisterExampleWorkflows(w, &example.Workflows{})
return w, nil
}),
)
if err != nil {
log.Fatalf("error initializing example cli: %v", err)
}
app.Commands = append(app.Commands, &cli.Command{
Name: "codec",
Usage: "run remote codec server",
Action: func(cmd *cli.Context) error {
handler := converter.NewPayloadCodecHTTPHandler(
codec.NewProtoJSONCodec(
scheme.New(
examplev1.WithExampleSchemeTypes(),
),
),
)
srv := &http.Server{
Addr: "0.0.0.0:8080",
Handler: handler,
}
go func() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
if err := srv.Shutdown(context.Background()); err != nil {
log.Fatalf("error shutting down server: %v", err)
}
}()
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("server error: %v", err)
}
return nil
},
})
// run cli
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
Run this example
- Clone the examples
git clone https://github.com/cludden/protoc-gen-go-temporal && cd protoc-gen-go-temporal
- Start the codec server
go run examples/codecserver/main.go codec
- In a different terminal, start temporal using the codec server
temporal server start-dev \
--dynamic-config-value "frontend.enableUpdateWorkflowExecution=true" \
--dynamic-config-value "frontend.enableUpdateWorkflowExecutionAsyncAccepted=true" \
--ui-codec-endpoint http://localhost:8080 - In a different terminal, run the worker
go run examples/codecserver/main.go worker
- In a different terminal, execute a workflow, signal, query, and update
# execute a workflow in the background
go run examples/codecserver/main.go create-foo --name test -d
# signal the workflow
go run examples/codecserver/main.go set-foo-progress -w create-foo/test --progress 5.7
# query the workflow
go run examples/codecserver/main.go get-foo-progress -w create-foo/test
# update the workflow
go run examples/codecserver/main.go update-foo-progress -w create-foo/test --progress 100 - In the UI, switch to the JSON tab and disable the
Decode Event History
toggle and verify that all payloads have metadata with"encoding": "YmluYXJ5L3Byb3RvYnVm"
, which isbinary/protobuf
base64-encoded