Skip to content

Implement UpdateWorkerDeploymentVersionComputeConfig#9746

Merged
ShahabT merged 3 commits intoserverlessfrom
wdv-compute-config
Mar 31, 2026
Merged

Implement UpdateWorkerDeploymentVersionComputeConfig#9746
ShahabT merged 3 commits intoserverlessfrom
wdv-compute-config

Conversation

@ShahabT
Copy link
Copy Markdown
Contributor

@ShahabT ShahabT commented Mar 30, 2026

What changed?

Implement UpdateWorkerDeploymentVersionComputeConfig

Why?

For server-scaled workers

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Potential risks

None

@ShahabT ShahabT requested review from a team as code owners March 30, 2026 20:38
@rkannan82 rkannan82 self-requested a review March 30, 2026 22:55
for name, sg := range scalingGroups {
specs[name] = wciiface.ScalingGroupSpec{
TaskTypes: sg.GetTaskQueueTypes(),
Compute: wciiface.ComputeProviderSpec{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

also set the scaling spec?

}

// Apply the validated config to state.
d.VersionState.ComputeConfig = newConfig
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you will need to call the Worker Controller Instance Client Update method to actually apply the config

Copy link
Copy Markdown
Contributor

@rkannan82 rkannan82 left a comment

Choose a reason for hiding this comment

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

Minor comments only.

}

// used as Worker Deployment Version workflow update input:
message UpdateVersionComputeConfigArgs {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: can we drop this version here?

map<string, temporal.api.compute.v1.ComputeConfigScalingGroup> scaling_groups = 1;
}

// used as Worker Deployment Version workflow update input:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Input for the UpdateComputeConfig workflow update on a version workflow.

temporal.api.deployment.v1.WorkerDeploymentInfo.WorkerDeploymentVersionSummary ramping_version_summary = 6;
}

// used as activity input for validating compute config scaling groups via
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Input for the activity that validates ...

string request_id = 2;
// Scaling groups to add or update.
map<string, ScalingGroupUpdate> upsert_scaling_groups = 3;
// Names of scaling groups to remove.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Names that don't match an existing group are ignored.

// Supports top-level fields and one level of nesting (e.g. "provider.type").
func applyFieldMask(dst, src *computepb.ComputeConfigScalingGroup, paths []string) {
for _, path := range paths {
switch path {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we fail if we encounter an unsupported field?

}

if err := d.computeConfigLock.Lock(ctx); err != nil {
d.logger.Error("Could not acquire compute config lock")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we add some context here like what workflow, etc?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we're using the sdk logger which has the workflow info

// also lock compute config lock to ensure that the compute config is not updated while the version is being deleted.
err = d.computeConfigLock.Lock(ctx)
if err != nil {
d.logger.Error("Could not acquire compute config lock")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we add some context here like what workflow, etc?


if err := d.computeConfigLock.Lock(ctx); err != nil {
d.logger.Error("Could not acquire compute config lock")
return nil, serviceerror.NewDeadlineExceeded("Could not acquire compute config lock")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not return the original error? Deadline exceeded can be misleading.

// it's better to CaN because some history events are built now.
d.setStateChanged()
d.lock.Unlock()
d.computeConfigLock.Unlock()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Convention is to release the lock in reverse order.

computeConfigLock.Unlock()
lock.Unlock();

a: nil,
logger: sdklog.With(workflow.GetLogger(ctx), "wf-namespace", versionWorkflowArgs.NamespaceName),
metrics: workflow.GetMetricsHandler(ctx).WithTags(map[string]string{"namespace": versionWorkflowArgs.NamespaceName}),
lock: workflow.NewMutex(ctx),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggest adding: // Lock ordering: always acquire lock before computeConfigLock.

groupSpec := wciiface.ScalingGroupSpec{
TaskTypes: sg.GetTaskQueueTypes(),
Compute: wciiface.ComputeProviderSpec{
ProviderType: wciiface.ComputeProviderType(sg.GetProvider().GetType()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@ShahabT @02strich ok, so are we going to do the requisite converter.DataConverter.FromPayload() calls here or are we going to change the WCI ifaces to have blob/string fields and do the FromPayload() conversion stuff in temporal-auto-scaled-workers?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the FromPayload() conversion stuff in temporal-auto-scaled-workers

this ^

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@ShahabT OK, in that case, we will need to change the client interface and structs in temporal-auto-scaled-workers, yes?

@ShahabT ShahabT merged commit 867bbc0 into serverless Mar 31, 2026
12 of 14 checks passed
@ShahabT ShahabT deleted the wdv-compute-config branch March 31, 2026 20:24
ShahabT added a commit that referenced this pull request Apr 3, 2026
This PR merges the serverless feature branch into main.

Individual PRs included in this branch:
- #9380
- #9651
- #9412
- #9746
- #9759

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Stefan Richter <stefan.richter@temporal.io>
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.

4 participants