From 9d31228132a86e36ce175e242fabaabddba616f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 09:24:20 -0800 Subject: [PATCH 1/8] Bump golang.org/x/net from 0.31.0 to 0.33.0 (#738) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.31.0 to 0.33.0. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 33ed68d1..74afbf20 100644 --- a/go.mod +++ b/go.mod @@ -132,7 +132,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect - golang.org/x/net v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/go.sum b/go.sum index e915a2a4..fcc188a3 100644 --- a/go.sum +++ b/go.sum @@ -436,8 +436,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= From d201c23842b74170e045ea5cf2aa40adbfebd755 Mon Sep 17 00:00:00 2001 From: Josh Berry Date: Tue, 14 Jan 2025 13:43:02 -0800 Subject: [PATCH 2/8] UI Server -> 2.34.0 (#739) --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 74afbf20..96bde9e1 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.10.0 - github.com/temporalio/ui-server/v2 v2.32.0 + github.com/temporalio/ui-server/v2 v2.34.0 go.temporal.io/api v1.43.0 go.temporal.io/sdk v1.31.0 go.temporal.io/server v1.26.2 diff --git a/go.sum b/go.sum index fcc188a3..070e4896 100644 --- a/go.sum +++ b/go.sum @@ -311,6 +311,8 @@ github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938 h1:sEJGh github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938/go.mod h1:ezRQRwu9KQXy8Wuuv1aaFFxoCNz5CeNbVOOkh3xctbY= github.com/temporalio/ui-server/v2 v2.32.0 h1:mR6eet9n4eRkGgHcZqaJdXWK5sfQguN4LoWxQXsqpY0= github.com/temporalio/ui-server/v2 v2.32.0/go.mod h1:b8whRt0/lbgNDzG7alSdiDzXFO8Fk783eRMhIycWtn8= +github.com/temporalio/ui-server/v2 v2.34.0 h1:KLTTMh870/h1oxYqOtGMnmQBOP0oIcwFEnP7/i0C0hA= +github.com/temporalio/ui-server/v2 v2.34.0/go.mod h1:Um2G8/8bDQczAdY+21ba+y+nLXwUdL7ZLlhAAaIeVqA= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber-common/bark v1.0.0/go.mod h1:g0ZuPcD7XiExKHynr93Q742G/sbrdVQkghrqLGOoFuY= From 4285d3993ff446c086c4891615b6f7d89749f10c Mon Sep 17 00:00:00 2001 From: Antonio Lain <135073478+antlai-temporal@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:34:05 -0800 Subject: [PATCH 3/8] Versioning 3 (#740) --- go.mod | 2 +- go.sum | 6 +- temporalcli/commands.gen.go | 207 ++++++++++ temporalcli/commands.taskqueue_test.go | 26 +- temporalcli/commands.worker.deployment.go | 377 ++++++++++++++++++ .../commands.worker.deployment_test.go | 191 +++++++++ temporalcli/commands.workflow.go | 115 ++++++ temporalcli/commands.workflow_test.go | 188 +++++++++ temporalcli/commands.workflow_view.go | 26 ++ temporalcli/commands.workflow_view_test.go | 75 ++++ temporalcli/commands_test.go | 1 + temporalcli/commandsgen/commands.yml | 263 +++++++++++- 12 files changed, 1464 insertions(+), 13 deletions(-) create mode 100644 temporalcli/commands.worker.deployment.go create mode 100644 temporalcli/commands.worker.deployment_test.go diff --git a/go.mod b/go.mod index 96bde9e1..05ea017c 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/stretchr/testify v1.10.0 github.com/temporalio/ui-server/v2 v2.34.0 go.temporal.io/api v1.43.0 - go.temporal.io/sdk v1.31.0 + go.temporal.io/sdk v1.32.1 go.temporal.io/server v1.26.2 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 diff --git a/go.sum b/go.sum index 070e4896..d1edbcaa 100644 --- a/go.sum +++ b/go.sum @@ -309,8 +309,6 @@ github.com/temporalio/sqlparser v0.0.0-20231115171017-f4060bcfa6cb/go.mod h1:143 github.com/temporalio/tchannel-go v1.22.1-0.20220818200552-1be8d8cffa5b/go.mod h1:c+V9Z/ZgkzAdyGvHrvC5AsXgN+M9Qwey04cBdKYzV7U= github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938 h1:sEJGhmDo+0FaPWM6f0v8Tjia0H5pR6/Baj6+kS78B+M= github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938/go.mod h1:ezRQRwu9KQXy8Wuuv1aaFFxoCNz5CeNbVOOkh3xctbY= -github.com/temporalio/ui-server/v2 v2.32.0 h1:mR6eet9n4eRkGgHcZqaJdXWK5sfQguN4LoWxQXsqpY0= -github.com/temporalio/ui-server/v2 v2.32.0/go.mod h1:b8whRt0/lbgNDzG7alSdiDzXFO8Fk783eRMhIycWtn8= github.com/temporalio/ui-server/v2 v2.34.0 h1:KLTTMh870/h1oxYqOtGMnmQBOP0oIcwFEnP7/i0C0hA= github.com/temporalio/ui-server/v2 v2.34.0/go.mod h1:Um2G8/8bDQczAdY+21ba+y+nLXwUdL7ZLlhAAaIeVqA= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= @@ -361,8 +359,8 @@ go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeX go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.temporal.io/api v1.43.0 h1:lBhq+u5qFJqGMXwWsmg/i8qn1UA/3LCwVc88l2xUMHg= go.temporal.io/api v1.43.0/go.mod h1:1WwYUMo6lao8yl0371xWUm13paHExN5ATYT/B7QtFis= -go.temporal.io/sdk v1.31.0 h1:CLYiP0R5Sdj0gq8LyYKDDz4ccGOdJPR8wNGJU0JGwj8= -go.temporal.io/sdk v1.31.0/go.mod h1:8U8H7rF9u4Hyb4Ry9yiEls5716DHPNvVITPNkgWUwE8= +go.temporal.io/sdk v1.32.1 h1:slA8prhdFr4lxpsTcRusWVitD/cGjELfKUh0mBj73SU= +go.temporal.io/sdk v1.32.1/go.mod h1:8U8H7rF9u4Hyb4Ry9yiEls5716DHPNvVITPNkgWUwE8= go.temporal.io/server v1.26.2 h1:vDW11lxslYPlGDbQklWi/tqbkVZ2ExtRO1jNjvZmUUI= go.temporal.io/server v1.26.2/go.mod h1:tgY+4z/PuIdqs6ouV1bT90RWSWfEioWkzmrNrLYLUrk= go.temporal.io/version v0.3.0 h1:dMrei9l9NyHt8nG6EB8vAwDLLTwx2SvRyucCSumAiig= diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index 3ddc1c1e..ff6c537a 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -131,6 +131,18 @@ func (v *WorkflowReferenceOptions) buildFlags(cctx *CommandContext, f *pflag.Fla f.StringVarP(&v.RunId, "run-id", "r", "", "Run ID.") } +type DeploymentReferenceOptions struct { + SeriesName string + BuildId string +} + +func (v *DeploymentReferenceOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { + f.StringVar(&v.SeriesName, "series-name", "", "Series Name for a Worker Deployment. Required.") + _ = cobra.MarkFlagRequired(f, "series-name") + f.StringVar(&v.BuildId, "build-id", "", "Build ID for a Worker Deployment. Required.") + _ = cobra.MarkFlagRequired(f, "build-id") +} + type SingleWorkflowOrBatchOptions struct { WorkflowId string Query string @@ -296,6 +308,7 @@ func NewTemporalCommand(cctx *CommandContext) *TemporalCommand { s.Command.AddCommand(&NewTemporalScheduleCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalServerCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalTaskQueueCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkerCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowCommand(cctx, &s).Command) s.Command.PersistentFlags().StringVar(&s.Env, "env", "default", "Active environment name (`ENV`).") cctx.BindFlagEnvVar(s.Command.PersistentFlags().Lookup("env"), "TEMPORAL_ENV") @@ -2492,6 +2505,164 @@ func NewTemporalTaskQueueVersioningReplaceRedirectRuleCommand(cctx *CommandConte return &s } +type TemporalWorkerCommand struct { + Parent *TemporalCommand + Command cobra.Command + ClientOptions +} + +func NewTemporalWorkerCommand(cctx *CommandContext, parent *TemporalCommand) *TemporalWorkerCommand { + var s TemporalWorkerCommand + s.Parent = parent + s.Command.Use = "worker" + s.Command.Short = "Read or update Worker state" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker is experimental. Worker commands are subject to |\n| change. |\n+---------------------------------------------------------------------+\n\nModify or read state associated with a Worker, for example,\nusing Worker Deployments commands:\n\n\x1b[1mtemporal worker deployment\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker is experimental. Worker commands are subject to |\n| change. |\n+---------------------------------------------------------------------+\n\nModify or read state associated with a Worker, for example,\nusing Worker Deployments commands:\n\n```\ntemporal worker deployment\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.AddCommand(&NewTemporalWorkerDeploymentCommand(cctx, &s).Command) + s.ClientOptions.buildFlags(cctx, s.Command.PersistentFlags()) + return &s +} + +type TemporalWorkerDeploymentCommand struct { + Parent *TemporalWorkerCommand + Command cobra.Command +} + +func NewTemporalWorkerDeploymentCommand(cctx *CommandContext, parent *TemporalWorkerCommand) *TemporalWorkerDeploymentCommand { + var s TemporalWorkerDeploymentCommand + s.Parent = parent + s.Command.Use = "deployment" + s.Command.Short = "Describe, list, and operate on Worker Deployments" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nDeployment commands perform operations on Worker Deployments:\n\n\x1b[1mtemporal worker deployment [command] [options]\x1b[0m\n\nFor example:\n\n\x1b[1mtemporal worker deployment list\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nDeployment commands perform operations on Worker Deployments:\n\n```\ntemporal worker deployment [command] [options]\n```\n\nFor example:\n\n```\ntemporal worker deployment list\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.AddCommand(&NewTemporalWorkerDeploymentDescribeCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkerDeploymentGetCurrentCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkerDeploymentListCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkerDeploymentSetCurrentCommand(cctx, &s).Command) + return &s +} + +type TemporalWorkerDeploymentDescribeCommand struct { + Parent *TemporalWorkerDeploymentCommand + Command cobra.Command + DeploymentReferenceOptions + ReportReachability bool +} + +func NewTemporalWorkerDeploymentDescribeCommand(cctx *CommandContext, parent *TemporalWorkerDeploymentCommand) *TemporalWorkerDeploymentDescribeCommand { + var s TemporalWorkerDeploymentDescribeCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "describe [flags]" + s.Command.Short = "Show properties of a Worker Deployment" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nDescribes properties of a Worker Deployment, such as whether it is\ncurrent, the non-empty list of its task queues, custom metadata if\npresent, and reachability status when requested.\n\n\x1b[1mtemporal worker deployment describe [options]\x1b[0m\n\nFor example, to also include reachability information:\n\n\x1b[1mtemporal worker deployment describe \\\n --series-name YourDeploymentSeriesName \\\n --build-id YourDeploymentBuildId \\\n --report-reachability\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nDescribes properties of a Worker Deployment, such as whether it is\ncurrent, the non-empty list of its task queues, custom metadata if\npresent, and reachability status when requested.\n\n```\ntemporal worker deployment describe [options]\n```\n\nFor example, to also include reachability information:\n\n```\ntemporal worker deployment describe \\\n --series-name YourDeploymentSeriesName \\\n --build-id YourDeploymentBuildId \\\n --report-reachability\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().BoolVar(&s.ReportReachability, "report-reachability", false, "Include reachability information of a Worker Deployment.") + s.DeploymentReferenceOptions.buildFlags(cctx, s.Command.Flags()) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + +type TemporalWorkerDeploymentGetCurrentCommand struct { + Parent *TemporalWorkerDeploymentCommand + Command cobra.Command + SeriesName string +} + +func NewTemporalWorkerDeploymentGetCurrentCommand(cctx *CommandContext, parent *TemporalWorkerDeploymentCommand) *TemporalWorkerDeploymentGetCurrentCommand { + var s TemporalWorkerDeploymentGetCurrentCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "get-current [flags]" + s.Command.Short = "Show the current Worker Deployment" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nGets the current Worker Deployment for a Deployment Series Name.\nWhen a Deployment is current, Workers of that Deployment will receive\ntasks from new Workflows and from existing AutoUpgrade Workflows that\nare running on this Deployment Series.\n\n\x1b[1mtemporal worker deployment get-current [options]\x1b[0m\n\nFor example:\n\n\x1b[1mtemporal worker deployment get-current \\\n --series-name YourDeploymentSeriesName\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nGets the current Worker Deployment for a Deployment Series Name.\nWhen a Deployment is current, Workers of that Deployment will receive\ntasks from new Workflows and from existing AutoUpgrade Workflows that\nare running on this Deployment Series.\n\n```\ntemporal worker deployment get-current [options]\n```\n\nFor example:\n\n```\ntemporal worker deployment get-current \\\n --series-name YourDeploymentSeriesName\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().StringVar(&s.SeriesName, "series-name", "", "Series Name for the current Worker Deployment. Required.") + _ = cobra.MarkFlagRequired(s.Command.Flags(), "series-name") + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + +type TemporalWorkerDeploymentListCommand struct { + Parent *TemporalWorkerDeploymentCommand + Command cobra.Command + SeriesName string +} + +func NewTemporalWorkerDeploymentListCommand(cctx *CommandContext, parent *TemporalWorkerDeploymentCommand) *TemporalWorkerDeploymentListCommand { + var s TemporalWorkerDeploymentListCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "list [flags]" + s.Command.Short = "Enumerate Worker Deployments in the client's namespace" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nList existing Worker Deployments in the client's namespace, optionally\nfiltering them by Deployment Series Name.\n\n\n\x1b[1mtemporal worker deployment list [options]\x1b[0m\n\nFor example, adding an optional filter:\n\n\x1b[1mtemporal worker deployment list \\\n --series-name YourDeploymentSeriesName\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker Deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nList existing Worker Deployments in the client's namespace, optionally\nfiltering them by Deployment Series Name.\n\n\n```\ntemporal worker deployment list [options]\n```\n\nFor example, adding an optional filter:\n\n```\ntemporal worker deployment list \\\n --series-name YourDeploymentSeriesName\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().StringVar(&s.SeriesName, "series-name", "", "Series Name to filter Worker Deployments.") + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + +type TemporalWorkerDeploymentSetCurrentCommand struct { + Parent *TemporalWorkerDeploymentCommand + Command cobra.Command + DeploymentReferenceOptions + Metadata []string +} + +func NewTemporalWorkerDeploymentSetCurrentCommand(cctx *CommandContext, parent *TemporalWorkerDeploymentCommand) *TemporalWorkerDeploymentSetCurrentCommand { + var s TemporalWorkerDeploymentSetCurrentCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "set-current [flags]" + s.Command.Short = "Change the current Worker Deployment" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nSets the current Deployment for a given Deployment Series.\nWhen a Deployment is current, Workers of that Deployment will receive\ntasks from new Workflows and from existing AutoUpgrade Workflows that\nare running on this Deployment Series.\n\n\x1b[1mtemporal worker deployment set-current [options]\x1b[0m\n\nFor example:\n\n\x1b[1mtemporal worker deployment set-current \\\n --series-name YourDeploymentSeriesName \\\n --build-id YourDeploymentBuildId\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worker deployment is experimental. Deployment commands are |\n| subject to change. |\n+---------------------------------------------------------------------+\n\nSets the current Deployment for a given Deployment Series.\nWhen a Deployment is current, Workers of that Deployment will receive\ntasks from new Workflows and from existing AutoUpgrade Workflows that\nare running on this Deployment Series.\n\n```\ntemporal worker deployment set-current [options]\n```\n\nFor example:\n\n```\ntemporal worker deployment set-current \\\n --series-name YourDeploymentSeriesName \\\n --build-id YourDeploymentBuildId\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().StringArrayVar(&s.Metadata, "metadata", nil, "Set deployment metadata using `KEY=\"VALUE\"` pairs. Keys must be identifiers, and values must be JSON values. For example: 'YourKey={\"your\": \"value\"}'. Can be passed multiple times.") + s.DeploymentReferenceOptions.buildFlags(cctx, s.Command.Flags()) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + type TemporalWorkflowCommand struct { Parent *TemporalCommand Command cobra.Command @@ -2526,6 +2697,7 @@ func NewTemporalWorkflowCommand(cctx *CommandContext, parent *TemporalCommand) * s.Command.AddCommand(&NewTemporalWorkflowTerminateCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowTraceCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowUpdateCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkflowUpdateOptionsCommand(cctx, &s).Command) s.ClientOptions.buildFlags(cctx, s.Command.PersistentFlags()) return &s } @@ -3195,3 +3367,38 @@ func NewTemporalWorkflowUpdateStartCommand(cctx *CommandContext, parent *Tempora } return &s } + +type TemporalWorkflowUpdateOptionsCommand struct { + Parent *TemporalWorkflowCommand + Command cobra.Command + SingleWorkflowOrBatchOptions + VersioningOverrideBehavior StringEnum + VersioningOverrideSeriesName string + VersioningOverrideBuildId string +} + +func NewTemporalWorkflowUpdateOptionsCommand(cctx *CommandContext, parent *TemporalWorkflowCommand) *TemporalWorkflowUpdateOptionsCommand { + var s TemporalWorkflowUpdateOptionsCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "update-options [flags]" + s.Command.Short = "Change Workflow Execution Options" + if hasHighlighting { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worflow update-options is experimental. Workflow Execution |\n| properties are subject to change. |\n+---------------------------------------------------------------------+\n\nModify properties of Workflow Executions:\n\n\x1b[1mtemporal workflow update-options [options]\x1b[0m\n\nIt can override the Worker Deployment configuration of a\nWorkflow Execution, which controls Worker Versioning.\n\nFor example, to force Workers in the current Deployment execute the\nnext Workflow Task change behavior to \x1b[1mauto_upgrade\x1b[0m:\n\n\x1b[1mtemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior auto_upgrade\x1b[0m\n\nor to pin the workflow execution to a Worker Deployment, set behavior\nto \x1b[1mpinned\x1b[0m:\n\n\x1b[1mtemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior pinned \\\n --versioning-override-series-name YourDeploymentSeriesName \\\n --versioning-override-build-id YourDeploymentBuildId\x1b[0m\n\nTo remove any previous overrides, set the behavior to\n\x1b[1munspecified\x1b[0m:\n\n\x1b[1mtemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior unspecified\x1b[0m\n\nTo see the current override use \x1b[1mtemporal workflow describe\x1b[0m" + } else { + s.Command.Long = "+---------------------------------------------------------------------+\n| CAUTION: Worflow update-options is experimental. Workflow Execution |\n| properties are subject to change. |\n+---------------------------------------------------------------------+\n\nModify properties of Workflow Executions:\n\n```\ntemporal workflow update-options [options]\n```\n\nIt can override the Worker Deployment configuration of a\nWorkflow Execution, which controls Worker Versioning.\n\nFor example, to force Workers in the current Deployment execute the\nnext Workflow Task change behavior to `auto_upgrade`:\n\n```\ntemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior auto_upgrade\n```\n\nor to pin the workflow execution to a Worker Deployment, set behavior\nto `pinned`:\n\n```\ntemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior pinned \\\n --versioning-override-series-name YourDeploymentSeriesName \\\n --versioning-override-build-id YourDeploymentBuildId\n```\n\nTo remove any previous overrides, set the behavior to\n`unspecified`:\n\n```\ntemporal workflow update-options \\\n --workflow-id YourWorkflowId \\\n --versioning-override-behavior unspecified\n```\n\nTo see the current override use `temporal workflow describe`" + } + s.Command.Args = cobra.NoArgs + s.VersioningOverrideBehavior = NewStringEnum([]string{"unspecified", "pinned", "auto_upgrade"}, "") + s.Command.Flags().Var(&s.VersioningOverrideBehavior, "versioning-override-behavior", "Override the versioning behavior of a Workflow. Accepted values: unspecified, pinned, auto_upgrade. Required.") + _ = cobra.MarkFlagRequired(s.Command.Flags(), "versioning-override-behavior") + s.Command.Flags().StringVar(&s.VersioningOverrideSeriesName, "versioning-override-series-name", "", "Override Series Name for a Worker Deployment (Only for pinned).") + s.Command.Flags().StringVar(&s.VersioningOverrideBuildId, "versioning-override-build-id", "", "Override Build ID for a Worker Deployment (Only for pinned).") + s.SingleWorkflowOrBatchOptions.buildFlags(cctx, s.Command.Flags()) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} diff --git a/temporalcli/commands.taskqueue_test.go b/temporalcli/commands.taskqueue_test.go index dd863844..346df180 100644 --- a/temporalcli/commands.taskqueue_test.go +++ b/temporalcli/commands.taskqueue_test.go @@ -2,11 +2,12 @@ package temporalcli_test import ( "encoding/json" - "github.com/stretchr/testify/assert" - "go.temporal.io/sdk/workflow" "strings" "time" + "github.com/stretchr/testify/assert" + "go.temporal.io/sdk/workflow" + "github.com/google/uuid" "github.com/temporalio/cli/temporalcli" "go.temporal.io/api/enums/v1" @@ -261,6 +262,10 @@ func (s *SharedServerSuite) TestTaskQueue_Describe_Simple() { ) s.NoError(res.Err) + // TODO(antlai-temporal): Delete when a server caching bug in 1.26.2 is fixed, + // see https://github.com/temporalio/temporal/pull/6978 + time.Sleep(1 * time.Second) + // Text res = s.Execute( "task-queue", "describe", @@ -270,11 +275,14 @@ func (s *SharedServerSuite) TestTaskQueue_Describe_Simple() { "--task-queue", s.Worker().Options.TaskQueue, ) s.NoError(res.Err) - s.ContainsOnSameLine(res.Stdout.String(), "id1", "reachable") // No pollers on id1 s.NotContains(res.Stdout.String(), "now") + // TODO(antlai-temporal): Delete when a server caching bug in 1.26.2 is fixed, + // see https://github.com/temporalio/temporal/pull/6978 + time.Sleep(1 * time.Second) + res = s.Execute( "task-queue", "describe", "--select-unversioned", @@ -286,8 +294,12 @@ func (s *SharedServerSuite) TestTaskQueue_Describe_Simple() { s.NoError(res.Err) s.ContainsOnSameLine(res.Stdout.String(), "UNVERSIONED", "unreachable") - s.ContainsOnSameLine(res.Stdout.String(), "UNVERSIONED", "workflow", s.DevServer.Options.ClientOptions.Identity, "now", "100000") - s.ContainsOnSameLine(res.Stdout.String(), "UNVERSIONED", "activity", s.DevServer.Options.ClientOptions.Identity, "now", "100000") + s.ContainsOnSameLine(res.Stdout.String(), "UNVERSIONED", "workflow", s.DevServer.Options.ClientOptions.Identity, "2 seconds ago", "100000") + s.ContainsOnSameLine(res.Stdout.String(), "UNVERSIONED", "activity", s.DevServer.Options.ClientOptions.Identity, "2 seconds ago", "100000") + + // TODO(antlai-temporal): Delete when a server caching bug in 1.26.2 is fixed, + // see https://github.com/temporalio/temporal/pull/6978 + time.Sleep(1 * time.Second) res = s.Execute( "task-queue", "describe", @@ -303,6 +315,10 @@ func (s *SharedServerSuite) TestTaskQueue_Describe_Simple() { // No pollers on id2 s.NotContains(res.Stdout.String(), "now") + // TODO(antlai-temporal): Delete when a server caching bug in 1.26.2 is fixed, + // see https://github.com/temporalio/temporal/pull/6978 + time.Sleep(1 * time.Second) + res = s.Execute( "task-queue", "describe", "--select-all-active", diff --git a/temporalcli/commands.worker.deployment.go b/temporalcli/commands.worker.deployment.go new file mode 100644 index 00000000..45a44ec0 --- /dev/null +++ b/temporalcli/commands.worker.deployment.go @@ -0,0 +1,377 @@ +package temporalcli + +import ( + "fmt" + "time" + + "github.com/fatih/color" + "github.com/temporalio/cli/temporalcli/internal/printer" + "go.temporal.io/api/common/v1" + "go.temporal.io/sdk/client" +) + +type taskQueuesInfosRowType struct { + Name string `json:"name"` + Type string `json:"type"` + FirstPollerTime time.Time `json:"firstPollerTime"` +} + +type deploymentType struct { + SeriesName string `json:"seriesName"` + BuildID string `json:"buildId"` +} + +type formattedDeploymentInfoType struct { + Deployment deploymentType `json:"deployment"` + CreateTime time.Time `json:"createTime"` + IsCurrent bool `json:"isCurrent"` + TaskQueuesInfos []taskQueuesInfosRowType `json:"taskQueuesInfos,omitempty"` + Metadata map[string]*common.Payload `json:"metadata,omitempty"` +} + +type formattedDeploymentReachabilityInfoType struct { + DeploymentInfo formattedDeploymentInfoType `json:"deploymentInfo"` + Reachability string `json:"reachability"` + LastUpdateTime time.Time `json:"lastUpdateTime"` +} + +type formattedDeploymentListEntryType struct { + SeriesName string + BuildID string + CreateTime time.Time + IsCurrent bool +} + +type formattedDualDeploymentInfoType struct { + Previous formattedDeploymentInfoType `json:"previous"` + Current formattedDeploymentInfoType `json:"current"` +} + +func formatTaskQueuesInfos(tqis []client.DeploymentTaskQueueInfo) ([]taskQueuesInfosRowType, error) { + var tqiRows []taskQueuesInfosRowType + for _, tqi := range tqis { + tqTypeStr, err := taskQueueTypeToStr(tqi.Type) + if err != nil { + return tqiRows, err + } + tqiRows = append(tqiRows, taskQueuesInfosRowType{ + Name: tqi.Name, + Type: tqTypeStr, + FirstPollerTime: tqi.FirstPollerTime, + }) + } + return tqiRows, nil +} + +func deploymentInfoToRows(deploymentInfo client.DeploymentInfo) (formattedDeploymentInfoType, error) { + tqi, err := formatTaskQueuesInfos(deploymentInfo.TaskQueuesInfos) + if err != nil { + return formattedDeploymentInfoType{}, err + } + + return formattedDeploymentInfoType{ + Deployment: deploymentType{ + SeriesName: deploymentInfo.Deployment.SeriesName, + BuildID: deploymentInfo.Deployment.BuildID, + }, + CreateTime: deploymentInfo.CreateTime, + IsCurrent: deploymentInfo.IsCurrent, + TaskQueuesInfos: tqi, + Metadata: deploymentInfo.Metadata, + }, nil +} + +func printDeploymentInfo(cctx *CommandContext, deploymentInfo client.DeploymentInfo, msg string) error { + + fDeploymentInfo, err := deploymentInfoToRows(deploymentInfo) + if err != nil { + return err + } + + if !cctx.JSONOutput { + cctx.Printer.Println(color.MagentaString(msg)) + printMe := struct { + SeriesName string + BuildID string + CreateTime time.Time + IsCurrent bool + Metadata map[string]*common.Payload `cli:",cardOmitEmpty"` + }{ + SeriesName: deploymentInfo.Deployment.SeriesName, + BuildID: deploymentInfo.Deployment.BuildID, + CreateTime: deploymentInfo.CreateTime, + IsCurrent: deploymentInfo.IsCurrent, + Metadata: deploymentInfo.Metadata, + } + err := cctx.Printer.PrintStructured(printMe, printer.StructuredOptions{}) + if err != nil { + return fmt.Errorf("displaying worker deployment info failed: %w", err) + } + + if len(deploymentInfo.TaskQueuesInfos) > 0 { + cctx.Printer.Println() + cctx.Printer.Println(color.MagentaString("Task Queues:")) + err := cctx.Printer.PrintStructured( + deploymentInfo.TaskQueuesInfos, + printer.StructuredOptions{Table: &printer.TableOptions{}}, + ) + if err != nil { + return fmt.Errorf("displaying task queues info failed: %w", err) + } + } + + return nil + } + + // json output + return cctx.Printer.PrintStructured(fDeploymentInfo, printer.StructuredOptions{}) +} + +func deploymentReachabilityTypeToStr(reachabilityType client.DeploymentReachability) (string, error) { + switch reachabilityType { + case client.DeploymentReachabilityUnspecified: + return "unspecified", nil + case client.DeploymentReachabilityReachable: + return "reachable", nil + case client.DeploymentReachabilityClosedWorkflows: + return "closed", nil + case client.DeploymentReachabilityUnreachable: + return "unreachable", nil + default: + return "", fmt.Errorf("unrecognized deployment reachability type: %d", reachabilityType) + } +} + +func printDeploymentReachabilityInfo(cctx *CommandContext, reachability client.DeploymentReachabilityInfo) error { + fDeploymentInfo, err := deploymentInfoToRows(reachability.DeploymentInfo) + if err != nil { + return err + } + + rTypeStr, err := deploymentReachabilityTypeToStr(reachability.Reachability) + if err != nil { + return err + } + + fReachabilityInfo := formattedDeploymentReachabilityInfoType{ + DeploymentInfo: fDeploymentInfo, + LastUpdateTime: reachability.LastUpdateTime, + Reachability: rTypeStr, + } + + if !cctx.JSONOutput { + err := printDeploymentInfo(cctx, reachability.DeploymentInfo, "Worker Deployment:") + if err != nil { + return err + } + + cctx.Printer.Println() + cctx.Printer.Println(color.MagentaString("Reachability:")) + printMe := struct { + LastUpdateTime time.Time + Reachability string + }{ + LastUpdateTime: fReachabilityInfo.LastUpdateTime, + Reachability: fReachabilityInfo.Reachability, + } + return cctx.Printer.PrintStructured(printMe, printer.StructuredOptions{}) + } + + // json output + return cctx.Printer.PrintStructured(fReachabilityInfo, printer.StructuredOptions{}) +} + +func printDeploymentSetCurrentResponse(cctx *CommandContext, response client.DeploymentSetCurrentResponse) error { + + if !cctx.JSONOutput { + err := printDeploymentInfo(cctx, response.Previous, "Previous Worker Deployment:") + if err != nil { + return fmt.Errorf("displaying previous worker deployment info failed: %w", err) + } + + err = printDeploymentInfo(cctx, response.Current, "Current Worker Deployment:") + if err != nil { + return fmt.Errorf("displaying current worker deployment info failed: %w", err) + } + + return nil + } + + previous, err := deploymentInfoToRows(response.Previous) + if err != nil { + return fmt.Errorf("displaying previous worker deployment info failed: %w", err) + } + current, err := deploymentInfoToRows(response.Current) + if err != nil { + return fmt.Errorf("displaying current worker deployment info failed: %w", err) + } + + return cctx.Printer.PrintStructured(formattedDualDeploymentInfoType{ + Previous: previous, + Current: current, + }, printer.StructuredOptions{}) +} + +func (c *TemporalWorkerDeploymentDescribeCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + if c.ReportReachability { + // Expensive call, rate-limited by target method + resp, err := cl.DeploymentClient().GetReachability(cctx, client.DeploymentGetReachabilityOptions{ + Deployment: client.Deployment{ + SeriesName: c.SeriesName, + BuildID: c.BuildId, + }, + }) + if err != nil { + return fmt.Errorf("error describing worker deployment with reachability: %w", err) + } + + err = printDeploymentReachabilityInfo(cctx, resp) + if err != nil { + return err + } + } else { + resp, err := cl.DeploymentClient().Describe(cctx, client.DeploymentDescribeOptions{ + Deployment: client.Deployment{ + SeriesName: c.SeriesName, + BuildID: c.BuildId, + }, + }) + if err != nil { + return fmt.Errorf("error describing worker deployment: %w", err) + } + err = printDeploymentInfo(cctx, resp.DeploymentInfo, "Worker Deployment:") + if err != nil { + return err + } + + } + + return nil +} + +func (c *TemporalWorkerDeploymentGetCurrentCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + resp, err := cl.DeploymentClient().GetCurrent(cctx, client.DeploymentGetCurrentOptions{ + SeriesName: c.SeriesName, + }) + if err != nil { + return fmt.Errorf("error getting the current deployment: %w", err) + } + + err = printDeploymentInfo(cctx, resp.DeploymentInfo, "Current Worker Deployment:") + if err != nil { + return err + } + + return nil +} + +func (c *TemporalWorkerDeploymentListCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.Parent.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + res, err := cl.DeploymentClient().List(cctx, client.DeploymentListOptions{ + SeriesName: c.SeriesName, + }) + if err != nil { + return err + } + + // This is a listing command subject to json vs jsonl rules + cctx.Printer.StartList() + defer cctx.Printer.EndList() + + printTableOpts := printer.StructuredOptions{ + Table: &printer.TableOptions{}, + } + + // make artificial "pages" so we get better aligned columns + page := make([]*formattedDeploymentListEntryType, 0, 100) + + for res.HasNext() { + entry, err := res.Next() + if err != nil { + return err + } + listEntry := formattedDeploymentInfoType{ + Deployment: deploymentType{ + SeriesName: entry.Deployment.SeriesName, + BuildID: entry.Deployment.BuildID, + }, + CreateTime: entry.CreateTime, + IsCurrent: entry.IsCurrent, + } + if cctx.JSONOutput { + // For JSON dump one line of JSON per deployment + _ = cctx.Printer.PrintStructured(listEntry, printer.StructuredOptions{}) + } else { + // For non-JSON, we are doing a table for each page + page = append(page, &formattedDeploymentListEntryType{ + SeriesName: listEntry.Deployment.SeriesName, + BuildID: listEntry.Deployment.BuildID, + CreateTime: listEntry.CreateTime, + IsCurrent: listEntry.IsCurrent, + }) + if len(page) == cap(page) { + _ = cctx.Printer.PrintStructured(page, printTableOpts) + page = page[:0] + printTableOpts.Table.NoHeader = true + } + } + } + + if !cctx.JSONOutput { + // Last partial page for non-JSON + _ = cctx.Printer.PrintStructured(page, printTableOpts) + } + + return nil +} + +func (c *TemporalWorkerDeploymentSetCurrentCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.Parent.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + metadata, err := stringKeysJSONValues(c.Metadata, false) + if err != nil { + return fmt.Errorf("invalid metadata values: %w", err) + } + + resp, err := cl.DeploymentClient().SetCurrent(cctx, client.DeploymentSetCurrentOptions{ + Deployment: client.Deployment{ + SeriesName: c.SeriesName, + BuildID: c.BuildId, + }, + MetadataUpdate: client.DeploymentMetadataUpdate{ + UpsertEntries: metadata, + }, + }) + if err != nil { + return fmt.Errorf("error setting the current worker deployment: %w", err) + } + + err = printDeploymentSetCurrentResponse(cctx, resp) + if err != nil { + return err + } + + cctx.Printer.Println("Successfully setting the current worker deployment") + return nil +} diff --git a/temporalcli/commands.worker.deployment_test.go b/temporalcli/commands.worker.deployment_test.go new file mode 100644 index 00000000..87dba990 --- /dev/null +++ b/temporalcli/commands.worker.deployment_test.go @@ -0,0 +1,191 @@ +package temporalcli_test + +import ( + "encoding/base64" + "encoding/json" + "sort" + "time" + + "github.com/google/uuid" + "go.temporal.io/api/common/v1" +) + +type jsonTaskQueuesInfosRowType struct { + Name string `json:"name"` + Type string `json:"type"` + FirstPollerTime time.Time `json:"firstPollerTime"` +} + +type jsonDeploymentType struct { + SeriesName string `json:"seriesName"` + BuildID string `json:"buildId"` +} + +type jsonDeploymentInfoType struct { + Deployment jsonDeploymentType `json:"deployment"` + CreateTime time.Time `json:"createTime"` + IsCurrent bool `json:"isCurrent"` + TaskQueuesInfos []jsonTaskQueuesInfosRowType `json:"taskQueuesInfos,omitempty"` + Metadata map[string]*common.Payload `json:"metadata,omitempty"` +} + +type jsonDeploymentReachabilityInfoType struct { + DeploymentInfo jsonDeploymentInfoType `json:"deploymentInfo"` + Reachability string `json:"reachability"` + LastUpdateTime time.Time `json:"lastUpdateTime"` +} + +type jsonDeploymentListEntryType struct { + Deployment jsonDeploymentType `json:"deployment"` + CreateTime time.Time `json:"createTime"` + IsCurrent bool `json:"isCurrent"` +} + +func (s *SharedServerSuite) TestDeployment_Set_Current() { + seriesName := uuid.NewString() + buildId := uuid.NewString() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId, + "--metadata", "bar=1", + ) + s.NoError(res.Err) + + res = s.Execute( + "worker", "deployment", "get-current", + "--address", s.Address(), + "--series-name", seriesName, + ) + s.NoError(res.Err) + + s.ContainsOnSameLine(res.Stdout.String(), "SeriesName", seriesName) + s.ContainsOnSameLine(res.Stdout.String(), "BuildID", buildId) + s.ContainsOnSameLine(res.Stdout.String(), "IsCurrent", "true") + s.ContainsOnSameLine(res.Stdout.String(), "Metadata", "data:\"1\"") + + // json + res = s.Execute( + "worker", "deployment", "get-current", + "--address", s.Address(), + "--series-name", seriesName, + "--output", "json", + ) + s.NoError(res.Err) + + var jsonOut jsonDeploymentInfoType + s.NoError(json.Unmarshal(res.Stdout.Bytes(), &jsonOut)) + s.Equal(jsonDeploymentType{SeriesName: seriesName, BuildID: buildId}, jsonOut.Deployment) + s.True(jsonOut.IsCurrent) + // "1" is "MQ==" + s.Equal("MQ==", base64.StdEncoding.EncodeToString(jsonOut.Metadata["bar"].GetData())) + // "json/plain" is "anNvbi9wbGFpbg==" + s.Equal("anNvbi9wbGFpbg==", base64.StdEncoding.EncodeToString(jsonOut.Metadata["bar"].GetMetadata()["encoding"])) +} + +func (s *SharedServerSuite) TestDeployment_List() { + seriesName := uuid.NewString() + buildId1 := uuid.NewString() + buildId2 := uuid.NewString() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId1, + ) + s.NoError(res.Err) + + res = s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId2, + ) + s.NoError(res.Err) + + res = s.Execute( + "worker", "deployment", "list", + "--address", s.Address(), + "--series-name", seriesName, + ) + s.NoError(res.Err) + + s.ContainsOnSameLine(res.Stdout.String(), seriesName, buildId1, "now", "false") + s.ContainsOnSameLine(res.Stdout.String(), seriesName, buildId2, "now", "true") + + // json + res = s.Execute( + "worker", "deployment", "list", + "--address", s.Address(), + "--series-name", seriesName, + "--output", "json", + ) + s.NoError(res.Err) + + var jsonOut []jsonDeploymentListEntryType + s.NoError(json.Unmarshal(res.Stdout.Bytes(), &jsonOut)) + sort.Slice(jsonOut, func(i, j int) bool { + return jsonOut[i].CreateTime.Before(jsonOut[j].CreateTime) + }) + s.Equal(len(jsonOut), 2) + s.Equal(jsonDeploymentType{SeriesName: seriesName, BuildID: buildId1}, jsonOut[0].Deployment) + s.True(!jsonOut[0].IsCurrent) + s.Equal(jsonDeploymentType{SeriesName: seriesName, BuildID: buildId2}, jsonOut[1].Deployment) + s.True(jsonOut[1].IsCurrent) +} + +func (s *SharedServerSuite) TestDeployment_Describe_Reachability() { + seriesName := uuid.NewString() + buildId1 := uuid.NewString() + buildId2 := uuid.NewString() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId1, + ) + s.NoError(res.Err) + + res = s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId2, + ) + s.NoError(res.Err) + + res = s.Execute( + "worker", "deployment", "describe", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId1, + "--report-reachability", + ) + s.NoError(res.Err) + + s.ContainsOnSameLine(res.Stdout.String(), "SeriesName", seriesName) + s.ContainsOnSameLine(res.Stdout.String(), "BuildID", buildId1) + s.ContainsOnSameLine(res.Stdout.String(), "IsCurrent", "false") + s.ContainsOnSameLine(res.Stdout.String(), "Reachability", "unreachable") + + // json + res = s.Execute( + "worker", "deployment", "describe", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId2, + "--report-reachability", + "--output", "json", + ) + s.NoError(res.Err) + + var jsonOut jsonDeploymentReachabilityInfoType + s.NoError(json.Unmarshal(res.Stdout.Bytes(), &jsonOut)) + s.Equal(jsonDeploymentType{SeriesName: seriesName, BuildID: buildId2}, jsonOut.DeploymentInfo.Deployment) + s.True(jsonOut.DeploymentInfo.IsCurrent) + s.Equal(jsonOut.Reachability, "reachable") +} diff --git a/temporalcli/commands.workflow.go b/temporalcli/commands.workflow.go index 02316aad..481f881f 100644 --- a/temporalcli/commands.workflow.go +++ b/temporalcli/commands.workflow.go @@ -8,18 +8,22 @@ import ( "os/user" "go.temporal.io/sdk/converter" + "go.temporal.io/sdk/workflow" "github.com/fatih/color" "github.com/google/uuid" "github.com/temporalio/cli/temporalcli/internal/printer" "go.temporal.io/api/batch/v1" "go.temporal.io/api/common/v1" + deploymentpb "go.temporal.io/api/deployment/v1" "go.temporal.io/api/enums/v1" "go.temporal.io/api/query/v1" "go.temporal.io/api/update/v1" + workflowpb "go.temporal.io/api/workflow/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" "go.temporal.io/sdk/temporal" + "google.golang.org/protobuf/types/known/fieldmaskpb" ) func (c *TemporalWorkflowCancelCommand) run(cctx *CommandContext, args []string) error { @@ -88,6 +92,117 @@ func (c *TemporalWorkflowDeleteCommand) run(cctx *CommandContext, args []string) return nil } +func (c *TemporalWorkflowUpdateOptionsCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + if c.VersioningOverrideBehavior.Value == "unspecified" || c.VersioningOverrideBehavior.Value == "auto_upgrade" { + if c.VersioningOverrideSeriesName != "" { + return fmt.Errorf("cannot set deployment series name with %v behavior", c.VersioningOverrideBehavior) + } + if c.VersioningOverrideBuildId != "" { + return fmt.Errorf("cannot set deployment build ID with %v behavior", c.VersioningOverrideBehavior) + } + } + + if c.VersioningOverrideBehavior.Value == "pinned" { + if c.VersioningOverrideSeriesName == "" { + return fmt.Errorf("missing deployment series name with 'pinned' behavior") + } + if c.VersioningOverrideBuildId == "" { + return fmt.Errorf("missing deployment build ID with 'pinned' behavior") + } + } + + exec, batchReq, err := c.workflowExecOrBatch(cctx, c.Parent.Namespace, cl, singleOrBatchOverrides{}) + + // Run single or batch + if err != nil { + return err + } else if exec != nil { + behavior := workflow.VersioningBehaviorUnspecified + switch c.VersioningOverrideBehavior.Value { + case "unspecified": + case "pinned": + behavior = workflow.VersioningBehaviorPinned + case "auto_upgrade": + behavior = workflow.VersioningBehaviorAutoUpgrade + default: + return fmt.Errorf( + "invalid deployment behavior: %v, valid values are: 'unspecified', 'pinned', and 'auto_upgrade'", + c.VersioningOverrideBehavior, + ) + } + + _, err := cl.UpdateWorkflowExecutionOptions(cctx, client.UpdateWorkflowExecutionOptionsRequest{ + WorkflowId: exec.WorkflowId, + RunId: exec.RunId, + WorkflowExecutionOptionsChanges: client.WorkflowExecutionOptionsChanges{ + VersioningOverride: &client.VersioningOverride{ + Behavior: behavior, + Deployment: client.Deployment{ + SeriesName: c.VersioningOverrideSeriesName, + BuildID: c.VersioningOverrideBuildId, + }, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to update workflow options: %w", err) + } + cctx.Printer.Println("Update workflow options succeeded") + } else { // Run batch + var workflowExecutionOptions *workflowpb.WorkflowExecutionOptions + protoMask, err := fieldmaskpb.New(workflowExecutionOptions, "versioning_override") + if err != nil { + return fmt.Errorf("invalid field mask: %w", err) + } + + behavior := enums.VERSIONING_BEHAVIOR_UNSPECIFIED + switch c.VersioningOverrideBehavior.Value { + case "unspecified": + case "pinned": + behavior = enums.VERSIONING_BEHAVIOR_PINNED + case "auto_upgrade": + behavior = enums.VERSIONING_BEHAVIOR_AUTO_UPGRADE + default: + return fmt.Errorf( + "invalid deployment behavior: %v, valid values are: 'unspecified', 'pinned', and 'auto_upgrade'", + c.VersioningOverrideBehavior, + ) + } + + deployment := &deploymentpb.Deployment{ + SeriesName: c.VersioningOverrideSeriesName, + BuildId: c.VersioningOverrideBuildId, + } + if c.VersioningOverrideSeriesName == "" && c.VersioningOverrideBuildId == "" { + // auto_upgrade needs a `nil` pointer + deployment = nil + } + + batchReq.Operation = &workflowservice.StartBatchOperationRequest_UpdateWorkflowOptionsOperation{ + UpdateWorkflowOptionsOperation: &batch.BatchOperationUpdateWorkflowExecutionOptions{ + Identity: clientIdentity(), + WorkflowExecutionOptions: &workflowpb.WorkflowExecutionOptions{ + VersioningOverride: &workflowpb.VersioningOverride{ + Behavior: behavior, + Deployment: deployment, + }, + }, + UpdateMask: protoMask, + }, + } + if err := startBatchJob(cctx, cl, batchReq); err != nil { + return err + } + } + return nil +} + func (c *TemporalWorkflowQueryCommand) run(cctx *CommandContext, args []string) error { return queryHelper(cctx, c.Parent, c.PayloadInputOptions, c.Name, c.RejectCondition, c.WorkflowReferenceOptions) diff --git a/temporalcli/commands.workflow_test.go b/temporalcli/commands.workflow_test.go index 8ee07293..af873bb7 100644 --- a/temporalcli/commands.workflow_test.go +++ b/temporalcli/commands.workflow_test.go @@ -11,9 +11,12 @@ import ( "time" "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/temporalio/cli/temporalcli" "go.temporal.io/api/enums/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" + "go.temporal.io/sdk/worker" "go.temporal.io/sdk/workflow" "google.golang.org/grpc" ) @@ -418,6 +421,191 @@ func (s *SharedServerSuite) TestWorkflow_Cancel_SingleWorkflowSuccess() { s.Error(workflow.ErrCanceled, run.Get(s.Context, nil)) } +func (s *SharedServerSuite) TestWorkflow_Batch_Update_Options_Versioning_Override() { + buildId1 := uuid.NewString() + buildId2 := uuid.NewString() + seriesName := uuid.NewString() + // Workflow that waits to be canceled. + waitingWorkflow := func(ctx workflow.Context) error { + ctx.Done().Receive(ctx, nil) + return ctx.Err() + } + w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + BuildID: buildId1, + UseBuildIDForVersioning: true, + DeploymentOptions: worker.DeploymentOptions{ + DeploymentSeriesName: seriesName, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + Workflows: []any{waitingWorkflow}, + }) + defer w.Stop() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId1, + ) + s.NoError(res.Err) + + // Start workflows + numWorkflows := 5 + runs := make([]client.WorkflowRun, numWorkflows) + searchAttr := "keyword-" + uuid.NewString() + for i := range runs { + run, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{ + TaskQueue: w.Options.TaskQueue, + SearchAttributes: map[string]any{"CustomKeywordField": searchAttr}, + }, + waitingWorkflow, + ) + s.NoError(err) + runs[i] = run + } + + s.EventuallyWithT(func(t *assert.CollectT) { + for _, run := range runs { + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + ) + assert.NoError(t, res.Err) + assert.Contains(t, res.Stdout.String(), buildId1) + assert.Contains(t, res.Stdout.String(), "Pinned") + } + }, 30*time.Second, 100*time.Millisecond) + + s.CommandHarness.Stdin.WriteString("y\n") + res = s.Execute( + "workflow", "update-options", + "--address", s.Address(), + "--query", "CustomKeywordField = '"+searchAttr+"'", + "--versioning-override-behavior", "pinned", + "--versioning-override-series-name", seriesName, + "--versioning-override-build-id", buildId2, + ) + s.NoError(res.Err) + + s.EventuallyWithT(func(t *assert.CollectT) { + for _, run := range runs { + // json + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + "--output", "json", + ) + assert.NoError(t, res.Err) + + var jsonResp workflowservice.DescribeWorkflowExecutionResponse + assert.NoError(t, temporalcli.UnmarshalProtoJSONWithOptions(res.Stdout.Bytes(), &jsonResp, true)) + versioningInfo := jsonResp.WorkflowExecutionInfo.VersioningInfo + assert.NotNil(t, versioningInfo.VersioningOverride) + assert.Equal(t, buildId2, versioningInfo.VersioningOverride.Deployment.BuildId) + } + }, 30*time.Second, 100*time.Millisecond) +} + +func (s *SharedServerSuite) TestWorkflow_Update_Options_Versioning_Override() { + buildId1 := uuid.NewString() + buildId2 := uuid.NewString() + seriesName := uuid.NewString() + // Workflow that waits to be canceled. + waitingWorkflow := func(ctx workflow.Context) error { + ctx.Done().Receive(ctx, nil) + return ctx.Err() + } + w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + BuildID: buildId1, + UseBuildIDForVersioning: true, + DeploymentOptions: worker.DeploymentOptions{ + DeploymentSeriesName: seriesName, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + Workflows: []any{waitingWorkflow}, + }) + defer w.Stop() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId1, + ) + s.NoError(res.Err) + + // Start the workflow and wait until the operation is started. + run, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{TaskQueue: w.Options.TaskQueue}, + waitingWorkflow, + ) + s.NoError(err) + + s.EventuallyWithT(func(t *assert.CollectT) { + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + ) + assert.NoError(t, res.Err) + assert.Contains(t, res.Stdout.String(), buildId1) + assert.Contains(t, res.Stdout.String(), "Pinned") + }, 30*time.Second, 100*time.Millisecond) + + res = s.Execute( + "workflow", "update-options", + "--address", s.Address(), + "-w", run.GetID(), + "--versioning-override-behavior", "pinned", + "--versioning-override-series-name", seriesName, + "--versioning-override-build-id", buildId2, + ) + s.NoError(res.Err) + + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + ) + s.NoError(res.Err) + + s.ContainsOnSameLine(res.Stdout.String(), "OverrideBehavior", "Pinned") + s.ContainsOnSameLine(res.Stdout.String(), "OverrideDeploymentSeriesName", seriesName) + s.ContainsOnSameLine(res.Stdout.String(), "OverrideDeploymentBuildID", buildId2) + + // remove override + res = s.Execute( + "workflow", "update-options", + "--address", s.Address(), + "-w", run.GetID(), + "--versioning-override-behavior", "unspecified", + ) + s.NoError(res.Err) + + // json + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + "--output", "json", + ) + s.NoError(res.Err) + + var jsonResp workflowservice.DescribeWorkflowExecutionResponse + s.NoError(temporalcli.UnmarshalProtoJSONWithOptions(res.Stdout.Bytes(), &jsonResp, true)) + versioningInfo := jsonResp.WorkflowExecutionInfo.VersioningInfo + s.Nil(versioningInfo.VersioningOverride) +} + func (s *SharedServerSuite) TestWorkflow_Update_Execute() { workflowUpdateTest{ s: s, diff --git a/temporalcli/commands.workflow_view.go b/temporalcli/commands.workflow_view.go index 15677b40..0552dd95 100644 --- a/temporalcli/commands.workflow_view.go +++ b/temporalcli/commands.workflow_view.go @@ -134,6 +134,32 @@ func (c *TemporalWorkflowDescribeCommand) run(cctx *CommandContext, args []strin HistorySize: info.HistorySizeBytes, }, printer.StructuredOptions{}) + if info.VersioningInfo != nil { + cctx.Printer.Println() + cctx.Printer.Println(color.MagentaString("Versioning Info:")) + cctx.Printer.Println() + vInfo := info.VersioningInfo + _ = cctx.Printer.PrintStructured(struct { + Behavior string + DeploymentSeriesName string + DeploymentBuildID string + OverrideBehavior string `cli:",cardOmitEmpty"` + OverrideDeploymentSeriesName string `cli:",cardOmitEmpty"` + OverrideDeploymentBuildID string `cli:",cardOmitEmpty"` + TransitionDeploymentSeriesName string `cli:",cardOmitEmpty"` + TransitionDeploymentBuildID string `cli:",cardOmitEmpty"` + }{ + Behavior: vInfo.Behavior.String(), + DeploymentSeriesName: vInfo.Deployment.GetSeriesName(), + DeploymentBuildID: vInfo.Deployment.GetBuildId(), + OverrideBehavior: vInfo.VersioningOverride.GetBehavior().String(), + OverrideDeploymentSeriesName: vInfo.VersioningOverride.GetDeployment().GetSeriesName(), + OverrideDeploymentBuildID: vInfo.VersioningOverride.GetDeployment().GetBuildId(), + TransitionDeploymentSeriesName: vInfo.DeploymentTransition.GetDeployment().GetSeriesName(), + TransitionDeploymentBuildID: vInfo.DeploymentTransition.GetDeployment().GetBuildId(), + }, printer.StructuredOptions{}) + } + if len(resp.Callbacks) > 0 { cctx.Printer.Println() cctx.Printer.Println(color.MagentaString("Callbacks: %v", len(resp.Callbacks))) diff --git a/temporalcli/commands.workflow_view_test.go b/temporalcli/commands.workflow_view_test.go index f1c6a60c..3f589449 100644 --- a/temporalcli/commands.workflow_view_test.go +++ b/temporalcli/commands.workflow_view_test.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/nexus-rpc/sdk-go/nexus" + "github.com/stretchr/testify/assert" "github.com/temporalio/cli/temporalcli" "go.temporal.io/api/enums/v1" nexuspb "go.temporal.io/api/nexus/v1" @@ -21,6 +22,7 @@ import ( "go.temporal.io/sdk/client" "go.temporal.io/sdk/temporal" "go.temporal.io/sdk/temporalnexus" + "go.temporal.io/sdk/worker" "go.temporal.io/sdk/workflow" ) @@ -546,6 +548,79 @@ func (s *SharedServerSuite) TestWorkflow_Count() { s.Contains(out, `{"groupValues":["Completed"],"count":"3"}`) } +func (s *SharedServerSuite) TestWorkflow_Describe_Deployment() { + buildId := uuid.NewString() + seriesName := uuid.NewString() + // Workflow that waits to be canceled. + waitingWorkflow := func(ctx workflow.Context) error { + ctx.Done().Receive(ctx, nil) + return ctx.Err() + } + w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Worker: worker.Options{ + BuildID: buildId, + UseBuildIDForVersioning: true, + DeploymentOptions: worker.DeploymentOptions{ + DeploymentSeriesName: seriesName, + DefaultVersioningBehavior: workflow.VersioningBehaviorPinned, + }, + }, + Workflows: []any{waitingWorkflow}, + }) + defer w.Stop() + + res := s.Execute( + "worker", "deployment", "set-current", + "--address", s.Address(), + "--series-name", seriesName, + "--build-id", buildId, + ) + s.NoError(res.Err) + + // Start the workflow and wait until the operation is started. + run, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{TaskQueue: w.Options.TaskQueue}, + waitingWorkflow, + ) + s.NoError(err) + + s.EventuallyWithT(func(t *assert.CollectT) { + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + ) + assert.NoError(t, res.Err) + assert.Contains(t, res.Stdout.String(), buildId) + assert.Contains(t, res.Stdout.String(), "Pinned") + }, 30*time.Second, 100*time.Millisecond) + + out := res.Stdout.String() + s.ContainsOnSameLine(out, "Behavior", "Pinned") + s.ContainsOnSameLine(out, "DeploymentBuildID", buildId) + s.ContainsOnSameLine(out, "DeploymentSeriesName", seriesName) + s.ContainsOnSameLine(out, "OverrideBehavior", "Unspecified") + + // json + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + "--output", "json", + ) + s.NoError(res.Err) + + var jsonResp workflowservice.DescribeWorkflowExecutionResponse + s.NoError(temporalcli.UnmarshalProtoJSONWithOptions(res.Stdout.Bytes(), &jsonResp, true)) + versioningInfo := jsonResp.WorkflowExecutionInfo.VersioningInfo + s.Equal("Pinned", versioningInfo.Behavior.String()) + s.Equal(buildId, versioningInfo.Deployment.BuildId) + s.Equal(seriesName, versioningInfo.Deployment.SeriesName) + s.Nil(versioningInfo.VersioningOverride) + s.Nil(versioningInfo.DeploymentTransition) +} + func (s *SharedServerSuite) TestWorkflow_Describe_NexusOperationAndCallback() { handlerWorkflowID := uuid.NewString() endpointName := validEndpointName(s.T()) diff --git a/temporalcli/commands_test.go b/temporalcli/commands_test.go index 5c120d60..4b3a823a 100644 --- a/temporalcli/commands_test.go +++ b/temporalcli/commands_test.go @@ -369,6 +369,7 @@ func StartDevServer(t *testing.T, options DevServerOptions) *DevServer { d.Options.DynamicConfigValues["frontend.workerVersioningRuleAPIs"] = true d.Options.DynamicConfigValues["frontend.workerVersioningDataAPIs"] = true d.Options.DynamicConfigValues["frontend.workerVersioningWorkflowAPIs"] = true + d.Options.DynamicConfigValues["system.enableDeployments"] = true d.Options.DynamicConfigValues["worker.buildIdScavengerEnabled"] = true d.Options.DynamicConfigValues["frontend.enableUpdateWorkflowExecution"] = true d.Options.DynamicConfigValues["frontend.MaxConcurrentBatchOperationPerNamespace"] = 1000 diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index f6832f10..8046d759 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -605,6 +605,184 @@ commands: description: Reason for terminating the batch job. required: true + - name: temporal worker + summary: Read or update Worker state + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker is experimental. Worker commands are subject to | + | change. | + +---------------------------------------------------------------------+ + + Modify or read state associated with a Worker, for example, + using Worker Deployments commands: + + ``` + temporal worker deployment + ``` + option-sets: + - client + docs: + description-header: >- + Learn how to read or modify state associated with a Worker, + such as Worker Deployments. + keywords: + - worker + - worker deployment + + - name: temporal worker deployment + summary: Describe, list, and operate on Worker Deployments + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker Deployment is experimental. Deployment commands are | + | subject to change. | + +---------------------------------------------------------------------+ + + Deployment commands perform operations on Worker Deployments: + + ``` + temporal worker deployment [command] [options] + ``` + + For example: + + ``` + temporal worker deployment list + ``` + docs: + description-header: >- + Temporal Deployment commands enable operations on Worker Deployments, + such as describe, list, set-current, and get-current, simplifying + versioning and management of workers. + keywords: + - worker deployment + - worker deployment describe + - worker deployment list + - worker deployment get-current + - worker deployment set-current + + - name: temporal worker deployment describe + summary: Show properties of a Worker Deployment + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker Deployment is experimental. Deployment commands are | + | subject to change. | + +---------------------------------------------------------------------+ + + Describes properties of a Worker Deployment, such as whether it is + current, the non-empty list of its task queues, custom metadata if + present, and reachability status when requested. + + ``` + temporal worker deployment describe [options] + ``` + + For example, to also include reachability information: + + ``` + temporal worker deployment describe \ + --series-name YourDeploymentSeriesName \ + --build-id YourDeploymentBuildId \ + --report-reachability + ``` + option-sets: + - deployment-reference + options: + - name: report-reachability + type: bool + description: | + Include reachability information of a Worker Deployment. + + - name: temporal worker deployment get-current + summary: Show the current Worker Deployment + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker Deployment is experimental. Deployment commands are | + | subject to change. | + +---------------------------------------------------------------------+ + + Gets the current Worker Deployment for a Deployment Series Name. + When a Deployment is current, Workers of that Deployment will receive + tasks from new Workflows and from existing AutoUpgrade Workflows that + are running on this Deployment Series. + + ``` + temporal worker deployment get-current [options] + ``` + + For example: + + ``` + temporal worker deployment get-current \ + --series-name YourDeploymentSeriesName + ``` + options: + - name: series-name + type: string + description: Series Name for the current Worker Deployment. + required: true + + - name: temporal worker deployment list + summary: Enumerate Worker Deployments in the client's namespace + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker Deployment is experimental. Deployment commands are | + | subject to change. | + +---------------------------------------------------------------------+ + + List existing Worker Deployments in the client's namespace, optionally + filtering them by Deployment Series Name. + + + ``` + temporal worker deployment list [options] + ``` + + For example, adding an optional filter: + + ``` + temporal worker deployment list \ + --series-name YourDeploymentSeriesName + ``` + options: + - name: series-name + type: string + description: Series Name to filter Worker Deployments. + + - name: temporal worker deployment set-current + summary: Change the current Worker Deployment + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worker deployment is experimental. Deployment commands are | + | subject to change. | + +---------------------------------------------------------------------+ + + Sets the current Deployment for a given Deployment Series. + When a Deployment is current, Workers of that Deployment will receive + tasks from new Workflows and from existing AutoUpgrade Workflows that + are running on this Deployment Series. + + ``` + temporal worker deployment set-current [options] + ``` + + For example: + + ``` + temporal worker deployment set-current \ + --series-name YourDeploymentSeriesName \ + --build-id YourDeploymentBuildId + ``` + option-sets: + - deployment-reference + options: + - name: metadata + type: string[] + description: | + Set deployment metadata using `KEY="VALUE"` pairs. + Keys must be identifiers, and values must be JSON values. + For example: 'YourKey={"your": "value"}'. + Can be passed multiple times. + - name: temporal env summary: Manage environments description: | @@ -2495,9 +2673,9 @@ commands: docs: description-header: >- Temporal Workflow commands enable operations on Workflow Executions, - such as cancel, count, delete, describe, execute, list, query, reset, - reset-batch, show, signal, stack, start, terminate, trace, and update, - enhancing efficiency and control. + such as cancel, count, delete, describe, execute, list, update-options, + query, reset, reset-batch, show, signal, stack, start, terminate, + trace, and update, enhancing efficiency and control. keywords: - call stack - cancellation @@ -2520,6 +2698,7 @@ commands: - workflow execute - workflow execution - workflow list + - workflow update-options - workflow query - workflow reset - workflow reset-batch @@ -2707,6 +2886,73 @@ commands: type: int description: Maximum number of Workflow Executions to display. + - name: temporal workflow update-options + summary: Change Workflow Execution Options + description: | + +---------------------------------------------------------------------+ + | CAUTION: Worflow update-options is experimental. Workflow Execution | + | properties are subject to change. | + +---------------------------------------------------------------------+ + + Modify properties of Workflow Executions: + + ``` + temporal workflow update-options [options] + ``` + + It can override the Worker Deployment configuration of a + Workflow Execution, which controls Worker Versioning. + + For example, to force Workers in the current Deployment execute the + next Workflow Task change behavior to `auto_upgrade`: + + ``` + temporal workflow update-options \ + --workflow-id YourWorkflowId \ + --versioning-override-behavior auto_upgrade + ``` + + or to pin the workflow execution to a Worker Deployment, set behavior + to `pinned`: + + ``` + temporal workflow update-options \ + --workflow-id YourWorkflowId \ + --versioning-override-behavior pinned \ + --versioning-override-series-name YourDeploymentSeriesName \ + --versioning-override-build-id YourDeploymentBuildId + ``` + + To remove any previous overrides, set the behavior to + `unspecified`: + + ``` + temporal workflow update-options \ + --workflow-id YourWorkflowId \ + --versioning-override-behavior unspecified + ``` + + To see the current override use `temporal workflow describe` + + option-sets: + - single-workflow-or-batch + options: + - name: versioning-override-behavior + type: string-enum + description: | + Override the versioning behavior of a Workflow. + required: true + enum-values: + - unspecified + - pinned + - auto_upgrade + - name: versioning-override-series-name + type: string + description: Override Series Name for a Worker Deployment (Only for pinned). + - name: versioning-override-build-id + type: string + description: Override Build ID for a Worker Deployment (Only for pinned). + - name: temporal workflow query summary: Retrieve Workflow Execution state description: | @@ -3311,6 +3557,17 @@ option-sets: short: r description: Run ID. + - name: deployment-reference + options: + - name: series-name + type: string + description: Series Name for a Worker Deployment. + required: true + - name: build-id + type: string + description: Build ID for a Worker Deployment. + required: true + - name: single-workflow-or-batch options: - name: workflow-id From de6f1c732caaf1b9ab60e3d8a0267571348f9a1e Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Thu, 23 Jan 2025 09:06:39 -0800 Subject: [PATCH 4/8] Add `workflow metadata` command (#743) --- temporalcli/commands.gen.go | 70 ++++++++++++++----- temporalcli/commands.workflow.go | 75 +++++++++++++++++--- temporalcli/commands.workflow_test.go | 93 +++++++++++++++++++++++++ temporalcli/commandsgen/commands.yml | 77 ++++++++++++-------- temporalcli/internal/printer/printer.go | 26 +++++-- 5 files changed, 281 insertions(+), 60 deletions(-) diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index ff6c537a..e4562335 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -278,6 +278,15 @@ func (v *NexusEndpointConfigOptions) buildFlags(cctx *CommandContext, f *pflag.F f.StringVar(&v.TargetUrl, "target-url", "", "An external Nexus Endpoint that receives forwarded Nexus requests. May be used as an alternative to `--target-namespace` and `--target-task-queue`.") } +type QueryModifiersOptions struct { + RejectCondition StringEnum +} + +func (v *QueryModifiersOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { + v.RejectCondition = NewStringEnum([]string{"not_open", "not_completed_cleanly"}, "") + f.Var(&v.RejectCondition, "reject-condition", "Optional flag for rejecting Queries based on Workflow state. Accepted values: not_open, not_completed_cleanly.") +} + type TemporalCommand struct { Command cobra.Command Env string @@ -342,9 +351,9 @@ func NewTemporalActivityCommand(cctx *CommandContext, parent *TemporalCommand) * s.Command.Use = "activity" s.Command.Short = "Complete, update, pause, unpause, reset or fail an Activity" if hasHighlighting { - s.Command.Long = "Update an Activity's options, manage activity lifecycle or update \nan Activity's state to completed or failed.\n\nUpdating activity state marks an Activity as successfully finished or as\nhaving encountered an error.\n\n\x1b[1mtemporal activity complete \\\n --activity-id=YourActivityId \\\n --workflow-id=YourWorkflowId \\\n --result='{\"YourResultKey\": \"YourResultValue\"}'\x1b[0m" + s.Command.Long = "Update an Activity's options, manage activity lifecycle or update\nan Activity's state to completed or failed.\n\nUpdating activity state marks an Activity as successfully finished or as\nhaving encountered an error.\n\n\x1b[1mtemporal activity complete \\\n --activity-id=YourActivityId \\\n --workflow-id=YourWorkflowId \\\n --result='{\"YourResultKey\": \"YourResultValue\"}'\x1b[0m" } else { - s.Command.Long = "Update an Activity's options, manage activity lifecycle or update \nan Activity's state to completed or failed.\n\nUpdating activity state marks an Activity as successfully finished or as\nhaving encountered an error.\n\n```\ntemporal activity complete \\\n --activity-id=YourActivityId \\\n --workflow-id=YourWorkflowId \\\n --result='{\"YourResultKey\": \"YourResultValue\"}'\n```" + s.Command.Long = "Update an Activity's options, manage activity lifecycle or update\nan Activity's state to completed or failed.\n\nUpdating activity state marks an Activity as successfully finished or as\nhaving encountered an error.\n\n```\ntemporal activity complete \\\n --activity-id=YourActivityId \\\n --workflow-id=YourWorkflowId \\\n --result='{\"YourResultKey\": \"YourResultValue\"}'\n```" } s.Command.Args = cobra.NoArgs s.Command.AddCommand(&NewTemporalActivityCompleteCommand(cctx, &s).Command) @@ -477,15 +486,15 @@ func NewTemporalActivityResetCommand(cctx *CommandContext, parent *TemporalActiv s.Command.Use = "reset [flags]" s.Command.Short = "Reset an Activity" if hasHighlighting { - s.Command.Long = "Resetting an activity resets both the number of attempts and the activity \ntimeout. If activity is paused, it will be un-paused. \n\nIf the \x1b[1mno-wait\x1b[0m flag is provided, the activity will be rescheduled \nimmediately. Even if the activity is currently running.\nIf the \x1b[1mno-wait\x1b[0m flag is not provided, the activity will be scheduled \nafter the current instance completes, if needed. \nIf the 'reset_heartbeats' flag is set, the activity heartbeat timer and \nheartbeats will be reset.\n\nSpecify the Activity and Workflow IDs:\n\n\x1b[1mtemporal activity reset \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --no-wait\n --reset-heartbeats\x1b[0m" + s.Command.Long = "Resetting an activity resets both the number of attempts and the activity\ntimeout. If activity is paused, it will be un-paused.\n\nIf the \x1b[1mno-wait\x1b[0m flag is provided, the activity will be rescheduled\nimmediately. Even if the activity is currently running.\nIf the \x1b[1mno-wait\x1b[0m flag is not provided, the activity will be scheduled\nafter the current instance completes, if needed.\nIf the 'reset_heartbeats' flag is set, the activity heartbeat timer and\nheartbeats will be reset.\n\nSpecify the Activity and Workflow IDs:\n\n\x1b[1mtemporal activity reset \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --no-wait\n --reset-heartbeats\x1b[0m" } else { - s.Command.Long = "Resetting an activity resets both the number of attempts and the activity \ntimeout. If activity is paused, it will be un-paused. \n\nIf the `no-wait` flag is provided, the activity will be rescheduled \nimmediately. Even if the activity is currently running.\nIf the `no-wait` flag is not provided, the activity will be scheduled \nafter the current instance completes, if needed. \nIf the 'reset_heartbeats' flag is set, the activity heartbeat timer and \nheartbeats will be reset.\n\nSpecify the Activity and Workflow IDs:\n\n```\ntemporal activity reset \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --no-wait\n --reset-heartbeats\n```" + s.Command.Long = "Resetting an activity resets both the number of attempts and the activity\ntimeout. If activity is paused, it will be un-paused.\n\nIf the `no-wait` flag is provided, the activity will be rescheduled\nimmediately. Even if the activity is currently running.\nIf the `no-wait` flag is not provided, the activity will be scheduled\nafter the current instance completes, if needed.\nIf the 'reset_heartbeats' flag is set, the activity heartbeat timer and\nheartbeats will be reset.\n\nSpecify the Activity and Workflow IDs:\n\n```\ntemporal activity reset \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --no-wait\n --reset-heartbeats\n```" } s.Command.Args = cobra.NoArgs s.Command.Flags().StringVarP(&s.ActivityId, "activity-id", "a", "", "Activity ID to pause. Required.") _ = cobra.MarkFlagRequired(s.Command.Flags(), "activity-id") s.Command.Flags().StringVar(&s.Identity, "identity", "", "Identity of the user submitting this request.") - s.Command.Flags().BoolVar(&s.NoWait, "no-wait", false, "Schedule the Activity immediately, even if its retry timeout has not expired or the activity is currently running.") + s.Command.Flags().BoolVar(&s.NoWait, "no-wait", false, "Schedule the Activity immediately, even if its retry timeout has not expired or the activity is currently running.") s.Command.Flags().BoolVar(&s.ResetHeartbeats, "reset-heartbeats", false, "Reset the Activity's heartbeat.") s.WorkflowReferenceOptions.buildFlags(cctx, s.Command.Flags()) s.Command.Run = func(c *cobra.Command, args []string) { @@ -558,28 +567,28 @@ func NewTemporalActivityUpdateOptionsCommand(cctx *CommandContext, parent *Tempo s.Command.Use = "update-options [flags]" s.Command.Short = "Update Activity options" if hasHighlighting { - s.Command.Long = "Update Activity options. Specify the Activity and Workflow IDs, and \noptions you want to update. \nUpdates are incremental, only changing the specified options. \n\n\x1b[1mtemporal activity update-options \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId \\\n --task-queue NewTaskQueueName \\\n --schedule-to-close-timeout DURATION \\\n --schedule-to-start-timeout DURATION \\\n --start-to-close-timeout DURATION \\\n --heartbeat-timeout DURATION \\\n --retry-initial-interval DURATION \\\n --retry-maximum-interval DURATION \\\n --retry-backoff-coefficient NewBackoffCoefficient \\\n --retry-maximum-attempts NewMaximumAttempts\x1b[0m" + s.Command.Long = "Update Activity options. Specify the Activity and Workflow IDs, and\noptions you want to update.\nUpdates are incremental, only changing the specified options.\n\n\x1b[1mtemporal activity update-options \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId \\\n --task-queue NewTaskQueueName \\\n --schedule-to-close-timeout DURATION \\\n --schedule-to-start-timeout DURATION \\\n --start-to-close-timeout DURATION \\\n --heartbeat-timeout DURATION \\\n --retry-initial-interval DURATION \\\n --retry-maximum-interval DURATION \\\n --retry-backoff-coefficient NewBackoffCoefficient \\\n --retry-maximum-attempts NewMaximumAttempts\x1b[0m" } else { - s.Command.Long = "Update Activity options. Specify the Activity and Workflow IDs, and \noptions you want to update. \nUpdates are incremental, only changing the specified options. \n\n```\ntemporal activity update-options \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId \\\n --task-queue NewTaskQueueName \\\n --schedule-to-close-timeout DURATION \\\n --schedule-to-start-timeout DURATION \\\n --start-to-close-timeout DURATION \\\n --heartbeat-timeout DURATION \\\n --retry-initial-interval DURATION \\\n --retry-maximum-interval DURATION \\\n --retry-backoff-coefficient NewBackoffCoefficient \\\n --retry-maximum-attempts NewMaximumAttempts\n\n```" + s.Command.Long = "Update Activity options. Specify the Activity and Workflow IDs, and\noptions you want to update.\nUpdates are incremental, only changing the specified options.\n\n```\ntemporal activity update-options \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId \\\n --task-queue NewTaskQueueName \\\n --schedule-to-close-timeout DURATION \\\n --schedule-to-start-timeout DURATION \\\n --start-to-close-timeout DURATION \\\n --heartbeat-timeout DURATION \\\n --retry-initial-interval DURATION \\\n --retry-maximum-interval DURATION \\\n --retry-backoff-coefficient NewBackoffCoefficient \\\n --retry-maximum-attempts NewMaximumAttempts\n\n```" } s.Command.Args = cobra.NoArgs s.Command.Flags().StringVar(&s.ActivityId, "activity-id", "", "Activity ID. Required.") _ = cobra.MarkFlagRequired(s.Command.Flags(), "activity-id") s.Command.Flags().StringVar(&s.TaskQueue, "task-queue", "", "Name of the task queue for the Activity.") s.ScheduleToCloseTimeout = 0 - s.Command.Flags().Var(&s.ScheduleToCloseTimeout, "schedule-to-close-timeout", "Indicates how long the caller is willing to wait for an activity completion. Limits how long retries will be attempted.") + s.Command.Flags().Var(&s.ScheduleToCloseTimeout, "schedule-to-close-timeout", "Indicates how long the caller is willing to wait for an activity completion. Limits how long retries will be attempted.") s.ScheduleToStartTimeout = 0 - s.Command.Flags().Var(&s.ScheduleToStartTimeout, "schedule-to-start-timeout", "Limits time an activity task can stay in a task queue before a worker picks it up. This timeout is always non retryable, as all a retry would achieve is to put it back into the same queue. Defaults to the schedule-to-close timeout or workflow execution timeout if not specified.") + s.Command.Flags().Var(&s.ScheduleToStartTimeout, "schedule-to-start-timeout", "Limits time an activity task can stay in a task queue before a worker picks it up. This timeout is always non retryable, as all a retry would achieve is to put it back into the same queue. Defaults to the schedule-to-close timeout or workflow execution timeout if not specified.") s.StartToCloseTimeout = 0 - s.Command.Flags().Var(&s.StartToCloseTimeout, "start-to-close-timeout", "Maximum time an activity is allowed to execute after being picked up by a worker. This timeout is always retryable.") + s.Command.Flags().Var(&s.StartToCloseTimeout, "start-to-close-timeout", "Maximum time an activity is allowed to execute after being picked up by a worker. This timeout is always retryable.") s.HeartbeatTimeout = 0 s.Command.Flags().Var(&s.HeartbeatTimeout, "heartbeat-timeout", "Maximum permitted time between successful worker heartbeats.") s.RetryInitialInterval = 0 s.Command.Flags().Var(&s.RetryInitialInterval, "retry-initial-interval", "Interval of the first retry. If retryBackoffCoefficient is 1.0 then it is used for all retries.") s.RetryMaximumInterval = 0 - s.Command.Flags().Var(&s.RetryMaximumInterval, "retry-maximum-interval", "Maximum interval between retries. Exponential backoff leads to interval increase. This value is the cap of the increase.") + s.Command.Flags().Var(&s.RetryMaximumInterval, "retry-maximum-interval", "Maximum interval between retries. Exponential backoff leads to interval increase. This value is the cap of the increase.") s.Command.Flags().Float32Var(&s.RetryBackoffCoefficient, "retry-backoff-coefficient", 0, "Coefficient used to calculate the next retry interval. The next retry interval is previous interval multiplied by the backoff coefficient. Must be 1 or larger.") - s.Command.Flags().IntVar(&s.RetryMaximumAttempts, "retry-maximum-attempts", 0, "Maximum number of attempts. When exceeded the retries stop even if not expired yet. Setting this value to 1 disables retries. Setting this value to 0 means unlimited attempts(up to the timeouts).") + s.Command.Flags().IntVar(&s.RetryMaximumAttempts, "retry-maximum-attempts", 0, "Maximum number of attempts. When exceeded the retries stop even if not expired yet. Setting this value to 1 disables retries. Setting this value to 0 means unlimited attempts(up to the timeouts).") s.Command.Flags().StringVar(&s.Identity, "identity", "", "Identity of the user submitting this request.") s.WorkflowReferenceOptions.buildFlags(cctx, s.Command.Flags()) s.Command.Run = func(c *cobra.Command, args []string) { @@ -2687,6 +2696,7 @@ func NewTemporalWorkflowCommand(cctx *CommandContext, parent *TemporalCommand) * s.Command.AddCommand(&NewTemporalWorkflowExecuteCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowFixHistoryJsonCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowListCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkflowMetadataCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowQueryCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowResetCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowResultCommand(cctx, &s).Command) @@ -2911,13 +2921,42 @@ func NewTemporalWorkflowListCommand(cctx *CommandContext, parent *TemporalWorkfl return &s } +type TemporalWorkflowMetadataCommand struct { + Parent *TemporalWorkflowCommand + Command cobra.Command + WorkflowReferenceOptions + QueryModifiersOptions +} + +func NewTemporalWorkflowMetadataCommand(cctx *CommandContext, parent *TemporalWorkflowCommand) *TemporalWorkflowMetadataCommand { + var s TemporalWorkflowMetadataCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "metadata [flags]" + s.Command.Short = "Query the Workflow for user-specified metadata" + if hasHighlighting { + s.Command.Long = "Issue a Query for and display user-set metadata like summary and\ndetails for a specific Workflow Execution:\n\n\x1b[1mtemporal workflow metadata \\\n --workflow-id YourWorkflowId\x1b[0m" + } else { + s.Command.Long = "Issue a Query for and display user-set metadata like summary and\ndetails for a specific Workflow Execution:\n\n```\ntemporal workflow metadata \\\n --workflow-id YourWorkflowId\n```" + } + s.Command.Args = cobra.NoArgs + s.WorkflowReferenceOptions.buildFlags(cctx, s.Command.Flags()) + s.QueryModifiersOptions.buildFlags(cctx, s.Command.Flags()) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + type TemporalWorkflowQueryCommand struct { Parent *TemporalWorkflowCommand Command cobra.Command PayloadInputOptions WorkflowReferenceOptions - Name string - RejectCondition StringEnum + QueryModifiersOptions + Name string } func NewTemporalWorkflowQueryCommand(cctx *CommandContext, parent *TemporalWorkflowCommand) *TemporalWorkflowQueryCommand { @@ -2934,10 +2973,9 @@ func NewTemporalWorkflowQueryCommand(cctx *CommandContext, parent *TemporalWorkf s.Command.Args = cobra.NoArgs s.Command.Flags().StringVar(&s.Name, "name", "", "Query Type/Name. Required. Aliased as \"--type\".") _ = cobra.MarkFlagRequired(s.Command.Flags(), "name") - s.RejectCondition = NewStringEnum([]string{"not_open", "not_completed_cleanly"}, "") - s.Command.Flags().Var(&s.RejectCondition, "reject-condition", "Optional flag for rejecting Queries based on Workflow state. Accepted values: not_open, not_completed_cleanly.") s.PayloadInputOptions.buildFlags(cctx, s.Command.Flags()) s.WorkflowReferenceOptions.buildFlags(cctx, s.Command.Flags()) + s.QueryModifiersOptions.buildFlags(cctx, s.Command.Flags()) s.Command.Flags().SetNormalizeFunc(aliasNormalizer(map[string]string{ "type": "name", })) diff --git a/temporalcli/commands.workflow.go b/temporalcli/commands.workflow.go index 481f881f..421fa354 100644 --- a/temporalcli/commands.workflow.go +++ b/temporalcli/commands.workflow.go @@ -18,6 +18,7 @@ import ( deploymentpb "go.temporal.io/api/deployment/v1" "go.temporal.io/api/enums/v1" "go.temporal.io/api/query/v1" + sdkpb "go.temporal.io/api/sdk/v1" "go.temporal.io/api/update/v1" workflowpb "go.temporal.io/api/workflow/v1" "go.temporal.io/api/workflowservice/v1" @@ -26,6 +27,8 @@ import ( "google.golang.org/protobuf/types/known/fieldmaskpb" ) +const metadataQueryName = "__temporal_workflow_metadata" + func (c *TemporalWorkflowCancelCommand) run(cctx *CommandContext, args []string) error { cl, err := c.Parent.ClientOptions.dialClient(cctx) if err != nil { @@ -203,6 +206,11 @@ func (c *TemporalWorkflowUpdateOptionsCommand) run(cctx *CommandContext, args [] return nil } +func (c *TemporalWorkflowMetadataCommand) run(cctx *CommandContext, _ []string) error { + return queryHelper(cctx, c.Parent, PayloadInputOptions{}, + metadataQueryName, c.RejectCondition, c.WorkflowReferenceOptions) +} + func (c *TemporalWorkflowQueryCommand) run(cctx *CommandContext, args []string) error { return queryHelper(cctx, c.Parent, c.PayloadInputOptions, c.Name, c.RejectCondition, c.WorkflowReferenceOptions) @@ -637,14 +645,63 @@ func queryHelper(cctx *CommandContext, return cctx.Printer.PrintStructured(result, printer.StructuredOptions{}) } - cctx.Printer.Println(color.MagentaString("Query result:")) - output := struct { - QueryResult json.RawMessage `cli:",cardOmitEmpty"` - }{} - output.QueryResult, err = cctx.MarshalFriendlyJSONPayloads(result.QueryResult) - if err != nil { - return fmt.Errorf("failed to marshal query result: %w", err) - } + if queryType == metadataQueryName { + var metadata sdkpb.WorkflowMetadata + err := UnmarshalProtoJSONWithOptions(result.QueryResult.Payloads[0].Data, &metadata, true) + if err != nil { + return fmt.Errorf("failed to unmarshal metadata: %w", err) + } + cctx.Printer.Println(color.MagentaString("Metadata:")) + + qDefs := metadata.GetDefinition().GetQueryDefinitions() + if len(qDefs) > 0 { + cctx.Printer.Println(printer.NonJSONIndent, color.MagentaString("Query Definitions:")) + err := cctx.Printer.PrintStructured(qDefs, printer.StructuredOptions{ + Table: &printer.TableOptions{NoHeader: true}, + NonJSONExtraIndent: 1, + }) + if err != nil { + return err + } + } + sigDefs := metadata.GetDefinition().GetSignalDefinitions() + if len(sigDefs) > 0 { + cctx.Printer.Println(printer.NonJSONIndent, color.MagentaString("Signal Definitions:")) + err := cctx.Printer.PrintStructured(sigDefs, printer.StructuredOptions{ + Table: &printer.TableOptions{NoHeader: true}, + NonJSONExtraIndent: 1, + }) + if err != nil { + return err + } + } + updDefs := metadata.GetDefinition().GetUpdateDefinitions() + if len(updDefs) > 0 { + cctx.Printer.Println(printer.NonJSONIndent, color.MagentaString("Update Definitions:")) + err := cctx.Printer.PrintStructured(updDefs, printer.StructuredOptions{ + Table: &printer.TableOptions{NoHeader: true}, + NonJSONExtraIndent: 1, + }) + if err != nil { + return err + } + } + if metadata.GetCurrentDetails() != "" { + cctx.Printer.Println(printer.NonJSONIndent, color.MagentaString("Current Details:")) + cctx.Printer.Println(printer.NonJSONIndent, printer.NonJSONIndent, + metadata.GetCurrentDetails()) + } + return nil + } else { + cctx.Printer.Println(color.MagentaString("Query result:")) + output := struct { + QueryResult json.RawMessage `cli:",cardOmitEmpty"` + }{} + output.QueryResult, err = cctx.MarshalFriendlyJSONPayloads(result.QueryResult) + if err != nil { + return fmt.Errorf("failed to marshal query result: %w", err) + } - return cctx.Printer.PrintStructured(output, printer.StructuredOptions{}) + return cctx.Printer.PrintStructured(output, printer.StructuredOptions{}) + } } diff --git a/temporalcli/commands.workflow_test.go b/temporalcli/commands.workflow_test.go index af873bb7..81ae0721 100644 --- a/temporalcli/commands.workflow_test.go +++ b/temporalcli/commands.workflow_test.go @@ -1148,3 +1148,96 @@ func (s *SharedServerSuite) testStackWorkflow(json bool) { s.Error(res.Err) s.Contains(res.Err.Error(), "query was rejected, workflow has status: Completed") } + +func (s *SharedServerSuite) TestWorkflow_MetadataJSON() { + s.testWorkflowMetadata(true) +} + +func (s *SharedServerSuite) TestWorkflow_Metadata() { + s.testWorkflowMetadata(false) +} + +func (s *SharedServerSuite) testWorkflowMetadata(json bool) { + // Make workflow wait for signal and then return it + s.Worker().OnDevWorkflow(func(ctx workflow.Context, a any) (any, error) { + done := false + workflow.Go(ctx, func(ctx workflow.Context) { + _ = workflow.Await(ctx, func() bool { + return done + }) + }) + workflow.SetQueryHandlerWithOptions(ctx, "my-query", func(arg string) (string, error) { + return "hi", nil + }, workflow.QueryHandlerOptions{Description: "q-desc"}) + workflow.SetUpdateHandlerWithOptions(ctx, "my-update", + func(ctx workflow.Context, arg string) (string, error) { return "hi", nil }, + workflow.UpdateHandlerOptions{Description: "upd-desc"}) + workflow.SetCurrentDetails(ctx, "current-deets") + workflow.GetSignalChannelWithOptions(ctx, "my-signal", + workflow.SignalChannelOptions{Description: "sig-desc"}).Receive(ctx, nil) + done = true + return nil, nil + + }) + + // Start the workflow + run, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{ + TaskQueue: s.Worker().Options.TaskQueue, + StaticSummary: "summie", + StaticDetails: "deets", + }, + DevWorkflow, + "ignored", + ) + s.NoError(err) + + args := []string{ + "workflow", "metadata", + "--address", s.Address(), + "-w", run.GetID(), + } + if json { + args = append(args, "-o", "json") + } + + res := s.Execute(args...) + s.NoError(res.Err) + if !json { + s.Contains(res.Stdout.String(), "Query Definitions:") + s.ContainsOnSameLine(res.Stdout.String(), "my-query", "q-desc") + s.Contains(res.Stdout.String(), "Signal Definitions:") + s.ContainsOnSameLine(res.Stdout.String(), "my-signal", "sig-desc") + s.Contains(res.Stdout.String(), "Update Definitions:") + s.ContainsOnSameLine(res.Stdout.String(), "my-update", "upd-desc") + s.Contains(res.Stdout.String(), "Current Details:") + s.Contains(res.Stdout.String(), "current-deets") + } else { + s.Contains(res.Stdout.String(), "queryDefinitions") + s.ContainsOnSameLine(res.Stdout.String(), "name", "my-query") + s.Contains(res.Stdout.String(), "signalDefinitions") + s.ContainsOnSameLine(res.Stdout.String(), "name", "my-signal") + s.Contains(res.Stdout.String(), "updateDefinitions") + s.ContainsOnSameLine(res.Stdout.String(), "name", "my-update") + s.ContainsOnSameLine(res.Stdout.String(), "currentDetails", "current-deets") + } + + // Unblock the workflow with a signal + s.NoError(s.Client.SignalWorkflow(s.Context, run.GetID(), "", "my-signal", nil)) + s.NoError(run.Get(s.Context, nil)) + + // Ensure query is rejected when using not open rejection condition + args = []string{ + "workflow", "metadata", + "--address", s.Address(), + "-w", run.GetID(), + "--reject-condition", "not_open", + } + if json { + args = append(args, "-o", "json") + } + res = s.Execute(args...) + s.Error(res.Err) + s.Contains(res.Err.Error(), "query was rejected, workflow has status: Completed") +} diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 8046d759..3df25670 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -206,7 +206,7 @@ commands: - name: temporal activity summary: Complete, update, pause, unpause, reset or fail an Activity description: | - Update an Activity's options, manage activity lifecycle or update + Update an Activity's options, manage activity lifecycle or update an Activity's state to completed or failed. Updating activity state marks an Activity as successfully finished or as @@ -297,9 +297,9 @@ commands: - name: temporal activity update-options summary: Update Activity options description: | - Update Activity options. Specify the Activity and Workflow IDs, and - options you want to update. - Updates are incremental, only changing the specified options. + Update Activity options. Specify the Activity and Workflow IDs, and + options you want to update. + Updates are incremental, only changing the specified options. ``` temporal activity update-options \ @@ -327,22 +327,22 @@ commands: - name: schedule-to-close-timeout type: duration description: | - Indicates how long the caller is willing to wait for an activity - completion. + Indicates how long the caller is willing to wait for an activity + completion. Limits how long retries will be attempted. - name: schedule-to-start-timeout type: duration description: | - Limits time an activity task can stay in a task queue before a worker - picks it up. - This timeout is always non retryable, as all a retry would achieve is + Limits time an activity task can stay in a task queue before a worker + picks it up. + This timeout is always non retryable, as all a retry would achieve is to put it back into the same queue. Defaults to the schedule-to-close timeout or workflow execution timeout if not specified. - name: start-to-close-timeout type: duration description: | - Maximum time an activity is allowed to execute after being picked up + Maximum time an activity is allowed to execute after being picked up by a worker. This timeout is always retryable. - name: heartbeat-timeout type: duration @@ -356,7 +356,7 @@ commands: - name: retry-maximum-interval type: duration description: | - Maximum interval between retries. Exponential backoff leads to + Maximum interval between retries. Exponential backoff leads to interval increase. This value is the cap of the increase. - name: retry-backoff-coefficient @@ -371,7 +371,7 @@ commands: description: | Maximum number of attempts. When exceeded the retries stop even if not expired yet. - Setting this value to 1 disables retries. Setting this value to 0 + Setting this value to 1 disables retries. Setting this value to 0 means unlimited attempts(up to the timeouts). - name: identity type: string @@ -459,14 +459,14 @@ commands: - name: temporal activity reset summary: Reset an Activity description: | - Resetting an activity resets both the number of attempts and the activity - timeout. If activity is paused, it will be un-paused. + Resetting an activity resets both the number of attempts and the activity + timeout. If activity is paused, it will be un-paused. - If the `no-wait` flag is provided, the activity will be rescheduled + If the `no-wait` flag is provided, the activity will be rescheduled immediately. Even if the activity is currently running. - If the `no-wait` flag is not provided, the activity will be scheduled - after the current instance completes, if needed. - If the 'reset_heartbeats' flag is set, the activity heartbeat timer and + If the `no-wait` flag is not provided, the activity will be scheduled + after the current instance completes, if needed. + If the 'reset_heartbeats' flag is set, the activity heartbeat timer and heartbeats will be reset. Specify the Activity and Workflow IDs: @@ -490,7 +490,7 @@ commands: - name: no-wait type: bool description: | - Schedule the Activity immediately, even if its retry timeout has not + Schedule the Activity immediately, even if its retry timeout has not expired or the activity is currently running. - name: reset-heartbeats type: bool @@ -623,8 +623,8 @@ commands: - client docs: description-header: >- - Learn how to read or modify state associated with a Worker, - such as Worker Deployments. + Learn how to read or modify state associated with a Worker, + such as Worker Deployments. keywords: - worker - worker deployment @@ -2698,7 +2698,7 @@ commands: - workflow execute - workflow execution - workflow list - - workflow update-options + - workflow metadata - workflow query - workflow reset - workflow reset-batch @@ -2708,6 +2708,7 @@ commands: - workflow start - workflow terminate - workflow trace + - workflow update-options - name: temporal workflow cancel summary: Send cancellation to Workflow Execution @@ -2886,6 +2887,20 @@ commands: type: int description: Maximum number of Workflow Executions to display. + - name: temporal workflow metadata + summary: Query the Workflow for user-specified metadata + description: | + Issue a Query for and display user-set metadata like summary and + details for a specific Workflow Execution: + + ``` + temporal workflow metadata \ + --workflow-id YourWorkflowId + ``` + option-sets: + - workflow-reference + - query-modifiers + - name: temporal workflow update-options summary: Change Workflow Execution Options description: | @@ -2970,6 +2985,7 @@ commands: option-sets: - payload-input - workflow-reference + - query-modifiers options: - name: name type: string @@ -2977,13 +2993,6 @@ commands: required: true aliases: - type - - name: reject-condition - type: string-enum - description: | - Optional flag for rejecting Queries based on Workflow state. - enum-values: - - not_open - - not_completed_cleanly - name: temporal workflow reset summary: Move Workflow Execution history point @@ -3800,3 +3809,13 @@ option-sets: An external Nexus Endpoint that receives forwarded Nexus requests. May be used as an alternative to `--target-namespace` and `--target-task-queue`. + + - name: query-modifiers + options: + - name: reject-condition + type: string-enum + description: | + Optional flag for rejecting Queries based on Workflow state. + enum-values: + - not_open + - not_completed_cleanly diff --git a/temporalcli/internal/printer/printer.go b/temporalcli/internal/printer/printer.go index 6c3fdac1..d20b806f 100644 --- a/temporalcli/internal/printer/printer.go +++ b/temporalcli/internal/printer/printer.go @@ -17,6 +17,8 @@ import ( "google.golang.org/protobuf/proto" ) +const NonJSONIndent = " " + type Colorer func(string, ...interface{}) string type Printer struct { @@ -99,6 +101,8 @@ type StructuredOptions struct { // printing. Table *TableOptions OverrideJSONPayloadShorthand *bool + // Indent this many additional times when printing non-JSON + NonJSONExtraIndent int } type Align int @@ -260,6 +264,7 @@ type col struct { width int cardOmitEmpty bool align Align + indentAmount int } type colVal struct { @@ -313,6 +318,7 @@ func adjustColsToOptions(cols []*col, options StructuredOptions) []*col { col.align = align } } + col.indentAmount = options.NonJSONExtraIndent + 1 adjusted = append(adjusted, col) } return adjusted @@ -331,8 +337,9 @@ func (p *Printer) printHeader(cols []*col) { colorer = color.MagentaString } for _, col := range cols { - // We want to indent even the first field - p.writeStr(" ") + for i := 0; i < col.indentAmount; i++ { + p.writeStr(NonJSONIndent) + } p.writeStr(tablewriter.Pad(colorer("%v", col.name), " ", col.width)) } p.writeStr("\n") @@ -346,8 +353,9 @@ func (p *Printer) printRows(cols []*col, rows []map[string]colVal) { func (p *Printer) printRow(cols []*col, row map[string]colVal) { for _, col := range cols { - // We want to indent even the first field - p.writeStr(" ") + for i := 0; i < col.indentAmount; i++ { + p.writeStr(NonJSONIndent) + } p.printCol(col, row[col.name].text) } p.writeStr("\n") @@ -377,6 +385,12 @@ func (p *Printer) printCards(cols []*col, rows []map[string]colVal) { func (p *Printer) printCard(cols []*col, row map[string]colVal) { nameValueRows := make([]map[string]colVal, 0, len(cols)) + indentAmount := 1 + // Since this option applies to everything in a structured print, there should be + // no difference among columns + if len(cols) > 0 { + indentAmount = cols[0].indentAmount + } for _, col := range cols { rowVal := row[col.name].val if !col.cardOmitEmpty || (rowVal != nil && !reflect.ValueOf(row[col.name].val).IsZero()) { @@ -387,10 +401,10 @@ func (p *Printer) printCard(cols []*col, row map[string]colVal) { } } nameValueCols := []*col{ - {name: "Name"}, + {name: "Name", indentAmount: indentAmount}, // We want to set the width to 1 here, because we want it to stretch as far // as it needs to the right - {name: "Value", width: 1}, + {name: "Value", width: 1, indentAmount: indentAmount}, } p.calculateUnsetColWidths(nameValueCols, nameValueRows) p.printRows(nameValueCols, nameValueRows) From df499119f3715667d69e10990561f2cee0ff118b Mon Sep 17 00:00:00 2001 From: Rodrigo Zhou <2068124+rodrigozhou@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:24:24 -0600 Subject: [PATCH 5/8] Update dependencies (#752) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What was changed Update dependencies ## Why? ## Checklist 1. Closes 2. How was this tested: 3. Any docs updates needed? --- go.mod | 160 ++++++++++++----------- go.sum | 407 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 280 insertions(+), 287 deletions(-) diff --git a/go.mod b/go.mod index 05ea017c..eabff5a6 100644 --- a/go.mod +++ b/go.mod @@ -3,35 +3,41 @@ module github.com/temporalio/cli go 1.23.2 require ( - github.com/alitto/pond v1.9.1 + github.com/alitto/pond v1.9.2 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/dustin/go-humanize v1.0.1 - github.com/fatih/color v1.17.0 + github.com/fatih/color v1.18.0 github.com/google/uuid v1.6.0 github.com/mattn/go-isatty v0.0.20 - github.com/nexus-rpc/sdk-go v0.1.0 + github.com/nexus-rpc/sdk-go v0.2.0 github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 - github.com/temporalio/ui-server/v2 v2.34.0 + github.com/temporalio/ui-server/v2 v2.35.0 go.temporal.io/api v1.43.0 go.temporal.io/sdk v1.32.1 go.temporal.io/server v1.26.2 - google.golang.org/grpc v1.67.1 - google.golang.org/protobuf v1.35.1 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.5 gopkg.in/yaml.v3 v3.0.1 ) require ( - cloud.google.com/go v0.114.0 // indirect - cloud.google.com/go/auth v0.5.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect - cloud.google.com/go/iam v1.1.8 // indirect - cloud.google.com/go/storage v1.41.0 // indirect - github.com/apache/thrift v0.20.0 // indirect - github.com/aws/aws-sdk-go v1.53.15 // indirect + cel.dev/expr v0.19.2 // indirect + cloud.google.com/go v0.118.2 // indirect + cloud.google.com/go/auth v0.14.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/iam v1.3.1 // indirect + cloud.google.com/go/monitoring v1.24.0 // indirect + cloud.google.com/go/storage v1.50.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 // indirect + github.com/apache/thrift v0.21.0 // indirect + github.com/aws/aws-sdk-go v1.55.6 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect @@ -39,49 +45,48 @@ require ( github.com/cactus/go-statsd-client/v5 v5.1.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/coreos/go-oidc/v3 v3.11.0 // indirect + github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/coreos/go-oidc/v3 v3.12.0 // indirect github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-sql-driver/mysql v1.7.1 // indirect - github.com/gocql/gocql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/gocql/gocql v1.7.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.7.0-rc.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gomarkdown/markdown v0.0.0-20241105142532-d03b89096d81 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20250207164621-7a1f277a159e // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/securecookie v1.1.1 // indirect + github.com/gorilla/securecookie v1.1.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect - github.com/jackc/pgx/v5 v5.6.0 // indirect - github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.2 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jmoiron/sqlx v1.3.4 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect - github.com/labstack/echo/v4 v4.9.1 // indirect - github.com/labstack/gommon v0.4.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/labstack/echo/v4 v4.13.3 // indirect + github.com/labstack/gommon v0.4.2 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect @@ -89,10 +94,11 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.4 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -102,54 +108,52 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/sony/gobreaker v1.0.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/temporalio/ringpop-go v0.0.0-20241119001152-e505ebd8f887 // indirect + github.com/temporalio/ringpop-go v0.0.0-20250130211428-b97329e994f7 // indirect github.com/temporalio/sqlparser v0.0.0-20231115171017-f4060bcfa6cb // indirect github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938 // indirect github.com/twmb/murmur3 v1.1.8 // indirect github.com/uber-common/bark v1.3.0 // indirect github.com/uber-go/tally/v4 v4.1.17-0.20240412215630-22fe011f5ff0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.1 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.53.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect - go.opentelemetry.io/proto/otlp v1.3.1 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.temporal.io/version v0.3.0 // indirect go.uber.org/atomic v1.11.0 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.22.0 // indirect - go.uber.org/mock v0.4.0 // indirect + go.uber.org/dig v1.18.0 // indirect + go.uber.org/fx v1.23.0 // indirect + go.uber.org/mock v0.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.5.0 // indirect - google.golang.org/api v0.182.0 // indirect - google.golang.org/genproto v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/oauth2 v0.26.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.10.0 // indirect + google.golang.org/api v0.220.0 // indirect + google.golang.org/genproto v0.0.0-20250207221924-e9438ea467c6 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/validator.v2 v2.0.1 // indirect - modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect - modernc.org/libc v1.55.3 // indirect - modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.8.0 // indirect - modernc.org/sqlite v1.34.1 // indirect - modernc.org/strutil v1.2.0 // indirect - modernc.org/token v1.1.0 // indirect + modernc.org/libc v1.61.13 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.8.2 // indirect + modernc.org/sqlite v1.34.5 // indirect ) diff --git a/go.sum b/go.sum index d1edbcaa..57276cd3 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,48 @@ +cel.dev/expr v0.19.2 h1:V354PbqIXr9IQdwy4SYA4xa0HXaWq1BUPAGzugBY5V4= +cel.dev/expr v0.19.2/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= -cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= -cloud.google.com/go/auth v0.5.0 h1:GtSZfKJkPrZi/s3AkiHnUYVI4dTP/kg8+I3unm0omag= -cloud.google.com/go/auth v0.5.0/go.mod h1:Kqvlz1cf1sNA0D+sYJnkPQOP+JMHkuHeIgVmCRtZOLc= -cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= -cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= -cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= -cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= -cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= +cloud.google.com/go v0.118.2 h1:bKXO7RXMFDkniAAvvuMrAPtQ/VHrs9e7J5UT3yrGdTY= +cloud.google.com/go v0.118.2/go.mod h1:CFO4UPEPi8oV21xoezZCrd3d81K4fFkDTEJu4R8K+9M= +cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0= +cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM= +cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= +cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/iam v1.3.1 h1:KFf8SaT71yYq+sQtRISn90Gyhyf4X8RGgeAVC8XGf3E= +cloud.google.com/go/iam v1.3.1/go.mod h1:3wMtuyT4NcbnYNPLMBzYRFiEfjKfJlLVLrisE7bwm34= +cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= +cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= +cloud.google.com/go/longrunning v0.6.4 h1:3tyw9rO3E2XVXzSApn1gyEEnH2K9SynNQjMlBi3uHLg= +cloud.google.com/go/longrunning v0.6.4/go.mod h1:ttZpLCe6e7EXvn9OxpBRx7kZEB0efv8yBO6YnVMfhJs= +cloud.google.com/go/monitoring v1.24.0 h1:csSKiCJ+WVRgNkRzzz3BPoGjFhjPY23ZTcaenToJxMM= +cloud.google.com/go/monitoring v1.24.0/go.mod h1:Bd1PRK5bmQBQNnuGwHBfUamAV1ys9049oEPHnn4pcsc= +cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs= +cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY= +cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= +cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 h1:f2Qw/Ehhimh5uO1fayV0QIW7DShEQqhtUfhYc+cBPlw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0/go.mod h1:2bIszWvQRlJVmJLiuLhukLImRjKPcYdzzsx6darK02A= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 h1:5IT7xOdq17MtcdtL/vtl6mGfzhaq4m4vpollPRmlsBQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0/go.mod h1:ZV4VOm0/eHR06JLrXWe09068dHpr3TRpY9Uo7T+anuA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.50.0 h1:nNMpRpnkWDAaqcpxMJvxa/Ud98gjbYwayJY4/9bdjiU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.50.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 h1:ig/FpDD2JofP/NExKQUbn7uOSZzJAQqogfqluZK4ed4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alitto/pond v1.9.1 h1:OfCpIrMyrWJpn34f647DcFmUxjK8+7Nu3eoVN/WTP+o= -github.com/alitto/pond v1.9.1/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= +github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs= +github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/apache/thrift v0.20.0 h1:631+KvYbsBZxmuJjYwhezVsrfc/TbqtZV4QcxOX1fOI= -github.com/apache/thrift v0.20.0/go.mod h1:hOk1BQqcp2OLzGsyVXdfMk7YFlMxK3aoEVhjD06QhB8= -github.com/aws/aws-sdk-go v1.53.15 h1:FtZmkg7xM8RfP2oY6p7xdKBYrRgkITk9yve2QV7N938= -github.com/aws/aws-sdk-go v1.53.15/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= +github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= +github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= +github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= 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.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= @@ -50,8 +70,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= -github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= +github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= +github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/crossdock/crossdock-go v0.0.0-20160816171116-049aabb0122b/go.mod h1:v9FBN7gdVTpiD/+LZ7Po0UKvROyT87uLVxTHVky/dlQ= @@ -69,11 +91,19 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM 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= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -82,8 +112,8 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/go-faker/faker/v4 v4.4.1 h1:LY1jDgjVkBZWIhATCt+gkl0x9i/7wC61gZx73GTFb+Q= github.com/go-faker/faker/v4 v4.4.1/go.mod h1:HRLrjis+tYsbFtIHufEPTAIzcZiRu0rS9EYl2Ccwme4= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= -github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -91,23 +121,17 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gocql/gocql v1.6.0 h1:IdFdOTbnpbd0pDhl4REKQDM+Q0SzKXQ1Yh+YZZ8T/qU= -github.com/gocql/gocql v1.6.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= +github.com/gocql/gocql v1.7.0 h1:O+7U7/1gSN7QTEAaMEsJc1Oq2QHXvCWoF3DFK9HDHus= +github.com/gocql/gocql v1.7.0/go.mod h1:vnlvXyFZeLBF0Wy+RS8hrOdbn0UWsWtdg07XJnFxZ+4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U= @@ -115,83 +139,70 @@ github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomarkdown/markdown v0.0.0-20241105142532-d03b89096d81 h1:5lyLWsV+qCkoYqsKUDuycESh9DEIPVKN6iCFeL7ag50= -github.com/gomarkdown/markdown v0.0.0-20241105142532-d03b89096d81/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/gomarkdown/markdown v0.0.0-20250207164621-7a1f277a159e h1:ESHlT0RVZphh4JGBz49I5R6nTdC8Qyc08vU25GQHzzQ= +github.com/gomarkdown/markdown v0.0.0-20250207164621-7a1f277a159e/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -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/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= -github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI= +github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 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 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= -github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= 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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -203,35 +214,31 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= -github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= +github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/nexus-rpc/sdk-go v0.1.0 h1:PUL/0vEY1//WnqyEHT5ao4LBRQ6MeNUihmnNGn0xMWY= -github.com/nexus-rpc/sdk-go v0.1.0/go.mod h1:TpfkM2Cw0Rlk9drGkoiSMpFqflKTiQLWUNyKJjF8mKQ= +github.com/nexus-rpc/sdk-go v0.2.0 h1:NKMkfTTQDEkbnP46/oB7cV7Ml25Wk+9w7lOyeYJQLAc= +github.com/nexus-rpc/sdk-go v0.2.0/go.mod h1:TpfkM2Cw0Rlk9drGkoiSMpFqflKTiQLWUNyKJjF8mKQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -245,18 +252,20 @@ github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a h1:AA9vgIBDjMHPC2McaGPojgV2dcI78ZC0TLNhYCXEKH8= github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a/go.mod h1:lzZQ3Noex5pfAy7mkAeCjcBDteYU85uWWnJ/y6gKU8k= -github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= -github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rcrowley/go-metrics v0.0.0-20141108142129-dee209f2455f/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -284,12 +293,11 @@ github.com/sony/gobreaker v1.0.0 h1:feX5fGGXSl3dYd4aHZItw+FpHLvvoaqkawKjVNiFMNQ= github.com/sony/gobreaker v1.0.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -297,20 +305,17 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/temporalio/ringpop-go v0.0.0-20241119001152-e505ebd8f887 h1:08Y1jDl4UKVu+TiQHIVKcW6TKQaHl15vBKkcZ094/SA= -github.com/temporalio/ringpop-go v0.0.0-20241119001152-e505ebd8f887/go.mod h1:RE+CHmY+kOZQk47AQaVzwrGmxpflnLgTd6EOK0853j4= +github.com/temporalio/ringpop-go v0.0.0-20250130211428-b97329e994f7 h1:lEebX/hZss+TSH3EBwhztnBavJVj7pWGJOH8UgKHS0w= +github.com/temporalio/ringpop-go v0.0.0-20250130211428-b97329e994f7/go.mod h1:RE+CHmY+kOZQk47AQaVzwrGmxpflnLgTd6EOK0853j4= github.com/temporalio/sqlparser v0.0.0-20231115171017-f4060bcfa6cb h1:YzHH/U/dN7vMP+glybzcXRTczTrgfdRisNTzAj7La04= github.com/temporalio/sqlparser v0.0.0-20231115171017-f4060bcfa6cb/go.mod h1:143qKdh3G45IgV9p+gbAwp3ikRDI8mxsijFiXDfuxsw= github.com/temporalio/tchannel-go v1.22.1-0.20220818200552-1be8d8cffa5b/go.mod h1:c+V9Z/ZgkzAdyGvHrvC5AsXgN+M9Qwey04cBdKYzV7U= github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938 h1:sEJGhmDo+0FaPWM6f0v8Tjia0H5pR6/Baj6+kS78B+M= github.com/temporalio/tchannel-go v1.22.1-0.20240528171429-1db37fdea938/go.mod h1:ezRQRwu9KQXy8Wuuv1aaFFxoCNz5CeNbVOOkh3xctbY= -github.com/temporalio/ui-server/v2 v2.34.0 h1:KLTTMh870/h1oxYqOtGMnmQBOP0oIcwFEnP7/i0C0hA= -github.com/temporalio/ui-server/v2 v2.34.0/go.mod h1:Um2G8/8bDQczAdY+21ba+y+nLXwUdL7ZLlhAAaIeVqA= +github.com/temporalio/ui-server/v2 v2.35.0 h1:9msJGma2dEiwI+nI3iU7TfpnmgRCQv+R8Yd8JWqurC4= +github.com/temporalio/ui-server/v2 v2.35.0/go.mod h1:suM9z9+8208achw/6ZWd3/mF4k9x567mIBAg10S5lf4= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber-common/bark v1.0.0/go.mod h1:g0ZuPcD7XiExKHynr93Q742G/sbrdVQkghrqLGOoFuY= @@ -325,38 +330,42 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 h1:FZ6ei8GFW7kyPYdxJaV2rgI6M+4tvZzhYsQ2wgyVC08= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/prometheus v0.53.0 h1:QXobPHrwiGLM4ufrY3EOmDPJpo2P90UuFau4CDPJA/I= -go.opentelemetry.io/otel/exporters/prometheus v0.53.0/go.mod h1:WOAXGr3D00CfzmFxtTV1eR0GpoHuPEu+HJT8UWW2SIU= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.temporal.io/api v1.43.0 h1:lBhq+u5qFJqGMXwWsmg/i8qn1UA/3LCwVc88l2xUMHg= go.temporal.io/api v1.43.0/go.mod h1:1WwYUMo6lao8yl0371xWUm13paHExN5ATYT/B7QtFis= go.temporal.io/sdk v1.32.1 h1:slA8prhdFr4lxpsTcRusWVitD/cGjELfKUh0mBj73SU= @@ -369,15 +378,15 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.22.0 h1:pApUK7yL0OUHMd8vkunWSlLxZVFFk70jR2nKde8X2NM= -go.uber.org/fx v1.22.0/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= +go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw= +go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg= +go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= @@ -394,16 +403,16 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= -golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -419,8 +428,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -429,18 +438,17 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -449,8 +457,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -462,21 +470,17 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -489,10 +493,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -511,51 +515,38 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.182.0 h1:if5fPvudRQ78GeRx3RayIoiuV7modtErPIZC/T2bIvE= -google.golang.org/api v0.182.0/go.mod h1:cGhjy4caqA5yXRzEhkHI8Y9mfyC2VLTlER2l08xaqtM= +google.golang.org/api v0.220.0 h1:3oMI4gdBgB72WFVwE1nerDD8W3HUOS4kypK6rRLbGns= +google.golang.org/api v0.220.0/go.mod h1:26ZAlY6aN/8WgpCzjPNy18QpYaz7Zgg1h0qe1GkZEmY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE= -google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto v0.0.0-20250207221924-e9438ea467c6 h1:SSk8oMbcHFbMwftDvX4PHbkqss3RkEZUF+k1h9d/sns= +google.golang.org/genproto v0.0.0-20250207221924-e9438ea467c6/go.mod h1:wkQ2Aj/xvshAUDtO/JHvu9y+AaN9cqs28QuSVSHtZSY= +google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6 h1:L9JNMl/plZH9wmzQUHleO/ZZDSN+9Gh41wPczNy+5Fk= +google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -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= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -579,30 +570,28 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= -modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= -modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= +modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo= +modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= -modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= -modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8= -modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= -modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= -modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= -modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= -modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk= -modernc.org/sqlite v1.34.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= -modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= -modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw= +modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8= +modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI= +modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g= +modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From 2467e7d5cae5ff9ef384513dfa5acdbee9554f9c Mon Sep 17 00:00:00 2001 From: Eddie Whiteside Date: Fri, 14 Feb 2025 21:42:11 +0000 Subject: [PATCH 6/8] Add codec-header config (closes #753) (#755) --- temporalcli/client.go | 39 ++++++++++++++++++++-------- temporalcli/commands.gen.go | 4 ++- temporalcli/commandsgen/commands.yml | 8 +++++- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/temporalcli/client.go b/temporalcli/client.go index d243f668..cb75e936 100644 --- a/temporalcli/client.go +++ b/temporalcli/client.go @@ -39,20 +39,25 @@ func (c *ClientOptions) dialClient(cctx *CommandContext) (client.Client, error) // Headers if len(c.GrpcMeta) > 0 { - headers := make(stringMapHeadersProvider, len(c.GrpcMeta)) - for _, kv := range c.GrpcMeta { - pieces := strings.SplitN(kv, "=", 2) - if len(pieces) != 2 { - return nil, fmt.Errorf("gRPC meta of %q does not have '='", kv) - } - headers[pieces[0]] = pieces[1] + headers, err := NewStringMapHeaderProvider(c.GrpcMeta) + if err != nil { + return nil, fmt.Errorf("grpc-meta %s", err) } clientOptions.HeadersProvider = headers } // Remote codec if c.CodecEndpoint != "" { - interceptor, err := payloadCodecInterceptor(c.Namespace, c.CodecEndpoint, c.CodecAuth) + codecHeaders, err := NewStringMapHeaderProvider(c.CodecHeader) + if err != nil { + return nil, fmt.Errorf("codec-header %s", err) + } + + if c.CodecAuth != "" { + codecHeaders["Authorization"] = c.CodecAuth + } + + interceptor, err := payloadCodecInterceptor(c.Namespace, c.CodecEndpoint, codecHeaders) if err != nil { return nil, fmt.Errorf("failed creating payload codec interceptor: %w", err) } @@ -145,7 +150,7 @@ func fixedHeaderOverrideInterceptor( return invoker(ctx, method, req, reply, cc, opts...) } -func payloadCodecInterceptor(namespace, codecEndpoint, codecAuth string) (grpc.UnaryClientInterceptor, error) { +func payloadCodecInterceptor(namespace, codecEndpoint string, codecHeaders stringMapHeadersProvider) (grpc.UnaryClientInterceptor, error) { codecEndpoint = strings.ReplaceAll(codecEndpoint, "{namespace}", namespace) payloadCodec := converter.NewRemotePayloadCodec( @@ -153,8 +158,8 @@ func payloadCodecInterceptor(namespace, codecEndpoint, codecAuth string) (grpc.U Endpoint: codecEndpoint, ModifyRequest: func(req *http.Request) error { req.Header.Set("X-Namespace", namespace) - if codecAuth != "" { - req.Header.Set("Authorization", codecAuth) + for headerName, headerValue := range codecHeaders { + req.Header.Set(headerName, headerValue) } return nil }, @@ -185,6 +190,18 @@ func (s stringMapHeadersProvider) GetHeaders(context.Context) (map[string]string return s, nil } +func NewStringMapHeaderProvider(config []string) (stringMapHeadersProvider, error) { + headers := make(stringMapHeadersProvider, len(config)) + for _, kv := range config { + pieces := strings.SplitN(kv, "=", 2) + if len(pieces) != 2 { + return nil, fmt.Errorf("%q does not have '='", kv) + } + headers[pieces[0]] = pieces[1] + } + return headers, nil +} + var DataConverterWithRawValue = converter.NewCompositeDataConverter( rawValuePayloadConverter{}, converter.NewNilPayloadConverter(), diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index e4562335..3ca46ec7 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -32,6 +32,7 @@ type ClientOptions struct { TlsServerName string CodecEndpoint string CodecAuth string + CodecHeader []string } func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { @@ -41,7 +42,7 @@ func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { cctx.BindFlagEnvVar(f.Lookup("namespace"), "TEMPORAL_NAMESPACE") f.StringVar(&v.ApiKey, "api-key", "", "API key for request.") cctx.BindFlagEnvVar(f.Lookup("api-key"), "TEMPORAL_API_KEY") - f.StringArrayVar(&v.GrpcMeta, "grpc-meta", nil, "HTTP headers for requests. format as a `KEY=VALUE` pair May be passed multiple times to set multiple headers.") + f.StringArrayVar(&v.GrpcMeta, "grpc-meta", nil, "HTTP headers for requests. Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers.") f.BoolVar(&v.Tls, "tls", false, "Enable base TLS encryption. Does not have additional options like mTLS or client certs.") cctx.BindFlagEnvVar(f.Lookup("tls"), "TEMPORAL_TLS") f.StringVar(&v.TlsCertPath, "tls-cert-path", "", "Path to x509 certificate. Can't be used with --tls-cert-data.") @@ -64,6 +65,7 @@ func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { cctx.BindFlagEnvVar(f.Lookup("codec-endpoint"), "TEMPORAL_CODEC_ENDPOINT") f.StringVar(&v.CodecAuth, "codec-auth", "", "Authorization header for Codec Server requests.") cctx.BindFlagEnvVar(f.Lookup("codec-auth"), "TEMPORAL_CODEC_AUTH") + f.StringArrayVar(&v.CodecHeader, "codec-header", nil, "HTTP headers for requests to codec server. Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers.") } type OverlapPolicyOptions struct { diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 3df25670..0fc73568 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -3405,7 +3405,7 @@ option-sets: type: string[] description: | HTTP headers for requests. - format as a `KEY=VALUE` pair + Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers. - name: tls type: bool @@ -3465,6 +3465,12 @@ option-sets: type: string description: Authorization header for Codec Server requests. env: TEMPORAL_CODEC_AUTH + - name: codec-header + type: string[] + description: | + HTTP headers for requests to codec server. + Format as a `KEY=VALUE` pair. + May be passed multiple times to set multiple headers. - name: overlap-policy options: From 1cb1264ae0d0d2b08b627acf6dee2794b9dbb4d1 Mon Sep 17 00:00:00 2001 From: Yimin Chen Date: Thu, 20 Feb 2025 12:59:12 -0800 Subject: [PATCH 7/8] Specify pagesize for workflow list command (#748) ## What was changed Add optional --page-size parameter to workflow list command. ## Why? Be able to specify page size is useful when default page is too large for cases where it leads to timeout due to large amount of data. --- temporalcli/commands.gen.go | 2 ++ temporalcli/commands.workflow_view.go | 10 +++++++--- temporalcli/commands.workflow_view_test.go | 2 ++ temporalcli/commandsgen/commands.yml | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index 3ca46ec7..044143ad 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -2898,6 +2898,7 @@ type TemporalWorkflowListCommand struct { Query string Archived bool Limit int + PageSize int } func NewTemporalWorkflowListCommand(cctx *CommandContext, parent *TemporalWorkflowCommand) *TemporalWorkflowListCommand { @@ -2915,6 +2916,7 @@ func NewTemporalWorkflowListCommand(cctx *CommandContext, parent *TemporalWorkfl s.Command.Flags().StringVarP(&s.Query, "query", "q", "", "Content for an SQL-like `QUERY` List Filter.") s.Command.Flags().BoolVar(&s.Archived, "archived", false, "Limit output to archived Workflow Executions.") s.Command.Flags().IntVar(&s.Limit, "limit", 0, "Maximum number of Workflow Executions to display.") + s.Command.Flags().IntVar(&s.PageSize, "page-size", 0, "Maximum number of Workflow Executions to fetch at a time from the server.") s.Command.Run = func(c *cobra.Command, args []string) { if err := s.run(cctx, args); err != nil { cctx.Options.Fail(err) diff --git a/temporalcli/commands.workflow_view.go b/temporalcli/commands.workflow_view.go index 0552dd95..c57e2d25 100644 --- a/temporalcli/commands.workflow_view.go +++ b/temporalcli/commands.workflow_view.go @@ -306,9 +306,7 @@ func (c *TemporalWorkflowListCommand) run(cctx *CommandContext, _ []string) erro cctx.Printer.StartList() defer cctx.Printer.EndList() - // Build request and start looping. We always use default page size regardless - // of user-defined limit, because we're ok w/ extra page data and the default - // is not clearly defined. + // Build request and start looping. pageFetcher := c.pageFetcher(cctx, cl) var nextPageToken []byte var execsProcessed int @@ -360,16 +358,22 @@ func (c *TemporalWorkflowListCommand) pageFetcher( cctx *CommandContext, cl client.Client, ) func(next []byte) (workflowPage, error) { + + if c.Limit > 0 && c.Limit < c.PageSize { + c.PageSize = c.Limit + } return func(next []byte) (workflowPage, error) { if c.Archived { return cl.ListArchivedWorkflow(cctx, &workflowservice.ListArchivedWorkflowExecutionsRequest{ Query: c.Query, NextPageToken: next, + PageSize: int32(c.PageSize), }) } return cl.ListWorkflow(cctx, &workflowservice.ListWorkflowExecutionsRequest{ Query: c.Query, NextPageToken: next, + PageSize: int32(c.PageSize), }) } } diff --git a/temporalcli/commands.workflow_view_test.go b/temporalcli/commands.workflow_view_test.go index 3f589449..a39e6512 100644 --- a/temporalcli/commands.workflow_view_test.go +++ b/temporalcli/commands.workflow_view_test.go @@ -442,10 +442,12 @@ func (s *SharedServerSuite) TestWorkflow_List() { "workflow", "list", "--address", s.Address(), "--query", fmt.Sprintf(`TaskQueue="%s"`, s.Worker().Options.TaskQueue), + "--page-size", "1", ) s.NoError(res.Err) out := res.Stdout.String() s.ContainsOnSameLine(out, "Completed", "DevWorkflow") + s.Equal(3, strings.Count(out, "DevWorkflow")) // JSON res = s.Execute( diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 0fc73568..7a8878e3 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -2886,6 +2886,9 @@ commands: - name: limit type: int description: Maximum number of Workflow Executions to display. + - name: page-size + type: int + description: Maximum number of Workflow Executions to fetch at a time from the server. - name: temporal workflow metadata summary: Query the Workflow for user-specified metadata From f968fa315c0f4ae398ace33b2a925a9088de9e2c Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Fri, 21 Feb 2025 13:38:53 -0500 Subject: [PATCH 8/8] Add `temporal workflow signal-with-start` command (#758) Added `temporal workflow signal-with-start` command. Description and sample usage: Send an asynchronous notification (Signal) to a Workflow Execution. If the Workflow Execution is not running or is not found, it starts the workflow then sends the signal. ``` temporal workflow signal-with-start \ --signal-name YourSignal \ --signal-input '{"some-key": "some-value"}' \ --workflow-id YourWorkflowId \ --type YourWorkflowType \ --task-queue YourTaskQueue \ --input '{"some-key": "some-value"}' ``` 1. Closes #664 2. How was this tested: Added unit tests 3. Any docs updates needed? Yes --- temporalcli/commands.gen.go | 47 ++++++++ temporalcli/commands.go | 19 +++ temporalcli/commands.schedule.go | 20 +--- temporalcli/commands.workflow_exec.go | 112 ++++++++++++++++++ temporalcli/commands.workflow_exec_test.go | 101 ++++++++++++++++ temporalcli/commandsgen/commands.yml | 54 +++++++++ temporalcli/internal/cmd/gen-commands/main.go | 2 +- 7 files changed, 335 insertions(+), 20 deletions(-) diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index 044143ad..4fcfd717 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -2704,6 +2704,7 @@ func NewTemporalWorkflowCommand(cctx *CommandContext, parent *TemporalCommand) * s.Command.AddCommand(&NewTemporalWorkflowResultCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowShowCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowSignalCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalWorkflowSignalWithStartCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowStackCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowStartCommand(cctx, &s).Command) s.Command.AddCommand(&NewTemporalWorkflowTerminateCommand(cctx, &s).Command) @@ -3133,6 +3134,52 @@ func NewTemporalWorkflowSignalCommand(cctx *CommandContext, parent *TemporalWork return &s } +type TemporalWorkflowSignalWithStartCommand struct { + Parent *TemporalWorkflowCommand + Command cobra.Command + SharedWorkflowStartOptions + WorkflowStartOptions + PayloadInputOptions + SignalName string + SignalInput []string + SignalInputFile []string + SignalInputMeta []string + SignalInputBase64 bool +} + +func NewTemporalWorkflowSignalWithStartCommand(cctx *CommandContext, parent *TemporalWorkflowCommand) *TemporalWorkflowSignalWithStartCommand { + var s TemporalWorkflowSignalWithStartCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "signal-with-start [flags]" + s.Command.Short = "Send a message to a Workflow Execution, start the execution if it isn't running" + if hasHighlighting { + s.Command.Long = "Send an asynchronous notification (Signal) to a Workflow Execution.\nIf the Workflow Execution is not running or is not found, it starts the \nworkflow then sends the signal.\n\n\x1b[1mtemporal workflow signal-with-start \\\n --signal-name YourSignal \\\n --signal-input '{\"some-key\": \"some-value\"}' \\\n --workflow-id YourWorkflowId \\\n --type YourWorkflowType \\\n --task-queue YourTaskQueue \\\n --input '{\"some-key\": \"some-value\"}'\x1b[0m" + } else { + s.Command.Long = "Send an asynchronous notification (Signal) to a Workflow Execution.\nIf the Workflow Execution is not running or is not found, it starts the \nworkflow then sends the signal.\n\n```\ntemporal workflow signal-with-start \\\n --signal-name YourSignal \\\n --signal-input '{\"some-key\": \"some-value\"}' \\\n --workflow-id YourWorkflowId \\\n --type YourWorkflowType \\\n --task-queue YourTaskQueue \\\n --input '{\"some-key\": \"some-value\"}'\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().StringVar(&s.SignalName, "signal-name", "", "Signal name. Required. Aliased as \"--signal-type\".") + _ = cobra.MarkFlagRequired(s.Command.Flags(), "signal-name") + s.Command.Flags().StringArrayVar(&s.SignalInput, "signal-input", nil, "Signal input value. Use JSON content or set --signal-input-meta to override. Can't be combined with --signal-input-file. Can be passed multiple times to pass multiple arguments.") + s.Command.Flags().StringArrayVar(&s.SignalInputFile, "signal-input-file", nil, "A path or paths for input file(s). Use JSON content or set --signal-input-meta to override. Can't be combined with --signal-input. Can be passed multiple times to pass multiple arguments.") + s.Command.Flags().StringArrayVar(&s.SignalInputMeta, "signal-input-meta", nil, "Input signal payload metadata as a `KEY=VALUE` pair. When the KEY is \"encoding\", this overrides the default (\"json/plain\"). Can be passed multiple times.") + s.Command.Flags().BoolVar(&s.SignalInputBase64, "signal-input-base64", false, "Assume signal inputs are base64-encoded and attempt to decode them.") + s.SharedWorkflowStartOptions.buildFlags(cctx, s.Command.Flags()) + s.WorkflowStartOptions.buildFlags(cctx, s.Command.Flags()) + s.PayloadInputOptions.buildFlags(cctx, s.Command.Flags()) + s.Command.Flags().SetNormalizeFunc(aliasNormalizer(map[string]string{ + "name": "type", + "signal-type": "signal-name", + })) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + type TemporalWorkflowStackCommand struct { Parent *TemporalWorkflowCommand Command cobra.Command diff --git a/temporalcli/commands.go b/temporalcli/commands.go index b9ba6322..217f2f29 100644 --- a/temporalcli/commands.go +++ b/temporalcli/commands.go @@ -23,8 +23,10 @@ import ( "github.com/temporalio/cli/temporalcli/internal/printer" "github.com/temporalio/ui-server/v2/server/version" "go.temporal.io/api/common/v1" + commonpb "go.temporal.io/api/common/v1" "go.temporal.io/api/failure/v1" "go.temporal.io/api/temporalproto" + "go.temporal.io/sdk/converter" "go.temporal.io/sdk/temporal" "go.temporal.io/server/common/headers" "google.golang.org/grpc" @@ -589,3 +591,20 @@ func fromApplicationError(err *temporal.ApplicationError) (*structuredError, err Details: deets, }, nil } + +func encodeMapToPayloads(in map[string]any) (map[string]*commonpb.Payload, error) { + if len(in) == 0 { + return nil, nil + } + // search attributes always use default dataconverter + dc := converter.GetDefaultDataConverter() + out := make(map[string]*commonpb.Payload, len(in)) + for key, val := range in { + payload, err := dc.ToPayload(val) + if err != nil { + return nil, err + } + out[key] = payload + } + return out, nil +} diff --git a/temporalcli/commands.schedule.go b/temporalcli/commands.schedule.go index e458ba91..3d645cb2 100644 --- a/temporalcli/commands.schedule.go +++ b/temporalcli/commands.schedule.go @@ -16,7 +16,6 @@ import ( schedpb "go.temporal.io/api/schedule/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" - "go.temporal.io/sdk/converter" "go.temporal.io/server/common/primitives/timestamp" ) @@ -257,7 +256,7 @@ func toScheduleAction(sw *SharedWorkflowStartOptions, i *PayloadInputOptions) (c if err != nil { return nil, err } - untypedSearchAttributes, err := encodeSearchAttributesToPayloads(opts.SearchAttributes) + untypedSearchAttributes, err := encodeMapToPayloads(opts.SearchAttributes) if err != nil { return nil, err } @@ -605,20 +604,3 @@ func formatDuration(d time.Duration) string { s = strings.TrimSpace(s) return s } - -func encodeSearchAttributesToPayloads(in map[string]any) (map[string]*commonpb.Payload, error) { - if len(in) == 0 { - return nil, nil - } - // search attributes always use default dataconverter - dc := converter.GetDefaultDataConverter() - out := make(map[string]*commonpb.Payload, len(in)) - for key, val := range in { - payload, err := dc.ToPayload(val) - if err != nil { - return nil, err - } - out[key] = payload - } - return out, nil -} diff --git a/temporalcli/commands.workflow_exec.go b/temporalcli/commands.workflow_exec.go index b885e4ca..08393a7d 100644 --- a/temporalcli/commands.workflow_exec.go +++ b/temporalcli/commands.workflow_exec.go @@ -12,12 +12,18 @@ import ( "time" "github.com/fatih/color" + "github.com/google/uuid" "github.com/temporalio/cli/temporalcli/internal/printer" "go.temporal.io/api/common/v1" + commonpb "go.temporal.io/api/common/v1" "go.temporal.io/api/enums/v1" + enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/history/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" "go.temporal.io/api/temporalproto" + "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" + "google.golang.org/protobuf/types/known/durationpb" ) func (c *TemporalWorkflowStartCommand) run(cctx *CommandContext, args []string) error { @@ -92,6 +98,112 @@ func (c *TemporalWorkflowExecuteCommand) run(cctx *CommandContext, args []string return err } +func (c *TemporalWorkflowSignalWithStartCommand) run(cctx *CommandContext, _ []string) error { + if c.SharedWorkflowStartOptions.WorkflowId == "" { + return fmt.Errorf("--workflow-id flag must be provided") + } + + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + wfStartOpts, err := buildStartOptions(&c.SharedWorkflowStartOptions, &c.WorkflowStartOptions) + if err != nil { + return err + } + wfInput, err := c.buildRawInputPayloads() + if err != nil { + return err + } + + signalPayloadInputOpts := PayloadInputOptions{ + Input: c.SignalInput, + InputFile: c.SignalInputFile, + InputMeta: c.InputMeta, + InputBase64: c.SignalInputBase64, + } + signalInput, err := signalPayloadInputOpts.buildRawInputPayloads() + if err != nil { + return err + } + + var retryPolicy *common.RetryPolicy + if wfStartOpts.RetryPolicy != nil { + retryPolicy = &commonpb.RetryPolicy{ + MaximumInterval: durationpb.New(wfStartOpts.RetryPolicy.MaximumInterval), + InitialInterval: durationpb.New(wfStartOpts.RetryPolicy.InitialInterval), + BackoffCoefficient: wfStartOpts.RetryPolicy.BackoffCoefficient, + MaximumAttempts: wfStartOpts.RetryPolicy.MaximumAttempts, + NonRetryableErrorTypes: wfStartOpts.RetryPolicy.NonRetryableErrorTypes, + } + } + var memo *common.Memo + if wfStartOpts.Memo != nil { + fields, err := encodeMapToPayloads(wfStartOpts.Memo) + if err != nil { + return err + } + memo = &common.Memo{Fields: fields} + } + var searchAttr *common.SearchAttributes + if wfStartOpts.SearchAttributes != nil { + fields, err := encodeMapToPayloads(wfStartOpts.SearchAttributes) + if err != nil { + return err + } + searchAttr = &common.SearchAttributes{IndexedFields: fields} + } + + if wfStartOpts.VersioningOverride != (client.VersioningOverride{}) { + cctx.Logger.Warn("VersioningOverride is not configured for the signal-with-start command") + } + + // We have to use the raw signal service call here because the Go SDK's + // signal-with-start call doesn't accept multiple signal arguments. + resp, err := cl.WorkflowService().SignalWithStartWorkflowExecution( + cctx, + &workflowservice.SignalWithStartWorkflowExecutionRequest{ + Namespace: c.Parent.Namespace, + RequestId: uuid.NewString(), + WorkflowId: c.WorkflowId, + WorkflowType: &common.WorkflowType{Name: c.Type}, + TaskQueue: &taskqueuepb.TaskQueue{Name: c.TaskQueue, Kind: enumspb.TASK_QUEUE_KIND_NORMAL}, + Input: wfInput, + WorkflowExecutionTimeout: durationpb.New(wfStartOpts.WorkflowExecutionTimeout), + WorkflowRunTimeout: durationpb.New(wfStartOpts.WorkflowRunTimeout), + WorkflowTaskTimeout: durationpb.New(wfStartOpts.WorkflowTaskTimeout), + SignalName: c.SignalName, + SignalInput: signalInput, + Identity: clientIdentity(), + RetryPolicy: retryPolicy, + CronSchedule: wfStartOpts.CronSchedule, + Memo: memo, + SearchAttributes: searchAttr, + WorkflowIdReusePolicy: wfStartOpts.WorkflowIDReusePolicy, + WorkflowIdConflictPolicy: wfStartOpts.WorkflowIDConflictPolicy, + }, + ) + if err != nil { + return err + } + cctx.Printer.Println(color.MagentaString("Running execution:")) + return cctx.Printer.PrintStructured(struct { + WorkflowId string `json:"workflowId"` + RunId string `json:"runId"` + Type string `json:"type"` + Namespace string `json:"namespace"` + TaskQueue string `json:"taskQueue"` + }{ + WorkflowId: c.WorkflowId, + RunId: resp.RunId, + Type: c.Type, + Namespace: c.Parent.Namespace, + TaskQueue: c.TaskQueue, + }, printer.StructuredOptions{}) +} + type workflowJSONResult struct { WorkflowId string `json:"workflowId"` RunId string `json:"runId"` diff --git a/temporalcli/commands.workflow_exec_test.go b/temporalcli/commands.workflow_exec_test.go index 88a0a6d7..e706d946 100644 --- a/temporalcli/commands.workflow_exec_test.go +++ b/temporalcli/commands.workflow_exec_test.go @@ -664,3 +664,104 @@ func (s *SharedServerSuite) TestWorkflow_Execute_NullValue() { s.ContainsOnSameLine(out, "Status", "COMPLETED") s.ContainsOnSameLine(out, "Result", `{"foo":null}`) } + +func (s *SharedServerSuite) TestWorkflow_SignalWithStart_WorkflowIDMandatory() { + res := s.Execute( + "workflow", "signal-with-start", + "--type", "wfType", + "--task-queue", "tq", + "--signal-name", "sigName", + ) + s.ErrorContains(res.Err, "--workflow-id flag must be provided") +} + +func (s *SharedServerSuite) TestWorkflow_SignalWithStart_StartsWorkflow() { + wfId := uuid.NewString() + + // Send signal-with-start command. + res := s.Execute( + "workflow", "signal-with-start", + "--address", s.Address(), + "--workflow-id", wfId, + "--type", "DevWorkflow", + "--input", `{"wf-signal-with-start": "workflow-input"}`, + "--task-queue", "tq", + "--signal-name", "sigName", + "--signal-input", `{"signal-with-start": "signal-input"}`, + ) + + s.NoError(res.Err) + + // Confirm text output has key/vals as expected + out := res.Stdout.String() + s.ContainsOnSameLine(out, "WorkflowId", wfId) + s.Contains(out, "RunId") + s.ContainsOnSameLine(out, "TaskQueue", "tq") + s.ContainsOnSameLine(out, "Type", "DevWorkflow") + s.ContainsOnSameLine(out, "Namespace", "default") + + // Check that new workflow was started with expected workflow ID. + run := s.Client.GetWorkflow(s.Context, wfId, "") + s.Equal(wfId, run.GetID()) + + // Run workflow, block on signal. + var sigReceived any + s.StartDevWorker(s.t, DevWorkerOptions{TaskQueue: "tq"}).OnDevWorkflow(func(ctx workflow.Context, wfInput any) (any, error) { + workflow.GetSignalChannel(ctx, "sigName").Receive(ctx, &sigReceived) + return wfInput, nil + }) + + // Wait for workflow to complete. + var wfReturn any + err := s.Client.GetWorkflow(s.Context, wfId, "").Get(s.Context, &wfReturn) + s.NoError(err) + + // Expect workflow to have received signal and given inputs from signal-with-start. + s.Equal(map[string]any{"signal-with-start": "signal-input"}, sigReceived) + s.Equal(map[string]any{"wf-signal-with-start": "workflow-input"}, wfReturn) +} + +func (s *SharedServerSuite) TestWorkflow_SignalWithStart_ExistingWorkflow() { + // Run workflow, block on signal. + var sigReceived any + s.Worker().OnDevWorkflow(func(ctx workflow.Context, wfInput any) (any, error) { + workflow.GetSignalChannel(ctx, "sigName").Receive(ctx, &sigReceived) + return wfInput, nil + }) + + // Start workflow + run, err := s.Client.ExecuteWorkflow(s.Context, client.StartWorkflowOptions{TaskQueue: s.Worker().Options.TaskQueue}, DevWorkflow, "not-signal-with-start-input") + s.NoError(err) + + wfId := run.GetID() + + // Send signal-with-start command. + res := s.Execute( + "workflow", "signal-with-start", + "--address", s.Address(), + "--workflow-id", wfId, + "--type", "DevWorkflow", + "--input", `{"workflow": "workflow-input"}`, + "--task-queue", s.Worker().Options.TaskQueue, + "--signal-name", "sigName", + "--signal-input", `{"signal-with-start": "signal-input"}`, + ) + s.NoError(res.Err) + + // Confirm text output has key/vals as expected + out := res.Stdout.String() + s.ContainsOnSameLine(out, "WorkflowId", wfId) + s.Contains(out, "RunId") + s.ContainsOnSameLine(out, "TaskQueue", s.Worker().Options.TaskQueue) + s.ContainsOnSameLine(out, "Type", "DevWorkflow") + s.ContainsOnSameLine(out, "Namespace", "default") + + // Wait for workflow to complete. + var ret any + s.NoError(run.Get(s.Context, &ret)) + + // Expect workflow to have not been started by the signal-with-start command. + s.Equal("not-signal-with-start-input", ret) + // Expect signal to have been received with given input. + s.Equal(map[string]any{"signal-with-start": "signal-input"}, sigReceived) +} diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 7a8878e3..19edcf4f 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -3156,6 +3156,59 @@ commands: aliases: - type + - name: temporal workflow signal-with-start + summary: Send a message to a Workflow Execution, start the execution if it isn't running + description: | + Send an asynchronous notification (Signal) to a Workflow Execution. + If the Workflow Execution is not running or is not found, it starts the + workflow then sends the signal. + + ``` + temporal workflow signal-with-start \ + --signal-name YourSignal \ + --signal-input '{"some-key": "some-value"}' \ + --workflow-id YourWorkflowId \ + --type YourWorkflowType \ + --task-queue YourTaskQueue \ + --input '{"some-key": "some-value"}' + ``` + option-sets: + # workflow-id is "required" (runtime check) + - shared-workflow-start + - workflow-start + - payload-input + options: + - name: signal-name + type: string + description: Signal name. + required: true + aliases: + - signal-type + - name: signal-input + type: string[] + description: | + Signal input value. + Use JSON content or set --signal-input-meta to override. + Can't be combined with --signal-input-file. + Can be passed multiple times to pass multiple arguments. + - name: signal-input-file + type: string[] + description: | + A path or paths for input file(s). + Use JSON content or set --signal-input-meta to override. + Can't be combined with --signal-input. + Can be passed multiple times to pass multiple arguments. + - name: signal-input-meta + type: string[] + description: | + Input signal payload metadata as a `KEY=VALUE` pair. + When the KEY is "encoding", this overrides the default ("json/plain"). + Can be passed multiple times. + - name: signal-input-base64 + type: bool + description: | + Assume signal inputs are base64-encoded and attempt to decode them. + - name: temporal workflow stack summary: Trace a Workflow Execution description: | @@ -3707,6 +3760,7 @@ option-sets: - Fail - UseExisting - TerminateExisting + - name: payload-input options: - name: input diff --git a/temporalcli/internal/cmd/gen-commands/main.go b/temporalcli/internal/cmd/gen-commands/main.go index 00df1848..817ff296 100644 --- a/temporalcli/internal/cmd/gen-commands/main.go +++ b/temporalcli/internal/cmd/gen-commands/main.go @@ -21,7 +21,7 @@ func run() error { _, file, _, _ := runtime.Caller(0) commandsDir := filepath.Join(file, "../../../../") - // Parse markdown + // Parse YAML cmds, err := commandsgen.ParseCommands() if err != nil { return fmt.Errorf("failed parsing markdown: %w", err)