diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d65f4909..07fa7e9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,6 @@ jobs: submodules: recursive - uses: actions/setup-go@v2 with: - go-version: "1.18" + go-version: "1.19" - name: CI Build run: make ci-build diff --git a/README.md b/README.md index 2a4e7588..1ac5234f 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,7 @@ Each sample demonstrates one feature of the SDK, together with tests. execute a Child Workflow from a Parent Workflow Execution. A Child Workflow Execution only returns to the Parent Workflow Execution after completing its last Run. -- [**Child Workflow with - ContinueAsNew**](./child-workflow-continue-as-new): Demonstrates +- [**Child Workflow with ContinueAsNew**](./child-workflow-continue-as-new): Demonstrates that the call to Continue-As-New, by a Child Workflow Execution, is *not visible to the a parent*. The Parent Workflow Execution receives a notification only when a Child Workflow Execution completes, fails or times out. This is a useful feature when there is a need to **process a large set of data**. The child can iterate over the data set calling @@ -135,6 +134,9 @@ Each sample demonstrates one feature of the SDK, together with tests. - [**Interceptors**](./interceptor): Demonstrates how to use interceptors to intercept calls, in this case for adding context to the logger. +- [**Update**](./update): Demonstrates how to create a workflow that reacts + to workflow update requests. + ### Dynamic Workflow logic examples These samples demonstrate some common control flow patterns using Temporal's Go SDK API. @@ -218,6 +220,9 @@ resource waiting its successful completion - [**Request/Response with Response Queries**](./reqrespquery): Demonstrates how to accept requests via signals and use queries to poll for responses. +- [**Request/Response with Response Updates**](./reqrespupdate): + Demonstrates how to accept requests and responsond via updates. + ### Pending examples Mostly examples we haven't yet ported from https://github.com/temporalio/samples-java/ diff --git a/build-id-versioning/README.md b/build-id-versioning/README.md new file mode 100644 index 00000000..6f62325c --- /dev/null +++ b/build-id-versioning/README.md @@ -0,0 +1,23 @@ +# Build ID Based Versioning +This sample illustrates how to use Build ID based versioning to help you appropriately roll out +incompatible and compatible changes to workflow and activity code for the same task queue. + +## Description +The sample shows you how to roll out both a compatible change and an incompatible change to a +workflow. + +## Running +1) Run a [Temporal service](https://github.com/temporalio/samples-go/tree/main/#how-to-use). +2) Run + ``` + go run build-id-versioning/worker/main.go + ``` + to start the appropriate workers. It will print a task queue name to the console, which you + will need to copy and paste when running the next step. This is to allow running the sample + repeatedly without encountering issues due to Build IDs already existing on the queue. + +3) Run + ``` + go run build-id-versioning/starter/main.go + ``` + to start the workflows. diff --git a/build-id-versioning/starter/main.go b/build-id-versioning/starter/main.go new file mode 100644 index 00000000..d6ff6bc0 --- /dev/null +++ b/build-id-versioning/starter/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "context" + "log" + "os" + "time" + + "go.temporal.io/api/workflowservice/v1" + + "github.com/pborman/uuid" + + "go.temporal.io/sdk/client" +) + +func main() { + ctx := context.Background() + + // Get task queue name from CLI arg + taskQueue := os.Args[1] + if taskQueue == "" { + log.Fatalln("Must provide task queue name as first and only argument") + } + log.Println("Using task queue", taskQueue) + + // The client is a heavyweight object that should be created once per process. + c, err := client.Dial(client.Options{ + HostPort: client.DefaultHostPort, + }) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + // First, let's make the task queue use the build id versioning feature by adding an initial + // default version to the queue: + err = c.UpdateWorkerBuildIdCompatibility(ctx, &client.UpdateWorkerBuildIdCompatibilityOptions{ + TaskQueue: taskQueue, + Operation: &client.BuildIDOpAddNewIDInNewDefaultSet{ + BuildID: "1.0", + }, + }) + if err != nil { + log.Fatalln("Unable to update worker build id compatibility", err) + } + + firstWorkflowID := "build-id-versioning-first_" + uuid.New() + firstWorkflowOptions := client.StartWorkflowOptions{ + ID: firstWorkflowID, + TaskQueue: taskQueue, + WorkflowExecutionTimeout: 5 * time.Minute, + } + firstExecution, err := c.ExecuteWorkflow(ctx, firstWorkflowOptions, "SampleChangingWorkflow") + if err != nil { + log.Fatalln("Unable to start workflow", err) + } + log.Println("Started first workflow", + "WorkflowID", firstExecution.GetID(), "RunID", firstExecution.GetRunID()) + + // Signal this workflow a few times to drive it + for i := 0; i < 3; i++ { + err = c.SignalWorkflow(ctx, firstExecution.GetID(), firstExecution.GetRunID(), + "do-next-signal", "do-activity") + if err != nil { + log.Fatalln("Unable to signal workflow", err) + } + } + + // Give a chance for these signals to be processed by the 1.0 worker + time.Sleep(5 * time.Second) + + // Now, let's update the task queue with a new compatible version: + err = c.UpdateWorkerBuildIdCompatibility(ctx, &client.UpdateWorkerBuildIdCompatibilityOptions{ + TaskQueue: taskQueue, + Operation: &client.BuildIDOpAddNewCompatibleVersion{ + BuildID: "1.1", + ExistingCompatibleBuildID: "1.0", + }, + }) + if err != nil { + log.Fatalln("Unable to update build id compatability", err) + } + + // Continue driving the workflow. Take note that the new version of the workflow run by the + // 1.1 worker is the one that takes over! You might see a workflow task timeout, if the 1.0 + // worker is processing a task as the version update happens. That's normal. + for i := 0; i < 3; i++ { + err = c.SignalWorkflow(ctx, firstExecution.GetID(), firstExecution.GetRunID(), + "do-next-signal", "do-activity") + if err != nil { + log.Fatalln("Unable to signal workflow", err) + } + } + + // Add a new *incompatible* version to the task queue, which will become the new overall default + // for the queue. + err = c.UpdateWorkerBuildIdCompatibility(ctx, &client.UpdateWorkerBuildIdCompatibilityOptions{ + TaskQueue: taskQueue, + Operation: &client.BuildIDOpAddNewIDInNewDefaultSet{ + BuildID: "2.0", + }, + }) + if err != nil { + log.Fatalln("Unable to update build id compatability", err) + } + + // Start a new workflow, note that it will run on the new 2.0 version, without the client + // invocation changing at all! + secondWorkflowID := "build-id-versioning-second_" + uuid.New() + secondWorkflowOptions := client.StartWorkflowOptions{ + ID: secondWorkflowID, + TaskQueue: taskQueue, + WorkflowExecutionTimeout: 5 * time.Minute, + } + secondExecution, err := c.ExecuteWorkflow(ctx, secondWorkflowOptions, "SampleChangingWorkflow") + if err != nil { + log.Fatalln("Unable to start workflow", err) + } + log.Println("Started second workflow", + "WorkflowID", secondExecution.GetID(), "RunID", secondExecution.GetRunID()) + + // Drive the first workflow to completion, the second will finish on its own + err = c.SignalWorkflow(ctx, firstExecution.GetID(), firstExecution.GetRunID(), + "do-next-signal", "do-activity") + if err != nil { + log.Fatalln("Unable to signal workflow", err) + } + err = c.SignalWorkflow(ctx, firstExecution.GetID(), firstExecution.GetRunID(), + "do-next-signal", "finish") + if err != nil { + log.Fatalln("Unable to signal workflow", err) + } + + // Lastly we'll demonstrate how you can use the gRPC api to determine if certain bulid IDs are + // ready to be retied. There's more information in the documentation, but here's a quick example + // that will show us that we can retire the 1.0 worker: + retirementInfo, err := c.WorkflowService().GetWorkerTaskReachability(ctx, &workflowservice.GetWorkerTaskReachabilityRequest{ + Namespace: "default", + BuildIds: []string{"1.0"}, + }) + if err != nil { + log.Fatalln("Unable to get build id reachability", err) + } + reachabilityOf1Dot0 := retirementInfo.GetBuildIdReachability()[0] + noReachableQueues := true + for _, tq := range reachabilityOf1Dot0.GetTaskQueueReachability() { + if tq.GetReachability() != nil && len(tq.GetReachability()) > 0 { + noReachableQueues = false + } + } + if noReachableQueues { + log.Println("We have determined 1.0 is ready to be retired") + } + +} diff --git a/build-id-versioning/worker/main.go b/build-id-versioning/worker/main.go new file mode 100644 index 00000000..837990df --- /dev/null +++ b/build-id-versioning/worker/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "github.com/pborman/uuid" + build_id_versioning "github.com/temporalio/samples-go/build-id-versioning" + "sync" + + "log" + + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/worker" + "go.temporal.io/sdk/workflow" +) + +func main() { + c, err := client.Dial(client.Options{ + HostPort: client.DefaultHostPort, + }) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + taskQueue := "build-id-versioning-" + uuid.New() + log.Println("Using Task Queue name: ", taskQueue, "(Copy this!)") + + // We will start a handful of workers, each with a different build identifier. + wg := sync.WaitGroup{} + createAndRunWorker(c, taskQueue, "1.0", build_id_versioning.SampleChangingWorkflowV1, &wg) + createAndRunWorker(c, taskQueue, "1.1", build_id_versioning.SampleChangingWorkflowV1b, &wg) + createAndRunWorker(c, taskQueue, "2.0", build_id_versioning.SampleChangingWorkflowV2, &wg) + wg.Wait() +} + +func createAndRunWorker(c client.Client, taskQueue, buildID string, workflowFunc func(ctx workflow.Context) error, wg *sync.WaitGroup) { + w := worker.New(c, taskQueue, worker.Options{ + // Both of these options must be set to opt into the feature + BuildID: buildID, + UseBuildIDForVersioning: true, + }) + // It's important that we register all the different implementations of the workflow using + // the same name. This allows us to demonstrate what would happen if you were making changes + // to this workflow code over time while keeping the same workflow name/type. + w.RegisterWorkflowWithOptions(workflowFunc, workflow.RegisterOptions{Name: "SampleChangingWorkflow"}) //workflowcheck:ignore + w.RegisterActivity(build_id_versioning.SomeActivity) + w.RegisterActivity(build_id_versioning.SomeIncompatibleActivity) + + wg.Add(1) + go func() { + defer wg.Done() + err := w.Run(worker.InterruptCh()) + if err != nil { + log.Fatalf("Unable to start %s worker: %v", buildID, err) + } + }() +} diff --git a/build-id-versioning/workflows.go b/build-id-versioning/workflows.go new file mode 100644 index 00000000..78666686 --- /dev/null +++ b/build-id-versioning/workflows.go @@ -0,0 +1,132 @@ +package build_id_versioning + +import ( + "context" + "go.temporal.io/sdk/activity" + "go.temporal.io/sdk/workflow" + "time" +) + +// SampleChangingWorkflowV1 is a workflow we'll be making changes to, and represents the first +// version +func SampleChangingWorkflowV1(ctx workflow.Context) error { + workflow.GetLogger(ctx).Info("Changing workflow v1 started.", "StartTime", workflow.Now(ctx)) + + // This workflow will listen for signals from our starter, and upon each signal either run + // an activity, or conclude execution. + signalChan := workflow.GetSignalChannel(ctx, "do-next-signal") + for { + var signal string + signalChan.Receive(ctx, &signal) + + if signal == "do-activity" { + workflow.GetLogger(ctx).Info("Changing workflow v1 running activity") + ao := workflow.ActivityOptions{ + StartToCloseTimeout: 10 * time.Second, + } + ctx1 := workflow.WithActivityOptions(ctx, ao) + err := workflow.ExecuteActivity(ctx1, SomeActivity, "v1").Get(ctx1, nil) + if err != nil { + return err + } + } else { + workflow.GetLogger(ctx).Info("Concluding workflow v1") + return nil + } + } +} + +// SampleChangingWorkflowV1b represents us having made *compatible* changes to +// SampleChangingWorkflowV1. +// +// The compatible changes we've made are: +// - Altering the log lines +// - Using the workflow.GetVersion API to properly introduce branching behavior while maintaining +// compatibility +func SampleChangingWorkflowV1b(ctx workflow.Context) error { + workflow.GetLogger(ctx).Info("Changing workflow v1b started.", "StartTime", workflow.Now(ctx)) + + // This workflow will listen for signals from our starter, and upon each signal either run + // an activity, or conclude execution. + signalChan := workflow.GetSignalChannel(ctx, "do-next-signal") + for { + var signal string + signalChan.Receive(ctx, &signal) + + if signal == "do-activity" { + workflow.GetLogger(ctx).Info("Changing workflow v1b running activity") + v := workflow.GetVersion(ctx, "DifferentActivity", workflow.DefaultVersion, 1) + if v == workflow.DefaultVersion { + ao := workflow.ActivityOptions{ + StartToCloseTimeout: 10 * time.Second, + } + ctx1 := workflow.WithActivityOptions(ctx, ao) + // Note it is a valid compatible change to alter the input to an activity. + // However, because we're using the GetVersion API, this branch will never be + // taken. + err := workflow.ExecuteActivity(ctx1, SomeActivity, "v1b").Get(ctx1, nil) + if err != nil { + return err + } + } else { + ao := workflow.ActivityOptions{ + StartToCloseTimeout: 10 * time.Second, + } + ctx1 := workflow.WithActivityOptions(ctx, ao) + err := workflow.ExecuteActivity(ctx1, SomeIncompatibleActivity, &IncompatibleActivityInput{ + CalledBy: "v1b", + MoreData: "hello!", + }).Get(ctx1, nil) + if err != nil { + return err + } + } + } else { + workflow.GetLogger(ctx).Info("Concluding workflow v1b") + break + } + } + + return nil +} + +// SampleChangingWorkflowV2 is fully incompatible with the other workflows, since it alters the +// sequence of commands without using workflow.GetVersion. +func SampleChangingWorkflowV2(ctx workflow.Context) error { + workflow.GetLogger(ctx).Info("Changing workflow v2 started.", "StartTime", workflow.Now(ctx)) + err := workflow.Sleep(ctx, 10*time.Second) + if err != nil { + return err + + } + ao := workflow.ActivityOptions{ + StartToCloseTimeout: 10 * time.Second, + } + ctx1 := workflow.WithActivityOptions(ctx, ao) + err = workflow.ExecuteActivity(ctx1, SomeActivity, "v2").Get(ctx, nil) + if err != nil { + return err + } + return nil +} + +func SomeActivity(ctx context.Context, calledBy string) (string, error) { + activity.GetLogger(ctx).Info("SomeActivity executing", "called by", calledBy) + return calledBy, nil +} + +// SomeIncompatibleActivity represents the need to change the interface to SomeActivity. Perhaps +// we didn't realize we would need to pass additional data, and we change the string parameter to +// a struct. (Hint: It's a great idea to always start with structs for this reason, as they can +// be extended without breaking compatibility as long as you use a wire format that maintains +// compatibility.) +func SomeIncompatibleActivity(ctx context.Context, input IncompatibleActivityInput) error { + activity.GetLogger(ctx).Info("SomeIncompatibleActivity executing", + "called by", input.CalledBy, "more data", input.MoreData) + return nil +} + +type IncompatibleActivityInput struct { + CalledBy string + MoreData string +} diff --git a/docker-compose.yml b/docker-compose.yml index 2f60183b..3e336320 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,8 @@ services: depends_on: - temporal environment: - - TEMPORAL_CLI_ADDRESS=temporal:7233 + - TEMPORAL_ADDRESS=temporal:7233 # used by temporal + - TEMPORAL_CLI_ADDRESS=temporal:7233 # used by tctl image: temporalio/admin-tools:${TEMPORAL_VERSION} networks: - temporal-network diff --git a/go.mod b/go.mod index 25a69039..72f47a45 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ module github.com/temporalio/samples-go -go 1.16 +go 1.19 replace github.com/cactus/go-statsd-client => github.com/cactus/go-statsd-client v3.2.1+incompatible require ( - github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/golang/mock v1.6.0 github.com/golang/snappy v0.0.4 github.com/google/uuid v1.3.0 @@ -16,12 +15,11 @@ require ( github.com/stretchr/testify v1.8.3 github.com/uber-go/tally/v4 v4.1.1 github.com/uber/jaeger-client-go v2.29.1+incompatible - github.com/uber/jaeger-lib v2.4.1+incompatible // indirect go.temporal.io/api v1.21.0 - go.temporal.io/sdk v1.23.0 + go.temporal.io/sdk v1.24.0 go.temporal.io/sdk/contrib/opentracing v0.1.0 go.temporal.io/sdk/contrib/tally v0.2.0 - go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230413153418-eaa3802876de + go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230612164027-11c2cb9e7d2d go.temporal.io/server v1.15.2 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.20.0 @@ -29,3 +27,74 @@ require ( gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.1 ) + +require ( + github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect + github.com/aws/aws-sdk-go v1.42.44 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e // indirect + github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/go-logr/logr v1.2.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gocql/gocql v0.0.0-20211222173705-d73e6b1002a7 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/gogo/status v1.1.1 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect + github.com/hashicorp/go-hclog v1.1.0 // indirect + github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/olivere/elastic v6.2.37+incompatible // indirect + github.com/olivere/elastic/v7 v7.0.31 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/robfig/cron v1.2.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/twmb/murmur3 v1.1.6 // indirect + github.com/uber/jaeger-lib v2.4.1+incompatible // indirect + github.com/uber/tchannel-go v1.22.2 // indirect + go.opentelemetry.io/otel v1.3.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.26.0 // indirect + go.opentelemetry.io/otel/internal/metric v0.26.0 // indirect + go.opentelemetry.io/otel/metric v0.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.3.0 // indirect + go.opentelemetry.io/otel/sdk/export/metric v0.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v0.26.0 // indirect + go.opentelemetry.io/otel/trace v1.3.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/dig v1.13.0 // indirect + go.uber.org/fx v1.16.0 // indirect + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.9.3 // indirect + google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0 // indirect +) diff --git a/go.sum b/go.sum index 389d3b6b..f6f500c4 100644 --- a/go.sum +++ b/go.sum @@ -158,7 +158,6 @@ cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQky cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= @@ -301,7 +300,6 @@ cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2r cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= @@ -523,7 +521,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.19.0/go.mod h1:6rgiTRjOqI/Zd9YKimub5TIB4d+p3LH33V3ZE1DMuUM= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= @@ -616,14 +613,11 @@ github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.0.0-20150905105024-5bc8b5a3a5da/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= github.com/aws/aws-sdk-go v1.42.44 h1:vPlF4cUsdN5ETfvb7ewZFbFZyB6Rsfndt3kS2XqLXKo= github.com/aws/aws-sdk-go v1.42.44/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= -github.com/benbjohnson/clock v0.0.0-20160125162948-a620c1cc9866/go.mod h1:UMqtWQTnOe4byzwe7Zhwh8f8s+36uszN51sJrSIZlTE= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -637,18 +631,15 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= +github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e h1:mWOqoK5jV13ChKf/aF3plwQ96laasTJgZi4f1aSOu+M= +github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/brianvoe/gofakeit/v6 v6.10.0/go.mod h1:palrJUk4Fyw38zIFB/uBZqsgzW5VsNllhHKKwAebzew= -github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c h1:HIGF0r/56+7fuIZw2V4isE22MK6xpxWx7BbV8dJ290w= github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -671,19 +662,14 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/go-farm v0.0.0-20140601200337-fc41e106ee0e/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -734,7 +720,6 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gocql/gocql v0.0.0-20211222173705-d73e6b1002a7 h1:jmIMM+nEO+vjz9xaRIg9sZNtNLq5nsSbsxwe1OtRwv4= @@ -854,7 +839,6 @@ github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57Q github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -881,7 +865,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -904,7 +887,6 @@ github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -916,8 +898,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -933,10 +913,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -956,7 +932,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic v6.2.37+incompatible h1:UfSGJem5czY+x/LqxgeCBgjDn6St+z8OnsCuxwD3L0U= github.com/olivere/elastic v6.2.37+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= github.com/olivere/elastic/v7 v7.0.31 h1:VJu9/zIsbeiulwlRCfGQf6Tzsr++uo+FeUgj5oj+xKk= @@ -1004,10 +979,7 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rcrowley/go-metrics v0.0.0-20141108142129-dee209f2455f/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -1017,17 +989,11 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/samuel/go-thrift v0.0.0-20191111193933-5165175b40af/go.mod h1:Vrkh1pnjV9Bl8c3P9zH0/D4NlOHWP5d4/hF4YTULaec= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.2-0.20170726183946-abee6f9b0679/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak= @@ -1035,8 +1001,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= +github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d h1:X4+kt6zM/OVO6gbJdAfJR60MGPsqCzbtXNnjoGqdfAs= +github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1054,27 +1020,17 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/temporalio/ringpop-go v0.0.0-20211012191444-6f91b5915e95/go.mod h1:Ek9J8CAfI1IwVSqHpTOgj7FjzRSJ5SM/ud52eCmkhsw= github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/uber-common/bark v1.0.0/go.mod h1:g0ZuPcD7XiExKHynr93Q742G/sbrdVQkghrqLGOoFuY= -github.com/uber-common/bark v1.3.0/go.mod h1:5fDe/YcIVP55XhFF9hUihX2lDsDcpFrTZEAwAVwtPDw= github.com/uber-go/tally/v4 v4.1.1 h1:jhy6WOZp4nHyCqeV43x3Wz370LXUGBhgW2JmzOIHCWI= github.com/uber-go/tally/v4 v4.1.1/go.mod h1:aXeSTDMl4tNosyf6rdU8jlgScHyjEGGtfJ/uwCIf/vM= -github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/uber/tchannel-go v1.16.0/go.mod h1:Rrgz1eL8kMjW/nEzZos0t+Heq0O4LhnUJVA32OvWKHo= github.com/uber/tchannel-go v1.22.2 h1:NKA5FVESYh6Ij6V+tujK+IFZnBKDyUHdsBY264UYhgk= github.com/uber/tchannel-go v1.22.2/go.mod h1:Rrgz1eL8kMjW/nEzZos0t+Heq0O4LhnUJVA32OvWKHo= -github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/vektra/mockery v0.0.0-20181123154057-e78b021dcbb5/go.mod h1:ppEjwdhyy7Y31EnHRDm1JkChoC7LXIJ7Ex0VYLWtZtQ= -github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1112,26 +1068,20 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.temporal.io/api v1.5.0/go.mod h1:BqKxEJJYdxb5dqf0ODfzfMxh8UEQ5L3zKS51FiIYYkA= -go.temporal.io/api v1.6.1-0.20211110205628-60c98e9cbfe2/go.mod h1:IlUgOTGfmJuOkGrCZdptNxyXKE9CQz6oOx7/aH9bFY4= -go.temporal.io/api v1.7.1-0.20220131203817-08fe71b1361d/go.mod h1:RJ6blV8Zh4cdZvR48DzFuMHUCP8fV4lIIBLDPkLkMBk= go.temporal.io/api v1.21.0 h1:l2HrMI/gE5JwFu9wgmZdofBIQ5MzziOEBs8mnbJUcJs= go.temporal.io/api v1.21.0/go.mod h1:xlsUEakkN2vU2/WV7e5NqMG4N93nfuNfvbXdaXUpU8w= go.temporal.io/sdk v1.12.0/go.mod h1:lSp3lH1lI0TyOsus0arnO3FYvjVXBZGi/G7DjnAnm6o= -go.temporal.io/sdk v1.13.0/go.mod h1:TCof7U/xas2FyDnx/UUEv4c/O/S41Lnhva+6JVer+Jo= -go.temporal.io/sdk v1.23.0 h1:oa9/1f3bbcBLiNGbYf9woIx7uWFJ153q0JOkPeZqJtQ= -go.temporal.io/sdk v1.23.0/go.mod h1:S7vWxU01lGcCny0sWx03bkkYw4VtVrpzeqBTn2A6y+E= +go.temporal.io/sdk v1.24.0 h1:mAk5VFR+z4s8QVzRx3iIpRnHcEO3m10CYNjnRXrhVq4= +go.temporal.io/sdk v1.24.0/go.mod h1:S7vWxU01lGcCny0sWx03bkkYw4VtVrpzeqBTn2A6y+E= go.temporal.io/sdk/contrib/opentracing v0.1.0 h1:z5F1EoZQ6v8bMH/pzcFRgzoPKZCB+exUKMYt0jzuWME= go.temporal.io/sdk/contrib/opentracing v0.1.0/go.mod h1:rQavYHnrTXlFKvKrn5R91eOLdvaJJ27gtxaKFqH3LuM= go.temporal.io/sdk/contrib/tally v0.2.0 h1:XnTJIQcjOv+WuCJ1u8Ve2nq+s2H4i/fys34MnWDRrOo= go.temporal.io/sdk/contrib/tally v0.2.0/go.mod h1:1kpSuCms/tHeJQDPuuKkaBsMqfHnIIRnCtUYlPNXxuE= -go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230413153418-eaa3802876de h1:e818Pvmg4wl5nzvacVW539OOK0rXsxAopFiOYX/yvIU= -go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230413153418-eaa3802876de/go.mod h1:CW0zVy7oLeWxBo3wG5bMU2dy4xaprM2net3/DkBzruw= +go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230612164027-11c2cb9e7d2d h1:mCFwh4u5G5taa/sKbA/7Ve5pxkZZ2UFFLvJ9W8aw2hI= +go.temporal.io/sdk/contrib/tools/workflowcheck v0.0.0-20230612164027-11c2cb9e7d2d/go.mod h1:CW0zVy7oLeWxBo3wG5bMU2dy4xaprM2net3/DkBzruw= go.temporal.io/server v1.15.2 h1:3za3YwtJz9g/KOKfASLD6QWQwtfGObTUqny/q/EVi3o= go.temporal.io/server v1.15.2/go.mod h1:AXMXBNqMzAKVYUtnJhDoqk7COOykPdJ9i+TxOMgL/Rc= -go.temporal.io/version v0.3.0/go.mod h1:UA9S8/1LaKYae6TyD9NaPMJTZb911JcbqghI2CBSP78= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -1144,15 +1094,12 @@ go.uber.org/fx v1.16.0/go.mod h1:OMoT5BnXcOaiexlpjtpE4vcAmzyDKyRs9TRYXCzamx8= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.20.0 h1:N4oPlghZwYG55MlU6LXk/Zp00FVNE9X9wrYO8CEs4lc= go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= @@ -1224,8 +1171,9 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1269,7 +1217,6 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211109214657-ef0fda0de508/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1351,7 +1298,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1403,7 +1349,6 @@ golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1459,14 +1404,12 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181112210238-4b1f3b6b1646/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1495,7 +1438,6 @@ golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200128220307-520188d60f50/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1531,8 +1473,9 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= 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= @@ -1580,9 +1523,6 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= -google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg= -google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= @@ -1648,7 +1588,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1679,18 +1618,11 @@ google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= @@ -1805,7 +1737,6 @@ google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3 google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/examples v0.0.0-20220201220150-c7f7d3a75c27/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1839,7 +1770,6 @@ gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/validator.v2 v2.0.0-20200605151824-2b28d334fa05/go.mod h1:o4V0GXN9/CAmCsvJ0oXYZvrZOe7syiDZSN1GWGZTGzc= gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0 h1:EFLtLCwd8tGN+r/ePz3cvRtdsfYNhDEdt/vp6qsT+0A= gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0/go.mod h1:o4V0GXN9/CAmCsvJ0oXYZvrZOe7syiDZSN1GWGZTGzc= -gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/reqrespupdate/README.md b/reqrespupdate/README.md new file mode 100644 index 00000000..c2b06f83 --- /dev/null +++ b/reqrespupdate/README.md @@ -0,0 +1,49 @@ +# Request/Response Sample with Update-Based Responses + +This sample demonstrates how to send a request and get a response from a Temporal workflow via an update. + +[Update](https://docs.temporal.io/workflows#update) is a new feature available for preview on [Temporal Server v1.21](https://github.com/temporalio/temporal/releases/tag/v1.21.0). + +### Running + +Follow the below steps to run this sample: + +1) Run a [Temporal service](https://github.com/temporalio/samples-go/tree/main/#how-to-use). Note, update is only supported on [Temporal Server v1.21](https://github.com/temporalio/temporal/releases/tag/v1.21.0) + +2) Update functionality is disabled by default but can be enabled per Namespace by setting the `frontend.enableUpdateWorkflowExecution` flag to true for that Namespace in dynamic config. + +3) Run the following command in the background or in another terminal to run the worker: + + go run ./reqrespupdate/worker + +4) Run the following command to start the workflow: + + go run ./reqrespupdate/starter + +5) Run the following command to uppercase a string every second: + + go run ./reqrespupdate/request + +Multiple of those can be run on different terminals to confirm that the processes are independent. + +### Comparison with activity-based responses and query-based response + +There are two other samples showing how to do a request response pattern under [reqrespactivity](../reqrespactivity) sample and the [reqrespquery](../reqrespquery). The update based approach is the superior option, and once released, will be the recommend approach. + + +### Explanation of continue-as-new + +Workflows cannot have infinitely-sized history and when the event count grows too large, `ContinueAsNew` can be returned +to start a new one atomically. However, in order not to lose any data, update requests must be handled and any other futures +that need to be reacted to must be completed first. This means there must be a period where there are no updates to +process and no futures to wait on. If update requests come in faster than processed or futures wait so long there is no idle +period, `ContinueAsNew` will not happen in a timely manner and history will grow. + +Since this sample is a long-running workflow, once the request count reaches a certain size, we perform a +`ContinueAsNew`. To not lose any data, we only send this if there are no in-flight update requests or executing +activities. An executing activity can mean it is busy retrying. Care must be taken designing these systems where they do +not receive requests so frequent that they can never have a idle period to return a `ContinueAsNew`. Signals are usually +fast to receive, so they are less of a problem. Waiting on activities (as a response to the request or as a response +callback activity) can be a tougher problem. Since we rely on the response of the activity, activity must complete +including all retries. Retry policies of these activities should be set balancing the resiliency needs with the need to +have a period of idleness at some point. diff --git a/reqrespupdate/request/main.go b/reqrespupdate/request/main.go new file mode 100644 index 00000000..44fffa99 --- /dev/null +++ b/reqrespupdate/request/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "context" + "errors" + "flag" + "log" + "os" + "os/signal" + "strconv" + "time" + + "github.com/temporalio/samples-go/reqrespupdate" + "go.temporal.io/sdk/client" +) + +func main() { + var opts reqrespupdate.RequesterOptions + flag.StringVar(&opts.TargetWorkflowID, "w", "reqrespupdate_workflow", "WorkflowID") + flag.Parse() + + // Create client + var err error + opts.Client, err = client.Dial(client.Options{ + HostPort: client.DefaultHostPort, + }) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer opts.Client.Close() + + // Create requester + req, err := reqrespupdate.NewRequester(opts) + if err != nil { + log.Fatalln("Unable to create requester", err) + } + + // Run until ctrl+c + log.Printf("Requesting every second until ctrl+c") + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + <-c + cancel() + }() + + // Request every second + t := time.NewTicker(1 * time.Second) + defer t.Stop() + for i := 0; ; i++ { + str := "foo" + strconv.Itoa(i) + log.Printf("Requesting %q be uppercased", str) + if val, err := req.RequestUppercase(ctx, str); err != nil { + log.Printf(" Failed: %v", errors.Unwrap(err)) + // Backoff so the workflow can continue as new + if errors.Unwrap(err).Error() == reqrespupdate.ErrBackoff.Error() { + log.Printf("Workflow trying to continue as new, backing off") + time.Sleep(2 * time.Second) + } + } else { + log.Printf(" Result: %q", val) + } + select { + case <-ctx.Done(): + return + case <-t.C: + } + } +} diff --git a/reqrespupdate/requester.go b/reqrespupdate/requester.go new file mode 100644 index 00000000..b3ef4b8f --- /dev/null +++ b/reqrespupdate/requester.go @@ -0,0 +1,46 @@ +package reqrespupdate + +import ( + "context" + "fmt" + + "go.temporal.io/sdk/client" +) + +// Requester can request uppercasing of strings. +type Requester struct { + options RequesterOptions +} + +// RequesterOptions are options for NewRequester. +type RequesterOptions struct { + // Client to the Temporal server. Required. + Client client.Client + // ID of the workflow listening for signals to uppercase. Required. + TargetWorkflowID string +} + +// NewRequester creates a new Requester for the given options. +func NewRequester(options RequesterOptions) (*Requester, error) { + if options.Client == nil { + return nil, fmt.Errorf("client required") + } else if options.TargetWorkflowID == "" { + return nil, fmt.Errorf("target workflow required") + } + return &Requester{options}, nil +} + +// RequestUppercase sends a request and returns a response. +func (r *Requester) RequestUppercase(ctx context.Context, str string) (string, error) { + // Send request and poll on an interval for response + handle, err := r.options.Client.UpdateWorkflow(ctx, r.options.TargetWorkflowID, "", UpdateHandler, Request{Input: str}) + if err != nil { + return "", fmt.Errorf("failed updating workflow: %w", err) + } + var response Response + err = handle.Get(ctx, &response) + if err != nil { + return "", fmt.Errorf("failed getting update response: %w", err) + } + return response.Output, nil +} diff --git a/reqrespupdate/starter/main.go b/reqrespupdate/starter/main.go new file mode 100644 index 00000000..bf9fa12f --- /dev/null +++ b/reqrespupdate/starter/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "context" + "log" + + "github.com/temporalio/samples-go/reqrespupdate" + "go.temporal.io/sdk/client" +) + +func main() { + c, err := client.Dial(client.Options{ + HostPort: client.DefaultHostPort, + }) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + workflowOptions := client.StartWorkflowOptions{ + ID: "reqrespupdate_workflow", + TaskQueue: "reqrespupdate", + } + + we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, reqrespupdate.UppercaseWorkflow, true) + if err != nil { + log.Fatalln("Unable to execute workflow", err) + } + log.Println("Started workflow", "WorkflowID", we.GetID(), "RunID", we.GetRunID()) +} diff --git a/reqrespupdate/worker/main.go b/reqrespupdate/worker/main.go new file mode 100644 index 00000000..b29622fa --- /dev/null +++ b/reqrespupdate/worker/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "log" + + "github.com/temporalio/samples-go/reqrespupdate" + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/worker" +) + +func main() { + c, err := client.Dial(client.Options{ + HostPort: client.DefaultHostPort, + }) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + w := worker.New(c, "reqrespupdate", worker.Options{}) + + w.RegisterWorkflow(reqrespupdate.UppercaseWorkflow) + w.RegisterActivity(reqrespupdate.UppercaseActivity) + + err = w.Run(worker.InterruptCh()) + if err != nil { + log.Fatalln("Unable to start worker", err) + } +} diff --git a/reqrespupdate/workflow.go b/reqrespupdate/workflow.go new file mode 100644 index 00000000..2ae1a747 --- /dev/null +++ b/reqrespupdate/workflow.go @@ -0,0 +1,121 @@ +package reqrespupdate + +import ( + "context" + "errors" + "fmt" + "strings" + "time" + + "go.temporal.io/sdk/temporal" + "go.temporal.io/sdk/workflow" +) + +const ( + UpdateHandler = "update" +) + +var ( + ErrBackoff = errors.New("trying to continue as new") +) + +// UppercaseWorkflow is a workflow that accepts requests to uppercase strings +// via updates and provides a response. +func UppercaseWorkflow(ctx workflow.Context, rejectUpdateOnPendingContinueAsNew bool) error { + // Create and run the uppercaser. We choose to use a separate struct for this + // to make state management easier. + u, err := newUppercaser(ctx, rejectUpdateOnPendingContinueAsNew) + if err == nil { + err = u.run(ctx) + } + return err +} + +// UppercaseActivity uppercases the given string. +func UppercaseActivity(ctx context.Context, input string) (string, error) { + return strings.ToUpper(input), nil +} + +// Request is a request to uppercase a string, passed as a update argument to +// UppercaseWorkflow. +type Request struct { + // String to be uppercased. + Input string `json:"input"` +} + +// Response is a response to a Request. This is returned as a response to the update request +type Response struct { + Output string `json:"output"` +} + +type uppercaser struct { + workflow.Context + requestsBeforeContinueAsNew int + rejectUpdateOnPendingContinueAsNew bool +} + +func newUppercaser(ctx workflow.Context, rejectUpdateOnPendingContinueAsNew bool) (*uppercaser, error) { + u := &uppercaser{ + // For the main context, we're only going to allow 1 retry and only a 5 + // second schedule-to-close timeout. WARNING: The timeout and retry affect + // how long this workflow stays open and may prevent it from performing its + // continue-as-new until timeout occurs and/or retries are finished. + Context: workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + ScheduleToCloseTimeout: 5 * time.Second, + RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 2}, + }), + // We'll allow 500 requests before we continue-as-new the workflow. This is + // required because the history will grow very large otherwise for an + // interminable workflow fielding update requests and executing activities. + requestsBeforeContinueAsNew: 500, + // If the workflow is trying to continue as new, but update requests are coming + // in faster than they are handled it is possible the workflow will never be able + // continue as new. To try to mitigate this the workflow can be set to reject incoming update + // through the validator. The requester will see this rejection and backoff. + rejectUpdateOnPendingContinueAsNew: rejectUpdateOnPendingContinueAsNew, + } + return u, nil +} + +func (u *uppercaser) run(ctx workflow.Context) error { + var requestCount int + var pendingUpdates int + + var options workflow.UpdateHandlerOptions + if u.rejectUpdateOnPendingContinueAsNew { + options.Validator = func(ctx workflow.Context, request Request) error { + if requestCount >= u.requestsBeforeContinueAsNew { + // Rejecting an update in the validator will not persist the update + // to history which is useful if the history size is growing large. + return ErrBackoff + } + return nil + } + } + // Set update handler + err := workflow.SetUpdateHandlerWithOptions(ctx, UpdateHandler, func(ctx workflow.Context, request Request) (Response, error) { + requestCount++ + pendingUpdates++ + defer func() { + pendingUpdates-- + }() + var response Response + err := workflow.ExecuteActivity(u, UppercaseActivity, request.Input).Get(ctx, &response.Output) + return response, err + }, options) + if err != nil { + return fmt.Errorf("failed setting updatex handler: %w", err) + } + + // Wait until we can continue as new or are cancelled. + err = workflow.Await(ctx, func() bool { return requestCount >= u.requestsBeforeContinueAsNew && pendingUpdates == 0 }) + if err != nil { + return err + } + + // Continue as new since there were too many responses and there is no pending updates. + // Note, if update requests come in faster than they + // are handled, there will not be a moment where the workflow has + // nothing pending which means this will run forever. + return workflow.NewContinueAsNewError(u, UppercaseWorkflow, u.rejectUpdateOnPendingContinueAsNew) +} diff --git a/reqrespupdate/workflow_test.go b/reqrespupdate/workflow_test.go new file mode 100644 index 00000000..8d433e05 --- /dev/null +++ b/reqrespupdate/workflow_test.go @@ -0,0 +1,66 @@ +package reqrespupdate_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "github.com/temporalio/samples-go/reqrespupdate" + "go.temporal.io/sdk/testsuite" +) + +type updateCallback struct { + accept func() + reject func(error) + complete func(interface{}, error) +} + +func (uc *updateCallback) Accept() { + uc.accept() +} + +func (uc *updateCallback) Reject(err error) { + uc.reject(err) +} + +func (uc *updateCallback) Complete(success interface{}, err error) { + uc.complete(success, err) +} + +func TestUppercaseWorkflow(t *testing.T) { + // Create env + var suite testsuite.WorkflowTestSuite + env := suite.NewTestWorkflowEnvironment() + env.RegisterWorkflow(reqrespupdate.UppercaseWorkflow) + env.RegisterActivity(reqrespupdate.UppercaseActivity) + + // Use delayed callbacks to send enoguh updates to cause a continue as new + for i := 0; i < 550; i++ { + i := i + env.RegisterDelayedCallback(func() { + env.UpdateWorkflow(reqrespupdate.UpdateHandler, "test id", &updateCallback{ + accept: func() { + if i >= 500 { + require.Fail(t, "update should fail since it should be trying to continue-as-new") + } + }, + reject: func(err error) { + if i < 500 { + require.Fail(t, "this update should not fail") + } + require.Error(t, err) + }, + complete: func(response interface{}, err error) { + if i >= 500 { + require.Fail(t, "update should fail since it should be trying to continue-as-new") + } + require.NoError(t, err) + require.Equal(t, reqrespupdate.Response{Output: fmt.Sprintf("FOO %d", i)}, response) + }, + }, &reqrespupdate.Request{Input: fmt.Sprintf("foo %d", i)}) + }, 1) + } + + // Run workflow + env.ExecuteWorkflow(reqrespupdate.UppercaseWorkflow, true) +} diff --git a/zapadapter/README.md b/zapadapter/README.md index bac617d4..64008eb3 100644 --- a/zapadapter/README.md +++ b/zapadapter/README.md @@ -2,11 +2,11 @@ 1) Run a [Temporal service](https://github.com/temporalio/samples-go/tree/main/#how-to-use). 2) Run the following command to start the worker ``` -go run zaplogger/worker/main.go +go run zapadapter/worker/main.go ``` 3) Run the following command to start the example ``` -go run zaplogger/starter/main.go +go run zapadapter/starter/main.go ``` 4) Check worker logs in colorful JSON format: ```json @@ -29,4 +29,4 @@ go.temporal.io/sdk/internal.(*activityTaskPoller).ProcessTask go.temporal.io/sdk/internal.(*baseWorker).processTask /home/user/go/pkg/mod/go.temporal.io/sdk@v1.7.0/internal/internal_worker_base.go:343 2021-06-21T17:32:02.310-0700 INFO reflect/value.go:476 Workflow completed. {"Namespace": "default", "TaskQueue": "zap-logger", "WorkerID": "506926@MainWorker@", "WorkflowType": "Workflow", "WorkflowID": "zap_logger_workflow_id", "RunID": "7f59f2a4-87a5-4a73-9020-076fdfa3c766", "Attempt": 1} -``` \ No newline at end of file +```