From 22a9ab445dfcd53dc24ead08b6e845548c0f24e0 Mon Sep 17 00:00:00 2001 From: Lenny Chen Date: Thu, 9 Apr 2026 13:13:27 -0700 Subject: [PATCH 1/4] docs: add Go external storage snipsync snippets Add Go snippet files for external storage documentation alongside the existing Python snippets. Covers S3 driver setup, custom storage driver, threshold configuration, and multiple driver selection. Co-Authored-By: Claude Opus 4.6 (1M context) --- features/go.mod | 21 +++++ features/go.sum | 50 +++++++++++ .../custom_driver/custom_storage_driver.go | 83 +++++++++++++++++++ .../multiple_drivers/multiple_drivers.go | 27 ++++++ .../s3_setup/s3_driver_create.go | 32 +++++++ .../s3_setup/s3_external_storage_setup.go | 27 ++++++ .../threshold/threshold_config.go | 23 +++++ 7 files changed, 263 insertions(+) create mode 100644 features/snippets/external_storage/custom_driver/custom_storage_driver.go create mode 100644 features/snippets/external_storage/multiple_drivers/multiple_drivers.go create mode 100644 features/snippets/external_storage/s3_setup/s3_driver_create.go create mode 100644 features/snippets/external_storage/s3_setup/s3_external_storage_setup.go create mode 100644 features/snippets/external_storage/threshold/threshold_config.go diff --git a/features/go.mod b/features/go.mod index b23a9d5b..8e016988 100644 --- a/features/go.mod +++ b/features/go.mod @@ -5,6 +5,8 @@ go 1.24.0 toolchain go1.24.3 require ( + github.com/aws/aws-sdk-go-v2/config v1.32.14 + github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 github.com/google/uuid v1.6.0 github.com/nexus-rpc/sdk-go v0.6.0 github.com/stretchr/testify v1.10.0 @@ -13,6 +15,8 @@ require ( github.com/urfave/cli/v2 v2.3.0 go.temporal.io/api v1.62.7 go.temporal.io/sdk v1.42.0 + go.temporal.io/sdk/contrib/aws/s3driver v0.1.1 + go.temporal.io/sdk/contrib/aws/s3driver/awssdkv2 v0.1.1 go.temporal.io/sdk/contrib/sysinfo v0.1.0 go.temporal.io/sdk/contrib/tally v0.2.0 golang.org/x/mod v0.31.0 @@ -21,6 +25,23 @@ require ( ) require ( + github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect + github.com/aws/smithy-go v1.24.2 // indirect github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect diff --git a/features/go.sum b/features/go.sum index 7d91e24d..d9674534 100644 --- a/features/go.sum +++ b/features/go.sum @@ -8,6 +8,44 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= +github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/config v1.32.14 h1:opVIRo/ZbbI8OIqSOKmpFaY7IwfFUOCCXBsUpJOwDdI= +github.com/aws/aws-sdk-go-v2/config v1.32.14/go.mod h1:U4/V0uKxh0Tl5sxmCBZ3AecYny4UNlVmObYjKuuaiOo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk= +github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -112,6 +150,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/johannesboyne/gofakes3 v0.0.0-20260208201424-4c385a1f6a73 h1:0xkWp+RMC2ImuKacheMHEAtrbOTMOa0kYkxyzM1Z/II= +github.com/johannesboyne/gofakes3 v0.0.0-20260208201424-4c385a1f6a73/go.mod h1:S4S9jGBVlLri0OeqrSSbCGG5vsI6he06UJyuz1WT1EE= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -177,6 +217,8 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8= +github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= github.com/shirou/gopsutil/v4 v4.24.8 h1:pVQjIenQkIhqO81mwTaXjTzOMT7d3TZkf43PlVFHENI= github.com/shirou/gopsutil/v4 v4.24.8/go.mod h1:wE0OrJtj4dG+hYkxqDH3QiBICdKSf04/npcvLLc/oRg= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -234,12 +276,18 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5w go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.shabbyrobe.org/gocovmerge v0.0.0-20230507111327-fa4f82cfbf4d h1:Ns9kd1Rwzw7t0BR8XMphenji4SmIoNZPn8zhYmaVKP8= +go.shabbyrobe.org/gocovmerge v0.0.0-20230507111327-fa4f82cfbf4d/go.mod h1:92Uoe3l++MlthCm+koNi0tcUCX3anayogF0Pa/sp24k= go.temporal.io/api v1.5.0/go.mod h1:BqKxEJJYdxb5dqf0ODfzfMxh8UEQ5L3zKS51FiIYYkA= go.temporal.io/api v1.62.7 h1:joCtF30Dr+ynzrFJySewZsWbyf4AETZpuizHhFIyj/o= go.temporal.io/api v1.62.7/go.mod h1:iaxoP/9OXMJcQkETTECfwYq4cw/bj4nwov8b3ZLVnXM= go.temporal.io/sdk v1.12.0/go.mod h1:lSp3lH1lI0TyOsus0arnO3FYvjVXBZGi/G7DjnAnm6o= go.temporal.io/sdk v1.42.0 h1:2Zyrj1PZFd1xQVrrXF6RlE1nHZzZRuWfSyC2TqT3ri8= go.temporal.io/sdk v1.42.0/go.mod h1:Xp4TMHsie6kdw0lc0Ae4o8vktze5HZXBynF2DkiXcrQ= +go.temporal.io/sdk/contrib/aws/s3driver v0.1.1 h1:cV0nhvb5rTDxP06L3XVAqwTSgFDXFVBFaA3b9dQl4rk= +go.temporal.io/sdk/contrib/aws/s3driver v0.1.1/go.mod h1:/sYQljwSaVsL5bjdLeehUfKFlzA3y4jvbLShNv4PZ5Q= +go.temporal.io/sdk/contrib/aws/s3driver/awssdkv2 v0.1.1 h1:qNEdOWhbn+SeceOoCdd+WatLbIXFSuJa5EmiWhgH2F4= +go.temporal.io/sdk/contrib/aws/s3driver/awssdkv2 v0.1.1/go.mod h1:xAZx5FRbvG1MHG1TIhjcTiVnUdTSDyPHenbjWTQv4eA= go.temporal.io/sdk/contrib/sysinfo v0.1.0 h1:jqP6BFZ/n+BoTt/OnlD+llufgSJSoxlq+aAIZCxnBdI= go.temporal.io/sdk/contrib/sysinfo v0.1.0/go.mod h1:1i61HTH1W1M331FprZF3SHeLFhZQSmb/YEbFsPhI654= go.temporal.io/sdk/contrib/tally v0.2.0 h1:XnTJIQcjOv+WuCJ1u8Ve2nq+s2H4i/fys34MnWDRrOo= @@ -355,6 +403,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= 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= diff --git a/features/snippets/external_storage/custom_driver/custom_storage_driver.go b/features/snippets/external_storage/custom_driver/custom_storage_driver.go new file mode 100644 index 00000000..4f2056bb --- /dev/null +++ b/features/snippets/external_storage/custom_driver/custom_storage_driver.go @@ -0,0 +1,83 @@ +package customdriver + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/google/uuid" + commonpb "go.temporal.io/api/common/v1" + "go.temporal.io/sdk/converter" + "google.golang.org/protobuf/proto" +) + +// @@@SNIPSTART go-custom-storage-driver +type LocalDiskStorageDriver struct { + storeDir string +} + +func NewLocalDiskStorageDriver(storeDir string) *LocalDiskStorageDriver { + return &LocalDiskStorageDriver{storeDir: storeDir} +} + +func (d *LocalDiskStorageDriver) Name() string { + return "local-disk" +} + +func (d *LocalDiskStorageDriver) Type() string { + return "local-disk" +} + +func (d *LocalDiskStorageDriver) Store( + ctx converter.StorageDriverStoreContext, + payloads []*commonpb.Payload, +) ([]converter.StorageDriverClaim, error) { + dir := d.storeDir + if info, ok := ctx.Target.(converter.StorageDriverWorkflowInfo); ok && info.WorkflowID != "" { + dir = filepath.Join(d.storeDir, info.Namespace, info.WorkflowID) + } + if err := os.MkdirAll(dir, 0o755); err != nil { + return nil, fmt.Errorf("create store directory: %w", err) + } + + claims := make([]converter.StorageDriverClaim, len(payloads)) + for i, payload := range payloads { + key := uuid.NewString() + ".bin" + filePath := filepath.Join(dir, key) + + data, err := proto.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("marshal payload: %w", err) + } + if err := os.WriteFile(filePath, data, 0o644); err != nil { + return nil, fmt.Errorf("write payload: %w", err) + } + + claims[i] = converter.StorageDriverClaim{ + ClaimData: map[string]string{"path": filePath}, + } + } + return claims, nil +} + +func (d *LocalDiskStorageDriver) Retrieve( + ctx converter.StorageDriverRetrieveContext, + claims []converter.StorageDriverClaim, +) ([]*commonpb.Payload, error) { + payloads := make([]*commonpb.Payload, len(claims)) + for i, claim := range claims { + filePath := claim.ClaimData["path"] + data, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("read payload: %w", err) + } + payload := &commonpb.Payload{} + if err := proto.Unmarshal(data, payload); err != nil { + return nil, fmt.Errorf("unmarshal payload: %w", err) + } + payloads[i] = payload + } + return payloads, nil +} + +// @@@SNIPEND diff --git a/features/snippets/external_storage/multiple_drivers/multiple_drivers.go b/features/snippets/external_storage/multiple_drivers/multiple_drivers.go new file mode 100644 index 00000000..eab8746c --- /dev/null +++ b/features/snippets/external_storage/multiple_drivers/multiple_drivers.go @@ -0,0 +1,27 @@ +package multipledrivers + +import ( + commonpb "go.temporal.io/api/common/v1" + "go.temporal.io/sdk/converter" +) + +// @@@SNIPSTART go-external-storage-multiple-drivers +type PreferredSelector struct { + preferred converter.StorageDriver +} + +func (s *PreferredSelector) SelectDriver( + ctx converter.StorageDriverStoreContext, + payload *commonpb.Payload, +) (converter.StorageDriver, error) { + return s.preferred, nil +} + +func MultipleDriversSetup(preferredDriver, legacyDriver converter.StorageDriver) converter.ExternalStorage { + return converter.ExternalStorage{ + Drivers: []converter.StorageDriver{preferredDriver, legacyDriver}, + DriverSelector: &PreferredSelector{preferred: preferredDriver}, + } +} + +// @@@SNIPEND diff --git a/features/snippets/external_storage/s3_setup/s3_driver_create.go b/features/snippets/external_storage/s3_setup/s3_driver_create.go new file mode 100644 index 00000000..0d1ba7a4 --- /dev/null +++ b/features/snippets/external_storage/s3_setup/s3_driver_create.go @@ -0,0 +1,32 @@ +package s3setup + +import ( + "context" + "log" + + "github.com/aws/aws-sdk-go-v2/config" + awss3 "github.com/aws/aws-sdk-go-v2/service/s3" + "go.temporal.io/sdk/contrib/aws/s3driver" + "go.temporal.io/sdk/contrib/aws/s3driver/awssdkv2" + "go.temporal.io/sdk/converter" +) + +func CreateS3Driver() converter.StorageDriver { + // @@@SNIPSTART go-s3-driver-create + cfg, err := config.LoadDefaultConfig(context.Background(), + config.WithRegion("us-east-2"), + ) + if err != nil { + log.Fatalf("load AWS config: %v", err) + } + + driver, err := s3driver.NewDriver(s3driver.Options{ + Client: awssdkv2.NewClient(awss3.NewFromConfig(cfg)), + Bucket: s3driver.StaticBucket("my-temporal-payloads"), + }) + if err != nil { + log.Fatalf("create S3 driver: %v", err) + } + // @@@SNIPEND + return driver +} diff --git a/features/snippets/external_storage/s3_setup/s3_external_storage_setup.go b/features/snippets/external_storage/s3_setup/s3_external_storage_setup.go new file mode 100644 index 00000000..e2d45c14 --- /dev/null +++ b/features/snippets/external_storage/s3_setup/s3_external_storage_setup.go @@ -0,0 +1,27 @@ +package s3setup + +import ( + "log" + + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/converter" + "go.temporal.io/sdk/worker" +) + +func SetupExternalStorage(driver converter.StorageDriver) { + // @@@SNIPSTART go-s3-external-storage-setup + c, err := client.Dial(client.Options{ + HostPort: "localhost:7233", + ExternalStorage: converter.ExternalStorage{ + Drivers: []converter.StorageDriver{driver}, + }, + }) + if err != nil { + log.Fatalf("connect to Temporal: %v", err) + } + defer c.Close() + + w := worker.New(c, "my-task-queue", worker.Options{}) + // @@@SNIPEND + _ = w +} diff --git a/features/snippets/external_storage/threshold/threshold_config.go b/features/snippets/external_storage/threshold/threshold_config.go new file mode 100644 index 00000000..1b81bd65 --- /dev/null +++ b/features/snippets/external_storage/threshold/threshold_config.go @@ -0,0 +1,23 @@ +package threshold + +import ( + "log" + + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/converter" +) + +func ThresholdConfig(driver converter.StorageDriver) { + // @@@SNIPSTART go-external-storage-threshold + c, err := client.Dial(client.Options{ + ExternalStorage: converter.ExternalStorage{ + Drivers: []converter.StorageDriver{driver}, + PayloadSizeThreshold: 0, + }, + }) + // @@@SNIPEND + if err != nil { + log.Fatalf("connect to Temporal: %v", err) + } + defer c.Close() +} From cb790aa040ebdfa3c231ab35d0ca3cef062f93cc Mon Sep 17 00:00:00 2001 From: Lenny Chen Date: Fri, 10 Apr 2026 12:02:26 -0700 Subject: [PATCH 2/4] address engineer feedback on Go external storage snippets - Remove unnecessary awss3 import alias - Return converter.StorageDriver interface from constructor - Fix PayloadSizeThreshold minimum from 0 to 1 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../external_storage/custom_driver/custom_storage_driver.go | 4 ++-- .../snippets/external_storage/s3_setup/s3_driver_create.go | 4 ++-- .../snippets/external_storage/threshold/threshold_config.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/snippets/external_storage/custom_driver/custom_storage_driver.go b/features/snippets/external_storage/custom_driver/custom_storage_driver.go index 4f2056bb..1c17cea7 100644 --- a/features/snippets/external_storage/custom_driver/custom_storage_driver.go +++ b/features/snippets/external_storage/custom_driver/custom_storage_driver.go @@ -16,12 +16,12 @@ type LocalDiskStorageDriver struct { storeDir string } -func NewLocalDiskStorageDriver(storeDir string) *LocalDiskStorageDriver { +func NewLocalDiskStorageDriver(storeDir string) converter.StorageDriver { return &LocalDiskStorageDriver{storeDir: storeDir} } func (d *LocalDiskStorageDriver) Name() string { - return "local-disk" + return "my-local-disk" } func (d *LocalDiskStorageDriver) Type() string { diff --git a/features/snippets/external_storage/s3_setup/s3_driver_create.go b/features/snippets/external_storage/s3_setup/s3_driver_create.go index 0d1ba7a4..c8234ac2 100644 --- a/features/snippets/external_storage/s3_setup/s3_driver_create.go +++ b/features/snippets/external_storage/s3_setup/s3_driver_create.go @@ -5,7 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go-v2/config" - awss3 "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go-v2/service/s3" "go.temporal.io/sdk/contrib/aws/s3driver" "go.temporal.io/sdk/contrib/aws/s3driver/awssdkv2" "go.temporal.io/sdk/converter" @@ -21,7 +21,7 @@ func CreateS3Driver() converter.StorageDriver { } driver, err := s3driver.NewDriver(s3driver.Options{ - Client: awssdkv2.NewClient(awss3.NewFromConfig(cfg)), + Client: awssdkv2.NewClient(s3.NewFromConfig(cfg)), Bucket: s3driver.StaticBucket("my-temporal-payloads"), }) if err != nil { diff --git a/features/snippets/external_storage/threshold/threshold_config.go b/features/snippets/external_storage/threshold/threshold_config.go index 1b81bd65..e9f44619 100644 --- a/features/snippets/external_storage/threshold/threshold_config.go +++ b/features/snippets/external_storage/threshold/threshold_config.go @@ -12,7 +12,7 @@ func ThresholdConfig(driver converter.StorageDriver) { c, err := client.Dial(client.Options{ ExternalStorage: converter.ExternalStorage{ Drivers: []converter.StorageDriver{driver}, - PayloadSizeThreshold: 0, + PayloadSizeThreshold: 1, }, }) // @@@SNIPEND From 9553f4c784f7516ff6df30c27bd3615c2336033d Mon Sep 17 00:00:00 2001 From: Lenny Chen Date: Fri, 10 Apr 2026 12:53:21 -0700 Subject: [PATCH 3/4] address remaining engineer feedback on Go snippets - Add StorageDriverActivityInfo handling in custom driver - Remove blank lines before SNIPEND markers Co-Authored-By: Claude Opus 4.6 (1M context) --- .../custom_driver/custom_storage_driver.go | 12 +++++++++--- .../multiple_drivers/multiple_drivers.go | 1 - 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/features/snippets/external_storage/custom_driver/custom_storage_driver.go b/features/snippets/external_storage/custom_driver/custom_storage_driver.go index 1c17cea7..81d14eb2 100644 --- a/features/snippets/external_storage/custom_driver/custom_storage_driver.go +++ b/features/snippets/external_storage/custom_driver/custom_storage_driver.go @@ -33,8 +33,15 @@ func (d *LocalDiskStorageDriver) Store( payloads []*commonpb.Payload, ) ([]converter.StorageDriverClaim, error) { dir := d.storeDir - if info, ok := ctx.Target.(converter.StorageDriverWorkflowInfo); ok && info.WorkflowID != "" { - dir = filepath.Join(d.storeDir, info.Namespace, info.WorkflowID) + switch info := ctx.Target.(type) { + case converter.StorageDriverWorkflowInfo: + if info.WorkflowID != "" { + dir = filepath.Join(d.storeDir, info.Namespace, info.WorkflowID) + } + case converter.StorageDriverActivityInfo: + if info.ActivityID != "" { + dir = filepath.Join(d.storeDir, info.Namespace, info.ActivityID) + } } if err := os.MkdirAll(dir, 0o755); err != nil { return nil, fmt.Errorf("create store directory: %w", err) @@ -79,5 +86,4 @@ func (d *LocalDiskStorageDriver) Retrieve( } return payloads, nil } - // @@@SNIPEND diff --git a/features/snippets/external_storage/multiple_drivers/multiple_drivers.go b/features/snippets/external_storage/multiple_drivers/multiple_drivers.go index eab8746c..d2fb42cd 100644 --- a/features/snippets/external_storage/multiple_drivers/multiple_drivers.go +++ b/features/snippets/external_storage/multiple_drivers/multiple_drivers.go @@ -23,5 +23,4 @@ func MultipleDriversSetup(preferredDriver, legacyDriver converter.StorageDriver) DriverSelector: &PreferredSelector{preferred: preferredDriver}, } } - // @@@SNIPEND From 41dadb984ce566eb889c903a2badf3ddf3fab18e Mon Sep 17 00:00:00 2001 From: Lenny Chen Date: Fri, 10 Apr 2026 12:59:34 -0700 Subject: [PATCH 4/4] add comment clarifying StorageDriverActivityInfo usage Co-Authored-By: Claude Opus 4.6 (1M context) --- .../external_storage/custom_driver/custom_storage_driver.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/snippets/external_storage/custom_driver/custom_storage_driver.go b/features/snippets/external_storage/custom_driver/custom_storage_driver.go index 81d14eb2..0c6e6c41 100644 --- a/features/snippets/external_storage/custom_driver/custom_storage_driver.go +++ b/features/snippets/external_storage/custom_driver/custom_storage_driver.go @@ -39,6 +39,8 @@ func (d *LocalDiskStorageDriver) Store( dir = filepath.Join(d.storeDir, info.Namespace, info.WorkflowID) } case converter.StorageDriverActivityInfo: + // StorageDriverActivityInfo is only used for standalone (non-workflow-bound) + // activities. Activities started by a workflow use StorageDriverWorkflowInfo. if info.ActivityID != "" { dir = filepath.Join(d.storeDir, info.Namespace, info.ActivityID) }