Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cd0a8aa
UpdateTaskQueueConfig Cli support init
sivagirish81 Jul 31, 2025
a433729
Made namespace mandatory
sivagirish81 Jul 31, 2025
6ad0b6f
Added checks for required fields
sivagirish81 Jul 31, 2025
fb8080f
added support for report config in describeTaskQueue
sivagirish81 Aug 1, 2025
e7aee13
Display config updates in atabular manner
sivagirish81 Aug 1, 2025
f7ab06b
Handled unsetting of fields and updated tests
sivagirish81 Aug 1, 2025
3100d1a
Changed the long description for the command
sivagirish81 Aug 1, 2025
7fffa48
Updated tests and commands.yml
sivagirish81 Aug 1, 2025
bf068d1
Added Noop command + fixed tests
sivagirish81 Aug 1, 2025
d5fd1dc
Changed display of task queue configuration in describe command
sivagirish81 Aug 1, 2025
1c9e6e6
Fixed display to handle long strings in describe command
sivagirish81 Aug 1, 2025
d938a57
Added namespace to update-config command help
sivagirish81 Aug 1, 2025
a937427
Consistently passing the --identity parameter to server requests
sivagirish81 Aug 8, 2025
28ad827
Code refactor + removed default sentinel of -99999
sivagirish81 Aug 8, 2025
3317cb1
Added task queue config get/set commands
sivagirish81 Aug 10, 2025
000e994
Fixed tests
sivagirish81 Aug 10, 2025
3cf9e09
Added required tags for taskqueue name and type
sivagirish81 Aug 10, 2025
7acd905
Changed time to time.RFC3339
sivagirish81 Aug 12, 2025
8d0450b
Changed requests/second to rps
sivagirish81 Aug 12, 2025
f41f50a
rename flags to include rps
stephanos Sep 29, 2025
b4b2569
adjust flags to avoid -1
stephanos Sep 30, 2025
7a6cec7
remove dependency replace
stephanos Sep 30, 2025
3b42a83
Update temporalcli/commandsgen/commands.yml
stephanos Oct 1, 2025
2e793cc
re-generate
stephanos Oct 1, 2025
e41ee13
add `display-type` docs
stephanos Oct 2, 2025
74622a3
helper to override display type
stephanos Oct 2, 2025
43ff7f6
re-generate
stephanos Oct 2, 2025
d29e0e7
go mod tidy
stephanos Oct 2, 2025
e2df309
re-generate
stephanos Oct 2, 2025
9c708ab
re-generate
stephanos Oct 2, 2025
3e2c681
remove
stephanos Oct 2, 2025
075e87d
ge-generate
stephanos Oct 2, 2025
7214a44
unexport helper
stephanos Oct 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions temporalcli/commands.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2160,6 +2160,7 @@ func NewTemporalTaskQueueCommand(cctx *CommandContext, parent *TemporalCommand)
s.Command.Long = "Inspect and update Task Queues, the queues that Workers poll for Workflow and\nActivity tasks:\n\n```\ntemporal task-queue [command] [command options] \\\n --task-queue YourTaskQueue\n```\n\nFor example:\n\n```\ntemporal task-queue describe \\\n --task-queue YourTaskQueue\n```"
}
s.Command.Args = cobra.NoArgs
s.Command.AddCommand(&NewTemporalTaskQueueConfigCommand(cctx, &s).Command)
s.Command.AddCommand(&NewTemporalTaskQueueDescribeCommand(cctx, &s).Command)
s.Command.AddCommand(&NewTemporalTaskQueueGetBuildIdReachabilityCommand(cctx, &s).Command)
s.Command.AddCommand(&NewTemporalTaskQueueGetBuildIdsCommand(cctx, &s).Command)
Expand All @@ -2170,6 +2171,101 @@ func NewTemporalTaskQueueCommand(cctx *CommandContext, parent *TemporalCommand)
return &s
}

type TemporalTaskQueueConfigCommand struct {
Parent *TemporalTaskQueueCommand
Command cobra.Command
}

func NewTemporalTaskQueueConfigCommand(cctx *CommandContext, parent *TemporalTaskQueueCommand) *TemporalTaskQueueConfigCommand {
var s TemporalTaskQueueConfigCommand
s.Parent = parent
s.Command.Use = "config"
s.Command.Short = "Get and set Task Queue configuration"
if hasHighlighting {
s.Command.Long = "Manage Task Queue configuration:\n\n\x1b[1mtemporal task-queue config [command] [options]\x1b[0m\n\nAvailable commands:\n- \x1b[1mget\x1b[0m: Retrieve the current configuration for a task queue\n- \x1b[1mset\x1b[0m: Update the configuration for a task queue"
} else {
s.Command.Long = "Manage Task Queue configuration:\n\n```\ntemporal task-queue config [command] [options]\n```\n\nAvailable commands:\n- `get`: Retrieve the current configuration for a task queue\n- `set`: Update the configuration for a task queue"
}
s.Command.Args = cobra.NoArgs
s.Command.AddCommand(&NewTemporalTaskQueueConfigGetCommand(cctx, &s).Command)
s.Command.AddCommand(&NewTemporalTaskQueueConfigSetCommand(cctx, &s).Command)
return &s
}

type TemporalTaskQueueConfigGetCommand struct {
Parent *TemporalTaskQueueConfigCommand
Command cobra.Command
TaskQueue string
TaskQueueType StringEnum
}

func NewTemporalTaskQueueConfigGetCommand(cctx *CommandContext, parent *TemporalTaskQueueConfigCommand) *TemporalTaskQueueConfigGetCommand {
var s TemporalTaskQueueConfigGetCommand
s.Parent = parent
s.Command.DisableFlagsInUseLine = true
s.Command.Use = "get [flags]"
s.Command.Short = "Get Task Queue configuration"
if hasHighlighting {
s.Command.Long = "Retrieve the current configuration for a Task Queue:\n\n\x1b[1mtemporal task-queue config get \\\n --task-queue YourTaskQueue \\\n --task-queue-type activity\x1b[0m\n\nThis command returns the current configuration including:\n- Queue rate limit: The overall rate limit of the task queue.\n This setting overrides the worker rate limit if set.\n Unless modified, this is the system-defined rate limit.\n- Fairness key rate limit defaults: Default rate limits for fairness keys.\n If set, each individual fairness key will be limited to this rate,\n scaled by the weight of the fairness key."
} else {
s.Command.Long = "Retrieve the current configuration for a Task Queue:\n\n```\ntemporal task-queue config get \\\n --task-queue YourTaskQueue \\\n --task-queue-type activity\n```\n\nThis command returns the current configuration including:\n- Queue rate limit: The overall rate limit of the task queue.\n This setting overrides the worker rate limit if set.\n Unless modified, this is the system-defined rate limit.\n- Fairness key rate limit defaults: Default rate limits for fairness keys.\n If set, each individual fairness key will be limited to this rate,\n scaled by the weight of the fairness key."
}
s.Command.Args = cobra.NoArgs
s.Command.Flags().StringVarP(&s.TaskQueue, "task-queue", "t", "", "Task Queue name. Required.")
_ = cobra.MarkFlagRequired(s.Command.Flags(), "task-queue")
s.TaskQueueType = NewStringEnum([]string{"workflow", "activity", "nexus"}, "")
s.Command.Flags().Var(&s.TaskQueueType, "task-queue-type", "Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.")
_ = cobra.MarkFlagRequired(s.Command.Flags(), "task-queue-type")
s.Command.Run = func(c *cobra.Command, args []string) {
if err := s.run(cctx, args); err != nil {
cctx.Options.Fail(err)
}
}
return &s
}

type TemporalTaskQueueConfigSetCommand struct {
Parent *TemporalTaskQueueConfigCommand
Command cobra.Command
TaskQueue string
TaskQueueType StringEnum
QueueRpsLimit string
QueueRpsLimitReason string
FairnessKeyRpsLimitDefault string
FairnessKeyRpsLimitReason string
}

func NewTemporalTaskQueueConfigSetCommand(cctx *CommandContext, parent *TemporalTaskQueueConfigCommand) *TemporalTaskQueueConfigSetCommand {
var s TemporalTaskQueueConfigSetCommand
s.Parent = parent
s.Command.DisableFlagsInUseLine = true
s.Command.Use = "set [flags]"
s.Command.Short = "Set Task Queue configuration"
if hasHighlighting {
s.Command.Long = "Update configuration settings for a Task Queue.\n\n\x1b[1mtemporal task-queue config set \\\n --task-queue YourTaskQueue \\\n --task-queue-type activity \\\n --namespace YourNamespace \\\n --queue-rps-limit <requests_per_second:float> \\\n --queue-rps-limit-reason <reason_string> \\\n --fairness-key-rps-limit-default <requests_per_second:float> \\\n --fairness-key-rps-limit-reason <reason_string>\x1b[0m\n\nThis command supports updating:\n- Queue rate limits: Controls the overall rate limit of the task queue.\n This setting overrides the worker rate limit if set.\n Unless modified, this is the system-defined rate limit.\n- Fairness key rate limit defaults: Sets default rate limits for fairness keys.\n If set, each individual fairness key will be limited to this rate,\n scaled by the weight of the fairness key.\n\nTo unset a rate limit, pass in 'default', for example: --queue-rps-limit default"
} else {
s.Command.Long = "Update configuration settings for a Task Queue.\n\n```\ntemporal task-queue config set \\\n --task-queue YourTaskQueue \\\n --task-queue-type activity \\\n --namespace YourNamespace \\\n --queue-rps-limit <requests_per_second:float> \\\n --queue-rps-limit-reason <reason_string> \\\n --fairness-key-rps-limit-default <requests_per_second:float> \\\n --fairness-key-rps-limit-reason <reason_string>\n```\n\nThis command supports updating:\n- Queue rate limits: Controls the overall rate limit of the task queue.\n This setting overrides the worker rate limit if set.\n Unless modified, this is the system-defined rate limit.\n- Fairness key rate limit defaults: Sets default rate limits for fairness keys.\n If set, each individual fairness key will be limited to this rate,\n scaled by the weight of the fairness key.\n\nTo unset a rate limit, pass in 'default', for example: --queue-rps-limit default"
}
s.Command.Args = cobra.NoArgs
s.Command.Flags().StringVarP(&s.TaskQueue, "task-queue", "t", "", "Task Queue name. Required.")
_ = cobra.MarkFlagRequired(s.Command.Flags(), "task-queue")
s.TaskQueueType = NewStringEnum([]string{"workflow", "activity", "nexus"}, "")
s.Command.Flags().Var(&s.TaskQueueType, "task-queue-type", "Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.")
_ = cobra.MarkFlagRequired(s.Command.Flags(), "task-queue-type")
s.Command.Flags().StringVar(&s.QueueRpsLimit, "queue-rps-limit", "", "Queue rate limit in requests per second. Accepts a float; or 'default' to unset.")
overrideFlagDisplayType(s.Command.Flags().Lookup("queue-rps-limit"), "float|default")
s.Command.Flags().StringVar(&s.QueueRpsLimitReason, "queue-rps-limit-reason", "", "Reason for queue rate limit update.")
s.Command.Flags().StringVar(&s.FairnessKeyRpsLimitDefault, "fairness-key-rps-limit-default", "", "Fairness key rate limit default in requests per second. Accepts a float; or 'default' to unset.")
overrideFlagDisplayType(s.Command.Flags().Lookup("fairness-key-rps-limit-default"), "float|default")
s.Command.Flags().StringVar(&s.FairnessKeyRpsLimitReason, "fairness-key-rps-limit-reason", "", "Reason for fairness key rate limit update.")
s.Command.Run = func(c *cobra.Command, args []string) {
if err := s.run(cctx, args); err != nil {
cctx.Options.Fail(err)
}
}
return &s
}

type TemporalTaskQueueDescribeCommand struct {
Parent *TemporalTaskQueueCommand
Command cobra.Command
Expand All @@ -2183,6 +2279,7 @@ type TemporalTaskQueueDescribeCommand struct {
TaskQueueTypeLegacy StringEnum
PartitionsLegacy int
DisableStats bool
ReportConfig bool
}

func NewTemporalTaskQueueDescribeCommand(cctx *CommandContext, parent *TemporalTaskQueueCommand) *TemporalTaskQueueDescribeCommand {
Expand Down Expand Up @@ -2210,6 +2307,7 @@ func NewTemporalTaskQueueDescribeCommand(cctx *CommandContext, parent *TemporalT
s.Command.Flags().Var(&s.TaskQueueTypeLegacy, "task-queue-type-legacy", "Task Queue type (legacy mode only). Accepted values: workflow, activity.")
s.Command.Flags().IntVar(&s.PartitionsLegacy, "partitions-legacy", 1, "Query partitions 1 through `N`. Experimental/Temporary feature. Legacy mode only.")
s.Command.Flags().BoolVar(&s.DisableStats, "disable-stats", false, "Disable task queue statistics.")
s.Command.Flags().BoolVar(&s.ReportConfig, "report-config", false, "Include task queue configuration in the response. When enabled, the command will return the current rate limit configuration for the task queue.")
s.Command.Run = func(c *cobra.Command, args []string) {
if err := s.run(cctx, args); err != nil {
cctx.Options.Fail(err)
Expand Down
13 changes: 13 additions & 0 deletions temporalcli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,3 +576,16 @@ func encodeMapToPayloads(in map[string]any) (map[string]*commonpb.Payload, error
}
return out, nil
}

type overrideDisplayTypeFlagValue struct {
pflag.Value
displayType string
}

func (o *overrideDisplayTypeFlagValue) Type() string {
return o.displayType
}

func overrideFlagDisplayType(flag *pflag.Flag, displayType string) {
flag.Value = &overrideDisplayTypeFlagValue{Value: flag.Value, displayType: displayType}
}
38 changes: 35 additions & 3 deletions temporalcli/commands.taskqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ func (c *TemporalTaskQueueDescribeCommand) runLegacy(cctx *CommandContext, args

var statuses []*statusWithPartition
var pollers []*pollerWithPartition
var config *taskqueue.TaskQueueConfig

// TODO: remove this when the server does partition fan-out
for p := 0; p < partitions; p++ {
Expand All @@ -345,6 +346,7 @@ func (c *TemporalTaskQueueDescribeCommand) runLegacy(cctx *CommandContext, args
},
TaskQueueType: taskQueueType,
IncludeTaskQueueStatus: true,
ReportConfig: c.ReportConfig,
})
if err != nil {
return fmt.Errorf("unable to describe task queue: %w", err)
Expand All @@ -360,14 +362,25 @@ func (c *TemporalTaskQueueDescribeCommand) runLegacy(cctx *CommandContext, args
Versioning: pi.WorkerVersionCapabilities,
})
}
// Capture config from the first partition (they should all be the same)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, maybe it's time to remove this client-side fan-out feature? we have Describe doing fan-out now. or is that just for [deprecated] enhanced mode?

if we do keep client-side fan-out, I think we should either not ReportConfig on the ones other than the root, or disallow partition count > 1 with ReportConfig.

Copy link
Contributor Author

@sivagirish81 sivagirish81 Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The legacy version of DescribeTaskQueue does not do fanout the fanout happens only in the enhanced version.

if we do keep client-side fan-out, I think we should either not ReportConfig on the ones other than the root, or disallow partition count > 1 with ReportConfig.

Reading the data from config is not that expensive do we need to add this additional check?

if p == 0 && resp.Config != nil {
config = resp.Config
}
}

// For JSON, we'll just dump the proto
if cctx.JSONOutput {
return cctx.Printer.PrintStructured(map[string]any{
output := map[string]any{
"taskQueues": statuses,
"pollers": pollers,
}, printer.StructuredOptions{})
}

// Include config if requested
if c.ReportConfig && config != nil {
output["config"] = config
}

return cctx.Printer.PrintStructured(output, printer.StructuredOptions{})
}

// For text, we will use a table for pollers
Expand All @@ -382,7 +395,18 @@ func (c *TemporalTaskQueueDescribeCommand) runLegacy(cctx *CommandContext, args
items[i].LastAccessTime = poller.LastAccessTime.AsTime()
items[i].RatePerSecond = poller.RatePerSecond
}
return cctx.Printer.PrintStructured(items, printer.StructuredOptions{Table: &printer.TableOptions{}})
err = cctx.Printer.PrintStructured(items, printer.StructuredOptions{Table: &printer.TableOptions{}})
if err != nil {
return err
}

// Display config if requested
if c.ReportConfig && config != nil {
cctx.Printer.Println(color.MagentaString("\nTask Queue Configuration:"))
return printTaskQueueConfig(cctx, config)
}

return nil
}

func (c *TemporalTaskQueueListPartitionCommand) run(cctx *CommandContext, args []string) error {
Expand Down Expand Up @@ -425,3 +449,11 @@ func (c *TemporalTaskQueueListPartitionCommand) run(cctx *CommandContext, args [

return nil
}

// Helper function to truncate strings
func truncateString(s string, maxLength int) string {
if len(s) <= maxLength {
return s
}
return s[:maxLength-3] + "..."
}
100 changes: 100 additions & 0 deletions temporalcli/commands.taskqueue.helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package temporalcli

import (
"fmt"
"time"

"github.com/fatih/color"
"github.com/temporalio/cli/temporalcli/internal/printer"
"go.temporal.io/api/enums/v1"
"go.temporal.io/api/taskqueue/v1"
)

// Create a structured table for config display.
type configRow struct {
Setting string
Value string
Reason string
UpdatedBy string
UpdatedTime string
}

func parseTaskQueueType(input string) (enums.TaskQueueType, error) {
switch input {
case "", "workflow":
return enums.TASK_QUEUE_TYPE_WORKFLOW, nil
case "activity":
return enums.TASK_QUEUE_TYPE_ACTIVITY, nil
case "nexus":
return enums.TASK_QUEUE_TYPE_NEXUS, nil
default:
return enums.TASK_QUEUE_TYPE_WORKFLOW, fmt.Errorf(
"invalid task queue type: %s. Must be one of: workflow, activity, nexus", input)
}
}

func buildRateLimitConfigRow(setting string, rl *taskqueue.RateLimitConfig, format string) configRow {
value := "Not Set"
reason := ""
updatedBy := ""
updatedTime := ""

if rl.RateLimit != nil && rl.RateLimit.RequestsPerSecond > 0 {
value = fmt.Sprintf(format, rl.RateLimit.RequestsPerSecond)
}

if rl.Metadata != nil {
if rl.Metadata.Reason != "" {
reason = truncateString(rl.Metadata.Reason, 50)
}
if rl.Metadata.UpdateIdentity != "" {
updatedBy = truncateString(rl.Metadata.UpdateIdentity, 50)
}
if rl.Metadata.UpdateTime != nil {
updateTime := rl.Metadata.UpdateTime.AsTime()
updatedTime = updateTime.Format(time.RFC3339)
}
}

return configRow{
Setting: setting,
Value: value,
Reason: reason,
UpdatedBy: updatedBy,
UpdatedTime: updatedTime,
}
}

// printTaskQueueConfig is a shared function to print task queue configuration
// This can be used by both the config get command and the describe command
func printTaskQueueConfig(cctx *CommandContext, config *taskqueue.TaskQueueConfig) error {
// For JSON, we'll just dump the proto
if cctx.JSONOutput {
return cctx.Printer.PrintStructured(config, printer.StructuredOptions{})
}

// For text, we will use a table
var configRows []configRow

// Queue Rate Limit
if config.QueueRateLimit != nil {
configRows = append(configRows, buildRateLimitConfigRow("Queue Rate Limit", config.QueueRateLimit, "%.2f rps"))
}

// Fairness Key Rate Limit Default
if config.FairnessKeysRateLimitDefault != nil {
configRows = append(configRows, buildRateLimitConfigRow("Fairness Key Rate Limit Default", config.FairnessKeysRateLimitDefault, "%.2f rps"))
}

// Print the config table
if len(configRows) > 0 {
// Always show truncation note, regardless of actual truncation
cctx.Printer.Println(color.YellowString("Note: Long content may be truncated. Use --output json for full details."))

return cctx.Printer.PrintStructured(configRows, printer.StructuredOptions{
Table: &printer.TableOptions{},
})
}

return nil
}
Loading