Skip to content

Commit cf9259c

Browse files
cbsandeep10claude
andauthored
Add versioned PollerGroupsInfo, deprecate poller_group_infos (#819)
**What changed?** Introduce a `PollerGroupsInfo` message carrying a monotonically increasing `version` alongside the poller groups, so the SDK can ignore stale snapshots that arrive out of order (e.g. after polls are cancelled during cell migration). Deprecate the repeated `poller_group_infos` fields in favor of the new `poller_groups_info` field on `DescribeNamespaceResponse` and the Poll Workflow/Activity/Nexus TaskQueue responses. **Why?** The server sends poller-group assignment info to the SDK via poll responses. During cell migration, the server cancels in-flight polls and returns updated poller-group info, but responses can arrive out of order — a stale snapshot can land after a fresh one and overwrite it. Attaching a monotonically increasing `version` lets the SDK ignore any snapshot that isn't newer than the one it has already applied, preventing stale overwrites. **Breaking changes** None. New fields use fresh field numbers (no reuse), and the old `poller_group_infos` fields are only marked `[deprecated = true]` — still fully wire-compatible. `buf breaking` against `main` passes clean. Consumers referencing the deprecated fields will see deprecation warnings but will not break. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 7dfff2d commit cf9259c

4 files changed

Lines changed: 117 additions & 8 deletions

File tree

openapi/openapiv2.json

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15242,7 +15242,11 @@
1524215242
"type": "object",
1524315243
"$ref": "#/definitions/v1PollerGroupInfo"
1524415244
},
15245-
"description": "The initial info that client should use for poller group assignment. This information is\nupdated through poll response. Client is supposed to use the info received in the latest\npoll response."
15245+
"description": "Deprecated. Use `poller_groups_info` instead, which carries a version so the client can\nignore stale updates.\nThe initial info that client should use for poller group assignment. This information is\nupdated through poll response. Client is supposed to use the info received in the latest\npoll response."
15246+
},
15247+
"pollerGroupsInfo": {
15248+
"$ref": "#/definitions/v1PollerGroupsInfo",
15249+
"description": "The initial, versioned info that client should use for poller group assignment. This\ninformation is updated through poll responses. Client is supposed to use the info with the\nhighest version it has received."
1524615250
}
1524715251
}
1524815252
},
@@ -17943,7 +17947,11 @@
1794317947
"type": "object",
1794417948
"$ref": "#/definitions/v1PollerGroupInfo"
1794517949
},
17946-
"description": "The weighted list of poller groups IDs that client should use for future polls to this task\nqueue. Client is expected to:\n 1. Maintain minimum number of pollers no less than the number of groups.\n 2. Try to assign the next poll to a group without any pending polls,\n 3. If every group has some pending polls, assign the next poll to a group randomly\n according to the weights."
17950+
"description": "Deprecated. Use `poller_groups_info` instead, which carries a version so the client can\nignore stale updates.\nThe weighted list of poller groups IDs that client should use for future polls to this task\nqueue. Client is expected to:\n 1. Maintain minimum number of pollers no less than the number of groups.\n 2. Try to assign the next poll to a group without any pending polls,\n 3. If every group has some pending polls, assign the next poll to a group randomly\n according to the weights."
17951+
},
17952+
"pollerGroupsInfo": {
17953+
"$ref": "#/definitions/v1PollerGroupsInfo",
17954+
"description": "The weighted, versioned list of poller groups IDs that client should use for future polls to\nthis task queue. Client should ignore this if it has already applied a snapshot with a\nversion greater than or equal to `poller_groups_info.version`. Client is expected to:\n 1. Maintain minimum number of pollers no less than the number of groups.\n 2. Try to assign the next poll to a group without any pending polls,\n 3. If every group has some pending polls, assign the next poll to a group randomly\n according to the weights."
1794717955
}
1794817956
}
1794917957
},
@@ -17959,6 +17967,25 @@
1795917967
}
1796017968
}
1796117969
},
17970+
"v1PollerGroupsInfo": {
17971+
"type": "object",
17972+
"properties": {
17973+
"version": {
17974+
"type": "string",
17975+
"format": "int64",
17976+
"description": "Monotonically increasing version of this snapshot. A client should ignore any snapshot whose\nversion is not greater than the one it last applied."
17977+
},
17978+
"pollerGroups": {
17979+
"type": "array",
17980+
"items": {
17981+
"type": "object",
17982+
"$ref": "#/definitions/v1PollerGroupInfo"
17983+
},
17984+
"description": "The weighted list of poller groups the client should use for future polls to this task queue."
17985+
}
17986+
},
17987+
"description": "A versioned snapshot of the poller groups the client should use for future polls to a task\nqueue. The version is monotonically increasing so that a client can ignore a snapshot that is\nolder than the one it has already applied."
17988+
},
1796217989
"v1PollerInfo": {
1796317990
"type": "object",
1796417991
"properties": {

openapi/openapiv3.yaml

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11683,9 +11683,18 @@ components:
1168311683
items:
1168411684
$ref: '#/components/schemas/PollerGroupInfo'
1168511685
description: |-
11686-
The initial info that client should use for poller group assignment. This information is
11686+
Deprecated. Use `poller_groups_info` instead, which carries a version so the client can
11687+
ignore stale updates.
11688+
The initial info that client should use for poller group assignment. This information is
1168711689
updated through poll response. Client is supposed to use the info received in the latest
1168811690
poll response.
11691+
pollerGroupsInfo:
11692+
allOf:
11693+
- $ref: '#/components/schemas/PollerGroupsInfo'
11694+
description: |-
11695+
The initial, versioned info that client should use for poller group assignment. This
11696+
information is updated through poll responses. Client is supposed to use the info with the
11697+
highest version it has received.
1168911698
DescribeNexusOperationExecutionResponse:
1169011699
type: object
1169111700
properties:
@@ -14377,12 +14386,25 @@ components:
1437714386
items:
1437814387
$ref: '#/components/schemas/PollerGroupInfo'
1437914388
description: |-
14380-
The weighted list of poller groups IDs that client should use for future polls to this task
14389+
Deprecated. Use `poller_groups_info` instead, which carries a version so the client can
14390+
ignore stale updates.
14391+
The weighted list of poller groups IDs that client should use for future polls to this task
1438114392
queue. Client is expected to:
1438214393
1. Maintain minimum number of pollers no less than the number of groups.
1438314394
2. Try to assign the next poll to a group without any pending polls,
1438414395
3. If every group has some pending polls, assign the next poll to a group randomly
1438514396
according to the weights.
14397+
pollerGroupsInfo:
14398+
allOf:
14399+
- $ref: '#/components/schemas/PollerGroupsInfo'
14400+
description: |-
14401+
The weighted, versioned list of poller groups IDs that client should use for future polls to
14402+
this task queue. Client should ignore this if it has already applied a snapshot with a
14403+
version greater than or equal to `poller_groups_info.version`. Client is expected to:
14404+
1. Maintain minimum number of pollers no less than the number of groups.
14405+
2. Try to assign the next poll to a group without any pending polls,
14406+
3. If every group has some pending polls, assign the next poll to a group randomly
14407+
according to the weights.
1438614408
PollerGroupInfo:
1438714409
type: object
1438814410
properties:
@@ -14391,6 +14413,23 @@ components:
1439114413
weight:
1439214414
type: number
1439314415
format: float
14416+
PollerGroupsInfo:
14417+
type: object
14418+
properties:
14419+
version:
14420+
type: string
14421+
description: |-
14422+
Monotonically increasing version of this snapshot. A client should ignore any snapshot whose
14423+
version is not greater than the one it last applied.
14424+
pollerGroups:
14425+
type: array
14426+
items:
14427+
$ref: '#/components/schemas/PollerGroupInfo'
14428+
description: The weighted list of poller groups the client should use for future polls to this task queue.
14429+
description: |-
14430+
A versioned snapshot of the poller groups the client should use for future polls to a task
14431+
queue. The version is monotonically increasing so that a client can ignore a snapshot that is
14432+
older than the one it has already applied.
1439414433
PollerInfo:
1439514434
type: object
1439614435
properties:

temporal/api/taskqueue/v1/message.proto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,17 @@ message PollerGroupInfo {
308308
float weight = 2;
309309
}
310310

311+
// A versioned snapshot of the poller groups the client should use for future polls to a task
312+
// queue. The version is monotonically increasing so that a client can ignore a snapshot that is
313+
// older than the one it has already applied.
314+
message PollerGroupsInfo {
315+
// Monotonically increasing version of this snapshot. A client should ignore any snapshot whose
316+
// version is not greater than the one it last applied.
317+
int64 version = 1;
318+
// The weighted list of poller groups the client should use for future polls to this task queue.
319+
repeated PollerGroupInfo poller_groups = 2;
320+
}
321+
311322
// Attached to task responses to give hints to the SDK about how it may adjust its number of
312323
// pollers.
313324
message PollerScalingDecision {

temporal/api/workflowservice/v1/request_response.proto

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,16 @@ message DescribeNamespaceResponse {
102102
// Contains the historical state of failover_versions for the cluster, truncated to contain only the last N
103103
// states to ensure that the list does not grow unbounded.
104104
repeated temporal.api.replication.v1.FailoverStatus failover_history = 6;
105+
// Deprecated. Use `poller_groups_info` instead, which carries a version so the client can
106+
// ignore stale updates.
105107
// The initial info that client should use for poller group assignment. This information is
106108
// updated through poll response. Client is supposed to use the info received in the latest
107109
// poll response.
108-
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 7;
110+
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 7 [deprecated = true];
111+
// The initial, versioned info that client should use for poller group assignment. This
112+
// information is updated through poll responses. Client is supposed to use the info with the
113+
// highest version it has received.
114+
temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 8;
109115
}
110116

111117
message UpdateNamespaceRequest {
@@ -357,13 +363,23 @@ message PollWorkflowTaskQueueResponse {
357363
// This poller group ID identifies the owner of the workflow task awaiting for query response.
358364
// Corresponding RespondQueryTaskCompleted should pass this value for proper routing.
359365
string poller_group_id = 17;
366+
// Deprecated. Use `poller_groups_info` instead, which carries a version so the client can
367+
// ignore stale updates.
360368
// The weighted list of poller groups IDs that client should use for future polls to this task
361369
// queue. Client is expected to:
362370
// 1. Maintain minimum number of pollers no less than the number of groups.
363371
// 2. Try to assign the next poll to a group without any pending polls,
364372
// 3. If every group has some pending polls, assign the next poll to a group randomly
365373
// according to the weights.
366-
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 18;
374+
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 18 [deprecated = true];
375+
// The weighted, versioned list of poller groups IDs that client should use for future polls to
376+
// this task queue. Client should ignore this if it has already applied a snapshot with a
377+
// version greater than or equal to `poller_groups_info.version`. Client is expected to:
378+
// 1. Maintain minimum number of pollers no less than the number of groups.
379+
// 2. Try to assign the next poll to a group without any pending polls,
380+
// 3. If every group has some pending polls, assign the next poll to a group randomly
381+
// according to the weights.
382+
temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 19;
367383
}
368384

369385
message RespondWorkflowTaskCompletedRequest {
@@ -583,7 +599,15 @@ message PollActivityTaskQueueResponse {
583599
// 2. Try to assign the next poll to a group without any pending polls,
584600
// 3. If every group has some pending polls, assign the next poll to a group randomly
585601
// according to the weights.
586-
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 21;
602+
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 21 [deprecated = true];
603+
// The weighted, versioned list of poller groups IDs that client should use for future polls to
604+
// this task queue. Client should ignore this if it has already applied a snapshot with a
605+
// version greater than or equal to `poller_groups_info.version`. Client is expected to:
606+
// 1. Maintain minimum number of pollers no less than the number of groups.
607+
// 2. Try to assign the next poll to a group without any pending polls,
608+
// 3. If every group has some pending polls, assign the next poll to a group randomly
609+
// according to the weights.
610+
temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 22;
587611
}
588612

589613
message RecordActivityTaskHeartbeatRequest {
@@ -2006,7 +2030,15 @@ message PollNexusTaskQueueResponse {
20062030
// 2. Try to assign the next poll to a group without any pending polls,
20072031
// 3. If every group has some pending polls, assign the next poll to a group randomly
20082032
// according to the weights.
2009-
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 5;
2033+
repeated temporal.api.taskqueue.v1.PollerGroupInfo poller_group_infos = 5 [deprecated = true];
2034+
// The weighted, versioned list of poller groups IDs that client should use for future polls to
2035+
// this task queue. Client should ignore this if it has already applied a snapshot with a
2036+
// version greater than or equal to `poller_groups_info.version`. Client is expected to:
2037+
// 1. Maintain minimum number of pollers no less than the number of groups.
2038+
// 2. Try to assign the next poll to a group without any pending polls,
2039+
// 3. If every group has some pending polls, assign the next poll to a group randomly
2040+
// according to the weights.
2041+
temporal.api.taskqueue.v1.PollerGroupsInfo poller_groups_info = 6;
20102042
}
20112043

20122044
message RespondNexusTaskCompletedRequest {

0 commit comments

Comments
 (0)