diff --git a/go.mod b/go.mod index 5d392984..33ed68d1 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/temporalio/cli -go 1.23 - -toolchain go1.23.2 +go 1.23.2 require ( github.com/alitto/pond v1.9.1 @@ -11,17 +9,17 @@ require ( github.com/fatih/color v1.17.0 github.com/google/uuid v1.6.0 github.com/mattn/go-isatty v0.0.20 - github.com/nexus-rpc/sdk-go v0.0.10 + github.com/nexus-rpc/sdk-go v0.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/temporalio/ui-server/v2 v2.32.0 - go.temporal.io/api v1.38.0 - go.temporal.io/sdk v1.29.1 - go.temporal.io/server v1.25.2 - google.golang.org/grpc v1.65.0 - google.golang.org/protobuf v1.34.2 + go.temporal.io/api v1.43.0 + go.temporal.io/sdk v1.31.0 + go.temporal.io/server v1.26.2 + google.golang.org/grpc v1.67.1 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -29,7 +27,7 @@ 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.3.0 // 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 @@ -77,6 +75,7 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmoiron/sqlx v1.3.4 // 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/lib/pq v1.10.9 // indirect @@ -84,16 +83,17 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // 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 github.com/olivere/elastic/v7 v7.0.32 // indirect 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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.53.0 // indirect - github.com/prometheus/procfs v0.15.0 // indirect + github.com/prometheus/common v0.60.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 github.com/rivo/uniseg v0.4.7 // indirect @@ -102,7 +102,7 @@ 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-20240718232345-e2a435d149b6 // indirect + github.com/temporalio/ringpop-go v0.0.0-20241119001152-e505ebd8f887 // 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 @@ -111,44 +111,45 @@ require ( 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.52.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.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.49.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.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 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/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.28.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/net v0.31.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-20240822170219-fc7c04adadcd // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // 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 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.50.9 // 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.30.0 // indirect + modernc.org/sqlite v1.34.1 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 143b49e1..e915a2a4 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ 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.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +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= @@ -190,6 +190,8 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF 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/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= @@ -199,6 +201,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/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= @@ -222,10 +226,12 @@ github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRU github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 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.0.10 h1:7jEPUlsghxoD4OJ2H8YbFJ1t4wbxsUef7yZgBfyY3uA= -github.com/nexus-rpc/sdk-go v0.0.10/go.mod h1:TpfkM2Cw0Rlk9drGkoiSMpFqflKTiQLWUNyKJjF8mKQ= +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/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= @@ -244,15 +250,15 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI 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.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +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_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.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= -github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= -github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek= -github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -266,8 +272,8 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samuel/go-thrift v0.0.0-20190219015601-e8b6b52668fe/go.mod h1:Vrkh1pnjV9Bl8c3P9zH0/D4NlOHWP5d4/hF4YTULaec= github.com/sirupsen/logrus v1.0.2-0.20170726183946-abee6f9b0679/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -294,10 +300,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/temporalio/ringpop-go v0.0.0-20240718232345-e2a435d149b6 h1:LnuIZntMSwZJS0O9b9bA+3iUL+Cwwhk+838PB04XLz4= -github.com/temporalio/ringpop-go v0.0.0-20240718232345-e2a435d149b6/go.mod h1:RE+CHmY+kOZQk47AQaVzwrGmxpflnLgTd6EOK0853j4= +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/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= @@ -327,36 +333,36 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 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.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= +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.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 h1:bFgvUr3/O4PHj3VQcFEuYKvRZJX1SJDQ+11JXuSB3/w= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/exporters/prometheus v0.49.0 h1:Er5I1g/YhfYv9Affk9nJLfH/+qCCVVg1f2R9AbJfqDQ= -go.opentelemetry.io/otel/exporters/prometheus v0.49.0/go.mod h1:KfQ1wpjf3zsHjzP149P4LyAwWRupc6c7t1ZJ9eXpKQM= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= -go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= -go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= -go.temporal.io/api v1.38.0 h1:L5i+Ai7UoBa2Gq/goVHLY32064AgawxPDLkKm4I7fu4= -go.temporal.io/api v1.38.0/go.mod h1:fmh06EjstyrPp6SHbjJo7yYHBfHamPE4SytM+2NRejc= -go.temporal.io/sdk v1.29.1 h1:y+sUMbUhTU9rj50mwIZAPmcXCtgUdOWS9xHDYRYSgZ0= -go.temporal.io/sdk v1.29.1/go.mod h1:kp//DRvn3CqQVBCtjL51Oicp9wrZYB2s6row1UgzcKQ= -go.temporal.io/server v1.25.2 h1:AVlFfNStYVvgyIG/QlfPsp1RgiP+IBuMnEX/kIYAHJ4= -go.temporal.io/server v1.25.2/go.mod h1:3BzDvfiMwi9ETiv4UoE1LWhuIctR6Ep+G1RVomH9YZE= +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.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/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= go.temporal.io/version v0.3.0/go.mod h1:UA9S8/1LaKYae6TyD9NaPMJTZb911JcbqghI2CBSP78= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -370,6 +376,8 @@ go.uber.org/fx v1.22.0/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= 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/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= @@ -428,11 +436,11 @@ 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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.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= @@ -525,18 +533,18 @@ google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfG 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-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= -google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +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/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.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +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= @@ -546,8 +554,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +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= 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= @@ -571,18 +579,18 @@ 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.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= -modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs= -modernc.org/ccgo/v4 v4.17.8/go.mod h1:buJnJ6Fn0tyAdP/dqePbrrvLyr6qslFfTbFrCuaYvtA= +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/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.50.9 h1:hIWf1uz55lorXQhfoEoezdUHjxzuO6ceshET/yWjSjk= -modernc.org/libc v1.50.9/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE= +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= @@ -591,8 +599,8 @@ 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.30.0 h1:8YhPUs/HTnlEgErn/jSYQTwHN/ex8CjHHjg+K9iG7LM= -modernc.org/sqlite v1.30.0/go.mod h1:cgkTARJ9ugeXSNaLBPK3CqbOe7Ec7ZhWPoMFGldEYEw= +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/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/temporalcli/commands.activity.go b/temporalcli/commands.activity.go index 6750d0b8..c0953f88 100644 --- a/temporalcli/commands.activity.go +++ b/temporalcli/commands.activity.go @@ -2,10 +2,33 @@ package temporalcli import ( "fmt" + "time" + "github.com/google/uuid" + "github.com/temporalio/cli/temporalcli/internal/printer" + activitypb "go.temporal.io/api/activity/v1" "go.temporal.io/api/common/v1" "go.temporal.io/api/failure/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" "go.temporal.io/api/workflowservice/v1" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +type ( + updateOptionsDescribe struct { + TaskQueue string + + ScheduleToCloseTimeout time.Duration + ScheduleToStartTimeout time.Duration + StartToCloseTimeout time.Duration + HeartbeatTimeout time.Duration + + InitialInterval time.Duration + BackoffCoefficient float64 + MaximumInterval time.Duration + MaximumAttempts int32 + } ) func (c *TemporalActivityCompleteCommand) run(cctx *CommandContext, args []string) error { @@ -70,3 +93,200 @@ func (c *TemporalActivityFailCommand) run(cctx *CommandContext, args []string) e } return nil } + +func (c *TemporalActivityUpdateOptionsCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + updatePath := []string{} + activityOptions := &activitypb.ActivityOptions{} + + if c.Command.Flags().Changed("task-queue") { + activityOptions.TaskQueue = &taskqueuepb.TaskQueue{Name: c.TaskQueue} + updatePath = append(updatePath, "task_queue_name") + } + + if c.Command.Flags().Changed("schedule-to-close-timeout") { + activityOptions.ScheduleToCloseTimeout = durationpb.New(c.ScheduleToCloseTimeout.Duration()) + updatePath = append(updatePath, "schedule_to_close_timeout") + } + + if c.Command.Flags().Changed("schedule-to-start-timeout") { + activityOptions.ScheduleToStartTimeout = durationpb.New(c.ScheduleToStartTimeout.Duration()) + updatePath = append(updatePath, "schedule_to_start_timeout") + } + + if c.Command.Flags().Changed("start-to-close-timeout") { + activityOptions.StartToCloseTimeout = durationpb.New(c.StartToCloseTimeout.Duration()) + updatePath = append(updatePath, "start_to_close_timeout") + } + + if c.Command.Flags().Changed("heartbeat-timeout") { + activityOptions.HeartbeatTimeout = durationpb.New(c.HeartbeatTimeout.Duration()) + updatePath = append(updatePath, "heartbeat_timeout") + } + + if c.Command.Flags().Changed("retry-initial-interval") || + c.Command.Flags().Changed("retry-maximum-interval") || + c.Command.Flags().Changed("retry-backoff-coefficient") || + c.Command.Flags().Changed("retry-maximum-attempts") { + activityOptions.RetryPolicy = &common.RetryPolicy{} + } + + if c.Command.Flags().Changed("retry-initial-interval") { + activityOptions.RetryPolicy.InitialInterval = durationpb.New(c.RetryInitialInterval.Duration()) + updatePath = append(updatePath, "retry_policy.initial_interval") + } + + if c.Command.Flags().Changed("retry-maximum-interval") { + activityOptions.RetryPolicy.MaximumInterval = durationpb.New(c.RetryMaximumInterval.Duration()) + updatePath = append(updatePath, "retry_policy.maximum_interval") + } + + if c.Command.Flags().Changed("retry-backoff-coefficient") { + activityOptions.RetryPolicy.BackoffCoefficient = float64(c.RetryBackoffCoefficient) + updatePath = append(updatePath, "retry_policy.backoff_coefficient") + } + + if c.Command.Flags().Changed("retry-maximum-attempts") { + activityOptions.RetryPolicy.MaximumAttempts = int32(c.RetryMaximumAttempts) + updatePath = append(updatePath, "retry_policy.maximum_attempts") + } + + result, err := cl.WorkflowService().UpdateActivityOptionsById(cctx, &workflowservice.UpdateActivityOptionsByIdRequest{ + Namespace: c.Parent.Namespace, + WorkflowId: c.WorkflowId, + RunId: c.RunId, + ActivityId: c.ActivityId, + ActivityOptions: activityOptions, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: updatePath, + }, + + Identity: c.Identity, + RequestId: uuid.NewString(), + }) + if err != nil { + return fmt.Errorf("unable to update Activity options: %w", err) + } + + updatedOptions := updateOptionsDescribe{ + TaskQueue: result.GetActivityOptions().TaskQueue.GetName(), + + ScheduleToCloseTimeout: result.GetActivityOptions().ScheduleToCloseTimeout.AsDuration(), + ScheduleToStartTimeout: result.GetActivityOptions().ScheduleToStartTimeout.AsDuration(), + StartToCloseTimeout: result.GetActivityOptions().StartToCloseTimeout.AsDuration(), + HeartbeatTimeout: result.GetActivityOptions().HeartbeatTimeout.AsDuration(), + + InitialInterval: result.GetActivityOptions().RetryPolicy.InitialInterval.AsDuration(), + BackoffCoefficient: result.GetActivityOptions().RetryPolicy.BackoffCoefficient, + MaximumInterval: result.GetActivityOptions().RetryPolicy.MaximumInterval.AsDuration(), + MaximumAttempts: result.GetActivityOptions().RetryPolicy.MaximumAttempts, + } + + _ = cctx.Printer.PrintStructured(updatedOptions, printer.StructuredOptions{}) + + return nil +} + +func (c *TemporalActivityPauseCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + _, err = cl.WorkflowService().PauseActivityById(cctx, &workflowservice.PauseActivityByIdRequest{ + Namespace: c.Parent.Namespace, + WorkflowId: c.WorkflowId, + RunId: c.RunId, + ActivityId: c.ActivityId, + Identity: c.Identity, + RequestId: uuid.NewString(), + }) + if err != nil { + return fmt.Errorf("unable to update Activity options: %w", err) + } + + return nil +} + +func (c *TemporalActivityUnpauseCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + request := &workflowservice.UnpauseActivityByIdRequest{ + Namespace: c.Parent.Namespace, + WorkflowId: c.WorkflowId, + RunId: c.RunId, + ActivityId: c.ActivityId, + Identity: c.Identity, + } + if c.Reset { + request.Operation = &workflowservice.UnpauseActivityByIdRequest_Reset_{ + Reset_: &workflowservice.UnpauseActivityByIdRequest_ResetOperation{ + NoWait: c.NoWait, + ResetHeartbeat: c.ResetHeartbeats, + }, + } + } else { + if c.ResetHeartbeats { + return fmt.Errorf("reset-heartbeats flag can only be used with reset flag") + } + request.Operation = &workflowservice.UnpauseActivityByIdRequest_Resume{ + Resume: &workflowservice.UnpauseActivityByIdRequest_ResumeOperation{ + NoWait: c.NoWait, + }, + } + } + + _, err = cl.WorkflowService().UnpauseActivityById(cctx, request) + if err != nil { + return fmt.Errorf("unable to uppause an Activity: %w", err) + } + + return nil +} + +func (c *TemporalActivityResetCommand) run(cctx *CommandContext, args []string) error { + cl, err := c.Parent.ClientOptions.dialClient(cctx) + if err != nil { + return err + } + defer cl.Close() + + request := &workflowservice.ResetActivityByIdRequest{ + Namespace: c.Parent.Namespace, + WorkflowId: c.WorkflowId, + RunId: c.RunId, + ActivityId: c.ActivityId, + Identity: c.Identity, + NoWait: c.NoWait, + ResetHeartbeat: c.ResetHeartbeats, + } + + resp, err := cl.WorkflowService().ResetActivityById(cctx, request) + if err != nil { + return fmt.Errorf("unable to reset an Activity: %w", err) + } + + resetResponse := struct { + NoWait bool `json:"noWait"` + ResetHeartbeats bool `json:"resetHeartbeats"` + ServerResponse bool `json:"-"` + }{ + ServerResponse: resp != nil, + NoWait: c.NoWait, + ResetHeartbeats: c.ResetHeartbeats, + } + + _ = cctx.Printer.PrintStructured(resetResponse, printer.StructuredOptions{}) + + return nil +} diff --git a/temporalcli/commands.activity_test.go b/temporalcli/commands.activity_test.go index c5c11da6..fc2f3e4e 100644 --- a/temporalcli/commands.activity_test.go +++ b/temporalcli/commands.activity_test.go @@ -6,6 +6,7 @@ import ( "go.temporal.io/api/enums/v1" "go.temporal.io/api/history/v1" + "go.temporal.io/api/serviceerror" "go.temporal.io/sdk/client" ) @@ -106,6 +107,168 @@ func (s *SharedServerSuite) TestActivity_Fail_InvalidDetail() { s.Nil(failed) } +func (s *SharedServerSuite) TestActivityOptionsUpdate_Accept() { + run := s.waitActivityStarted() + wid := run.GetID() + aid := "dev-activity-id" + identity := "MyIdentity" + + res := s.Execute( + "activity", "update-options", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--task-queue", "new-task-queue", + "--schedule-to-close-timeout", "60s", + "--schedule-to-start-timeout", "5s", + "--start-to-close-timeout", "10s", + "--heartbeat-timeout", "20s", + "--retry-initial-interval", "5s", + "--retry-maximum-interval", "60s", + "--retry-backoff-coefficient", "2", + "--retry-maximum-attempts", "5", + "--address", s.Address(), + ) + + s.NoError(res.Err) + out := res.Stdout.String() + s.ContainsOnSameLine(out, "ScheduleToCloseTimeout", "1m0s") + s.ContainsOnSameLine(out, "ScheduleToStartTimeout", "5s") + s.ContainsOnSameLine(out, "StartToCloseTimeout", "10s") + s.ContainsOnSameLine(out, "HeartbeatTimeout", "10s") + s.ContainsOnSameLine(out, "InitialInterval", "5s") + s.ContainsOnSameLine(out, "MaximumInterval", "1m0s") + s.ContainsOnSameLine(out, "BackoffCoefficient", "2") + s.ContainsOnSameLine(out, "MaximumAttempts", "5") +} + +func (s *SharedServerSuite) TestActivityOptionsUpdate_Partial() { + run := s.waitActivityStarted() + wid := run.GetID() + aid := "dev-activity-id" + identity := "MyIdentity" + + res := s.Execute( + "activity", "update-options", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--task-queue", "new-task-queue", + "--schedule-to-close-timeout", "41s", + "--schedule-to-start-timeout", "11s", + "--retry-initial-interval", "4s", + "--retry-maximum-attempts", "10", + "--address", s.Address(), + ) + + s.NoError(res.Err) + out := res.Stdout.String() + + // updated + s.ContainsOnSameLine(out, "ScheduleToCloseTimeout", "41s") + s.ContainsOnSameLine(out, "ScheduleToStartTimeout", "11s") + s.ContainsOnSameLine(out, "StartToCloseTimeout", "10s") + s.ContainsOnSameLine(out, "InitialInterval", "4s") + s.ContainsOnSameLine(out, "MaximumAttempts", "10") + + // old value + // note - this is a snapshot of current values + // if this test fails, check the default values of activity options + s.ContainsOnSameLine(out, "StartToCloseTimeout", "10s") + s.ContainsOnSameLine(out, "HeartbeatTimeout", "0s") + s.ContainsOnSameLine(out, "MaximumInterval", "1m40s") + s.ContainsOnSameLine(out, "BackoffCoefficient", "2") +} + +func (s *SharedServerSuite) TestActivityPauseUnpause() { + run := s.waitActivityStarted() + wid := run.GetID() + aid := "dev-activity-id" + identity := "MyIdentity" + + res := s.Execute( + "activity", "pause", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--address", s.Address(), + ) + + s.NoError(res.Err) + + res = s.Execute( + "activity", "unpause", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--address", s.Address(), + "--reset", + ) + + s.NoError(res.Err) +} + +func (s *SharedServerSuite) TestActivityUnPause_Failed() { + run := s.waitActivityStarted() + wid := run.GetID() + aid := "dev-activity-id" + identity := "MyIdentity" + + // should fail because --reset-heartbeat is provided, but --reset flag is missing + res := s.Execute( + "activity", "unpause", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--address", s.Address(), + "--reset-heartbeats", + ) + + s.Error(res.Err) +} + +func (s *SharedServerSuite) TestActivityReset() { + run := s.waitActivityStarted() + wid := run.GetID() + aid := "dev-activity-id" + identity := "MyIdentity" + + res := s.Execute( + "activity", "reset", + "--activity-id", aid, + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--address", s.Address(), + ) + + s.NoError(res.Err) + // make sure we receive a server response + out := res.Stdout.String() + s.ContainsOnSameLine(out, "ServerResponse", "true") + + // reset should fail because activity is not found + + res = s.Execute( + "activity", "reset", + "--activity-id", "fake_id", + "--workflow-id", wid, + "--run-id", run.GetRunID(), + "--identity", identity, + "--address", s.Address(), + ) + + s.Error(res.Err) + // make sure we receive a NotFound error from the server` + var notFound *serviceerror.NotFound + s.ErrorAs(res.Err, ¬Found) +} + // Test helpers func (s *SharedServerSuite) waitActivityStarted() client.WorkflowRun { diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index 05c3722a..3ddc1c1e 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -327,15 +327,19 @@ func NewTemporalActivityCommand(cctx *CommandContext, parent *TemporalCommand) * var s TemporalActivityCommand s.Parent = parent s.Command.Use = "activity" - s.Command.Short = "Complete or fail an Activity" + s.Command.Short = "Complete, update, pause, unpause, reset or fail an Activity" if hasHighlighting { - s.Command.Long = "Update an Activity's state to completed or failed. This marks an Activity\nas successfully finished or as having 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 state to completed or failed. This marks an Activity\nas successfully finished or as having 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) s.Command.AddCommand(&NewTemporalActivityFailCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalActivityPauseCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalActivityResetCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalActivityUnpauseCommand(cctx, &s).Command) + s.Command.AddCommand(&NewTemporalActivityUpdateOptionsCommand(cctx, &s).Command) s.ClientOptions.buildFlags(cctx, s.Command.PersistentFlags()) return &s } @@ -411,6 +415,168 @@ func NewTemporalActivityFailCommand(cctx *CommandContext, parent *TemporalActivi return &s } +type TemporalActivityPauseCommand struct { + Parent *TemporalActivityCommand + Command cobra.Command + WorkflowReferenceOptions + ActivityId string + Identity string +} + +func NewTemporalActivityPauseCommand(cctx *CommandContext, parent *TemporalActivityCommand) *TemporalActivityPauseCommand { + var s TemporalActivityPauseCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "pause [flags]" + s.Command.Short = "Pause an Activity" + if hasHighlighting { + s.Command.Long = "Pause an Activity.\n\nIf the Activity is not currently running (e.g. because it previously\nfailed), it will not be run again until it is unpaused.\n\nHowever, if the Activity is currently running, it will run to completion.\nIf the Activity is on its last retry attempt and fails, the failure will\nbe returned to the caller, just as if the Activity had not been paused.\n\nSpecify the Activity and Workflow IDs:\n\n\x1b[1mtemporal activity pause \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\x1b[0m" + } else { + s.Command.Long = "Pause an Activity.\n\nIf the Activity is not currently running (e.g. because it previously\nfailed), it will not be run again until it is unpaused.\n\nHowever, if the Activity is currently running, it will run to completion.\nIf the Activity is on its last retry attempt and fails, the failure will\nbe returned to the caller, just as if the Activity had not been paused.\n\nSpecify the Activity and Workflow IDs:\n\n```\ntemporal activity pause \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\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.WorkflowReferenceOptions.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 TemporalActivityResetCommand struct { + Parent *TemporalActivityCommand + Command cobra.Command + WorkflowReferenceOptions + ActivityId string + Identity string + NoWait bool + ResetHeartbeats bool +} + +func NewTemporalActivityResetCommand(cctx *CommandContext, parent *TemporalActivityCommand) *TemporalActivityResetCommand { + var s TemporalActivityResetCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + 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" + } 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.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.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) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + +type TemporalActivityUnpauseCommand struct { + Parent *TemporalActivityCommand + Command cobra.Command + WorkflowReferenceOptions + ActivityId string + Identity string + Reset bool + NoWait bool + ResetHeartbeats bool +} + +func NewTemporalActivityUnpauseCommand(cctx *CommandContext, parent *TemporalActivityCommand) *TemporalActivityUnpauseCommand { + var s TemporalActivityUnpauseCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "unpause [flags]" + s.Command.Short = "Unpause an Activity" + if hasHighlighting { + s.Command.Long = "Re-schedule a previously-paused Activity for execution.\n\nIf the Activity is not running and is past its retry timeout, it will be\nscheduled immediately. Otherwise, it will be scheduled after its retry\ntimeout expires. The Activity can be retried immediately with \x1b[1m--no-wait\x1b[0m.\n\nUse \x1b[1m--reset\x1b[0m to reset the number of previous run attempts to zero. For\nexample, if an Activity is near the maximum number of attempts N specified\nin its retry policy, \x1b[1m--reset\x1b[0m will allow the Activity to be retried\nanother N times after unpausing.\n\nSpecify the Activity and Workflow IDs:\n\n\x1b[1mtemporal activity unpause \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --reset\n --no-wait\n --reset-heartbeats\x1b[0m" + } else { + s.Command.Long = "Re-schedule a previously-paused Activity for execution.\n\nIf the Activity is not running and is past its retry timeout, it will be\nscheduled immediately. Otherwise, it will be scheduled after its retry\ntimeout expires. The Activity can be retried immediately with `--no-wait`.\n\nUse `--reset` to reset the number of previous run attempts to zero. For\nexample, if an Activity is near the maximum number of attempts N specified\nin its retry policy, `--reset` will allow the Activity to be retried\nanother N times after unpausing.\n\nSpecify the Activity and Workflow IDs:\n\n```\ntemporal activity unpause \\\n --activity-id YourActivityId \\\n --workflow-id YourWorkflowId\n --reset\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.Reset, "reset", false, "Also reset the activity.") + s.Command.Flags().BoolVar(&s.NoWait, "no-wait", false, "Schedule the Activity immediately, even if its retry timeout has not expired.") + s.Command.Flags().BoolVar(&s.ResetHeartbeats, "reset-heartbeats", false, "Reset the Activity's heartbeat timeout. Only works with --reset.") + s.WorkflowReferenceOptions.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 TemporalActivityUpdateOptionsCommand struct { + Parent *TemporalActivityCommand + Command cobra.Command + WorkflowReferenceOptions + ActivityId string + TaskQueue string + ScheduleToCloseTimeout Duration + ScheduleToStartTimeout Duration + StartToCloseTimeout Duration + HeartbeatTimeout Duration + RetryInitialInterval Duration + RetryMaximumInterval Duration + RetryBackoffCoefficient float32 + RetryMaximumAttempts int + Identity string +} + +func NewTemporalActivityUpdateOptionsCommand(cctx *CommandContext, parent *TemporalActivityCommand) *TemporalActivityUpdateOptionsCommand { + var s TemporalActivityUpdateOptionsCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + 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" + } 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.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.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.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.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().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().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) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + type TemporalBatchCommand struct { Parent *TemporalCommand Command cobra.Command @@ -1702,7 +1868,7 @@ func NewTemporalServerStartDevCommand(cctx *CommandContext, parent *TemporalServ s.Command.Flags().StringVarP(&s.DbFilename, "db-filename", "f", "", "Path to file for persistent Temporal state store. By default, Workflow Executions are lost when the server process dies.") s.Command.Flags().StringArrayVarP(&s.Namespace, "namespace", "n", nil, "Namespaces to be created at launch. The \"default\" Namespace is always created automatically.") s.Command.Flags().IntVarP(&s.Port, "port", "p", 7233, "Port for the front-end gRPC Service.") - s.Command.Flags().IntVar(&s.HttpPort, "http-port", 0, "Port for the HTTP API service. Default is off.") + s.Command.Flags().IntVar(&s.HttpPort, "http-port", 0, "Port for the HTTP API service. Defaults to a random free port.") s.Command.Flags().IntVar(&s.MetricsPort, "metrics-port", 0, "Port for '/metrics'. Default is off.") s.Command.Flags().IntVar(&s.UiPort, "ui-port", 0, "Port for the Web UI. Default is '--port' value + 1000.") s.Command.Flags().BoolVar(&s.Headless, "headless", false, "Disable the Web UI.") diff --git a/temporalcli/commands.server.go b/temporalcli/commands.server.go index 3356518d..3edaef80 100644 --- a/temporalcli/commands.server.go +++ b/temporalcli/commands.server.go @@ -8,9 +8,6 @@ import ( "github.com/google/uuid" "github.com/temporalio/cli/temporalcli/devserver" "go.temporal.io/api/enums/v1" - "go.temporal.io/api/operatorservice/v1" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" ) var defaultDynamicConfigValues = map[string]any{ @@ -62,8 +59,11 @@ func (t *TemporalServerStartDevCommand) run(cctx *CommandContext, args []string) if err := devserver.CheckPortFree(opts.FrontendIP, opts.FrontendPort); err != nil { return fmt.Errorf("can't set frontend port %d: %w", opts.FrontendPort, err) } - if err := devserver.CheckPortFree(opts.FrontendIP, opts.FrontendHTTPPort); err != nil { - return fmt.Errorf("can't set frontend HTTP port %d: %w", opts.FrontendHTTPPort, err) + + if opts.FrontendHTTPPort > 0 { + if err := devserver.CheckPortFree(opts.FrontendIP, opts.FrontendHTTPPort); err != nil { + return fmt.Errorf("can't set frontend HTTP port %d: %w", opts.FrontendHTTPPort, err) + } } // Setup UI if !t.Headless { @@ -124,6 +124,7 @@ func (t *TemporalServerStartDevCommand) run(cctx *CommandContext, args []string) if err != nil { return err } + opts.SearchAttributes = searchAttrs // If not using DB file, set persistent cluster ID if t.DbFilename == "" { @@ -152,13 +153,12 @@ func (t *TemporalServerStartDevCommand) run(cctx *CommandContext, args []string) } defer s.Stop() - // Register search attributes - if err := t.registerSearchAttributes(cctx, searchAttrs, opts.Namespaces); err != nil { - return err - } - cctx.Printer.Printlnf("CLI %v\n", VersionString()) cctx.Printer.Printlnf("%-8s %v:%v", "Server:", toFriendlyIp(opts.FrontendIP), opts.FrontendPort) + // Only print HTTP port if explicitly provided to avoid promoting the unstable HTTP API. + if opts.FrontendHTTPPort > 0 { + cctx.Printer.Printlnf("%-8s %v:%v", "HTTP:", toFriendlyIp(opts.FrontendIP), opts.FrontendHTTPPort) + } if !t.Headless { cctx.Printer.Printlnf("%-8s http://%v:%v%v", "UI:", toFriendlyIp(opts.UIIP), opts.UIPort, opts.PublicPath) } @@ -217,34 +217,3 @@ func (t *TemporalServerStartDevCommand) prepareSearchAttributes() (map[string]en } return attrs, nil } - -func (t *TemporalServerStartDevCommand) registerSearchAttributes( - cctx *CommandContext, - attrs map[string]enums.IndexedValueType, - namespaces []string, -) error { - if len(attrs) == 0 { - return nil - } - - conn, err := grpc.NewClient( - fmt.Sprintf("%v:%v", t.Ip, t.Port), - grpc.WithTransportCredentials(insecure.NewCredentials()), - ) - if err != nil { - return fmt.Errorf("failed creating client to register search attributes: %w", err) - } - defer conn.Close() - client := operatorservice.NewOperatorServiceClient(conn) - // Call for each namespace - for _, ns := range namespaces { - _, err := client.AddSearchAttributes(cctx, &operatorservice.AddSearchAttributesRequest{ - Namespace: ns, - SearchAttributes: attrs, - }) - if err != nil { - return fmt.Errorf("failed registering search attributes: %w", err) - } - } - return nil -} diff --git a/temporalcli/commands.server_test.go b/temporalcli/commands.server_test.go index 40ca8962..e1b4586d 100644 --- a/temporalcli/commands.server_test.go +++ b/temporalcli/commands.server_test.go @@ -25,26 +25,29 @@ import ( func TestServer_StartDev_Simple(t *testing.T) { port := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) startDevServerAndRunSimpleTest( t, // TODO(cretz): Remove --headless when // https://github.com/temporalio/ui/issues/1773 fixed - []string{"server", "start-dev", "-p", port, "--headless"}, + []string{"server", "start-dev", "-p", port, "--http-port", httpPort, "--headless"}, "127.0.0.1:"+port, ) } func TestServer_StartDev_IPv4Unspecified(t *testing.T) { port := strconv.Itoa(devserver.MustGetFreePort("0.0.0.0")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) startDevServerAndRunSimpleTest( t, - []string{"server", "start-dev", "--ip", "0.0.0.0", "-p", port, "--headless"}, + []string{"server", "start-dev", "--ip", "0.0.0.0", "-p", port, "--http-port", httpPort, "--headless"}, "0.0.0.0:"+port, ) } func TestServer_StartDev_SQLitePragma(t *testing.T) { port := strconv.Itoa(devserver.MustGetFreePort("0.0.0.0")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) dbFilename := filepath.Join(os.TempDir(), "devserver-sqlite-pragma.sqlite") defer func() { _ = os.Remove(dbFilename) @@ -55,7 +58,9 @@ func TestServer_StartDev_SQLitePragma(t *testing.T) { t, []string{ "server", "start-dev", - "-p", port, "--headless", + "-p", port, + "--http-port", httpPort, + "--headless", "--db-filename", dbFilename, "--sqlite-pragma", "journal_mode=WAL", "--sqlite-pragma", "synchronous=NORMAL", @@ -76,12 +81,14 @@ func TestServer_StartDev_IPv6Unspecified(t *testing.T) { } port := strconv.Itoa(devserver.MustGetFreePort("::")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("::")) startDevServerAndRunSimpleTest( t, []string{ "server", "start-dev", "--ip", "::", "--ui-ip", "::1", "-p", port, + "--http-port", httpPort, "--ui-port", strconv.Itoa(devserver.MustGetFreePort("::")), "--http-port", strconv.Itoa(devserver.MustGetFreePort("::")), "--metrics-port", strconv.Itoa(devserver.MustGetFreePort("::"))}, @@ -138,9 +145,10 @@ func TestServer_StartDev_ConcurrentStarts(t *testing.T) { // Start in background, then wait for client to be able to connect port := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) resCh := make(chan *CommandResult, 1) go func() { - resCh <- h.Execute("server", "start-dev", "-p", port, "--headless", "--log-level", "never") + resCh <- h.Execute("server", "start-dev", "-p", port, "--http-port", httpPort, "--headless", "--log-level", "never") }() // Try to connect for a bit while checking for error @@ -191,11 +199,13 @@ func TestServer_StartDev_WithSearchAttributes(t *testing.T) { // Start in background, then wait for client to be able to connect port := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) + httpPort := strconv.Itoa(devserver.MustGetFreePort("127.0.0.1")) resCh := make(chan *CommandResult, 1) go func() { resCh <- h.Execute( "server", "start-dev", "-p", port, + "--http-port", httpPort, "--headless", "--search-attribute", "search-attr-1=Int", "--search-attribute", "search-attr-2=kEyWoRdLiSt", diff --git a/temporalcli/commands.workflow_view.go b/temporalcli/commands.workflow_view.go index ca7ea19d..15677b40 100644 --- a/temporalcli/commands.workflow_view.go +++ b/temporalcli/commands.workflow_view.go @@ -147,6 +147,7 @@ func (c *TemporalWorkflowDescribeCommand) run(cctx *CommandContext, args []strin NextAttemptScheduleTime time.Time `cli:",cardOmitEmpty"` LastAttemptCompleteTime time.Time `cli:",cardOmitEmpty"` LastAttemptFailure *failure.Failure `cli:",cardOmitEmpty"` + BlockedReason string `cli:",cardOmitEmpty"` }, len(resp.Callbacks)) for i, cb := range resp.Callbacks { cbs[i].URL = cb.GetCallback().GetNexus().GetUrl() @@ -160,6 +161,7 @@ func (c *TemporalWorkflowDescribeCommand) run(cctx *CommandContext, args []strin if cb.GetTrigger().GetWorkflowClosed() != nil { cbs[i].Trigger = "WorkflowClosed" } + cbs[i].BlockedReason = cb.GetBlockedReason() } _ = cctx.Printer.PrintStructured(cbs, printer.StructuredOptions{}) cctx.Printer.Println() @@ -222,12 +224,14 @@ func (c *TemporalWorkflowDescribeCommand) run(cctx *CommandContext, args []strin NextAttemptScheduleTime time.Time `cli:",cardOmitEmpty"` LastAttemptCompleteTime time.Time `cli:",cardOmitEmpty"` LastAttemptFailure *failure.Failure `cli:",cardOmitEmpty"` + BlockedReason string `cli:",cardOmitEmpty"` CancelationState enums.NexusOperationCancellationState `cli:",cardOmitEmpty"` CancelationAttempt int32 `cli:",cardOmitEmpty"` CancelationRequestedTime time.Time `cli:",cardOmitEmpty"` CancelationNextAttemptScheduleTime time.Time `cli:",cardOmitEmpty"` CancelationLastAttemptCompleteTime time.Time `cli:",cardOmitEmpty"` CancelationLastAttemptFailure *failure.Failure `cli:",cardOmitEmpty"` + CancelationBlockedReason string `cli:",cardOmitEmpty"` }, len(resp.PendingNexusOperations)) for i, op := range resp.PendingNexusOperations { ops[i].Endpoint = op.GetEndpoint() @@ -240,12 +244,14 @@ func (c *TemporalWorkflowDescribeCommand) run(cctx *CommandContext, args []strin ops[i].LastAttemptCompleteTime = timestampToTime(op.LastAttemptCompleteTime) ops[i].NextAttemptScheduleTime = timestampToTime(op.NextAttemptScheduleTime) ops[i].ScheduleToCloseTimeout = formatDuration(op.GetScheduleToCloseTimeout().AsDuration()) + ops[i].BlockedReason = op.GetBlockedReason() ops[i].CancelationState = op.GetCancellationInfo().GetState() ops[i].CancelationAttempt = op.GetCancellationInfo().GetAttempt() ops[i].CancelationLastAttemptFailure = op.GetCancellationInfo().GetLastAttemptFailure() ops[i].CancelationLastAttemptCompleteTime = timestampToTime(op.GetCancellationInfo().GetLastAttemptCompleteTime()) ops[i].CancelationNextAttemptScheduleTime = timestampToTime(op.GetCancellationInfo().GetNextAttemptScheduleTime()) ops[i].CancelationRequestedTime = timestampToTime(op.GetCancellationInfo().GetRequestedTime()) + ops[i].CancelationBlockedReason = op.GetCancellationInfo().GetBlockedReason() } _ = cctx.Printer.PrintStructured(ops, printer.StructuredOptions{}) cctx.Printer.Println() diff --git a/temporalcli/commands.workflow_view_test.go b/temporalcli/commands.workflow_view_test.go index e0c99e90..f1c6a60c 100644 --- a/temporalcli/commands.workflow_view_test.go +++ b/temporalcli/commands.workflow_view_test.go @@ -676,6 +676,99 @@ func (s *SharedServerSuite) TestWorkflow_Describe_NexusOperationAndCallback() { s.Equal(enums.CALLBACK_STATE_SUCCEEDED, handlerDesc.Callbacks[0].State) } +func (s *SharedServerSuite) TestWorkflow_Describe_NexusOperationBlocked() { + endpointName := validEndpointName(s.T()) + + // Call an unreachable operation from this workflow. + callerWorkflow := func(ctx workflow.Context) error { + client := workflow.NewNexusClient(endpointName, "test-service") + fut := client.ExecuteOperation(ctx, "test-op", nil, workflow.NexusOperationOptions{}) + // Destination is unreachable, the future will never complete. + return fut.GetNexusOperationExecution().Get(ctx, nil) + } + + w := s.DevServer.StartDevWorker(s.Suite.T(), DevWorkerOptions{ + Workflows: []any{callerWorkflow}, + }) + defer w.Stop() + + // Create an endpoint for this test. + _, err := s.Client.OperatorService().CreateNexusEndpoint( + s.Context, + &operatorservice.CreateNexusEndpointRequest{ + Spec: &nexuspb.EndpointSpec{ + Name: endpointName, + Target: &nexuspb.EndpointTarget{ + Variant: &nexuspb.EndpointTarget_External_{ + External: &nexuspb.EndpointTarget_External{ + Url: "http://localhost:12345", // unreachable destination + }, + }, + }, + }, + }, + ) + s.NoError(err) + + // Start the workflow and wait until the operation is started. + run, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{TaskQueue: w.Options.TaskQueue}, + callerWorkflow, + ) + s.NoError(err) + + // Start another workflow so it will trigger the circuit breaker faster. + dummyRun, err := s.Client.ExecuteWorkflow( + s.Context, + client.StartWorkflowOptions{TaskQueue: w.Options.TaskQueue}, + callerWorkflow, + ) + s.NoError(err) + + // Wait for the operation to be blocked + s.Eventually(func() bool { + resp, err := s.Client.DescribeWorkflowExecution(s.Context, run.GetID(), run.GetRunID()) + s.NoError(err) + return len(resp.PendingNexusOperations) > 0 && + resp.PendingNexusOperations[0].State == enums.PENDING_NEXUS_OPERATION_STATE_BLOCKED + }, 30*time.Second, 100*time.Millisecond) + + // Operations - Text + res := s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + ) + s.NoError(res.Err) + out := res.Stdout.String() + s.ContainsOnSameLine(out, "WorkflowId", run.GetID()) + s.Contains(out, "Pending Nexus Operations: 1") + s.ContainsOnSameLine(out, "Endpoint", endpointName) + s.ContainsOnSameLine(out, "Service", "test-service") + s.ContainsOnSameLine(out, "Operation", "test-op") + s.ContainsOnSameLine(out, "BlockedReason", "The circuit breaker is open.") + + // Operations - JSON + res = s.Execute( + "workflow", "describe", + "--address", s.Address(), + "-w", run.GetID(), + "--output", "json", + ) + s.NoError(res.Err) + var callerDesc workflowservice.DescribeWorkflowExecutionResponse + s.NoError(temporalcli.UnmarshalProtoJSONWithOptions(res.Stdout.Bytes(), &callerDesc, true)) + s.Equal(endpointName, callerDesc.PendingNexusOperations[0].Endpoint) + s.Equal("test-service", callerDesc.PendingNexusOperations[0].Service) + s.Equal("test-op", callerDesc.PendingNexusOperations[0].Operation) + s.Equal(enums.PENDING_NEXUS_OPERATION_STATE_BLOCKED, callerDesc.PendingNexusOperations[0].State) + s.Equal("The circuit breaker is open.", callerDesc.PendingNexusOperations[0].BlockedReason) + + s.NoError(s.Client.TerminateWorkflow(s.Context, run.GetID(), run.GetRunID(), "")) + s.NoError(s.Client.TerminateWorkflow(s.Context, dummyRun.GetID(), dummyRun.GetRunID(), "")) +} + func (s *SharedServerSuite) Test_WorkflowResult() { s.Worker().OnDevWorkflow(func(ctx workflow.Context, a any) (any, error) { sigs := 0 diff --git a/temporalcli/commands_test.go b/temporalcli/commands_test.go index cd15eb94..5c120d60 100644 --- a/temporalcli/commands_test.go +++ b/temporalcli/commands_test.go @@ -216,8 +216,10 @@ func (s *SharedServerSuite) SetupSuite() { // Allow a high rate of change to namespaces, particularly // for the task-queue command tests. "frontend.namespaceRPS.visibility": 10000, - // this is overridden since we don't want caching to be enabled while testing DescribeTaskQueue - // behaviour related to versioning + // Disable DescribeTaskQueue cache. + "frontend.activityAPIsEnabled": true, + // this is overridden since we don't want caching to be enabled + // while testing DescribeTaskQueue behaviour related to versioning "matching.TaskQueueInfoByBuildIdTTL": 0 * time.Second, }, }, @@ -369,7 +371,6 @@ func StartDevServer(t *testing.T, options DevServerOptions) *DevServer { d.Options.DynamicConfigValues["frontend.workerVersioningWorkflowAPIs"] = true d.Options.DynamicConfigValues["worker.buildIdScavengerEnabled"] = true d.Options.DynamicConfigValues["frontend.enableUpdateWorkflowExecution"] = true - d.Options.DynamicConfigValues["system.enableNexus"] = true d.Options.DynamicConfigValues["frontend.MaxConcurrentBatchOperationPerNamespace"] = 1000 d.Options.DynamicConfigValues["frontend.namespaceRPS.visibility"] = 100 d.Options.DynamicConfigValues["system.clusterMetadataRefreshInterval"] = 100 * time.Millisecond diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 899962a2..f6832f10 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -204,10 +204,13 @@ commands: The command execution timeout. 0s means no timeout. - name: temporal activity - summary: Complete or fail an Activity + summary: Complete, update, pause, unpause, reset or fail an Activity description: | - Update an Activity's state to completed or failed. This marks an Activity - as successfully finished or as having encountered an error: + 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 + having encountered an error. ``` temporal activity complete \ @@ -225,6 +228,10 @@ commands: keywords: - activity - activity complete + - activity update-options + - activity pause + - activity unpause + - activity reset - activity execution - activity fail - cli reference @@ -287,6 +294,210 @@ commands: option-sets: - workflow reference + - 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. + + ``` + temporal activity update-options \ + --activity-id YourActivityId \ + --workflow-id YourWorkflowId \ + --task-queue NewTaskQueueName \ + --schedule-to-close-timeout DURATION \ + --schedule-to-start-timeout DURATION \ + --start-to-close-timeout DURATION \ + --heartbeat-timeout DURATION \ + --retry-initial-interval DURATION \ + --retry-maximum-interval DURATION \ + --retry-backoff-coefficient NewBackoffCoefficient \ + --retry-maximum-attempts NewMaximumAttempts + + ``` + options: + - name: activity-id + type: string + description: Activity ID. + required: true + - name: task-queue + type: string + description: Name of the task queue for the Activity. + - name: schedule-to-close-timeout + type: duration + description: | + 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 + 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 + by a worker. This timeout is always retryable. + - name: heartbeat-timeout + type: duration + description: | + Maximum permitted time between successful worker heartbeats. + - name: retry-initial-interval + type: duration + description: | + Interval of the first retry. If retryBackoffCoefficient is 1.0 then it + is used for all retries. + - name: retry-maximum-interval + type: duration + description: | + Maximum interval between retries. Exponential backoff leads to + interval increase. + This value is the cap of the increase. + - name: retry-backoff-coefficient + type: float + description: | + 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. + - name: retry-maximum-attempts + type: int + 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 + means unlimited attempts(up to the timeouts). + - name: identity + type: string + description: Identity of the user submitting this request. + option-sets: + - workflow reference + + - name: temporal activity pause + summary: Pause an Activity + description: | + Pause an Activity. + + If the Activity is not currently running (e.g. because it previously + failed), it will not be run again until it is unpaused. + + However, if the Activity is currently running, it will run to completion. + If the Activity is on its last retry attempt and fails, the failure will + be returned to the caller, just as if the Activity had not been paused. + + Specify the Activity and Workflow IDs: + + ``` + temporal activity pause \ + --activity-id YourActivityId \ + --workflow-id YourWorkflowId + ``` + options: + - name: activity-id + short: a + type: string + description: Activity ID to pause. + required: true + - name: identity + type: string + description: Identity of the user submitting this request. + option-sets: + - workflow reference + + - name: temporal activity unpause + summary: Unpause an Activity + description: | + Re-schedule a previously-paused Activity for execution. + + If the Activity is not running and is past its retry timeout, it will be + scheduled immediately. Otherwise, it will be scheduled after its retry + timeout expires. The Activity can be retried immediately with `--no-wait`. + + Use `--reset` to reset the number of previous run attempts to zero. For + example, if an Activity is near the maximum number of attempts N specified + in its retry policy, `--reset` will allow the Activity to be retried + another N times after unpausing. + + Specify the Activity and Workflow IDs: + + ``` + temporal activity unpause \ + --activity-id YourActivityId \ + --workflow-id YourWorkflowId + --reset + --no-wait + --reset-heartbeats + ``` + options: + - name: activity-id + short: a + type: string + description: Activity ID to pause. + required: true + - name: identity + type: string + description: Identity of the user submitting this request. + - name: reset + type: bool + description: Also reset the activity. + - name: no-wait + type: bool + description: | + Schedule the Activity immediately, even if its retry timeout has not expired. + - name: reset-heartbeats + type: bool + description: Reset the Activity's heartbeat timeout. Only works with --reset. + option-sets: + - workflow reference + + - 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. + + 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 + heartbeats will be reset. + + Specify the Activity and Workflow IDs: + + ``` + temporal activity reset \ + --activity-id YourActivityId \ + --workflow-id YourWorkflowId + --no-wait + --reset-heartbeats + ``` + options: + - name: activity-id + short: a + type: string + description: Activity ID to pause. + required: true + - name: identity + type: string + description: Identity of the user submitting this request. + - name: no-wait + type: bool + description: | + Schedule the Activity immediately, even if its retry timeout has not + expired or the activity is currently running. + - name: reset-heartbeats + type: bool + description: Reset the Activity's heartbeat. + option-sets: + - workflow reference + - name: temporal batch summary: Manage running batch jobs description: | @@ -1479,9 +1690,8 @@ commands: default: 7233 - name: http-port type: int - description: | - Port for the HTTP API service. - Default is off. + description: Port for the HTTP API service. Defaults to a random free port. + default: 0 - name: metrics-port type: int description: | @@ -2919,7 +3129,6 @@ commands: required: true option-sets: - - name: client options: - name: address diff --git a/temporalcli/devserver/log.go b/temporalcli/devserver/log.go index f20a686a..a20cc952 100644 --- a/temporalcli/devserver/log.go +++ b/temporalcli/devserver/log.go @@ -14,6 +14,7 @@ type slogLogger struct { } var _ log.Logger = slogLogger{} +var _ log.SLogWrapper = slogLogger{} func (s slogLogger) Debug(msg string, tags ...tag.Tag) { s.Log(slog.LevelDebug, msg, tags) } func (s slogLogger) Info(msg string, tags ...tag.Tag) { s.Log(slog.LevelInfo, msg, tags) } @@ -25,6 +26,10 @@ func (s slogLogger) DPanic(msg string, tags ...tag.Tag) { s.Log(slog.LevelError, func (s slogLogger) Panic(msg string, tags ...tag.Tag) { s.Log(slog.LevelError, msg, tags) } func (s slogLogger) Fatal(msg string, tags ...tag.Tag) { s.Log(slog.LevelError, msg, tags) } +func (s slogLogger) SLog() *slog.Logger { + return s.log +} + func (s slogLogger) Log(level slog.Level, msg string, tags []tag.Tag) { if level >= s.level && s.log.Enabled(context.Background(), level) { s.log.LogAttrs(context.Background(), level, msg, logTagsToAttrs(tags)...) diff --git a/temporalcli/devserver/server.go b/temporalcli/devserver/server.go index 60effbb4..230107cf 100644 --- a/temporalcli/devserver/server.go +++ b/temporalcli/devserver/server.go @@ -38,6 +38,7 @@ import ( uiserver "github.com/temporalio/ui-server/v2/server" uiconfig "github.com/temporalio/ui-server/v2/server/config" uiserveroptions "github.com/temporalio/ui-server/v2/server/server_options" + "go.temporal.io/api/enums/v1" "go.temporal.io/server/common/authorization" "go.temporal.io/server/common/cluster" "go.temporal.io/server/common/config" @@ -84,6 +85,7 @@ type StartOptions struct { FrontendHTTPPort int EnableGlobalNamespace bool DynamicConfigValues map[string]any + SearchAttributes map[string]enums.IndexedValueType LogConfig func([]byte) GRPCInterceptors []grpc.UnaryServerInterceptor } @@ -115,6 +117,10 @@ func Start(options StartOptions) (*Server, error) { return nil, fmt.Errorf("missing initial failover version") } + if options.FrontendHTTPPort == 0 { + options.FrontendHTTPPort = MustGetFreePort(options.FrontendIP) + } + // Build servers var ui *uiserver.Server if options.UIIP != "" { @@ -225,7 +231,6 @@ func (s *StartOptions) buildServerOptions() ([]temporal.ServerOption, error) { dynConf[dynamicconfig.HistoryCacheHostLevelMaxSize.Key()] = 8096 // Up default visibility RPS dynConf[dynamicconfig.FrontendMaxNamespaceVisibilityRPSPerInstance.Key()] = 100 - // This doesn't enable Nexus but it is required for Nexus to work and simplifies the experience. // NOTE that the URL scheme is fixed to HTTP since the dev server doesn't support TLS at the time of writing. dynConf[nexusoperations.CallbackURLTemplate.Key()] = fmt.Sprintf( "http://%s:%d/namespaces/{{.NamespaceName}}/nexus/callback", MaybeEscapeIPv6(s.FrontendIP), s.FrontendHTTPPort) @@ -340,7 +345,11 @@ func (s *StartOptions) buildSQLConfig() (*config.SQL, error) { // Create namespaces namespaces := make([]*sqliteschema.NamespaceConfig, len(s.Namespaces)) for i, ns := range s.Namespaces { - namespaces[i] = sqlite.NewNamespaceConfig(s.CurrentClusterName, ns, false) + nsConfig, err := sqlite.NewNamespaceConfig(s.CurrentClusterName, ns, false, s.SearchAttributes) + if err != nil { + return nil, fmt.Errorf("failed creating namespace config: %w", err) + } + namespaces[i] = nsConfig } if err := sqliteschema.CreateNamespaces(&conf, namespaces...); err != nil { return nil, fmt.Errorf("failed creating namespaces: %w", err) @@ -353,9 +362,7 @@ func (s *StartOptions) buildServiceConfig(frontend bool) config.Service { if frontend { conf.RPC.GRPCPort = s.FrontendPort conf.RPC.BindOnIP = s.FrontendIP - if s.FrontendHTTPPort > 0 { - conf.RPC.HTTPPort = s.FrontendHTTPPort - } + conf.RPC.HTTPPort = s.FrontendHTTPPort } else { conf.RPC.GRPCPort = MustGetFreePort(s.FrontendIP) conf.RPC.BindOnIP = s.FrontendIP