Skip to content

Comments

Update task queue config cli#840

Merged
stephanos merged 33 commits intotemporalio:next-serverfrom
sivagirish81:updateTaskQueueConfigCLI
Oct 2, 2025
Merged

Update task queue config cli#840
stephanos merged 33 commits intotemporalio:next-serverfrom
sivagirish81:updateTaskQueueConfigCLI

Conversation

@sivagirish81
Copy link
Contributor

@sivagirish81 sivagirish81 commented Aug 1, 2025

What was changed

  • Added a new report-config field in the describe command to retrieve updated task queue configs if exists.
  • Implement display logic for config table along with truncation of large update reasons or update identities.
    Note : These changes are only a part of the legacy mode of the describeTaskQueueApi.
./temporal task-queue describe \                                                               
 --task-queue=test-display-queue \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode

Sample Response

./temporal task-queue describe \
 --task-queue=hello-world \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
Pollers:
  Identity  LastAccessTime  RatePerSecond

Task Queue Configuration:
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46

  • Added separate config Subcommand for getting/setting configs.
./temporal task-queue config --help  
Manage Task Queue configuration:

temporal task-queue config [command] [options]

Available commands:
- get: Retrieve the current configuration for a task queue
- set: Update the configuration for a task queue

Usage:
  temporal task-queue config [command]

Available Commands:
  get         Get Task Queue configuration
  set         Set Task Queue configuration

  • Get Subcommand
./temporal task-queue config get --help
Retrieve the current configuration for a Task Queue:

temporal task-queue config get \
    --task-queue YourTaskQueue \
    --task-queue-type activity

This command returns the current configuration including:
- Queue rate limit: The overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

Usage:
  temporal task-queue config get [flags]

Sample Response

./temporal task-queue config get \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --namespace=default
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46

  • Set Subcommand
./temporal task-queue config set --help
Update a Task Queue's overall rate limit and the default rate limit for all fairness keys:

temporal task-queue config set \
    --task-queue YourTaskQueue \
    --task-queue-type activity \
    --namespace YourNamespace \
    --queue-rps-limit <requests_per_second:float> \
    --queue-rps-limit-reason <reason_string> \
    --fairness-key-rps-limit-default <requests_per_second:float> \
    --fairness-key-rps-limit-reason <reason_string>

This command supports updating:
- Queue rate limits: Controls the overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Sets default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

To unset a rate limit, pass in 'default', for example: --queue-rps-limit default

Usage:
  temporal task-queue config set [flags]

Flags:
      --fairness-key-rps-limit-default float|default   Fairness key rate limit default in requests per second. Accepts a float; or 'default' to unset.
      --fairness-key-rps-limit-reason string           Reason for fairness key rate limit update.
  -h, --help                                           help for set
      --queue-rps-limit float|default                  Queue rate limit in requests per second. Accepts a float; or 'default' to unset.
      --queue-rps-limit-reason string                  Reason for queue rate limit update.
  -t, --task-queue string                              Task Queue name. Required.
      --task-queue-type string                         Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.

Sample response :

./temporal task-queue config set \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --fairness-key-rps-limit-default=100 \
  --fairness-key-rps-limit-reason="Fairness key test" \
  --identity="api-tester" \
  --namespace=default
Successfully updated task queue configuration
  Config  {"fairnessKeysRateLimitDefault":{"rateLimit":{"requestsPerSecond":100},"metadata":{"reason":"Fairness key test","updateIdentity":"api-tester","updateTime":"2025-08-12T04:31:46.640Z"}}}

Why?

  • Cli support for UpdateTaskQueueConfig api - new api that allows updates of rate limits against task queues.

Checklist

  1. How was this tested:
  • Added tests.
  1. Any docs updates needed?
    Pending.

@CLAassistant
Copy link

CLAassistant commented Aug 1, 2025

CLA assistant check
All committers have signed the CLA.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

go.mod Outdated
Comment on lines 178 to 181

replace go.temporal.io/api => go.temporal.io/api v1.51.1-0.20250725211336-3d6e39249ecf

replace go.temporal.io/server => go.temporal.io/server v1.29.0-135.0.0.20250730212656-fcd84c4be641
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will revert this when the server and api versions are updated.

@sivagirish81 sivagirish81 marked this pull request as ready for review August 1, 2025 23:01
@sivagirish81 sivagirish81 requested review from a team as code owners August 1, 2025 23:01
go.mod Outdated
github.com/stretchr/testify v1.10.0
github.com/temporalio/ui-server/v2 v2.39.0
go.temporal.io/api v1.50.0
go.temporal.io/api v1.51.1-0.20250725211336-3d6e39249ecf
Copy link
Member

@cretz cretz Aug 4, 2025

Choose a reason for hiding this comment

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

Note, we can't merge with untagged API, but feel free to keep developing

Comment on lines 3141 to 3143
- name: identity
type: string
description: Identity for the operation.
Copy link
Member

@cretz cretz Aug 4, 2025

Choose a reason for hiding this comment

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

This is a client-level option as was done in #831 (can add that to this PR if it's going to main or make this PR go to next-server, your choice)

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.

Added identity as a client level option in this PR.

- name: disable-stats
type: bool
description: Disable task queue statistics.
- name: report-config
Copy link
Contributor

Choose a reason for hiding this comment

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

What do people think about having a separate subcommand tree, like temporal task-queue config get and temporal task-queue config set instead of bundling it into describe? (or we could bundle it into describe also.) I'm feeling like describe is too much of a grab-bag now and when a user wants to mess with config, they would appreciate a config-focused command. The fact that it uses the same DescribeTaskQueue rpc under the hood doesn't matter.

Copy link
Member

Choose a reason for hiding this comment

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

This is a challenge we run into in a few places. I personally like CLI/SDK commands/API to be 1:1 with HTTP/gRPC API, otherwise we have seen it get really complicated as we add more things to RPC. But I do not have a strong opinion here.

Copy link
Contributor

Choose a reason for hiding this comment

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

The obvious counter-example is batch operations 🤷

Copy link
Member

@cretz cretz Aug 4, 2025

Choose a reason for hiding this comment

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

Yup, that's a tctl carry-over and one of the things I was referring to as "as we add more things to RPC". Batch not being a clear-cut command to represent it means as batch things are added we can't easily represent them. So now you have --rps on every workflow interaction because #675 needed it for batch. Granted making a single command multiple RPCs is the inverse of the problem here of multiple commands a single RPC, but there are still challenges for not being 1:1 and adding things (or being able to perform an invocation to get multiple things as results as you can with the HTTP API).

Copy link
Member

@cretz cretz Aug 4, 2025

Choose a reason for hiding this comment

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

Having said the above, I'd be ok splitting it out, but I think we should discuss what this looks like in the SDK, because at least having the CLI and SDK share some client commonalities helps here. Regardless, not blocking and I'm ok with whatever y'all decide.

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.

Added the report-config flag to the DescribeTaskQueue api to maintain 1:1 with HTTP/gRPC API.
Also introduced two additional subcommands task-queue config get/set to retrieve the task queue config and set the config.

  • Get - uses the DescribeTaskQueue rpc under the hood to retrieve the configs.
  • Set - uses the UpdateTaskQueueConfig rpc under the hood to set/update the configs.

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?

Comment on lines 489 to 501
// Add a note about truncation if any content was truncated
hasTruncatedContent := false
for _, row := range configRows {
if len(row.Reason) > 0 && strings.HasSuffix(row.Reason, "...") ||
len(row.UpdatedBy) > 0 && strings.HasSuffix(row.UpdatedBy, "...") {
hasTruncatedContent = true
break
}
}

if hasTruncatedContent {
cctx.Printer.Println(color.YellowString("Note: Long content has been truncated. Use --output json for full details."))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems like unnecessary complexity, the ... is plenty. or wrap instead of truncate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the check for truncation logic and simply left it at truncation and gave a hint message that tells the user to if they want to see the truncated content then they can view the json dump.

@sivagirish81 sivagirish81 requested review from cretz and dnr August 12, 2025 06:32
@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from b4fd9ef to 449ee21 Compare September 25, 2025 00:14
@stephanos
Copy link
Contributor

@cretz I'm picking up this PR from Siva who has since left the company. It looks like he has addressed the PR comments and has requested another review from you.

Copy link
Member

@cretz cretz left a comment

Choose a reason for hiding this comment

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

Nothing blocking

type: float
description: |
Fairness key rate limit default in requests per second.
Use -1 to unset.
Copy link
Member

@cretz cretz Sep 25, 2025

Choose a reason for hiding this comment

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

Are we incorporating overrides as appear in temporalio/api#626 or will that come later? The reason I ask is I am not sure the "-1 to unset" is the best way vs being able to provide what you want to unset. Are we expecting to force users to use this special -1 value for overrides too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We haven’t implemented fairness weight overrides in the CLI yet. We were thinking on the lines of supporting repeated flags for setting and unsetting fairness weight overrides for fairness keys, for example:

--fairness-key-weight userA=5
--fairness-key-weight userB=10
--fairness-key-weight userC=-1   # Unsets the weight override for fairness key userC

Copy link
Member

Choose a reason for hiding this comment

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

👍 I think we'll have to if we choose to use -1 here too. An alternative is to have separate flags and API fields for unsetting things so that magic numbers are not in use. But if we have decided that the magic number -1 will be used in all of our interfaces (API and CLI for now, maybe UI and SDK later), ok.

Copy link
Contributor

@stephanos stephanos Sep 26, 2025

Choose a reason for hiding this comment

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

I'm also not a big fan of the magic -1 number. Similarly. 0 here also means "stop all traffic" and not "unlimited" (like it often does). Seems dangerous.

I'm wondering if it's too much too have 3 flags (ie. --queue-rate-limit, --unset-queue-rate-limit and ... maybe --queue-rate-stop or sth). Or mix numbers and words; not sure if we allow that, like --queue-rate-limit=reset and --queue-rate-limit=block) - technically also a sentinel value but maybe a better one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

queue-rate-limit and fairness-key-rate-limit-default are single values tied to a task queue. In these cases, we could avoid sentinel values and instead provide explicit unset flags for each.

[ Not implemented yet ]
For fairness-weight-overrides map, however, it’s different: if we don’t use sentinel values, then we’d need to introduce separate fields in the request (e.g. a list of fairness keys to unset). At the time, we chose sentinel values instead of adding extra fields to keep the request simple.

That said, if we do end up using sentinel values for fairness weight overrides, it might be more consistent to use them here as well.

Or mix numbers and words; not sure if we allow that, like --queue-rate-limit=reset and --queue-rate-limit=block).

In cobra, By default I think a flag is always bound to a specific type so if we need to do this it needs to be a custom interface but I don't think this would be necessary.

0 here also means "stop all traffic" and not "unlimited"

Having a separate --queue-rate-stop flag to set to 0, might be misleading considering users are allowed to set the rate limit to 0 in the api. But it would be helpful to let users know that 0 effectively halts traffic. Maybe we could add a line about the significance of 0 in the help/documentation of the command.

Copy link
Contributor

Choose a reason for hiding this comment

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

That said, if we do end up using sentinel values for fairness weight overrides, it might be more consistent to use them here as well.

I agree; let's be consistent. I'd prefer to be consistent about not using -1; at least user-facing.

For fairness-weight-overrides [ ...] At the time, we chose sentinel values instead of adding extra fields to keep the request simple.

On the API level there, since it's not merged yet, we could consider using a nullable message instead, so that the API is clear about what it means to "unset".

In cobra, By default I think a flag is always bound to a specific type so if we need to do this it needs to be a custom interface but I don't think this would be necessary.

That's a technical detail I'm sure we could overcome if we want to; let's work back from the user experience (of the CLI overall and this particular command).

Having a separate --queue-rate-stop flag to set to 0, might be misleading considering users are allowed to set the rate limit to 0 in the api. But it would be helpful to let users know that 0 effectively halts traffic. Maybe we could add a line about the significance of 0 in the help/documentation of the command.

I was actually adding a line to that in the docs and I realized that that's not enough, given the magnitude of the impact that the change potentially has. I'm thinking either using a separate flag or add a confirmation step ("y/n") to make sure the user really knows what they're about to do.

Copy link
Member

@cretz cretz Sep 26, 2025

Choose a reason for hiding this comment

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

On the API level there, since it's not merged yet, we could consider using a nullable message instead, so that the API is clear about what it means to "unset".

The API this CLI refers to is merged and it does use -1 IIUC. To be consistent on the API you'd need to affect that too. You can't use a nullable message because there is a difference between proto "unset" (i.e. don't change) and "remove". If we do want to do this, we would need separate API fields (and separate CLI flags) clearly saying to remove config on things. I do think we should either use -1 everywhere (which is the current approach here but can be changed) or use unset flags/fields everywhere.

Copy link
Contributor

@stephanos stephanos Sep 26, 2025

Choose a reason for hiding this comment

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

The API this CLI refers to is merged and it does use -1 IIUC.

Actually; that's not true: https://github.com/temporalio/cli/pull/840/files#diff-32890f13f9441f095cb29ab32b7bd127282d33234c3d381b2d45cabc9b282dd7R77 - ie the way to unset in the API is to set RateLimit to null. So it's not too late for the CLI and upcoming API to be changed.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, makes sense, I misread an older commit I think. Yes, if server doesn't expect -1, awesome.

Copy link
Contributor

Choose a reason for hiding this comment

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

I've pushed the changes to resolve this issue.

- `get`: Retrieve the current configuration for a task queue
- `set`: Update the configuration for a task queue

- name: temporal task-queue config get
Copy link
Member

@cretz cretz Sep 25, 2025

Choose a reason for hiding this comment

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

Will start new thread carrying over from https://github.com/temporalio/cli/pull/840/files#r2252052265.

I am not expecting task-queue stats get or task-queue rate-limit get or adding a new command for every thing we add as a response to task queue describe. This is just a shortcut for task-queue describe --report-config which we don't normally do (have multiple CLI commands doing the same thing). I guess I don't have a strong opinion against this shortcut so it has symmetry with set, but hopefully it remains no more than a shortcut.

@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from 449ee21 to 35ec67d Compare September 30, 2025 18:15
Comment on lines 423 to 442
if o.DisplayType != "" {
// Use custom flag
w.writeLinef("{")
w.writeLinef("flag := newCustomStringFlag(&%v.%v, %q)",
selfVar, o.fieldName(), o.DisplayType)
method := "Var"
if o.Short != "" {
method += "P"
}
w.writeLinef("%v.%s(flag, %q, %q)", flagVar, method, o.Name, desc)
w.writeLinef("}")
} else {
w.writeLinef("%v.%v(&%v.%v, %q%v, %q)",
flagVar, flagMeth, selfVar, o.fieldName(), o.Name, defaultLit, desc)
// Use standard flag
if o.Short != "" {
w.writeLinef("%v.%vP(&%v.%v, %q, %q%v, %q)",
flagVar, flagMeth, selfVar, o.fieldName(), o.Name, o.Short, defaultLit, desc)
} else {
w.writeLinef("%v.%v(&%v.%v, %q%v, %q)",
flagVar, flagMeth, selfVar, o.fieldName(), o.Name, defaultLit, desc)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review.

Comment on lines 3189 to 3250
- name: temporal task-queue config set
summary: Set Task Queue configuration
description: |
Update a Task Queue's overall rate limit and the default rate limit for all fairness keys:

```
temporal task-queue config set \
--task-queue YourTaskQueue \
--task-queue-type activity \
--namespace YourNamespace \
--queue-rps-limit <requests_per_second:float> \
--queue-rps-limit-reason <reason_string> \
--fairness-key-rps-limit-default <requests_per_second:float> \
--fairness-key-rps-limit-reason <reason_string>
```

This command supports updating:
- Queue rate limits: Controls the overall rate limit of the task queue.
This setting overrides the worker rate limit if set.
Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Sets default rate limits for fairness keys.
If set, each individual fairness key will be limited to this rate,
scaled by the weight of the fairness key.

To unset a rate limit, pass in 'default', for example: --queue-rps-limit default
options:
- name: task-queue
type: string
description: |
Task Queue name.
required: true
short: t
- name: task-queue-type
type: string-enum
description: |
Task Queue type.
Accepted values: workflow, activity, nexus.
required: true
enum-values:
- workflow
- activity
- nexus
- name: queue-rps-limit
type: string
display-type: float|default
description: |
Queue rate limit in requests per second.
Accepts a float; or 'default' to unset.
- name: queue-rps-limit-reason
type: string
description: Reason for queue rate limit update.
hidden: true
- name: fairness-key-rps-limit-default
type: string
display-type: float|default
description: |
Fairness key rate limit default in requests per second.
Accepts a float; or 'default' to unset.
- name: fairness-key-rps-limit-reason
type: string
description: Reason for fairness key rate limit update.
hidden: true
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review.

The rate limit parameters now carry -rps- in their name.
And display-type was added.

Comment on lines +219 to +221
if o.Type != "string" && o.DisplayType != "" {
return fmt.Errorf("display-type is only allowed for string options")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review.

Comment on lines +85 to +124
// Helper to parse RPS values for a given flag name.
// Accepts "default" or a non-negative float string.
parseRPS := func(flagName string) (*taskqueue.RateLimit, error) {
raw := strings.TrimSpace(c.Command.Flags().Lookup(flagName).Value.String())
if raw == "" {
return nil, fmt.Errorf("invalid value for --%s: must be a non-negative number or 'default'", flagName)
}
if strings.EqualFold(raw, "default") {
// Unset: returning nil RateLimit removes the existing rate limit.
return nil, nil
}
v, err := strconv.ParseFloat(raw, 32)
if err != nil {
return nil, fmt.Errorf("invalid value for --%s: must be a non-negative number or 'default'", flagName)
}
if v < 0 {
return nil, fmt.Errorf("invalid value for --%s: must be >= 0 or 'default'", flagName)
}
return &taskqueue.RateLimit{RequestsPerSecond: float32(v)}, nil
}

var queueRpsLimitParsed *taskqueue.RateLimit
if c.Command.Flags().Changed("queue-rps-limit") {
var err error
if queueRpsLimitParsed, err = parseRPS("queue-rps-limit"); err != nil {
return err
}
} else if c.Command.Flags().Changed("queue-rps-limit-reason") {
return fmt.Errorf("queue-rps-limit-reason can only be set if queue-rps-limit is updated")
}

var fairnessKeyRpsLimitDefaultParsed *taskqueue.RateLimit
if c.Command.Flags().Changed("fairness-key-rps-limit-default") {
var err error
if fairnessKeyRpsLimitDefaultParsed, err = parseRPS("fairness-key-rps-limit-default"); err != nil {
return err
}
} else if c.Command.Flags().Changed("fairness-key-rps-limit-default-reason") {
return fmt.Errorf("fairness-key-rps-limit-default-reason can only be set if fairness-key-rps-limit-default is updated")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review.

Comment on lines +139 to +153
// Add queue rate limit if specified (including unset)
if c.Command.Flags().Changed("queue-rps-limit") {
request.UpdateQueueRateLimit = &workflowservice.UpdateTaskQueueConfigRequest_RateLimitUpdate{
RateLimit: queueRpsLimitParsed,
Reason: c.QueueRpsLimitReason,
}
}

// Add fairness key rate limit default if specified (including unset)
if c.Command.Flags().Changed("fairness-key-rps-limit-default") {
request.UpdateFairnessKeyRateLimitDefault = &workflowservice.UpdateTaskQueueConfigRequest_RateLimitUpdate{
RateLimit: fairnessKeyRpsLimitDefaultParsed,
Reason: c.FairnessKeyRpsLimitReason,
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review. The helper is gone.


func (v *customStringFlag) Type() string {
return v.displayType
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This has changed since the review. It's a helper to allow control over the type that's displayed in the help text.

go.mod Outdated
go.temporal.io/sdk v1.36.0
go.temporal.io/sdk/contrib/envconfig v0.1.0
go.temporal.io/server v1.28.1
go.temporal.io/server v1.29.0-142.2
Copy link
Contributor

Choose a reason for hiding this comment

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

Bump to de-facto release candidate.

Copy link
Member

Choose a reason for hiding this comment

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

I think increasing server version should ideally be done separately and can be merged into main with all of next-server instead of buried in this PR and not bring over things in next-server. I also think we need to be increasing the UI server version at the same time.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh but it doesn't build without this change.

In this case, do we wait for the server release? I thought we would only switch to the stable release once that's out. Otherwise you have several PRs blocked for merging, right?

Copy link
Member

@cretz cretz Oct 2, 2025

Choose a reason for hiding this comment

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

Oh but it doesn't build without this change.

Right, neither does anything in next-server I assume

In this case, do we wait for the server release?

You can target the next-server branch with this PR, that's where we put things that depend on non-OSS-stable server tags. We make unstable/RC CLI releases off of unstable OSS tags from there if there is an urgent need to get something in front of a user. But yes, for this to land in stable CLI, it needs to refer to stable OSS version.

@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from 2af50b7 to c22ad2f Compare October 1, 2025 18:06
@stephanos stephanos requested a review from cretz October 1, 2025 18:07
@stephanos
Copy link
Contributor

Re-requesting review due to significant changes since last one. I highlighted them in GH comments.

go.mod Outdated
go.temporal.io/sdk v1.36.0
go.temporal.io/sdk/contrib/envconfig v0.1.0
go.temporal.io/server v1.28.1
go.temporal.io/server v1.29.0-142.2
Copy link
Member

Choose a reason for hiding this comment

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

I think increasing server version should ideally be done separately and can be merged into main with all of next-server instead of buried in this PR and not bring over things in next-server. I also think we need to be increasing the UI server version at the same time.

hidden: true
- name: fairness-key-rps-limit-default
type: string
display-type: float|default
Copy link
Member

Choose a reason for hiding this comment

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

If introducing a new property into this YAML format, can we update the admittedly-terse docs at the top of this file with information about it?

Copy link
Member

@cretz cretz Oct 2, 2025

Choose a reason for hiding this comment

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

I wonder if this would be better as a utility, e.g.

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}
}

This is untested (I just hand-typed here in PR), but the idea is there. Then you can call with OverrideFlagDisplayType(s.Command.Flags().Lookup("task-queue-type"), "string|float") after you have created the flag the regular way. This is less code and more generally applicable. Also, not sure such a small amount of code really deserves its own file, can probably just put at the bottom of commands.go, but up to you.

Copy link
Contributor

@stephanos stephanos Oct 2, 2025

Choose a reason for hiding this comment

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

I like that; definitely more composable.

flagVar, flagMeth, selfVar, o.fieldName(), o.Name, o.Short, defaultLit, desc)
if o.DisplayType != "" {
// Use custom flag
w.writeLinef("{")
Copy link
Member

Choose a reason for hiding this comment

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

I think we can just inline the work we need to do into one line of code instead of introducing a new block

@stephanos stephanos changed the base branch from main to next-server October 2, 2025 15:23
@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from c22ad2f to 9fd5378 Compare October 2, 2025 15:32
@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from 9fd5378 to 9c708ab Compare October 2, 2025 15:36
@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from 9e0d3f0 to 806f7d3 Compare October 2, 2025 15:42
@stephanos stephanos force-pushed the updateTaskQueueConfigCLI branch from 806f7d3 to 075e87d Compare October 2, 2025 15:44
Copy link
Member

@cretz cretz left a comment

Choose a reason for hiding this comment

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

LGTM. Note, if this command/feature is not GA, we need to make sure we mark it as such in the description.

return o.displayType
}

func OverrideFlagDisplayType(flag *pflag.Flag, displayType string) {
Copy link
Member

Choose a reason for hiding this comment

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

Realized this is same package, could make this non-exported (i.e. lowercase), but not a big deal

@stephanos stephanos merged commit 81fc3b8 into temporalio:next-server Oct 2, 2025
7 checks passed
bergundy pushed a commit that referenced this pull request Oct 3, 2025
<!--- Note to EXTERNAL Contributors -->
<!-- Thanks for opening a PR! 
If it is a significant code change, please **make sure there is an open
issue** for this.
We work best with you when we have accepted the idea first before you
code. -->

<!--- For ALL Contributors 👇 -->

## What was changed
+ Added a new `report-config` field in the describe command to retrieve
updated task queue configs if exists.
+ Implement display logic for config table along with truncation of
large update reasons or update identities.
**Note : These changes are only a part of the legacy mode of the
describeTaskQueueApi.**

```
./temporal task-queue describe \                                                               
 --task-queue=test-display-queue \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
```

Sample Response
```
./temporal task-queue describe \
 --task-queue=hello-world \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
Pollers:
  Identity  LastAccessTime  RatePerSecond

Task Queue Configuration:
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Added separate config Subcommand for getting/setting configs.
```
./temporal task-queue config --help  
Manage Task Queue configuration:

temporal task-queue config [command] [options]

Available commands:
- get: Retrieve the current configuration for a task queue
- set: Update the configuration for a task queue

Usage:
  temporal task-queue config [command]

Available Commands:
  get         Get Task Queue configuration
  set         Set Task Queue configuration
```
---

+ Get Subcommand
```
./temporal task-queue config get --help
Retrieve the current configuration for a Task Queue:

temporal task-queue config get \
    --task-queue YourTaskQueue \
    --task-queue-type activity

This command returns the current configuration including:
- Queue rate limit: The overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

Usage:
  temporal task-queue config get [flags]
```
Sample Response
```
./temporal task-queue config get \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --namespace=default
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Set Subcommand
```
./temporal task-queue config set --help
Update a Task Queue's overall rate limit and the default rate limit for all fairness keys:

temporal task-queue config set \
    --task-queue YourTaskQueue \
    --task-queue-type activity \
    --namespace YourNamespace \
    --queue-rps-limit <requests_per_second:float> \
    --queue-rps-limit-reason <reason_string> \
    --fairness-key-rps-limit-default <requests_per_second:float> \
    --fairness-key-rps-limit-reason <reason_string>

This command supports updating:
- Queue rate limits: Controls the overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Sets default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

To unset a rate limit, pass in 'default', for example: --queue-rps-limit default

Usage:
  temporal task-queue config set [flags]

Flags:
      --fairness-key-rps-limit-default float|default   Fairness key rate limit default in requests per second. Accepts a float; or 'default' to unset.
      --fairness-key-rps-limit-reason string           Reason for fairness key rate limit update.
  -h, --help                                           help for set
      --queue-rps-limit float|default                  Queue rate limit in requests per second. Accepts a float; or 'default' to unset.
      --queue-rps-limit-reason string                  Reason for queue rate limit update.
  -t, --task-queue string                              Task Queue name. Required.
      --task-queue-type string                         Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.
```
   

Sample response : 
```
./temporal task-queue config set \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --fairness-key-rps-limit-default=100 \
  --fairness-key-rps-limit-reason="Fairness key test" \
  --identity="api-tester" \
  --namespace=default
Successfully updated task queue configuration
  Config  {"fairnessKeysRateLimitDefault":{"rateLimit":{"requestsPerSecond":100},"metadata":{"reason":"Fairness key test","updateIdentity":"api-tester","updateTime":"2025-08-12T04:31:46.640Z"}}}
```

## Why?
+ Cli support for `UpdateTaskQueueConfig` api - new api that allows
updates of rate limits against task queues.

## Checklist

1. How was this tested:
+ Added tests.

2. Any docs updates needed?
Pending.

---------

Co-authored-by: Stephan Behnke <[email protected]>
Co-authored-by: Stephan Behnke <[email protected]>
bergundy pushed a commit that referenced this pull request Oct 6, 2025
<!--- Note to EXTERNAL Contributors -->
<!-- Thanks for opening a PR! 
If it is a significant code change, please **make sure there is an open
issue** for this.
We work best with you when we have accepted the idea first before you
code. -->

<!--- For ALL Contributors 👇 -->

## What was changed
+ Added a new `report-config` field in the describe command to retrieve
updated task queue configs if exists.
+ Implement display logic for config table along with truncation of
large update reasons or update identities.
**Note : These changes are only a part of the legacy mode of the
describeTaskQueueApi.**

```
./temporal task-queue describe \                                                               
 --task-queue=test-display-queue \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
```

Sample Response
```
./temporal task-queue describe \
 --task-queue=hello-world \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
Pollers:
  Identity  LastAccessTime  RatePerSecond

Task Queue Configuration:
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Added separate config Subcommand for getting/setting configs.
```
./temporal task-queue config --help  
Manage Task Queue configuration:

temporal task-queue config [command] [options]

Available commands:
- get: Retrieve the current configuration for a task queue
- set: Update the configuration for a task queue

Usage:
  temporal task-queue config [command]

Available Commands:
  get         Get Task Queue configuration
  set         Set Task Queue configuration
```
---

+ Get Subcommand
```
./temporal task-queue config get --help
Retrieve the current configuration for a Task Queue:

temporal task-queue config get \
    --task-queue YourTaskQueue \
    --task-queue-type activity

This command returns the current configuration including:
- Queue rate limit: The overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

Usage:
  temporal task-queue config get [flags]
```
Sample Response
```
./temporal task-queue config get \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --namespace=default
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime    
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Set Subcommand
```
./temporal task-queue config set --help
Update a Task Queue's overall rate limit and the default rate limit for all fairness keys:

temporal task-queue config set \
    --task-queue YourTaskQueue \
    --task-queue-type activity \
    --namespace YourNamespace \
    --queue-rps-limit <requests_per_second:float> \
    --queue-rps-limit-reason <reason_string> \
    --fairness-key-rps-limit-default <requests_per_second:float> \
    --fairness-key-rps-limit-reason <reason_string>

This command supports updating:
- Queue rate limits: Controls the overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Sets default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

To unset a rate limit, pass in 'default', for example: --queue-rps-limit default

Usage:
  temporal task-queue config set [flags]

Flags:
      --fairness-key-rps-limit-default float|default   Fairness key rate limit default in requests per second. Accepts a float; or 'default' to unset.
      --fairness-key-rps-limit-reason string           Reason for fairness key rate limit update.
  -h, --help                                           help for set
      --queue-rps-limit float|default                  Queue rate limit in requests per second. Accepts a float; or 'default' to unset.
      --queue-rps-limit-reason string                  Reason for queue rate limit update.
  -t, --task-queue string                              Task Queue name. Required.
      --task-queue-type string                         Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.
```
   

Sample response : 
```
./temporal task-queue config set \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --fairness-key-rps-limit-default=100 \
  --fairness-key-rps-limit-reason="Fairness key test" \
  --identity="api-tester" \
  --namespace=default
Successfully updated task queue configuration
  Config  {"fairnessKeysRateLimitDefault":{"rateLimit":{"requestsPerSecond":100},"metadata":{"reason":"Fairness key test","updateIdentity":"api-tester","updateTime":"2025-08-12T04:31:46.640Z"}}}
```

## Why?
+ Cli support for `UpdateTaskQueueConfig` api - new api that allows
updates of rate limits against task queues.

## Checklist

1. How was this tested:
+ Added tests.

2. Any docs updates needed?
Pending.

---------

Co-authored-by: Stephan Behnke <[email protected]>
Co-authored-by: Stephan Behnke <[email protected]>
carlydf pushed a commit that referenced this pull request Jan 21, 2026
<!--- Note to EXTERNAL Contributors -->
<!-- Thanks for opening a PR!
If it is a significant code change, please **make sure there is an open
issue** for this.
We work best with you when we have accepted the idea first before you
code. -->

<!--- For ALL Contributors 👇 -->

+ Added a new `report-config` field in the describe command to retrieve
updated task queue configs if exists.
+ Implement display logic for config table along with truncation of
large update reasons or update identities.
**Note : These changes are only a part of the legacy mode of the
describeTaskQueueApi.**

```
./temporal task-queue describe \
 --task-queue=test-display-queue \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
```

Sample Response
```
./temporal task-queue describe \
 --task-queue=hello-world \
 --task-queue-type-legacy=activity \
 -n=default \
 --report-config \
 --legacy-mode
Pollers:
  Identity  LastAccessTime  RatePerSecond

Task Queue Configuration:
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Added separate config Subcommand for getting/setting configs.
```
./temporal task-queue config --help
Manage Task Queue configuration:

temporal task-queue config [command] [options]

Available commands:
- get: Retrieve the current configuration for a task queue
- set: Update the configuration for a task queue

Usage:
  temporal task-queue config [command]

Available Commands:
  get         Get Task Queue configuration
  set         Set Task Queue configuration
```
---

+ Get Subcommand
```
./temporal task-queue config get --help
Retrieve the current configuration for a Task Queue:

temporal task-queue config get \
    --task-queue YourTaskQueue \
    --task-queue-type activity

This command returns the current configuration including:
- Queue rate limit: The overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

Usage:
  temporal task-queue config get [flags]
```
Sample Response
```
./temporal task-queue config get \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --namespace=default
Note: Long content may be truncated. Use --output json for full details.
              Setting                     Value              Reason        UpdatedBy       UpdatedTime
  Fairness Key Rate Limit Default  100 requests/second  Fairness key test  api-tester  2025-08-12 04:31:46
```

---

+ Set Subcommand
```
./temporal task-queue config set --help
Update a Task Queue's overall rate limit and the default rate limit for all fairness keys:

temporal task-queue config set \
    --task-queue YourTaskQueue \
    --task-queue-type activity \
    --namespace YourNamespace \
    --queue-rps-limit <requests_per_second:float> \
    --queue-rps-limit-reason <reason_string> \
    --fairness-key-rps-limit-default <requests_per_second:float> \
    --fairness-key-rps-limit-reason <reason_string>

This command supports updating:
- Queue rate limits: Controls the overall rate limit of the task queue.
  This setting overrides the worker rate limit if set.
  Unless modified, this is the system-defined rate limit.
- Fairness key rate limit defaults: Sets default rate limits for fairness keys.
  If set, each individual fairness key will be limited to this rate,
  scaled by the weight of the fairness key.

To unset a rate limit, pass in 'default', for example: --queue-rps-limit default

Usage:
  temporal task-queue config set [flags]

Flags:
      --fairness-key-rps-limit-default float|default   Fairness key rate limit default in requests per second. Accepts a float; or 'default' to unset.
      --fairness-key-rps-limit-reason string           Reason for fairness key rate limit update.
  -h, --help                                           help for set
      --queue-rps-limit float|default                  Queue rate limit in requests per second. Accepts a float; or 'default' to unset.
      --queue-rps-limit-reason string                  Reason for queue rate limit update.
  -t, --task-queue string                              Task Queue name. Required.
      --task-queue-type string                         Task Queue type. Accepted values: workflow, activity, nexus. Accepted values: workflow, activity, nexus. Required.
```

Sample response :
```
./temporal task-queue config set \
  --task-queue=hello-world \
  --task-queue-type=activity \
  --fairness-key-rps-limit-default=100 \
  --fairness-key-rps-limit-reason="Fairness key test" \
  --identity="api-tester" \
  --namespace=default
Successfully updated task queue configuration
  Config  {"fairnessKeysRateLimitDefault":{"rateLimit":{"requestsPerSecond":100},"metadata":{"reason":"Fairness key test","updateIdentity":"api-tester","updateTime":"2025-08-12T04:31:46.640Z"}}}
```

+ Cli support for `UpdateTaskQueueConfig` api - new api that allows
updates of rate limits against task queues.

1. How was this tested:
+ Added tests.

2. Any docs updates needed?
Pending.

---------

Co-authored-by: Stephan Behnke <[email protected]>
Co-authored-by: Stephan Behnke <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants