diff --git a/api/matchingservice/v1/request_response.go-helpers.pb.go b/api/matchingservice/v1/request_response.go-helpers.pb.go index d6f02df5fd..8966fe90a5 100644 --- a/api/matchingservice/v1/request_response.go-helpers.pb.go +++ b/api/matchingservice/v1/request_response.go-helpers.pb.go @@ -2742,3 +2742,77 @@ func (this *DescribeWorkerResponse) Equal(that interface{}) bool { return proto.Equal(this, that1) } + +// Marshal an object of type CheckTaskQueueVersionMembershipRequest to the protobuf v3 wire format +func (val *CheckTaskQueueVersionMembershipRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CheckTaskQueueVersionMembershipRequest from the protobuf v3 wire format +func (val *CheckTaskQueueVersionMembershipRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CheckTaskQueueVersionMembershipRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CheckTaskQueueVersionMembershipRequest values are equivalent by recursively +// comparing the message's fields. +// For more information see the documentation for +// https://pkg.go.dev/google.golang.org/protobuf/proto#Equal +func (this *CheckTaskQueueVersionMembershipRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CheckTaskQueueVersionMembershipRequest + switch t := that.(type) { + case *CheckTaskQueueVersionMembershipRequest: + that1 = t + case CheckTaskQueueVersionMembershipRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CheckTaskQueueVersionMembershipResponse to the protobuf v3 wire format +func (val *CheckTaskQueueVersionMembershipResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CheckTaskQueueVersionMembershipResponse from the protobuf v3 wire format +func (val *CheckTaskQueueVersionMembershipResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CheckTaskQueueVersionMembershipResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CheckTaskQueueVersionMembershipResponse values are equivalent by recursively +// comparing the message's fields. +// For more information see the documentation for +// https://pkg.go.dev/google.golang.org/protobuf/proto#Equal +func (this *CheckTaskQueueVersionMembershipResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CheckTaskQueueVersionMembershipResponse + switch t := that.(type) { + case *CheckTaskQueueVersionMembershipResponse: + that1 = t + case CheckTaskQueueVersionMembershipResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} diff --git a/api/matchingservice/v1/request_response.pb.go b/api/matchingservice/v1/request_response.pb.go index 48503959c8..0c05163e11 100644 --- a/api/matchingservice/v1/request_response.pb.go +++ b/api/matchingservice/v1/request_response.pb.go @@ -4752,6 +4752,118 @@ func (x *DescribeWorkerResponse) GetWorkerInfo() *v114.WorkerInfo { return nil } +type CheckTaskQueueVersionMembershipRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + TaskQueue string `protobuf:"bytes,2,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` + TaskQueueType v19.TaskQueueType `protobuf:"varint,3,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + Version *v110.WorkerDeploymentVersion `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckTaskQueueVersionMembershipRequest) Reset() { + *x = CheckTaskQueueVersionMembershipRequest{} + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckTaskQueueVersionMembershipRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckTaskQueueVersionMembershipRequest) ProtoMessage() {} + +func (x *CheckTaskQueueVersionMembershipRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[74] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckTaskQueueVersionMembershipRequest.ProtoReflect.Descriptor instead. +func (*CheckTaskQueueVersionMembershipRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{74} +} + +func (x *CheckTaskQueueVersionMembershipRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *CheckTaskQueueVersionMembershipRequest) GetTaskQueue() string { + if x != nil { + return x.TaskQueue + } + return "" +} + +func (x *CheckTaskQueueVersionMembershipRequest) GetTaskQueueType() v19.TaskQueueType { + if x != nil { + return x.TaskQueueType + } + return v19.TaskQueueType(0) +} + +func (x *CheckTaskQueueVersionMembershipRequest) GetVersion() *v110.WorkerDeploymentVersion { + if x != nil { + return x.Version + } + return nil +} + +type CheckTaskQueueVersionMembershipResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + IsMember bool `protobuf:"varint,1,opt,name=is_member,json=isMember,proto3" json:"is_member,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckTaskQueueVersionMembershipResponse) Reset() { + *x = CheckTaskQueueVersionMembershipResponse{} + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckTaskQueueVersionMembershipResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckTaskQueueVersionMembershipResponse) ProtoMessage() {} + +func (x *CheckTaskQueueVersionMembershipResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[75] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckTaskQueueVersionMembershipResponse.ProtoReflect.Descriptor instead. +func (*CheckTaskQueueVersionMembershipResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{75} +} + +func (x *CheckTaskQueueVersionMembershipResponse) GetIsMember() bool { + if x != nil { + return x.IsMember + } + return false +} + // (-- api-linter: core::0123::resource-annotation=disabled --) type DescribeVersionedTaskQueuesRequest_VersionTaskQueue struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -4763,7 +4875,7 @@ type DescribeVersionedTaskQueuesRequest_VersionTaskQueue struct { func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) Reset() { *x = DescribeVersionedTaskQueuesRequest_VersionTaskQueue{} - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[75] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4775,7 +4887,7 @@ func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) String() string { func (*DescribeVersionedTaskQueuesRequest_VersionTaskQueue) ProtoMessage() {} func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[75] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4821,7 +4933,7 @@ type DescribeVersionedTaskQueuesResponse_VersionTaskQueue struct { func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) Reset() { *x = DescribeVersionedTaskQueuesResponse_VersionTaskQueue{} - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[76] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4833,7 +4945,7 @@ func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) String() string { func (*DescribeVersionedTaskQueuesResponse_VersionTaskQueue) ProtoMessage() {} func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[76] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4887,7 +4999,7 @@ type UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest struct { func (x *UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest) Reset() { *x = UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest{} - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[79] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4899,7 +5011,7 @@ func (x *UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest) String() st func (*UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest) ProtoMessage() {} func (x *UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[79] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4935,7 +5047,7 @@ type UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds struct { func (x *UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds) Reset() { *x = UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds{} - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[80] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4947,7 +5059,7 @@ func (x *UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds) String() string func (*UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds) ProtoMessage() {} func (x *UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[80] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4985,7 +5097,7 @@ type DispatchNexusTaskResponse_Timeout struct { func (x *DispatchNexusTaskResponse_Timeout) Reset() { *x = DispatchNexusTaskResponse_Timeout{} - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[82] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4997,7 +5109,7 @@ func (x *DispatchNexusTaskResponse_Timeout) String() string { func (*DispatchNexusTaskResponse_Timeout) ProtoMessage() {} func (x *DispatchNexusTaskResponse_Timeout) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[82] + mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5374,7 +5486,15 @@ const file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc "\arequest\x18\x02 \x01(\v26.temporal.api.workflowservice.v1.DescribeWorkerRequestR\arequest\"]\n" + "\x16DescribeWorkerResponse\x12C\n" + "\vworker_info\x18\x01 \x01(\v2\".temporal.api.worker.v1.WorkerInfoR\n" + - "workerInfoB>ZZ temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest - 84, // 1: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 85, // 2: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 86, // 3: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.query:type_name -> temporal.api.query.v1.WorkflowQuery - 87, // 4: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo - 88, // 5: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 89, // 6: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp - 89, // 7: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp - 74, // 8: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.queries:type_name -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry - 90, // 9: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.messages:type_name -> temporal.api.protocol.v1.Message - 91, // 10: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.history:type_name -> temporal.api.history.v1.History - 92, // 11: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision - 93, // 12: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest - 84, // 13: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 94, // 14: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.activity_type:type_name -> temporal.api.common.v1.ActivityType - 95, // 15: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.input:type_name -> temporal.api.common.v1.Payloads - 89, // 16: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp - 96, // 17: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.schedule_to_close_timeout:type_name -> google.protobuf.Duration - 89, // 18: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp - 96, // 19: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.start_to_close_timeout:type_name -> google.protobuf.Duration - 96, // 20: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_timeout:type_name -> google.protobuf.Duration - 89, // 21: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp - 95, // 22: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads - 85, // 23: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 97, // 24: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.header:type_name -> temporal.api.common.v1.Header - 92, // 25: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision - 98, // 26: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.priority:type_name -> temporal.api.common.v1.Priority - 99, // 27: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy - 84, // 28: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 88, // 29: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 96, // 30: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration - 100, // 31: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 101, // 32: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 102, // 33: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 98, // 34: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.priority:type_name -> temporal.api.common.v1.Priority - 84, // 35: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 88, // 36: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 96, // 37: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration - 100, // 38: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 101, // 39: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 102, // 40: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 98, // 41: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.priority:type_name -> temporal.api.common.v1.Priority - 88, // 42: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 103, // 43: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.query_request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest - 101, // 44: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 102, // 45: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 98, // 46: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.priority:type_name -> temporal.api.common.v1.Priority - 95, // 47: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_result:type_name -> temporal.api.common.v1.Payloads - 104, // 48: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_rejected:type_name -> temporal.api.query.v1.QueryRejected - 88, // 49: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 105, // 50: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.completed_request:type_name -> temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest - 106, // 51: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 88, // 52: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 107, // 53: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.desc_request:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueRequest - 108, // 54: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 109, // 55: temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse.desc_response:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueResponse - 106, // 56: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 88, // 57: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 108, // 58: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 75, // 59: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue - 76, // 60: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue - 110, // 61: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 111, // 62: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.versions:type_name -> temporal.api.taskqueue.v1.TaskQueueVersionSelection - 78, // 63: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.versions_info_internal:type_name -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry - 88, // 64: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 112, // 65: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.activity_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata - 112, // 66: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.workflow_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata - 79, // 67: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.apply_public_request:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest - 80, // 68: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.remove_build_ids:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.RemoveBuildIds - 113, // 69: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest - 114, // 70: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse - 115, // 71: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest - 116, // 72: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse - 117, // 73: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest - 118, // 74: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse - 106, // 75: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 119, // 76: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData - 106, // 77: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 106, // 78: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_types:type_name -> temporal.api.enums.v1.TaskQueueType - 120, // 79: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.deployment:type_name -> temporal.api.deployment.v1.Deployment - 121, // 80: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.data:type_name -> temporal.server.api.deployment.v1.TaskQueueData - 122, // 81: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_version_data:type_name -> temporal.server.api.deployment.v1.DeploymentVersionData - 108, // 82: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.forget_version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 123, // 83: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_routing_config:type_name -> temporal.api.deployment.v1.RoutingConfig - 81, // 84: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.upsert_versions_data:type_name -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry - 124, // 85: temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData - 110, // 86: temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 106, // 87: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 110, // 88: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 119, // 89: temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData - 124, // 90: temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData - 88, // 91: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 125, // 92: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.request:type_name -> temporal.api.nexus.v1.Request - 102, // 93: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 126, // 94: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.handler_error:type_name -> temporal.api.nexus.v1.HandlerError - 127, // 95: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.response:type_name -> temporal.api.nexus.v1.Response - 82, // 96: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.request_timeout:type_name -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.Timeout - 128, // 97: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.request:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueRequest - 129, // 98: temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse.response:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueResponse - 88, // 99: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 130, // 100: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest - 88, // 101: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 131, // 102: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest - 132, // 103: temporal.server.api.matchingservice.v1.CreateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec - 133, // 104: temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 132, // 105: temporal.server.api.matchingservice.v1.UpdateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec - 133, // 106: temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 133, // 107: temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse.entries:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 134, // 108: temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatRequest.heartbeart_request:type_name -> temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest - 135, // 109: temporal.server.api.matchingservice.v1.ListWorkersRequest.list_request:type_name -> temporal.api.workflowservice.v1.ListWorkersRequest - 136, // 110: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers_info:type_name -> temporal.api.worker.v1.WorkerInfo - 137, // 111: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest.update_taskqueue_config:type_name -> temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest - 138, // 112: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse.updated_taskqueue_config:type_name -> temporal.api.taskqueue.v1.TaskQueueConfig - 139, // 113: temporal.server.api.matchingservice.v1.DescribeWorkerRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkerRequest - 136, // 114: temporal.server.api.matchingservice.v1.DescribeWorkerResponse.worker_info:type_name -> temporal.api.worker.v1.WorkerInfo - 86, // 115: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery - 106, // 116: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType - 106, // 117: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType - 140, // 118: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats:type_name -> temporal.api.taskqueue.v1.TaskQueueStats - 77, // 119: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats_by_priority_key:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry - 140, // 120: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry.value:type_name -> temporal.api.taskqueue.v1.TaskQueueStats - 141, // 121: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry.value:type_name -> temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal - 142, // 122: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest - 143, // 123: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry.value:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersionData - 124, // [124:124] is the sub-list for method output_type - 124, // [124:124] is the sub-list for method input_type - 124, // [124:124] is the sub-list for extension type_name - 124, // [124:124] is the sub-list for extension extendee - 0, // [0:124] is the sub-list for field type_name + 85, // 0: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest + 86, // 1: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 87, // 2: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 88, // 3: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.query:type_name -> temporal.api.query.v1.WorkflowQuery + 89, // 4: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo + 90, // 5: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 91, // 6: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp + 91, // 7: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp + 76, // 8: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.queries:type_name -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry + 92, // 9: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.messages:type_name -> temporal.api.protocol.v1.Message + 93, // 10: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.history:type_name -> temporal.api.history.v1.History + 94, // 11: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision + 95, // 12: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest + 86, // 13: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 96, // 14: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.activity_type:type_name -> temporal.api.common.v1.ActivityType + 97, // 15: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.input:type_name -> temporal.api.common.v1.Payloads + 91, // 16: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp + 98, // 17: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.schedule_to_close_timeout:type_name -> google.protobuf.Duration + 91, // 18: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp + 98, // 19: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.start_to_close_timeout:type_name -> google.protobuf.Duration + 98, // 20: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_timeout:type_name -> google.protobuf.Duration + 91, // 21: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp + 97, // 22: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads + 87, // 23: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 99, // 24: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.header:type_name -> temporal.api.common.v1.Header + 94, // 25: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision + 100, // 26: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.priority:type_name -> temporal.api.common.v1.Priority + 101, // 27: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy + 86, // 28: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 90, // 29: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 98, // 30: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration + 102, // 31: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 103, // 32: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 104, // 33: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 100, // 34: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.priority:type_name -> temporal.api.common.v1.Priority + 86, // 35: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 90, // 36: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 98, // 37: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration + 102, // 38: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 103, // 39: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 104, // 40: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 100, // 41: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.priority:type_name -> temporal.api.common.v1.Priority + 90, // 42: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 105, // 43: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.query_request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest + 103, // 44: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 104, // 45: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 100, // 46: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.priority:type_name -> temporal.api.common.v1.Priority + 97, // 47: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_result:type_name -> temporal.api.common.v1.Payloads + 106, // 48: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_rejected:type_name -> temporal.api.query.v1.QueryRejected + 90, // 49: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 107, // 50: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.completed_request:type_name -> temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest + 108, // 51: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 90, // 52: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 109, // 53: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.desc_request:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueRequest + 110, // 54: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 111, // 55: temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse.desc_response:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueResponse + 108, // 56: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 90, // 57: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 110, // 58: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 77, // 59: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue + 78, // 60: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue + 112, // 61: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 113, // 62: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.versions:type_name -> temporal.api.taskqueue.v1.TaskQueueVersionSelection + 80, // 63: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.versions_info_internal:type_name -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry + 90, // 64: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 114, // 65: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.activity_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata + 114, // 66: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.workflow_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata + 81, // 67: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.apply_public_request:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest + 82, // 68: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.remove_build_ids:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.RemoveBuildIds + 115, // 69: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest + 116, // 70: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse + 117, // 71: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest + 118, // 72: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse + 119, // 73: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest + 120, // 74: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse + 108, // 75: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 121, // 76: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData + 108, // 77: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 108, // 78: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_types:type_name -> temporal.api.enums.v1.TaskQueueType + 122, // 79: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.deployment:type_name -> temporal.api.deployment.v1.Deployment + 123, // 80: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.data:type_name -> temporal.server.api.deployment.v1.TaskQueueData + 124, // 81: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_version_data:type_name -> temporal.server.api.deployment.v1.DeploymentVersionData + 110, // 82: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.forget_version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 125, // 83: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_routing_config:type_name -> temporal.api.deployment.v1.RoutingConfig + 83, // 84: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.upsert_versions_data:type_name -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry + 126, // 85: temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData + 112, // 86: temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 108, // 87: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 112, // 88: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 121, // 89: temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData + 126, // 90: temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData + 90, // 91: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 127, // 92: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.request:type_name -> temporal.api.nexus.v1.Request + 104, // 93: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 128, // 94: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.handler_error:type_name -> temporal.api.nexus.v1.HandlerError + 129, // 95: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.response:type_name -> temporal.api.nexus.v1.Response + 84, // 96: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.request_timeout:type_name -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.Timeout + 130, // 97: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.request:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueRequest + 131, // 98: temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse.response:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueResponse + 90, // 99: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 132, // 100: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest + 90, // 101: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 133, // 102: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest + 134, // 103: temporal.server.api.matchingservice.v1.CreateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec + 135, // 104: temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 134, // 105: temporal.server.api.matchingservice.v1.UpdateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec + 135, // 106: temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 135, // 107: temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse.entries:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 136, // 108: temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatRequest.heartbeart_request:type_name -> temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest + 137, // 109: temporal.server.api.matchingservice.v1.ListWorkersRequest.list_request:type_name -> temporal.api.workflowservice.v1.ListWorkersRequest + 138, // 110: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers_info:type_name -> temporal.api.worker.v1.WorkerInfo + 139, // 111: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest.update_taskqueue_config:type_name -> temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest + 140, // 112: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse.updated_taskqueue_config:type_name -> temporal.api.taskqueue.v1.TaskQueueConfig + 141, // 113: temporal.server.api.matchingservice.v1.DescribeWorkerRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkerRequest + 138, // 114: temporal.server.api.matchingservice.v1.DescribeWorkerResponse.worker_info:type_name -> temporal.api.worker.v1.WorkerInfo + 108, // 115: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 110, // 116: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 88, // 117: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery + 108, // 118: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType + 108, // 119: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType + 142, // 120: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats:type_name -> temporal.api.taskqueue.v1.TaskQueueStats + 79, // 121: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats_by_priority_key:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry + 142, // 122: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry.value:type_name -> temporal.api.taskqueue.v1.TaskQueueStats + 143, // 123: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry.value:type_name -> temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal + 144, // 124: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest + 145, // 125: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry.value:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersionData + 126, // [126:126] is the sub-list for method output_type + 126, // [126:126] is the sub-list for method input_type + 126, // [126:126] is the sub-list for extension type_name + 126, // [126:126] is the sub-list for extension extendee + 0, // [0:126] is the sub-list for field type_name } func init() { file_temporal_server_api_matchingservice_v1_request_response_proto_init() } @@ -5698,7 +5822,7 @@ func file_temporal_server_api_matchingservice_v1_request_response_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc)), NumEnums: 0, - NumMessages: 83, + NumMessages: 85, NumExtensions: 0, NumServices: 0, }, diff --git a/api/matchingservice/v1/service.pb.go b/api/matchingservice/v1/service.pb.go index e5858d9593..3ea668c0ab 100644 --- a/api/matchingservice/v1/service.pb.go +++ b/api/matchingservice/v1/service.pb.go @@ -25,7 +25,7 @@ var File_temporal_server_api_matchingservice_v1_service_proto protoreflect.FileD const file_temporal_server_api_matchingservice_v1_service_proto_rawDesc = "" + "\n" + - "4temporal/server/api/matchingservice/v1/service.proto\x12&temporal.server.api.matchingservice.v1\x1a=temporal/server/api/matchingservice/v1/request_response.proto2\x8b2\n" + + "4temporal/server/api/matchingservice/v1/service.proto\x12&temporal.server.api.matchingservice.v1\x1a=temporal/server/api/matchingservice/v1/request_response.proto2\xd23\n" + "\x0fMatchingService\x12\xa6\x01\n" + "\x15PollWorkflowTaskQueue\x12D.temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueRequest\x1aE.temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse\"\x00\x12\xa6\x01\n" + "\x15PollActivityTaskQueue\x12D.temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest\x1aE.temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse\"\x00\x12\x94\x01\n" + @@ -63,7 +63,8 @@ const file_temporal_server_api_matchingservice_v1_service_proto_rawDesc = "" + "\x15RecordWorkerHeartbeat\x12D.temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatRequest\x1aE.temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatResponse\"\x00\x12\x88\x01\n" + "\vListWorkers\x12:.temporal.server.api.matchingservice.v1.ListWorkersRequest\x1a;.temporal.server.api.matchingservice.v1.ListWorkersResponse\"\x00\x12\xa6\x01\n" + "\x15UpdateTaskQueueConfig\x12D.temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest\x1aE.temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse\"\x00\x12\x91\x01\n" + - "\x0eDescribeWorker\x12=.temporal.server.api.matchingservice.v1.DescribeWorkerRequest\x1a>.temporal.server.api.matchingservice.v1.DescribeWorkerResponse\"\x00B>Z.temporal.server.api.matchingservice.v1.DescribeWorkerResponse\"\x00\x12\xc4\x01\n" + + "\x1fCheckTaskQueueVersionMembership\x12N.temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest\x1aO.temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipResponse\"\x00B>Z temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueRequest @@ -179,45 +182,47 @@ var file_temporal_server_api_matchingservice_v1_service_proto_depIdxs = []int32{ 34, // 34: temporal.server.api.matchingservice.v1.MatchingService.ListWorkers:input_type -> temporal.server.api.matchingservice.v1.ListWorkersRequest 35, // 35: temporal.server.api.matchingservice.v1.MatchingService.UpdateTaskQueueConfig:input_type -> temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest 36, // 36: temporal.server.api.matchingservice.v1.MatchingService.DescribeWorker:input_type -> temporal.server.api.matchingservice.v1.DescribeWorkerRequest - 37, // 37: temporal.server.api.matchingservice.v1.MatchingService.PollWorkflowTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse - 38, // 38: temporal.server.api.matchingservice.v1.MatchingService.PollActivityTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse - 39, // 39: temporal.server.api.matchingservice.v1.MatchingService.AddWorkflowTask:output_type -> temporal.server.api.matchingservice.v1.AddWorkflowTaskResponse - 40, // 40: temporal.server.api.matchingservice.v1.MatchingService.AddActivityTask:output_type -> temporal.server.api.matchingservice.v1.AddActivityTaskResponse - 41, // 41: temporal.server.api.matchingservice.v1.MatchingService.QueryWorkflow:output_type -> temporal.server.api.matchingservice.v1.QueryWorkflowResponse - 42, // 42: temporal.server.api.matchingservice.v1.MatchingService.RespondQueryTaskCompleted:output_type -> temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedResponse - 43, // 43: temporal.server.api.matchingservice.v1.MatchingService.DispatchNexusTask:output_type -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse - 44, // 44: temporal.server.api.matchingservice.v1.MatchingService.PollNexusTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse - 45, // 45: temporal.server.api.matchingservice.v1.MatchingService.RespondNexusTaskCompleted:output_type -> temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedResponse - 46, // 46: temporal.server.api.matchingservice.v1.MatchingService.RespondNexusTaskFailed:output_type -> temporal.server.api.matchingservice.v1.RespondNexusTaskFailedResponse - 47, // 47: temporal.server.api.matchingservice.v1.MatchingService.CancelOutstandingPoll:output_type -> temporal.server.api.matchingservice.v1.CancelOutstandingPollResponse - 48, // 48: temporal.server.api.matchingservice.v1.MatchingService.DescribeTaskQueue:output_type -> temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse - 49, // 49: temporal.server.api.matchingservice.v1.MatchingService.DescribeTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse - 50, // 50: temporal.server.api.matchingservice.v1.MatchingService.DescribeVersionedTaskQueues:output_type -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse - 51, // 51: temporal.server.api.matchingservice.v1.MatchingService.ListTaskQueuePartitions:output_type -> temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse - 52, // 52: temporal.server.api.matchingservice.v1.MatchingService.UpdateWorkerBuildIdCompatibility:output_type -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityResponse - 53, // 53: temporal.server.api.matchingservice.v1.MatchingService.GetWorkerBuildIdCompatibility:output_type -> temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse - 54, // 54: temporal.server.api.matchingservice.v1.MatchingService.GetTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse - 55, // 55: temporal.server.api.matchingservice.v1.MatchingService.UpdateWorkerVersioningRules:output_type -> temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse - 56, // 56: temporal.server.api.matchingservice.v1.MatchingService.GetWorkerVersioningRules:output_type -> temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse - 57, // 57: temporal.server.api.matchingservice.v1.MatchingService.SyncDeploymentUserData:output_type -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataResponse - 58, // 58: temporal.server.api.matchingservice.v1.MatchingService.ApplyTaskQueueUserDataReplicationEvent:output_type -> temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventResponse - 59, // 59: temporal.server.api.matchingservice.v1.MatchingService.GetBuildIdTaskQueueMapping:output_type -> temporal.server.api.matchingservice.v1.GetBuildIdTaskQueueMappingResponse - 60, // 60: temporal.server.api.matchingservice.v1.MatchingService.ForceLoadTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionResponse - 61, // 61: temporal.server.api.matchingservice.v1.MatchingService.ForceUnloadTaskQueue:output_type -> temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueResponse - 62, // 62: temporal.server.api.matchingservice.v1.MatchingService.ForceUnloadTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionResponse - 63, // 63: temporal.server.api.matchingservice.v1.MatchingService.UpdateTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataResponse - 64, // 64: temporal.server.api.matchingservice.v1.MatchingService.ReplicateTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataResponse - 65, // 65: temporal.server.api.matchingservice.v1.MatchingService.CheckTaskQueueUserDataPropagation:output_type -> temporal.server.api.matchingservice.v1.CheckTaskQueueUserDataPropagationResponse - 66, // 66: temporal.server.api.matchingservice.v1.MatchingService.CreateNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse - 67, // 67: temporal.server.api.matchingservice.v1.MatchingService.UpdateNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse - 68, // 68: temporal.server.api.matchingservice.v1.MatchingService.DeleteNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.DeleteNexusEndpointResponse - 69, // 69: temporal.server.api.matchingservice.v1.MatchingService.ListNexusEndpoints:output_type -> temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse - 70, // 70: temporal.server.api.matchingservice.v1.MatchingService.RecordWorkerHeartbeat:output_type -> temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatResponse - 71, // 71: temporal.server.api.matchingservice.v1.MatchingService.ListWorkers:output_type -> temporal.server.api.matchingservice.v1.ListWorkersResponse - 72, // 72: temporal.server.api.matchingservice.v1.MatchingService.UpdateTaskQueueConfig:output_type -> temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse - 73, // 73: temporal.server.api.matchingservice.v1.MatchingService.DescribeWorker:output_type -> temporal.server.api.matchingservice.v1.DescribeWorkerResponse - 37, // [37:74] is the sub-list for method output_type - 0, // [0:37] is the sub-list for method input_type + 37, // 37: temporal.server.api.matchingservice.v1.MatchingService.CheckTaskQueueVersionMembership:input_type -> temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest + 38, // 38: temporal.server.api.matchingservice.v1.MatchingService.PollWorkflowTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse + 39, // 39: temporal.server.api.matchingservice.v1.MatchingService.PollActivityTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse + 40, // 40: temporal.server.api.matchingservice.v1.MatchingService.AddWorkflowTask:output_type -> temporal.server.api.matchingservice.v1.AddWorkflowTaskResponse + 41, // 41: temporal.server.api.matchingservice.v1.MatchingService.AddActivityTask:output_type -> temporal.server.api.matchingservice.v1.AddActivityTaskResponse + 42, // 42: temporal.server.api.matchingservice.v1.MatchingService.QueryWorkflow:output_type -> temporal.server.api.matchingservice.v1.QueryWorkflowResponse + 43, // 43: temporal.server.api.matchingservice.v1.MatchingService.RespondQueryTaskCompleted:output_type -> temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedResponse + 44, // 44: temporal.server.api.matchingservice.v1.MatchingService.DispatchNexusTask:output_type -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse + 45, // 45: temporal.server.api.matchingservice.v1.MatchingService.PollNexusTaskQueue:output_type -> temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse + 46, // 46: temporal.server.api.matchingservice.v1.MatchingService.RespondNexusTaskCompleted:output_type -> temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedResponse + 47, // 47: temporal.server.api.matchingservice.v1.MatchingService.RespondNexusTaskFailed:output_type -> temporal.server.api.matchingservice.v1.RespondNexusTaskFailedResponse + 48, // 48: temporal.server.api.matchingservice.v1.MatchingService.CancelOutstandingPoll:output_type -> temporal.server.api.matchingservice.v1.CancelOutstandingPollResponse + 49, // 49: temporal.server.api.matchingservice.v1.MatchingService.DescribeTaskQueue:output_type -> temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse + 50, // 50: temporal.server.api.matchingservice.v1.MatchingService.DescribeTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse + 51, // 51: temporal.server.api.matchingservice.v1.MatchingService.DescribeVersionedTaskQueues:output_type -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse + 52, // 52: temporal.server.api.matchingservice.v1.MatchingService.ListTaskQueuePartitions:output_type -> temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse + 53, // 53: temporal.server.api.matchingservice.v1.MatchingService.UpdateWorkerBuildIdCompatibility:output_type -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityResponse + 54, // 54: temporal.server.api.matchingservice.v1.MatchingService.GetWorkerBuildIdCompatibility:output_type -> temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse + 55, // 55: temporal.server.api.matchingservice.v1.MatchingService.GetTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse + 56, // 56: temporal.server.api.matchingservice.v1.MatchingService.UpdateWorkerVersioningRules:output_type -> temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse + 57, // 57: temporal.server.api.matchingservice.v1.MatchingService.GetWorkerVersioningRules:output_type -> temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse + 58, // 58: temporal.server.api.matchingservice.v1.MatchingService.SyncDeploymentUserData:output_type -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataResponse + 59, // 59: temporal.server.api.matchingservice.v1.MatchingService.ApplyTaskQueueUserDataReplicationEvent:output_type -> temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventResponse + 60, // 60: temporal.server.api.matchingservice.v1.MatchingService.GetBuildIdTaskQueueMapping:output_type -> temporal.server.api.matchingservice.v1.GetBuildIdTaskQueueMappingResponse + 61, // 61: temporal.server.api.matchingservice.v1.MatchingService.ForceLoadTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionResponse + 62, // 62: temporal.server.api.matchingservice.v1.MatchingService.ForceUnloadTaskQueue:output_type -> temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueResponse + 63, // 63: temporal.server.api.matchingservice.v1.MatchingService.ForceUnloadTaskQueuePartition:output_type -> temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionResponse + 64, // 64: temporal.server.api.matchingservice.v1.MatchingService.UpdateTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataResponse + 65, // 65: temporal.server.api.matchingservice.v1.MatchingService.ReplicateTaskQueueUserData:output_type -> temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataResponse + 66, // 66: temporal.server.api.matchingservice.v1.MatchingService.CheckTaskQueueUserDataPropagation:output_type -> temporal.server.api.matchingservice.v1.CheckTaskQueueUserDataPropagationResponse + 67, // 67: temporal.server.api.matchingservice.v1.MatchingService.CreateNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse + 68, // 68: temporal.server.api.matchingservice.v1.MatchingService.UpdateNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse + 69, // 69: temporal.server.api.matchingservice.v1.MatchingService.DeleteNexusEndpoint:output_type -> temporal.server.api.matchingservice.v1.DeleteNexusEndpointResponse + 70, // 70: temporal.server.api.matchingservice.v1.MatchingService.ListNexusEndpoints:output_type -> temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse + 71, // 71: temporal.server.api.matchingservice.v1.MatchingService.RecordWorkerHeartbeat:output_type -> temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatResponse + 72, // 72: temporal.server.api.matchingservice.v1.MatchingService.ListWorkers:output_type -> temporal.server.api.matchingservice.v1.ListWorkersResponse + 73, // 73: temporal.server.api.matchingservice.v1.MatchingService.UpdateTaskQueueConfig:output_type -> temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse + 74, // 74: temporal.server.api.matchingservice.v1.MatchingService.DescribeWorker:output_type -> temporal.server.api.matchingservice.v1.DescribeWorkerResponse + 75, // 75: temporal.server.api.matchingservice.v1.MatchingService.CheckTaskQueueVersionMembership:output_type -> temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipResponse + 38, // [38:76] is the sub-list for method output_type + 0, // [0:38] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/api/matchingservice/v1/service_grpc.pb.go b/api/matchingservice/v1/service_grpc.pb.go index c7e786c8e4..3398d06cae 100644 --- a/api/matchingservice/v1/service_grpc.pb.go +++ b/api/matchingservice/v1/service_grpc.pb.go @@ -57,6 +57,7 @@ const ( MatchingService_ListWorkers_FullMethodName = "/temporal.server.api.matchingservice.v1.MatchingService/ListWorkers" MatchingService_UpdateTaskQueueConfig_FullMethodName = "/temporal.server.api.matchingservice.v1.MatchingService/UpdateTaskQueueConfig" MatchingService_DescribeWorker_FullMethodName = "/temporal.server.api.matchingservice.v1.MatchingService/DescribeWorker" + MatchingService_CheckTaskQueueVersionMembership_FullMethodName = "/temporal.server.api.matchingservice.v1.MatchingService/CheckTaskQueueVersionMembership" ) // MatchingServiceClient is the client API for MatchingService service. @@ -221,6 +222,8 @@ type MatchingServiceClient interface { // DescribeWorker retrieves a worker information in the specified namespace that match the provided instance key. // Returns an error if the namespace or worker doesn't exist. DescribeWorker(ctx context.Context, in *DescribeWorkerRequest, opts ...grpc.CallOption) (*DescribeWorkerResponse, error) + // CheckTaskQueueVersionMembership checks if a task queue is part of a specific deployment version. + CheckTaskQueueVersionMembership(ctx context.Context, in *CheckTaskQueueVersionMembershipRequest, opts ...grpc.CallOption) (*CheckTaskQueueVersionMembershipResponse, error) } type matchingServiceClient struct { @@ -564,6 +567,15 @@ func (c *matchingServiceClient) DescribeWorker(ctx context.Context, in *Describe return out, nil } +func (c *matchingServiceClient) CheckTaskQueueVersionMembership(ctx context.Context, in *CheckTaskQueueVersionMembershipRequest, opts ...grpc.CallOption) (*CheckTaskQueueVersionMembershipResponse, error) { + out := new(CheckTaskQueueVersionMembershipResponse) + err := c.cc.Invoke(ctx, MatchingService_CheckTaskQueueVersionMembership_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MatchingServiceServer is the server API for MatchingService service. // All implementations must embed UnimplementedMatchingServiceServer // for forward compatibility @@ -726,6 +738,8 @@ type MatchingServiceServer interface { // DescribeWorker retrieves a worker information in the specified namespace that match the provided instance key. // Returns an error if the namespace or worker doesn't exist. DescribeWorker(context.Context, *DescribeWorkerRequest) (*DescribeWorkerResponse, error) + // CheckTaskQueueVersionMembership checks if a task queue is part of a specific deployment version. + CheckTaskQueueVersionMembership(context.Context, *CheckTaskQueueVersionMembershipRequest) (*CheckTaskQueueVersionMembershipResponse, error) mustEmbedUnimplementedMatchingServiceServer() } @@ -844,6 +858,9 @@ func (UnimplementedMatchingServiceServer) UpdateTaskQueueConfig(context.Context, func (UnimplementedMatchingServiceServer) DescribeWorker(context.Context, *DescribeWorkerRequest) (*DescribeWorkerResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DescribeWorker not implemented") } +func (UnimplementedMatchingServiceServer) CheckTaskQueueVersionMembership(context.Context, *CheckTaskQueueVersionMembershipRequest) (*CheckTaskQueueVersionMembershipResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckTaskQueueVersionMembership not implemented") +} func (UnimplementedMatchingServiceServer) mustEmbedUnimplementedMatchingServiceServer() {} // UnsafeMatchingServiceServer may be embedded to opt out of forward compatibility for this service. @@ -1523,6 +1540,24 @@ func _MatchingService_DescribeWorker_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _MatchingService_CheckTaskQueueVersionMembership_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckTaskQueueVersionMembershipRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MatchingServiceServer).CheckTaskQueueVersionMembership(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MatchingService_CheckTaskQueueVersionMembership_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MatchingServiceServer).CheckTaskQueueVersionMembership(ctx, req.(*CheckTaskQueueVersionMembershipRequest)) + } + return interceptor(ctx, in, info, handler) +} + // MatchingService_ServiceDesc is the grpc.ServiceDesc for MatchingService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -1678,6 +1713,10 @@ var MatchingService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DescribeWorker", Handler: _MatchingService_DescribeWorker_Handler, }, + { + MethodName: "CheckTaskQueueVersionMembership", + Handler: _MatchingService_CheckTaskQueueVersionMembership_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "temporal/server/api/matchingservice/v1/service.proto", diff --git a/api/matchingservicemock/v1/service_grpc.pb.mock.go b/api/matchingservicemock/v1/service_grpc.pb.mock.go index f25c075e61..58fed0b899 100644 --- a/api/matchingservicemock/v1/service_grpc.pb.mock.go +++ b/api/matchingservicemock/v1/service_grpc.pb.mock.go @@ -142,6 +142,26 @@ func (mr *MockMatchingServiceClientMockRecorder) CheckTaskQueueUserDataPropagati return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTaskQueueUserDataPropagation", reflect.TypeOf((*MockMatchingServiceClient)(nil).CheckTaskQueueUserDataPropagation), varargs...) } +// CheckTaskQueueVersionMembership mocks base method. +func (m *MockMatchingServiceClient) CheckTaskQueueVersionMembership(ctx context.Context, in *matchingservice.CheckTaskQueueVersionMembershipRequest, opts ...grpc.CallOption) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, in} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CheckTaskQueueVersionMembership", varargs...) + ret0, _ := ret[0].(*matchingservice.CheckTaskQueueVersionMembershipResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckTaskQueueVersionMembership indicates an expected call of CheckTaskQueueVersionMembership. +func (mr *MockMatchingServiceClientMockRecorder) CheckTaskQueueVersionMembership(ctx, in any, opts ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, in}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTaskQueueVersionMembership", reflect.TypeOf((*MockMatchingServiceClient)(nil).CheckTaskQueueVersionMembership), varargs...) +} + // CreateNexusEndpoint mocks base method. func (m *MockMatchingServiceClient) CreateNexusEndpoint(ctx context.Context, in *matchingservice.CreateNexusEndpointRequest, opts ...grpc.CallOption) (*matchingservice.CreateNexusEndpointResponse, error) { m.ctrl.T.Helper() @@ -881,6 +901,21 @@ func (mr *MockMatchingServiceServerMockRecorder) CheckTaskQueueUserDataPropagati return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTaskQueueUserDataPropagation", reflect.TypeOf((*MockMatchingServiceServer)(nil).CheckTaskQueueUserDataPropagation), arg0, arg1) } +// CheckTaskQueueVersionMembership mocks base method. +func (m *MockMatchingServiceServer) CheckTaskQueueVersionMembership(arg0 context.Context, arg1 *matchingservice.CheckTaskQueueVersionMembershipRequest) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckTaskQueueVersionMembership", arg0, arg1) + ret0, _ := ret[0].(*matchingservice.CheckTaskQueueVersionMembershipResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckTaskQueueVersionMembership indicates an expected call of CheckTaskQueueVersionMembership. +func (mr *MockMatchingServiceServerMockRecorder) CheckTaskQueueVersionMembership(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTaskQueueVersionMembership", reflect.TypeOf((*MockMatchingServiceServer)(nil).CheckTaskQueueVersionMembership), arg0, arg1) +} + // CreateNexusEndpoint mocks base method. func (m *MockMatchingServiceServer) CreateNexusEndpoint(arg0 context.Context, arg1 *matchingservice.CreateNexusEndpointRequest) (*matchingservice.CreateNexusEndpointResponse, error) { m.ctrl.T.Helper() diff --git a/client/matching/client_gen.go b/client/matching/client_gen.go index 1106425229..5f7ec3bbd6 100644 --- a/client/matching/client_gen.go +++ b/client/matching/client_gen.go @@ -73,6 +73,26 @@ func (c *clientImpl) CheckTaskQueueUserDataPropagation( return client.CheckTaskQueueUserDataPropagation(ctx, request, opts...) } +func (c *clientImpl) CheckTaskQueueVersionMembership( + ctx context.Context, + request *matchingservice.CheckTaskQueueVersionMembershipRequest, + opts ...grpc.CallOption, +) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) { + + p, err := tqid.NormalPartitionFromRpcName(request.GetTaskQueue(), request.GetNamespaceId(), request.GetTaskQueueType()) + if err != nil { + return nil, err + } + + client, err := c.getClientForTaskQueuePartition(p) + if err != nil { + return nil, err + } + ctx, cancel := c.createContext(ctx) + defer cancel() + return client.CheckTaskQueueVersionMembership(ctx, request, opts...) +} + func (c *clientImpl) CreateNexusEndpoint( ctx context.Context, request *matchingservice.CreateNexusEndpointRequest, diff --git a/client/matching/metric_client_gen.go b/client/matching/metric_client_gen.go index c72c917948..4c802e4894 100644 --- a/client/matching/metric_client_gen.go +++ b/client/matching/metric_client_gen.go @@ -51,6 +51,20 @@ func (c *metricClient) CheckTaskQueueUserDataPropagation( return c.client.CheckTaskQueueUserDataPropagation(ctx, request, opts...) } +func (c *metricClient) CheckTaskQueueVersionMembership( + ctx context.Context, + request *matchingservice.CheckTaskQueueVersionMembershipRequest, + opts ...grpc.CallOption, +) (_ *matchingservice.CheckTaskQueueVersionMembershipResponse, retError error) { + + metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientCheckTaskQueueVersionMembership") + defer func() { + c.finishMetricsRecording(metricsHandler, startTime, retError) + }() + + return c.client.CheckTaskQueueVersionMembership(ctx, request, opts...) +} + func (c *metricClient) CreateNexusEndpoint( ctx context.Context, request *matchingservice.CreateNexusEndpointRequest, diff --git a/client/matching/retryable_client_gen.go b/client/matching/retryable_client_gen.go index 18f1647881..b4dd0bcc3f 100644 --- a/client/matching/retryable_client_gen.go +++ b/client/matching/retryable_client_gen.go @@ -86,6 +86,21 @@ func (c *retryableClient) CheckTaskQueueUserDataPropagation( return resp, err } +func (c *retryableClient) CheckTaskQueueVersionMembership( + ctx context.Context, + request *matchingservice.CheckTaskQueueVersionMembershipRequest, + opts ...grpc.CallOption, +) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) { + var resp *matchingservice.CheckTaskQueueVersionMembershipResponse + op := func(ctx context.Context) error { + var err error + resp, err = c.client.CheckTaskQueueVersionMembership(ctx, request, opts...) + return err + } + err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable) + return resp, err +} + func (c *retryableClient) CreateNexusEndpoint( ctx context.Context, request *matchingservice.CreateNexusEndpointRequest, diff --git a/common/dynamicconfig/constants.go b/common/dynamicconfig/constants.go index b2b1799af0..fc6ae5102b 100644 --- a/common/dynamicconfig/constants.go +++ b/common/dynamicconfig/constants.go @@ -2667,6 +2667,12 @@ to the CHASM (V2) implementation on active scheduler workflows.`, instead of the previous HSM backed implementation.`, ) + VersionMembershipCacheTTL = NewGlobalDurationSetting( + "history.versionMembershipCacheTTL", + 1*time.Second, + `TTL for caching RPC results that check whether a version is present in a task queue.`, + ) + // keys for worker WorkerPersistenceMaxQPS = NewGlobalIntSetting( diff --git a/common/rpc/interceptor/logtags/matching_service_server_gen.go b/common/rpc/interceptor/logtags/matching_service_server_gen.go index 04eb583fa6..e3fbf66cd4 100644 --- a/common/rpc/interceptor/logtags/matching_service_server_gen.go +++ b/common/rpc/interceptor/logtags/matching_service_server_gen.go @@ -35,6 +35,10 @@ func (wt *WorkflowTags) extractFromMatchingServiceServerMessage(message any) []t return nil case *matchingservice.CheckTaskQueueUserDataPropagationResponse: return nil + case *matchingservice.CheckTaskQueueVersionMembershipRequest: + return nil + case *matchingservice.CheckTaskQueueVersionMembershipResponse: + return nil case *matchingservice.CreateNexusEndpointRequest: return nil case *matchingservice.CreateNexusEndpointResponse: diff --git a/common/testing/testvars/test_vars.go b/common/testing/testvars/test_vars.go index a4e1d59648..0f4edef128 100644 --- a/common/testing/testvars/test_vars.go +++ b/common/testing/testvars/test_vars.go @@ -310,6 +310,14 @@ func (tv *TestVars) WithTaskQueue(taskQueue string) *TestVars { return tv.cloneSetVal("task_queue", taskQueue) } +func (tv *TestVars) WithDeploymentSeries(deploymentSeries string) *TestVars { + return tv.cloneSetVal("deployment_series", deploymentSeries) +} + +func (tv *TestVars) WithBuildID(buildID string) *TestVars { + return tv.cloneSetVal("build_id", buildID) +} + func (tv *TestVars) WithTaskQueueNumber(n int) *TestVars { return tv.cloneSetN("task_queue", n) } diff --git a/common/worker_versioning/worker_versioning.go b/common/worker_versioning/worker_versioning.go index d2e57ddebc..dd35df6ba8 100644 --- a/common/worker_versioning/worker_versioning.go +++ b/common/worker_versioning/worker_versioning.go @@ -19,6 +19,7 @@ import ( "go.temporal.io/server/api/matchingservice/v1" persistencespb "go.temporal.io/server/api/persistence/v1" taskqueuespb "go.temporal.io/server/api/taskqueue/v1" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/namespace" "go.temporal.io/server/common/persistence/visibility/manager" "go.temporal.io/server/common/resource" @@ -265,21 +266,16 @@ func GetIsWFTaskQueueInVersionDetector(matchingClient resource.MatchingClient) I return func(ctx context.Context, namespaceID, tq string, version *deploymentpb.WorkerDeploymentVersion) (bool, error) { - resp, err := matchingClient.GetTaskQueueUserData(ctx, - &matchingservice.GetTaskQueueUserDataRequest{ - NamespaceId: namespaceID, - TaskQueue: tq, - TaskQueueType: enumspb.TASK_QUEUE_TYPE_WORKFLOW, - }) + resp, err := matchingClient.CheckTaskQueueVersionMembership(ctx, &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: namespaceID, + TaskQueue: tq, + TaskQueueType: enumspb.TASK_QUEUE_TYPE_WORKFLOW, + Version: DeploymentVersionFromDeployment(DeploymentFromExternalDeploymentVersion(version)), + }) if err != nil { return false, err } - tqData, ok := resp.GetUserData().GetData().GetPerType()[int32(enumspb.TASK_QUEUE_TYPE_WORKFLOW)] - if !ok { - // The TQ is unversioned - return false, nil - } - return HasDeploymentVersion(tqData.GetDeploymentData(), DeploymentVersionFromDeployment(DeploymentFromExternalDeploymentVersion(version))), nil + return resp.GetIsMember(), nil } } @@ -528,7 +524,53 @@ func ExtractVersioningBehaviorFromOverride(override *workflowpb.VersioningOverri return override.GetBehavior() } -func ValidateVersioningOverride(override *workflowpb.VersioningOverride) error { +func validatePinnedVersionInTaskQueue(ctx context.Context, + pinnedVersion *deploymentpb.WorkerDeploymentVersion, + matchingClient resource.MatchingClient, + versionMembershipCache cache.Cache, + tq string, + tqType enumspb.TaskQueueType, + namespaceID string) error { + + // Check if we have recently queried matching recently to validate if this version exists in the task queue. + // Key format: namespaceID:taskQueue:DeploymentName:BuildID + key := fmt.Sprintf("%s:%s:%s:%s", namespaceID, tq, pinnedVersion.DeploymentName, pinnedVersion.BuildId) + if cached := versionMembershipCache.Get(key); cached != nil { + if isMember, ok := cached.(bool); ok && isMember { + return nil + } + return serviceerror.NewFailedPrecondition( + "Pinned version is not present in the task queue", + ) + } + + resp, err := matchingClient.CheckTaskQueueVersionMembership(context.Background(), &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: namespaceID, + TaskQueue: tq, + TaskQueueType: tqType, + Version: DeploymentVersionFromDeployment(DeploymentFromExternalDeploymentVersion(pinnedVersion)), + }) + if err != nil { + return err + } + + // Add result to cache + versionMembershipCache.Put(key, resp.GetIsMember()) + if !resp.GetIsMember() { + return serviceerror.NewFailedPrecondition( + "Pinned version is not present in the task queue", + ) + } + return nil +} + +func ValidateVersioningOverride(ctx context.Context, + override *workflowpb.VersioningOverride, + matchingClient resource.MatchingClient, + versionMembershipCache cache.Cache, + tq string, + tqType enumspb.TaskQueueType, + namespaceID string) error { if override == nil { return nil } @@ -542,7 +584,7 @@ func ValidateVersioningOverride(override *workflowpb.VersioningOverride) error { if p.GetBehavior() == workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED { return serviceerror.NewInvalidArgument("must specify pinned override behavior if override is pinned.") } - return nil + return validatePinnedVersionInTaskQueue(ctx, p.GetVersion(), matchingClient, versionMembershipCache, tq, tqType, namespaceID) } //nolint:staticcheck // SA1019: worker versioning v0.31 @@ -552,7 +594,12 @@ func ValidateVersioningOverride(override *workflowpb.VersioningOverride) error { return ValidateDeployment(override.GetDeployment()) } else if override.GetPinnedVersion() != "" { _, err := ValidateDeploymentVersionStringV31(override.GetPinnedVersion()) - return err + if err != nil { + return err + } + + return validatePinnedVersionInTaskQueue(ctx, ExternalWorkerDeploymentVersionFromStringV31(override.GetPinnedVersion()), matchingClient, versionMembershipCache, tq, tqType, namespaceID) + } else { return serviceerror.NewInvalidArgument("must provide deployment (deprecated) or pinned version if behavior is 'PINNED'") } diff --git a/common/worker_versioning/worker_versioning_test.go b/common/worker_versioning/worker_versioning_test.go index 664e8ba41f..b447926b9d 100644 --- a/common/worker_versioning/worker_versioning_test.go +++ b/common/worker_versioning/worker_versioning_test.go @@ -1,15 +1,23 @@ package worker_versioning import ( + "context" "strconv" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" deploymentpb "go.temporal.io/api/deployment/v1" + enumspb "go.temporal.io/api/enums/v1" + workflowpb "go.temporal.io/api/workflow/v1" deploymentspb "go.temporal.io/server/api/deployment/v1" + "go.temporal.io/server/api/matchingservice/v1" + "go.temporal.io/server/api/matchingservicemock/v1" persistencespb "go.temporal.io/server/api/persistence/v1" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/primitives/timestamp" + "go.uber.org/mock/gomock" ) var ( @@ -467,3 +475,317 @@ func TestWorkerDeploymentVersionFromStringV32(t *testing.T) { }) } } + +func TestValidateVersioningOverride(t *testing.T) { + testNamespaceID := "test-namespace-id" + testTaskQueue := "test-task-queue" + testVersion := &deploymentpb.WorkerDeploymentVersion{ + DeploymentName: "test-deployment", + BuildId: "test-build-id", + } + + tests := []struct { + name string + override *workflowpb.VersioningOverride + setupCache func(c cache.Cache) + setupMock func(m *matchingservicemock.MockMatchingServiceClient) + expectError bool + errorContains string + }{ + { + name: "nil override returns nil", + override: nil, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: false, + }, + { + name: "v0.32: AutoUpgrade override returns nil", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_AutoUpgrade{AutoUpgrade: true}, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) // No RPC call expected! + }, + expectError: false, + }, + { + name: "v0.32: Pinned override, with cache hit, returns nil", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: testVersion, + }, + }, + }, + setupCache: func(c cache.Cache) { + key := testNamespaceID + ":" + testTaskQueue + ":" + testVersion.DeploymentName + ":" + testVersion.BuildId + c.Put(key, true) + }, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) // No RPC call expected! + }, + expectError: false, + }, + { + name: "v0.32: Pinned override, with cache hit, returns error (since version is not present in the task queue)", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: testVersion, + }, + }, + }, + setupCache: func(c cache.Cache) { + key := testNamespaceID + ":" + testTaskQueue + ":" + testVersion.DeploymentName + ":" + testVersion.BuildId + c.Put(key, false) + }, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) // No RPC call expected! + }, + expectError: true, + errorContains: "Pinned version is not present in the task queue", + }, + { + name: "v0.32: Pinned override, with cache miss, calls RPC and caches false", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: testVersion, + }, + }, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership( + gomock.Any(), + gomock.Any(), + ).Return(&matchingservice.CheckTaskQueueVersionMembershipResponse{ + IsMember: false, + }, nil) + }, + expectError: true, + errorContains: "Pinned version is not present in the task queue", + }, + { + name: "v0.32: Pinned override, with cache miss, calls RPC and caches true", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: testVersion, + }, + }, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership( + gomock.Any(), + gomock.Any(), + ).Return(&matchingservice.CheckTaskQueueVersionMembershipResponse{ + IsMember: true, + }, nil) + }, + expectError: false, + }, + { + name: "v0.32: Pinned override, without version, returns error", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: nil, + }, + }, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "must provide version if override is pinned", + }, + { + name: "v0.32: Pinned override, without behavior, returns error", + override: &workflowpb.VersioningOverride{ + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_UNSPECIFIED, + Version: testVersion, + }, + }, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "must specify pinned override behavior if override is pinned", + }, + // v0.31 tests (deprecated behavior field) + { + name: "v0.31: AUTO_UPGRADE behavior returns nil", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) + }, + expectError: false, + }, + { + name: "v0.31: AUTO_UPGRADE with deployment set returns error", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE, + Deployment: &deploymentpb.Deployment{SeriesName: "test", BuildId: "build1"}, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "only provide deployment if behavior is 'PINNED'", + }, + { + name: "v0.31: AUTO_UPGRADE with pinned_version set returns error", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE, + PinnedVersion: "test-deployment.test-build-id", + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "only provide pinned version if behavior is 'PINNED'", + }, + { + name: "v0.31: PINNED behavior with pinned_version, cache hit, returns nil", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + PinnedVersion: "test-deployment.test-build-id", + }, + setupCache: func(c cache.Cache) { + key := testNamespaceID + ":" + testTaskQueue + ":test-deployment:test-build-id" + c.Put(key, true) + }, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) + }, + expectError: false, + }, + { + name: "v0.31: PINNED behavior with pinned_version, cache hit, returns error (since version is not present in the task queue)", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + PinnedVersion: "test-deployment.test-build-id", + }, + setupCache: func(c cache.Cache) { + key := testNamespaceID + ":" + testTaskQueue + ":test-deployment:test-build-id" + c.Put(key, false) + }, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership(gomock.Any(), gomock.Any()).Times(0) + }, + expectError: true, + errorContains: "Pinned version is not present in the task queue", + }, + { + name: "v0.31: PINNED behavior with pinned_version, cache miss, calls RPC and caches false", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + PinnedVersion: "test-deployment.test-build-id", + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership( + gomock.Any(), + gomock.Any(), + ).Return(&matchingservice.CheckTaskQueueVersionMembershipResponse{ + IsMember: false, + }, nil) + }, + expectError: true, + errorContains: "Pinned version is not present in the task queue", + }, + { + name: "v0.31: PINNED behavior with pinned_version, cache miss, calls RPC and caches true", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + PinnedVersion: "test-deployment.test-build-id", + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) { + m.EXPECT().CheckTaskQueueVersionMembership( + gomock.Any(), + gomock.Any(), + ).Return(&matchingservice.CheckTaskQueueVersionMembershipResponse{ + IsMember: true, + }, nil) + }, + expectError: false, + }, + { + name: "v0.31: PINNED behavior without deployment or pinned_version returns error", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "must provide deployment (deprecated) or pinned version if behavior is 'PINNED'", + }, + { + name: "v0.31: PINNED behavior with invalid pinned_version format returns error", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, + PinnedVersion: "invalid-no-dot", + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "invalid version string", + }, + { + name: "v0.31: UNSPECIFIED behavior returns error", + override: &workflowpb.VersioningOverride{ + Behavior: enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED, + }, + setupCache: func(c cache.Cache) {}, + setupMock: func(m *matchingservicemock.MockMatchingServiceClient) {}, + expectError: true, + errorContains: "override behavior is required", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockMatchingClient := matchingservicemock.NewMockMatchingServiceClient(ctrl) + tt.setupMock(mockMatchingClient) + + testCache := cache.New(100, &cache.Options{ + TTL: time.Minute, + }) + tt.setupCache(testCache) + + err := ValidateVersioningOverride( + context.Background(), + tt.override, + mockMatchingClient, + testCache, + testTaskQueue, + enumspb.TASK_QUEUE_TYPE_WORKFLOW, + testNamespaceID, + ) + + if tt.expectError { + require.Error(t, err) + if tt.errorContains != "" { + assert.Contains(t, err.Error(), tt.errorContains) + } + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto b/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto index f615461ce4..67cbdb83df 100644 --- a/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto +++ b/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto @@ -641,3 +641,14 @@ message DescribeWorkerRequest { message DescribeWorkerResponse { temporal.api.worker.v1.WorkerInfo worker_info = 1; } + +message CheckTaskQueueVersionMembershipRequest { + string namespace_id = 1; + string task_queue = 2; + temporal.api.enums.v1.TaskQueueType task_queue_type = 3; + temporal.server.api.deployment.v1.WorkerDeploymentVersion version = 4; +} + +message CheckTaskQueueVersionMembershipResponse { + bool is_member = 1; +} diff --git a/proto/internal/temporal/server/api/matchingservice/v1/service.proto b/proto/internal/temporal/server/api/matchingservice/v1/service.proto index 993fc290f1..372dd6857e 100644 --- a/proto/internal/temporal/server/api/matchingservice/v1/service.proto +++ b/proto/internal/temporal/server/api/matchingservice/v1/service.proto @@ -190,5 +190,8 @@ service MatchingService { // Returns an error if the namespace or worker doesn't exist. rpc DescribeWorker (DescribeWorkerRequest) returns (DescribeWorkerResponse) {} + // CheckTaskQueueVersionMembership checks if a task queue is part of a specific deployment version. + rpc CheckTaskQueueVersionMembership(CheckTaskQueueVersionMembershipRequest) returns (CheckTaskQueueVersionMembershipResponse) {} + } diff --git a/service/frontend/workflow_handler.go b/service/frontend/workflow_handler.go index 3410ae7a7d..ffa90cd535 100644 --- a/service/frontend/workflow_handler.go +++ b/service/frontend/workflow_handler.go @@ -494,11 +494,6 @@ func (wh *WorkflowHandler) prepareStartWorkflowRequest( return nil, err } - // Validate versioning override, if present. - if err := worker_versioning.ValidateVersioningOverride(request.GetVersioningOverride()); err != nil { - return nil, err - } - enums.SetDefaultWorkflowIdReusePolicy(&request.WorkflowIdReusePolicy) enums.SetDefaultWorkflowIdConflictPolicy(&request.WorkflowIdConflictPolicy, enumspb.WORKFLOW_ID_CONFLICT_POLICY_FAIL) @@ -2092,10 +2087,6 @@ func (wh *WorkflowHandler) SignalWithStartWorkflowExecution(ctx context.Context, if err != nil { return nil, err } - // Validate versioning override, if present. - if err := worker_versioning.ValidateVersioningOverride(request.GetVersioningOverride()); err != nil { - return nil, err - } resp, err := wh.historyClient.SignalWithStartWorkflowExecution(ctx, &historyservice.SignalWithStartWorkflowExecutionRequest{ NamespaceId: namespaceID.String(), @@ -2131,10 +2122,6 @@ func (wh *WorkflowHandler) ResetWorkflowExecution(ctx context.Context, request * return nil, err } - if err := validatePostResetOperationInputs(request.GetPostResetOperations()); err != nil { - return nil, err - } - enums.SetDefaultResetReapplyType(&request.ResetReapplyType) if _, validType := enumspb.ResetReapplyType_name[int32(request.GetResetReapplyType())]; !validType { return nil, serviceerror.NewInternalf("unknown reset reapply type: %v", request.GetResetReapplyType()) @@ -2156,22 +2143,6 @@ func (wh *WorkflowHandler) ResetWorkflowExecution(ctx context.Context, request * return &workflowservice.ResetWorkflowExecutionResponse{RunId: resp.GetRunId()}, nil } -// validatePostResetOperationInputs validates the optional post reset operation inputs. -func validatePostResetOperationInputs(postResetOperations []*workflowpb.PostResetOperation) error { - for _, operation := range postResetOperations { - switch op := operation.GetVariant().(type) { - case *workflowpb.PostResetOperation_UpdateWorkflowOptions_: - opts := op.UpdateWorkflowOptions.GetWorkflowExecutionOptions() - if err := worker_versioning.ValidateVersioningOverride(opts.GetVersioningOverride()); err != nil { - return err - } - default: - return serviceerror.NewInvalidArgumentf("unsupported post reset operation: %T", op) - } - } - return nil -} - // TerminateWorkflowExecution terminates an existing workflow execution by recording WorkflowExecutionTerminated event // in the history and immediately terminating the execution instance. func (wh *WorkflowHandler) TerminateWorkflowExecution(ctx context.Context, request *workflowservice.TerminateWorkflowExecutionRequest) (_ *workflowservice.TerminateWorkflowExecutionResponse, retError error) { @@ -4822,6 +4793,8 @@ func (wh *WorkflowHandler) StartBatchOperation( case *workflowservice.StartBatchOperationRequest_UpdateWorkflowOptionsOperation: input.BatchType = enumspb.BATCH_OPERATION_TYPE_UPDATE_EXECUTION_OPTIONS identity = op.UpdateWorkflowOptionsOperation.GetIdentity() + // TODO (Shivam): Verify if this is the correct way to handle these errors. + input.NonRetryableErrors = append(input.NonRetryableErrors, "Pinned version is not present in the task queue") case *workflowservice.StartBatchOperationRequest_UnpauseActivitiesOperation: input.BatchType = enumspb.BATCH_OPERATION_TYPE_UNPAUSE_ACTIVITY identity = op.UnpauseActivitiesOperation.GetIdentity() @@ -6003,9 +5976,6 @@ func (wh *WorkflowHandler) UpdateWorkflowExecutionOptions( if err != nil { return nil, err } - if err := worker_versioning.ValidateVersioningOverride(opts.GetVersioningOverride()); err != nil { - return nil, err - } response, err := wh.historyClient.UpdateWorkflowExecutionOptions(ctx, &historyservice.UpdateWorkflowExecutionOptionsRequest{ NamespaceId: namespaceID.String(), diff --git a/service/history/api/multioperation/api.go b/service/history/api/multioperation/api.go index f2d254805d..5889b5eea0 100644 --- a/service/history/api/multioperation/api.go +++ b/service/history/api/multioperation/api.go @@ -11,6 +11,7 @@ import ( "go.temporal.io/server/api/historyservice/v1" "go.temporal.io/server/api/matchingservice/v1" "go.temporal.io/server/common" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/locks" "go.temporal.io/server/common/namespace" @@ -54,6 +55,7 @@ func Invoke( workflowConsistencyChecker api.WorkflowConsistencyChecker, tokenSerializer *tasktoken.Serializer, matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, testHooks testhooks.TestHooks, ) (*historyservice.ExecuteMultiOperationResponse, error) { namespaceEntry, err := api.GetActiveNamespace(shardContext, namespace.ID(req.GetNamespaceId())) @@ -92,6 +94,8 @@ func Invoke( workflowConsistencyChecker, tokenSerializer, startReq, + matchingClient, + versionMembershipCache, uws.workflowLeaseCallback(ctx), ) if err != nil { diff --git a/service/history/api/resetworkflow/api.go b/service/history/api/resetworkflow/api.go index 7890209b9d..c1f1cf0056 100644 --- a/service/history/api/resetworkflow/api.go +++ b/service/history/api/resetworkflow/api.go @@ -6,14 +6,19 @@ import ( "github.com/google/uuid" enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/serviceerror" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + workflowpb "go.temporal.io/api/workflow/v1" "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" "go.temporal.io/server/common" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/locks" "go.temporal.io/server/common/log/tag" "go.temporal.io/server/common/metrics" "go.temporal.io/server/common/namespace" "go.temporal.io/server/common/persistence/versionhistory" + "go.temporal.io/server/common/worker_versioning" "go.temporal.io/server/service/history/api" historyi "go.temporal.io/server/service/history/interfaces" "go.temporal.io/server/service/history/ndc" @@ -24,6 +29,8 @@ func Invoke( resetRequest *historyservice.ResetWorkflowExecutionRequest, shardContext historyi.ShardContext, workflowConsistencyChecker api.WorkflowConsistencyChecker, + matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, ) (_ *historyservice.ResetWorkflowExecutionResponse, retError error) { namespaceID := namespace.ID(resetRequest.GetNamespaceId()) err := api.ValidateNamespaceUUID(namespaceID) @@ -56,6 +63,16 @@ func Invoke( return nil, serviceerror.NewInvalidArgument("Workflow task finish ID must be > 1 && <= workflow last event ID.") } + // Validate versioning override, if any. + err = validatePostResetOperationInputs(ctx, request.GetPostResetOperations(), matchingClient, versionMembershipCache, + &taskqueuepb.TaskQueue{ + Name: baseMutableState.GetExecutionInfo().GetTaskQueue(), + Kind: enumspb.TASK_QUEUE_KIND_NORMAL, + }, namespaceID.String()) + if err != nil { + return nil, err + } + // also load the current run of the workflow, it can be different from the base runID currentRunID, err := workflowConsistencyChecker.GetCurrentWorkflowRunID( ctx, @@ -197,3 +214,24 @@ func GetResetReapplyExcludeTypes( } return exclude } + +// validatePostResetOperationInputs validates the optional post reset operation inputs. +func validatePostResetOperationInputs(ctx context.Context, + postResetOperations []*workflowpb.PostResetOperation, + matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, + taskQueue *taskqueuepb.TaskQueue, + namespaceID string) error { + for _, operation := range postResetOperations { + switch op := operation.GetVariant().(type) { + case *workflowpb.PostResetOperation_UpdateWorkflowOptions_: + opts := op.UpdateWorkflowOptions.GetWorkflowExecutionOptions() + if err := worker_versioning.ValidateVersioningOverride(ctx, opts.GetVersioningOverride(), matchingClient, versionMembershipCache, taskQueue.GetName(), enumspb.TASK_QUEUE_TYPE_WORKFLOW, namespaceID); err != nil { + return err + } + default: + return serviceerror.NewInvalidArgumentf("unsupported post reset operation: %T", op) + } + } + return nil +} diff --git a/service/history/api/signalwithstartworkflow/api.go b/service/history/api/signalwithstartworkflow/api.go index 6122f1f5d3..1e5c44f2f7 100644 --- a/service/history/api/signalwithstartworkflow/api.go +++ b/service/history/api/signalwithstartworkflow/api.go @@ -6,11 +6,14 @@ import ( enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/serviceerror" "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/enums" "go.temporal.io/server/common/locks" "go.temporal.io/server/common/metrics" "go.temporal.io/server/common/namespace" + "go.temporal.io/server/common/worker_versioning" "go.temporal.io/server/service/history/api" historyi "go.temporal.io/server/service/history/interfaces" ) @@ -20,6 +23,8 @@ func Invoke( signalWithStartRequest *historyservice.SignalWithStartWorkflowExecutionRequest, shard historyi.ShardContext, workflowConsistencyChecker api.WorkflowConsistencyChecker, + matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, ) (_ *historyservice.SignalWithStartWorkflowExecutionResponse, retError error) { namespaceEntry, err := api.GetActiveNamespace(shard, namespace.ID(signalWithStartRequest.GetNamespaceId())) if err != nil { @@ -70,6 +75,12 @@ func Invoke( return nil, err } + // Validation for versioning override, if any. + err = worker_versioning.ValidateVersioningOverride(ctx, request.GetVersioningOverride(), matchingClient, versionMembershipCache, request.GetTaskQueue().GetName(), enumspb.TASK_QUEUE_TYPE_WORKFLOW, namespaceID.String()) + if err != nil { + return nil, err + } + runID, started, err := SignalWithStartWorkflow( ctx, shard, diff --git a/service/history/api/startworkflow/api.go b/service/history/api/startworkflow/api.go index 613846794c..bafa6e6817 100644 --- a/service/history/api/startworkflow/api.go +++ b/service/history/api/startworkflow/api.go @@ -11,8 +11,10 @@ import ( "go.temporal.io/api/serviceerror" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" "go.temporal.io/server/chasm" "go.temporal.io/server/common" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/dynamicconfig" "go.temporal.io/server/common/enums" @@ -23,6 +25,7 @@ import ( "go.temporal.io/server/common/primitives" "go.temporal.io/server/common/softassert" "go.temporal.io/server/common/tasktoken" + "go.temporal.io/server/common/worker_versioning" "go.temporal.io/server/service/history/api" "go.temporal.io/server/service/history/consts" historyi "go.temporal.io/server/service/history/interfaces" @@ -53,11 +56,13 @@ type Starter struct { metricsHandler metrics.Handler shardContext historyi.ShardContext workflowConsistencyChecker api.WorkflowConsistencyChecker + matchingClient matchingservice.MatchingServiceClient tokenSerializer *tasktoken.Serializer request *historyservice.StartWorkflowExecutionRequest namespace *namespace.Namespace createOrUpdateLeaseFn api.CreateOrUpdateLeaseFunc enableRequestIdRefLinks dynamicconfig.BoolPropertyFn + versionMembershipCache cache.Cache } // creationParams is a container for all information obtained from creating the uncommitted execution. @@ -85,6 +90,8 @@ func NewStarter( workflowConsistencyChecker api.WorkflowConsistencyChecker, tokenSerializer *tasktoken.Serializer, request *historyservice.StartWorkflowExecutionRequest, + matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, createLeaseFn api.CreateOrUpdateLeaseFunc, ) (*Starter, error) { namespaceEntry, err := api.GetActiveNamespace(shardContext, namespace.ID(request.GetNamespaceId())) @@ -97,11 +104,13 @@ func NewStarter( metricsHandler: nil, shardContext: shardContext, workflowConsistencyChecker: workflowConsistencyChecker, + matchingClient: matchingClient, tokenSerializer: tokenSerializer, request: request, namespace: namespaceEntry, createOrUpdateLeaseFn: createLeaseFn, enableRequestIdRefLinks: shardContext.GetConfig().EnableRequestIdRefLinks, + versionMembershipCache: versionMembershipCache, }, nil } @@ -130,6 +139,12 @@ func (s *Starter) prepare(ctx context.Context) error { return err } + // Validation for versioning override, if any. + err = worker_versioning.ValidateVersioningOverride(ctx, request.GetVersioningOverride(), s.matchingClient, s.versionMembershipCache, request.GetTaskQueue().GetName(), enumspb.TASK_QUEUE_TYPE_WORKFLOW, s.namespace.ID().String()) + if err != nil { + return err + } + if request.RequestEagerExecution { metricsHandler := s.getMetricsHandler() metrics.WorkflowEagerExecutionCounter.With(metricsHandler).Record(1) diff --git a/service/history/api/updateworkflowoptions/api.go b/service/history/api/updateworkflowoptions/api.go index e3afe3c20d..9f0724216b 100644 --- a/service/history/api/updateworkflowoptions/api.go +++ b/service/history/api/updateworkflowoptions/api.go @@ -4,12 +4,16 @@ import ( "context" commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/serviceerror" workflowpb "go.temporal.io/api/workflow/v1" "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/namespace" "go.temporal.io/server/common/util" + "go.temporal.io/server/common/worker_versioning" "go.temporal.io/server/service/history/api" "go.temporal.io/server/service/history/consts" historyi "go.temporal.io/server/service/history/interfaces" @@ -22,6 +26,8 @@ func Invoke( request *historyservice.UpdateWorkflowExecutionOptionsRequest, shardCtx historyi.ShardContext, workflowConsistencyChecker api.WorkflowConsistencyChecker, + matchingClient matchingservice.MatchingServiceClient, + versionMembershipCache cache.Cache, ) (*historyservice.UpdateWorkflowExecutionOptionsResponse, error) { ns, err := api.GetActiveNamespace(shardCtx, namespace.ID(request.GetNamespaceId())) if err != nil { @@ -46,6 +52,12 @@ func Invoke( return nil, consts.ErrWorkflowCompleted } + // Validate versioning override, if any. + err = worker_versioning.ValidateVersioningOverride(ctx, req.GetWorkflowExecutionOptions().GetVersioningOverride(), matchingClient, versionMembershipCache, mutableState.GetExecutionInfo().GetTaskQueue(), enumspb.TASK_QUEUE_TYPE_WORKFLOW, ns.ID().String()) + if err != nil { + return nil, err + } + mergedOpts, hasChanges, err := MergeAndApply(mutableState, req.GetWorkflowExecutionOptions(), req.GetUpdateMask(), req.GetIdentity()) if err != nil { return nil, err diff --git a/service/history/api/updateworkflowoptions/api_test.go b/service/history/api/updateworkflowoptions/api_test.go index 51882ee556..ad7ddb273f 100644 --- a/service/history/api/updateworkflowoptions/api_test.go +++ b/service/history/api/updateworkflowoptions/api_test.go @@ -8,13 +8,17 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" commonpb "go.temporal.io/api/common/v1" + deploymentpb "go.temporal.io/api/deployment/v1" enumspb "go.temporal.io/api/enums/v1" historypb "go.temporal.io/api/history/v1" workflowpb "go.temporal.io/api/workflow/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" + "go.temporal.io/server/api/matchingservicemock/v1" persistencespb "go.temporal.io/server/api/persistence/v1" "go.temporal.io/server/chasm" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/cluster" "go.temporal.io/server/common/cluster/clustertest" "go.temporal.io/server/common/locks" @@ -140,6 +144,7 @@ type ( currentContext *historyi.MockWorkflowContext currentMutableState *historyi.MockMutableState + mockMatchingClient *matchingservicemock.MockMatchingServiceClient } ) @@ -185,6 +190,8 @@ func (s *updateWorkflowOptionsSuite) SetupTest() { s.shardContext, s.workflowCache, ) + + s.mockMatchingClient = matchingservicemock.NewMockMatchingServiceClient(s.controller) } func (s *updateWorkflowOptionsSuite) TearDownTest() { @@ -195,11 +202,24 @@ func (s *updateWorkflowOptionsSuite) TestInvoke_Success() { expectedOverrideOptions := &workflowpb.WorkflowExecutionOptions{ VersioningOverride: &workflowpb.VersioningOverride{ - Behavior: enumspb.VERSIONING_BEHAVIOR_PINNED, - PinnedVersion: "X.A", + Override: &workflowpb.VersioningOverride_Pinned{ + Pinned: &workflowpb.VersioningOverride_PinnedOverride{ + Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, + Version: &deploymentpb.WorkerDeploymentVersion{ + DeploymentName: "X", + BuildId: "A", + }, + }, + }, }, } s.currentMutableState.EXPECT().IsWorkflowExecutionRunning().Return(true) + s.mockMatchingClient.EXPECT().CheckTaskQueueVersionMembership( + gomock.Any(), + gomock.Any(), + ).Return(&matchingservice.CheckTaskQueueVersionMembershipResponse{ + IsMember: true, + }, nil) s.currentMutableState.EXPECT().AddWorkflowExecutionOptionsUpdatedEvent(expectedOverrideOptions.VersioningOverride, false, "", nil, nil, "", expectedOverrideOptions.Priority).Return(&historypb.HistoryEvent{}, nil) s.currentContext.EXPECT().UpdateWorkflowExecutionAsActive(gomock.Any(), s.shardContext).Return(nil) @@ -221,6 +241,8 @@ func (s *updateWorkflowOptionsSuite) TestInvoke_Success() { updateReq, s.shardContext, s.workflowConsistencyChecker, + s.mockMatchingClient, + cache.NewSimple(&cache.SimpleOptions{}), // cache.Cache is not meant to be used in the test which is why we are passing an empty dummy cache here. ) s.NoError(err) s.NotNil(resp) diff --git a/service/history/configs/config.go b/service/history/configs/config.go index 5f9e3e2412..eaad6904de 100644 --- a/service/history/configs/config.go +++ b/service/history/configs/config.go @@ -396,6 +396,7 @@ type Config struct { // Worker-Versioning related settings UseRevisionNumberForWorkerVersioning dynamicconfig.BoolPropertyFnWithNamespaceFilter + VersionMembershipCacheTTL dynamicconfig.DurationPropertyFn } // NewConfig returns new service config with default values @@ -752,6 +753,7 @@ func NewConfig( // Worker-Versioning related UseRevisionNumberForWorkerVersioning: dynamicconfig.UseRevisionNumberForWorkerVersioning.Get(dc), + VersionMembershipCacheTTL: dynamicconfig.VersionMembershipCacheTTL.Get(dc), } return cfg diff --git a/service/history/history_engine.go b/service/history/history_engine.go index 23f09873bb..69d235e14f 100644 --- a/service/history/history_engine.go +++ b/service/history/history_engine.go @@ -16,6 +16,7 @@ import ( "go.temporal.io/server/chasm" "go.temporal.io/server/client" "go.temporal.io/server/common" + "go.temporal.io/server/common/cache" "go.temporal.io/server/common/clock" "go.temporal.io/server/common/cluster" "go.temporal.io/server/common/collection" @@ -132,6 +133,7 @@ type ( eventSerializer serialization.Serializer workflowConsistencyChecker api.WorkflowConsistencyChecker versionChecker headers.VersionChecker + versionMembershipCache cache.Cache tracer trace.Tracer taskCategoryRegistry tasks.TaskCategoryRegistry commandHandlerRegistry *workflow.CommandHandlerRegistry @@ -313,6 +315,10 @@ func NewEngineWithShardContext( replicationTaskExecutorProvider, dlqWriter, ) + + historyEngImpl.versionMembershipCache = cache.New(10000, &cache.Options{ + TTL: max(1*time.Second, config.VersionMembershipCacheTTL())}, // ensure TTL is never zero (which would disable TTL) + ) return historyEngImpl } @@ -393,6 +399,8 @@ func (e *historyEngineImpl) StartWorkflowExecution( e.workflowConsistencyChecker, e.tokenSerializer, startRequest, + e.matchingClient, + e.versionMembershipCache, api.NewWorkflowLeaseAndContext, ) if err != nil { @@ -414,6 +422,7 @@ func (e *historyEngineImpl) ExecuteMultiOperation( e.workflowConsistencyChecker, e.tokenSerializer, e.matchingClient, + e.versionMembershipCache, e.testHooks, ) } @@ -627,7 +636,7 @@ func (e *historyEngineImpl) SignalWithStartWorkflowExecution( ctx context.Context, req *historyservice.SignalWithStartWorkflowExecutionRequest, ) (_ *historyservice.SignalWithStartWorkflowExecutionResponse, retError error) { - return signalwithstartworkflow.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker) + return signalwithstartworkflow.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker, e.matchingClient, e.versionMembershipCache) } func (e *historyEngineImpl) UpdateWorkflowExecution( @@ -828,7 +837,7 @@ func (e *historyEngineImpl) ResetWorkflowExecution( ctx context.Context, req *historyservice.ResetWorkflowExecutionRequest, ) (*historyservice.ResetWorkflowExecutionResponse, error) { - return resetworkflow.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker) + return resetworkflow.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker, e.matchingClient, e.versionMembershipCache) } // UpdateWorkflowExecutionOptions updates the options of a specific workflow execution. @@ -837,7 +846,7 @@ func (e *historyEngineImpl) UpdateWorkflowExecutionOptions( ctx context.Context, req *historyservice.UpdateWorkflowExecutionOptionsRequest, ) (*historyservice.UpdateWorkflowExecutionOptionsResponse, error) { - return updateworkflowoptions.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker) + return updateworkflowoptions.Invoke(ctx, req, e.shardContext, e.workflowConsistencyChecker, e.matchingClient, e.versionMembershipCache) } func (e *historyEngineImpl) NotifyNewHistoryEvent( diff --git a/service/matching/configs/quotas.go b/service/matching/configs/quotas.go index 741d112c94..6dec63ea76 100644 --- a/service/matching/configs/quotas.go +++ b/service/matching/configs/quotas.go @@ -50,6 +50,7 @@ var ( "/temporal.server.api.matchingservice.v1.MatchingService/ListWorkers": 1, "/temporal.server.api.matchingservice.v1.MatchingService/UpdateTaskQueueConfig": 1, "/temporal.server.api.matchingservice.v1.MatchingService/DescribeWorker": 1, + "/temporal.server.api.matchingservice.v1.MatchingService/CheckTaskQueueVersionMembership": 1, } APIPrioritiesOrdered = []int{0, 1} diff --git a/service/matching/handler.go b/service/matching/handler.go index 67d69a0f79..632ffac115 100644 --- a/service/matching/handler.go +++ b/service/matching/handler.go @@ -475,6 +475,14 @@ func (h *Handler) CheckTaskQueueUserDataPropagation( return h.engine.CheckTaskQueueUserDataPropagation(ctx, request) } +func (h *Handler) CheckTaskQueueVersionMembership( + ctx context.Context, + request *matchingservice.CheckTaskQueueVersionMembershipRequest, +) (_ *matchingservice.CheckTaskQueueVersionMembershipResponse, retError error) { + defer log.CapturePanic(h.logger, &retError) + return h.engine.CheckTaskQueueVersionMembership(ctx, request) +} + func (h *Handler) DispatchNexusTask(ctx context.Context, request *matchingservice.DispatchNexusTaskRequest) (_ *matchingservice.DispatchNexusTaskResponse, retError error) { defer log.CapturePanic(h.logger, &retError) return h.engine.DispatchNexusTask(ctx, request) diff --git a/service/matching/matching_engine.go b/service/matching/matching_engine.go index 333da88f62..1c19234670 100644 --- a/service/matching/matching_engine.go +++ b/service/matching/matching_engine.go @@ -3139,6 +3139,32 @@ func prepareTaskQueueUserData( return data } +func (e *matchingEngineImpl) CheckTaskQueueVersionMembership( + ctx context.Context, + request *matchingservice.CheckTaskQueueVersionMembershipRequest, +) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) { + partition, err := tqid.PartitionFromProto(&taskqueuepb.TaskQueue{ + Name: request.GetTaskQueue(), + Kind: enumspb.TASK_QUEUE_KIND_NORMAL, + }, request.GetNamespaceId(), request.GetTaskQueueType()) + if err != nil { + return nil, err + } + pm, _, err := e.getTaskQueuePartitionManager(ctx, partition, true, loadCauseOtherRead) + if err != nil { + return nil, err + } + + userData, _, err := pm.GetUserDataManager().GetUserData() + if err != nil { + return nil, err + } + + typedUserData := userData.GetData().GetPerType()[int32(request.GetTaskQueueType())] + present := worker_versioning.HasDeploymentVersion(typedUserData.GetDeploymentData(), request.GetVersion()) + return &matchingservice.CheckTaskQueueVersionMembershipResponse{IsMember: present}, nil +} + func (e *matchingEngineImpl) UpdateTaskQueueConfig( ctx context.Context, request *matchingservice.UpdateTaskQueueConfigRequest, diff --git a/service/matching/matching_engine_interfaces.go b/service/matching/matching_engine_interfaces.go index 3a4829fd47..6ba75b7db6 100644 --- a/service/matching/matching_engine_interfaces.go +++ b/service/matching/matching_engine_interfaces.go @@ -34,6 +34,7 @@ type ( UpdateTaskQueueUserData(ctx context.Context, request *matchingservice.UpdateTaskQueueUserDataRequest) (*matchingservice.UpdateTaskQueueUserDataResponse, error) ReplicateTaskQueueUserData(ctx context.Context, request *matchingservice.ReplicateTaskQueueUserDataRequest) (*matchingservice.ReplicateTaskQueueUserDataResponse, error) CheckTaskQueueUserDataPropagation(ctx context.Context, request *matchingservice.CheckTaskQueueUserDataPropagationRequest) (*matchingservice.CheckTaskQueueUserDataPropagationResponse, error) + CheckTaskQueueVersionMembership(ctx context.Context, request *matchingservice.CheckTaskQueueVersionMembershipRequest) (*matchingservice.CheckTaskQueueVersionMembershipResponse, error) DispatchNexusTask(ctx context.Context, request *matchingservice.DispatchNexusTaskRequest) (*matchingservice.DispatchNexusTaskResponse, error) PollNexusTaskQueue(ctx context.Context, request *matchingservice.PollNexusTaskQueueRequest, opMetrics metrics.Handler) (*matchingservice.PollNexusTaskQueueResponse, error) RespondNexusTaskCompleted(ctx context.Context, request *matchingservice.RespondNexusTaskCompletedRequest, opMetrics metrics.Handler) (*matchingservice.RespondNexusTaskCompletedResponse, error) diff --git a/service/worker/batcher/workflow.go b/service/worker/batcher/workflow.go index af17446d32..cbcaea271b 100644 --- a/service/worker/batcher/workflow.go +++ b/service/worker/batcher/workflow.go @@ -14,7 +14,6 @@ import ( "go.temporal.io/sdk/workflow" batchspb "go.temporal.io/server/api/batch/v1" "go.temporal.io/server/common/searchattribute/sadefs" - "go.temporal.io/server/common/worker_versioning" "google.golang.org/protobuf/types/known/durationpb" ) @@ -186,7 +185,8 @@ func ValidateBatchOperation(params *workflowservice.StartBatchOperationRequest) if op.UpdateWorkflowOptionsOperation.GetUpdateMask() == nil { return errors.New("must provide UpdateMask") } - return worker_versioning.ValidateVersioningOverride(op.UpdateWorkflowOptionsOperation.GetWorkflowExecutionOptions().GetVersioningOverride()) + // Validation for Versioning Override, if present, happens in history. + return nil case *workflowservice.StartBatchOperationRequest_CancellationOperation, *workflowservice.StartBatchOperationRequest_TerminationOperation, *workflowservice.StartBatchOperationRequest_DeletionOperation: diff --git a/tests/versioning_3_test.go b/tests/versioning_3_test.go index 46eb3e5984..48fa767860 100644 --- a/tests/versioning_3_test.go +++ b/tests/versioning_3_test.go @@ -145,6 +145,16 @@ func (s *Versioning3Suite) TestPinnedTask_NoProperPoller() { tv2 := tv.WithBuildIDNumber(2) go s.idlePollWorkflow(context.Background(), tv2, true, ver3MinPollTime, "second deployment should not receive pinned task") + // Start a versioned poller for the first version so that it registers the version in the task queue. + pollerCtx, cancelPoller := context.WithCancel(context.Background()) + go s.idlePollWorkflow(pollerCtx, tv, true, ver3MinPollTime, "first deployment should not receive any task. It is just creating a version in the task queue.") + + // Wait for the version to be present in the task queue + s.validatePinnedVersionExistsInTaskQueue(tv) + + // Cancel the poller after condition is met + cancelPoller() + s.startWorkflow(tv, tv.VersioningOverridePinned(s.useV32)) s.idlePollWorkflow(context.Background(), tv, false, ver3MinPollTime, "unversioned worker should not receive pinned task") @@ -273,6 +283,9 @@ func (s *Versioning3Suite) testWorkflowWithPinnedOverride(sticky bool) { return respondActivity(), nil }) + // Wait for the version to be present in the task queue. Version existence is required before it can be set as an override. + s.validatePinnedVersionExistsInTaskQueue(tv) + runID := s.startWorkflow(tv, tv.VersioningOverridePinned(s.useV32)) s.WaitForChannel(ctx, wftCompleted) @@ -443,6 +456,19 @@ func (s *Versioning3Suite) testQueryWithPinnedOverride(sticky bool) { return respondEmptyWft(tv, sticky, vbUnpinned), nil }) + // Wait for the version to be present in the task queue. Version existence is required before it can be set as an override. + s.EventuallyWithT(func(t *assert.CollectT) { + a := require.New(t) + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership(ctx, &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: tv.TaskQueue().GetName(), + TaskQueueType: tqTypeWf, + Version: worker_versioning.DeploymentVersionFromDeployment(tv.Deployment()), + }) + a.NoError(err) + a.True(resp.GetIsMember()) + }, 10*time.Second, 100*time.Millisecond) + runID := s.startWorkflow(tv, tv.VersioningOverridePinned(s.useV32)) s.WaitForChannel(ctx, wftCompleted) @@ -4571,3 +4597,58 @@ func (s *Versioning3Suite) TestWorkflowRetry_AutoUpgrade_AfterCAN_NoBounceBack() func (s *Versioning3Suite) TestWorkflowRetry_AutoUpgrade_ChildNoBounceBack() { s.testRetryNoBounceBack(false, true) } + +// The following tests test out the CheckTaskQueueVersionMembership RPC. +func (s *Versioning3Suite) TestCheckTaskQueueVersionMembership() { + tv1 := testvars.New(s).WithBuildIDNumber(1) + + // No version exists in the task queue's userData as of now + s.Eventually(func() bool { + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership(context.Background(), &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: tv1.TaskQueue().GetName(), + TaskQueueType: tqTypeWf, + Version: worker_versioning.DeploymentVersionFromDeployment(tv1.Deployment()), + }) + s.NoError(err) + return !resp.GetIsMember() // the check should pass if no version is present + }, 10*time.Second, 100*time.Millisecond) + + // Start v1 worker which shall register the version in the task queue + w1 := worker.New(s.SdkClient(), tv1.TaskQueue().GetName(), worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + Version: tv1.SDKDeploymentVersion(), + UseVersioning: true, + }, + }) + s.NoError(w1.Start()) + defer w1.Stop() + + // The version should eventually show up in the task queue's user data + s.Eventually(func() bool { + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership(context.Background(), &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: tv1.TaskQueue().GetName(), + TaskQueueType: tqTypeWf, + Version: worker_versioning.DeploymentVersionFromDeployment(tv1.Deployment()), + }) + s.NoError(err) + return resp.GetIsMember() + }, 10*time.Second, 100*time.Millisecond) +} + +// validatePinnedVersionExistsInTaskQueue validates that the version, to be pinned, exists in the task queue. +// TODO (future improvement): This can be further extended to validate the presence of any version instead of using the GetTaskQueueUserData RPC. +func (s *Versioning3Suite) validatePinnedVersionExistsInTaskQueue(tv *testvars.TestVars) { + s.EventuallyWithT(func(t *assert.CollectT) { + a := require.New(t) + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership(context.Background(), &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: tv.TaskQueue().GetName(), + TaskQueueType: tqTypeWf, + Version: worker_versioning.DeploymentVersionFromDeployment(tv.Deployment()), + }) + a.NoError(err) + a.True(resp.GetIsMember()) + }, 10*time.Second, 100*time.Millisecond) +} diff --git a/tests/worker_deployment_version_test.go b/tests/worker_deployment_version_test.go index ba28938b71..ec5d169ab1 100644 --- a/tests/worker_deployment_version_test.go +++ b/tests/worker_deployment_version_test.go @@ -58,10 +58,10 @@ var ( func TestDeploymentVersionSuite(t *testing.T) { t.Parallel() - t.Run("v0", func(t *testing.T) { + t.Run("sync_workflows", func(t *testing.T) { suite.Run(t, &DeploymentVersionSuite{workflowVersion: workerdeployment.InitialVersion}) }) - t.Run("v1", func(t *testing.T) { + t.Run("async_workflows", func(t *testing.T) { suite.Run(t, &DeploymentVersionSuite{workflowVersion: workerdeployment.AsyncSetCurrentAndRamping}) }) } @@ -84,6 +84,7 @@ func (s *DeploymentVersionSuite) SetupSuite() { dynamicconfig.VersionDrainageStatusRefreshInterval.Key(): testVersionDrainageRefreshInterval, dynamicconfig.VersionDrainageStatusVisibilityGracePeriod.Key(): testVersionDrainageVisibilityGracePeriod, + dynamicconfig.VersionMembershipCacheTTL.Key(): 5 * time.Second, })) } @@ -1306,6 +1307,61 @@ func (s *DeploymentVersionSuite) setAndCheckOverride(ctx context.Context, tv *te s.checkWorkflowUpdateOptionsEventIdentity(ctx, tv.WorkflowExecution(), tv.ClientIdentity()) } +// The following tests test the VersioningOverride functionality when passed via the UpdateWorkflowExecutionOptions API. +func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetPinned_CacheMissAndHits() { + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + tv := testvars.New(s) + + // start an unversioned workflow + s.startWorkflow(tv, nil) + + opts := &workflowpb.WorkflowExecutionOptions{VersioningOverride: s.makePinnedOverride(tv)} + + // Setting a pinned override should fail since the version does not exist + resp, err := s.FrontendClient().UpdateWorkflowExecutionOptions(ctx, &workflowservice.UpdateWorkflowExecutionOptionsRequest{ + Namespace: s.Namespace().String(), + WorkflowExecution: tv.WorkflowExecution(), + WorkflowExecutionOptions: opts, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"versioning_override"}}, + Identity: tv.ClientIdentity(), + }) + s.Error(err) + s.Nil(resp) + + // Start a versioned poller which shall create a version; however, the cache TTL is not expired yet. This would result in a cache hit which would return + // a stale value for the version presence in the task queue. + s.startVersionWorkflow(ctx, tv) + + // Setting a pinned override should fail since the stale cache entry is returned. + resp, err = s.FrontendClient().UpdateWorkflowExecutionOptions(ctx, &workflowservice.UpdateWorkflowExecutionOptionsRequest{ + Namespace: s.Namespace().String(), + WorkflowExecution: tv.WorkflowExecution(), + WorkflowExecutionOptions: opts, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"versioning_override"}}, + Identity: tv.ClientIdentity(), + }) + s.Error(err) + s.Nil(resp) + + // Wait for the cache TTL to expire + s.Eventually(func() bool { + _, err := s.FrontendClient().UpdateWorkflowExecutionOptions(ctx, &workflowservice.UpdateWorkflowExecutionOptionsRequest{ + Namespace: s.Namespace().String(), + WorkflowExecution: tv.WorkflowExecution(), + WorkflowExecutionOptions: opts, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"versioning_override"}}, + Identity: tv.ClientIdentity(), + }) + return err == nil + }, 10*time.Second, 500*time.Millisecond) + + // The Pinned Override should have now succeeded with no error. Verify that the + // the workflow shows the override. + s.checkDescribeWorkflowAfterOverride(ctx, tv.WorkflowExecution(), opts.VersioningOverride) +} + func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetUnpinnedThenUnset() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() @@ -1326,6 +1382,9 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetPinnedThe defer cancel() tv := testvars.New(s) + // Start a versioned poller which shall create a version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + // start an unversioned workflow s.startWorkflow(tv, nil) @@ -1341,6 +1400,9 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_EmptyFields( defer cancel() tv := testvars.New(s) + // Start a versioned poller which shall create a version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + // start an unversioned workflow s.startWorkflow(tv, nil) @@ -1365,6 +1427,10 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetPinnedSet tv1 := tv.WithBuildIDNumber(1) tv2 := tv.WithBuildIDNumber(2) + // Start a versioned poller which shall create the two versions; the versions must be present before they can be set as overrides. + s.startVersionWorkflow(ctx, tv1) + s.startVersionWorkflow(ctx, tv2) + // start an unversioned workflow s.startWorkflow(tv, nil) @@ -1395,6 +1461,9 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetUnpinnedS defer cancel() tv := testvars.New(s) + // Start a versioned poller which shall create a version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + // start an unversioned workflow s.startWorkflow(tv, nil) @@ -1410,6 +1479,9 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetPinnedSet defer cancel() tv := testvars.New(s) + // Start a versioned poller which shall create a version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + // start an unversioned workflow s.startWorkflow(tv, nil) @@ -1420,8 +1492,17 @@ func (s *DeploymentVersionSuite) TestUpdateWorkflowExecutionOptions_SetPinnedSet s.setAndCheckOverride(ctx, tv, s.makeAutoUpgradeOverride()) } +// The following tests test the VersioningOverride functionality when passed via the BatchUpdateWorkflowExecutionOptions API. +func (s *DeploymentVersionSuite) TestBatchUpdateWorkflowExecutionOptions_SetPinned_VersionDoesNotExist() { + s.runBatchUpdateWorkflowExecutionOptionsTest(false) +} + func (s *DeploymentVersionSuite) TestBatchUpdateWorkflowExecutionOptions_SetPinnedThenUnset() { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + s.runBatchUpdateWorkflowExecutionOptionsTest(true) +} + +func (s *DeploymentVersionSuite) runBatchUpdateWorkflowExecutionOptionsTest(createVersionFirst bool) { + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Second) defer cancel() tv := testvars.New(s) @@ -1437,11 +1518,15 @@ func (s *DeploymentVersionSuite) TestBatchUpdateWorkflowExecutionOptions_SetPinn }) } - // start batch update-options operation pinnedOverride := s.makePinnedOverride(tv) batchJobID := uuid.NewString() - // unpause the activities in both workflows with batch unpause + if createVersionFirst { + // Start a versioned poller which shall create a version + s.startVersionWorkflow(ctx, tv) + } + + // start batch update-options operation _, err := s.SdkClient().WorkflowService().StartBatchOperation(context.Background(), &workflowservice.StartBatchOperationRequest{ Namespace: s.Namespace().String(), Operation: &workflowservice.StartBatchOperationRequest_UpdateWorkflowOptionsOperation{ @@ -1457,7 +1542,15 @@ func (s *DeploymentVersionSuite) TestBatchUpdateWorkflowExecutionOptions_SetPinn }) s.NoError(err) - // wait til batch completes + if !createVersionFirst { + s.checkBatchOperationFails(ctx, batchJobID, len(workflows)) + for _, wf := range workflows { + s.checkDescribeWorkflowAfterOverride(ctx, wf, nil) + } + return + } + + // wait til batch completes successfully s.checkListAndWaitForBatchCompletion(ctx, batchJobID) // check all the workflows @@ -1492,7 +1585,6 @@ func (s *DeploymentVersionSuite) TestBatchUpdateWorkflowExecutionOptions_SetPinn s.checkWorkflowUpdateOptionsEventIdentity(ctx, wf, tv.ClientIdentity()) } } - func (s *DeploymentVersionSuite) startBatchJobWithinConcurrentJobLimit(ctx context.Context, req *workflowservice.StartBatchOperationRequest) error { var err error s.Eventually(func() bool { @@ -1532,6 +1624,19 @@ func (s *DeploymentVersionSuite) checkListAndWaitForBatchCompletion(ctx context. }, 10*time.Second, 50*time.Millisecond) } +func (s *DeploymentVersionSuite) checkBatchOperationFails(ctx context.Context, jobID string, numWorkflows int) { + s.EventuallyWithT(func(t *assert.CollectT) { + a := assert.New(t) + descResp, err := s.FrontendClient().DescribeBatchOperation(ctx, &workflowservice.DescribeBatchOperationRequest{ + Namespace: s.Namespace().String(), + JobId: jobID, + }) + a.NoError(err) + // All workflows should have failed validation + a.Equal(int64(numWorkflows), descResp.GetFailureOperationCount(), "expected all operations to fail") + }, 30*time.Second, 500*time.Millisecond) +} + func (s *DeploymentVersionSuite) makePinnedOverride(tv *testvars.TestVars) *workflowpb.VersioningOverride { if s.useV32 { return &workflowpb.VersioningOverride{Override: &workflowpb.VersioningOverride_Pinned{ @@ -1554,17 +1659,43 @@ func (s *DeploymentVersionSuite) makeAutoUpgradeOverride() *workflowpb.Versionin return &workflowpb.VersioningOverride{Behavior: enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE} //nolint:staticcheck // SA1019: worker versioning v0.31 } -func (s *DeploymentVersionSuite) TestStartWorkflowExecution_WithPinnedOverride() { +func (s *DeploymentVersionSuite) TestStartWorkflowExecution_WithPinnedOverride_CacheMissAndHits() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() tv := testvars.New(s) override := s.makePinnedOverride(tv) - wf := &commonpb.WorkflowExecution{ - WorkflowId: tv.WorkflowID(), - RunId: s.startWorkflow(tv, override), + request := &workflowservice.StartWorkflowExecutionRequest{ + RequestId: tv.Any().String(), + Namespace: s.Namespace().String(), + WorkflowId: tv.WorkflowID(), + WorkflowType: tv.WorkflowType(), + TaskQueue: tv.TaskQueue(), + Identity: tv.WorkerIdentity(), + VersioningOverride: override, } - s.checkDescribeWorkflowAfterOverride(ctx, wf, override) + + // First call should fail since the version to override is not present in the task queue. + _, err0 := s.FrontendClient().StartWorkflowExecution(ctx, request) + s.Error(err0) + + // Start a versioned poller which shall create the version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + + // Wait for the cache TTL to expire; On expiry of the cache TTL, it would result in a fresh RPC which would verify the version presence, + // eventually leading to the StartWorkflowExecution call succeeding. + var resp *workflowservice.StartWorkflowExecutionResponse + s.Eventually(func() bool { + var err error + resp, err = s.FrontendClient().StartWorkflowExecution(ctx, request) + return err == nil + }, 10*time.Second, 500*time.Millisecond) + + // The StartWorkflowExecution should now succeed with no error. Verify that the workflow shows the override. + s.checkDescribeWorkflowAfterOverride(ctx, &commonpb.WorkflowExecution{ + WorkflowId: tv.WorkflowID(), + RunId: resp.GetRunId(), + }, override) } func (s *DeploymentVersionSuite) TestStartWorkflowExecution_WithUnpinnedOverride() { @@ -1580,14 +1711,13 @@ func (s *DeploymentVersionSuite) TestStartWorkflowExecution_WithUnpinnedOverride s.checkDescribeWorkflowAfterOverride(ctx, wf, override) } -func (s *DeploymentVersionSuite) TestSignalWithStartWorkflowExecution_WithPinnedOverride() { +func (s *DeploymentVersionSuite) TestSignalWithStartWorkflowExecution_WithPinnedOverride_CacheMissAndHits() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() tv := testvars.New(s) override := s.makePinnedOverride(tv) - - resp, err := s.FrontendClient().SignalWithStartWorkflowExecution(ctx, &workflowservice.SignalWithStartWorkflowExecutionRequest{ + request := &workflowservice.SignalWithStartWorkflowExecutionRequest{ Namespace: s.Namespace().String(), WorkflowId: tv.WorkflowID(), WorkflowType: tv.WorkflowType(), @@ -1597,9 +1727,23 @@ func (s *DeploymentVersionSuite) TestSignalWithStartWorkflowExecution_WithPinned SignalName: "test-signal", SignalInput: nil, VersioningOverride: override, - }) - s.NoError(err) - s.True(resp.GetStarted()) + } + + // Since the version to override is not present in the task queue, the call should fail. + _, err := s.FrontendClient().SignalWithStartWorkflowExecution(ctx, request) + s.Error(err) + + // Start a versioned poller which shall create the version; the version must be present before it can be set as an override. + s.startVersionWorkflow(ctx, tv) + + // Wait for the cache TTL to expire; On expiry of the cache TTL, it would result in a fresh RPC which would verify the version presence, + // eventually leading to the SignalWithStartWorkflowExecution call succeeding. + var resp *workflowservice.SignalWithStartWorkflowExecutionResponse + s.Eventually(func() bool { + var err error + resp, err = s.FrontendClient().SignalWithStartWorkflowExecution(ctx, request) + return err == nil && resp.GetStarted() + }, 10*time.Second, 500*time.Millisecond) wf := &commonpb.WorkflowExecution{ WorkflowId: tv.WorkflowID(), diff --git a/tests/workflow_alias_search_attribute_test.go b/tests/workflow_alias_search_attribute_test.go index 03d1685c80..f05b1d5632 100644 --- a/tests/workflow_alias_search_attribute_test.go +++ b/tests/workflow_alias_search_attribute_test.go @@ -10,10 +10,14 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" commonpb "go.temporal.io/api/common/v1" + deploymentpb "go.temporal.io/api/deployment/v1" enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/operatorservice/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/workflow" + deploymentspb "go.temporal.io/server/api/deployment/v1" + "go.temporal.io/server/api/matchingservice/v1" "go.temporal.io/server/common/payload" "go.temporal.io/server/common/searchattribute/sadefs" "go.temporal.io/server/common/testing/testvars" @@ -39,11 +43,63 @@ func (s *WorkflowAliasSearchAttributeTestSuite) workflowFunc(ctx workflow.Contex return "done!", nil } +func (s *WorkflowAliasSearchAttributeTestSuite) startVersionedPollerAndValidate( + ctx context.Context, + taskQueueName string, + deploymentName string, + buildID string, +) { + taskQueue := &taskqueuepb.TaskQueue{ + Name: taskQueueName, + Kind: enumspb.TASK_QUEUE_KIND_NORMAL, + } + + // Start versioned poller in background + go func() { + _, _ = s.FrontendClient().PollWorkflowTaskQueue(ctx, &workflowservice.PollWorkflowTaskQueueRequest{ + Namespace: s.Namespace().String(), + TaskQueue: taskQueue, + Identity: "versioned-poller", + DeploymentOptions: &deploymentpb.WorkerDeploymentOptions{ + DeploymentName: deploymentName, + BuildId: buildID, + WorkerVersioningMode: enumspb.WORKER_VERSIONING_MODE_VERSIONED, + }, + }) + }() + + // Validate version is present via matching RPC + version := &deploymentspb.WorkerDeploymentVersion{ + DeploymentName: deploymentName, + BuildId: buildID, + } + s.EventuallyWithT(func(t *assert.CollectT) { + a := require.New(t) + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership( + ctx, + &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: taskQueueName, + TaskQueueType: enumspb.TASK_QUEUE_TYPE_WORKFLOW, + Version: version, + }, + ) + a.NoError(err) + a.True(resp.GetIsMember()) + }, 10*time.Second, 1*time.Second) +} + func (s *WorkflowAliasSearchAttributeTestSuite) createWorkflow( ctx context.Context, tv *testvars.TestVars, sa *commonpb.SearchAttributes, ) (*workflowservice.StartWorkflowExecutionResponse, error) { + // Start a versioned poller so that the version, which will be set as an override, is present in the task queue. + fmt.Println("task queue name ", tv.TaskQueue().Name) + fmt.Println("deployment name ", tv.DeploymentSeries()) + fmt.Println("build ID ", tv.BuildID()) + s.startVersionedPollerAndValidate(ctx, tv.TaskQueue().Name, tv.DeploymentSeries(), tv.BuildID()) + request := &workflowservice.StartWorkflowExecutionRequest{ RequestId: tv.Any().String(), Namespace: s.Namespace().String(), @@ -74,7 +130,12 @@ func (s *WorkflowAliasSearchAttributeTestSuite) TestWorkflowAliasSearchAttribute ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - tv := testvars.New(s.T()) + // Overriding the task queue name, deployment name, and build ID so that we don't hit length limitations + // for any of these in any of the databases. + tv := testvars.New(s.T()). + WithTaskQueue("tq-alias-sa"). + WithDeploymentSeries("dep-alias-sa"). + WithBuildID("build-alias-sa") _, err := s.createWorkflow(ctx, tv, nil) s.Require().NoError(err) @@ -118,7 +179,12 @@ func (s *WorkflowAliasSearchAttributeTestSuite) TestWorkflowAliasSearchAttribute ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - tv := testvars.New(s.T()) + // Overriding the task queue name, deployment name, and build ID so that we don't hit length limitations + // for any of these in any of the databases. + tv := testvars.New(s.T()). + WithTaskQueue("tq-alias-sa-custom"). + WithDeploymentSeries("dep-alias-sa-custom"). + WithBuildID("build-alias-sa-custom") _, err := s.SdkClient().OperatorService().AddSearchAttributes(ctx, &operatorservice.AddSearchAttributesRequest{ Namespace: s.Namespace().String(), diff --git a/tests/workflow_reset_test.go b/tests/workflow_reset_test.go index 864b1cf006..bdff6cec77 100644 --- a/tests/workflow_reset_test.go +++ b/tests/workflow_reset_test.go @@ -6,6 +6,8 @@ import ( "time" "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" batchpb "go.temporal.io/api/batch/v1" commandpb "go.temporal.io/api/command/v1" @@ -18,6 +20,8 @@ import ( "go.temporal.io/api/workflowservice/v1" "go.temporal.io/sdk/client" "go.temporal.io/server/api/adminservice/v1" + deploymentspb "go.temporal.io/server/api/deployment/v1" + "go.temporal.io/server/api/matchingservice/v1" "go.temporal.io/server/chasm" "go.temporal.io/server/common/payloads" "go.temporal.io/server/tests/testcore" @@ -30,6 +34,16 @@ type WorkflowResetSuite struct { testcore.FunctionalTestBase } +// versioningConfig contains configuration for setting up versioned pollers. +type versioningConfig struct { + // Required indicates whether a versioned poller should be started for a particular test. + Required bool + // DeploymentName is the deployment name for versioning. + DeploymentName string + // BuildID is the build ID for versioning. + BuildID string +} + func TestWorkflowResetTestSuite(t *testing.T) { t.Parallel() suite.Run(t, new(WorkflowResetSuite)) @@ -39,7 +53,7 @@ func TestWorkflowResetTestSuite(t *testing.T) { func (s *WorkflowResetSuite) TestNoBaseCurrentRunning() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, true) + runs := s.setupRuns(ctx, workflowID, 1, true, versioningConfig{}) currentRunID := runs[0] // Reset the current run (i.e don't give an explicit runID) @@ -68,7 +82,7 @@ func (s *WorkflowResetSuite) TestNoBaseCurrentRunning() { func (s *WorkflowResetSuite) TestNoBaseCurrentClosed() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, false) + runs := s.setupRuns(ctx, workflowID, 1, false, versioningConfig{}) currentRunID := runs[0] // Reset the current run (i.e don't give an explicit runID) @@ -97,7 +111,7 @@ func (s *WorkflowResetSuite) TestNoBaseCurrentClosed() { func (s *WorkflowResetSuite) TestSameBaseCurrentRunning() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, true) + runs := s.setupRuns(ctx, workflowID, 1, true, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[0] @@ -111,7 +125,7 @@ func (s *WorkflowResetSuite) TestSameBaseCurrentRunning() { func (s *WorkflowResetSuite) TestSameBaseCurrentClosed() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, false) + runs := s.setupRuns(ctx, workflowID, 1, false, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[0] @@ -124,7 +138,7 @@ func (s *WorkflowResetSuite) TestSameBaseCurrentClosed() { func (s *WorkflowResetSuite) TestDifferentBaseCurrentRunning() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 2, true) + runs := s.setupRuns(ctx, workflowID, 2, true, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[1] @@ -137,7 +151,7 @@ func (s *WorkflowResetSuite) TestDifferentBaseCurrentRunning() { func (s *WorkflowResetSuite) TestDifferentBaseCurrentClosed() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 2, false) + runs := s.setupRuns(ctx, workflowID, 2, false, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[1] @@ -150,7 +164,7 @@ func (s *WorkflowResetSuite) TestDifferentBaseCurrentClosed() { func (s *WorkflowResetSuite) TestRepeatedResets() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 2, false) + runs := s.setupRuns(ctx, workflowID, 2, false, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[1] @@ -168,7 +182,7 @@ func (s *WorkflowResetSuite) TestRepeatedResets() { func (s *WorkflowResetSuite) TestWithMoreClosedRuns() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 5, false) + runs := s.setupRuns(ctx, workflowID, 5, false, versioningConfig{}) baseRunID := runs[0] currentRunID := runs[4] noChangeRuns := runs[1:4] @@ -187,7 +201,7 @@ func (s *WorkflowResetSuite) TestWithMoreClosedRuns() { func (s *WorkflowResetSuite) TestOriginalExecutionRunId() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, true) + runs := s.setupRuns(ctx, workflowID, 1, true, versioningConfig{}) baseRunID := runs[0] // Reset the current run repeatedly. Verify that each time the new run points to the original baseRunID for i := 0; i < 5; i++ { @@ -206,7 +220,16 @@ func (s *WorkflowResetSuite) TestOriginalExecutionRunId() { func (s *WorkflowResetSuite) TestResetWorkflowWithOptionsUpdate() { workflowID := "test-reset" + uuid.NewString() ctx := testcore.NewContext() - runs := s.setupRuns(ctx, workflowID, 1, true) + deploymentName := "testing" + buildID := "v.123" + + // Setup runs with versioning enabled so that the version is present in the task queue before the + // versioning override is set. + runs := s.setupRuns(ctx, workflowID, 1, true, versioningConfig{ + Required: true, + DeploymentName: deploymentName, + BuildID: buildID, + }) currentRunID := runs[0] override := &workflowpb.VersioningOverride{ @@ -214,8 +237,8 @@ func (s *WorkflowResetSuite) TestResetWorkflowWithOptionsUpdate() { Pinned: &workflowpb.VersioningOverride_PinnedOverride{ Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, Version: &deploymentpb.WorkerDeploymentVersion{ - DeploymentName: "testing", - BuildId: "v.123", + DeploymentName: deploymentName, + BuildId: buildID, }, }, }, @@ -266,21 +289,25 @@ func (s *WorkflowResetSuite) TestResetWorkflowWithOptionsUpdate() { s.NoError(err) // TODO (Carly): remove deprecated values from verification once we stop populating them - override.Behavior = enumspb.VERSIONING_BEHAVIOR_PINNED //nolint:staticcheck - override.PinnedVersion = "testing.v.123" //nolint:staticcheck + override.Behavior = enumspb.VERSIONING_BEHAVIOR_PINNED //nolint:staticcheck + override.PinnedVersion = deploymentName + "." + buildID //nolint:staticcheck s.ProtoEqual(override, info.WorkflowExecutionInfo.GetVersioningInfo().GetVersioningOverride()) } // Test batch reset operation with version update as post reset operation func (s *WorkflowResetSuite) TestBatchResetWithOptionsUpdate() { ctx := testcore.NewContext() + deploymentName := "batch-testing" + buildID := "v.456" // Create 2 workflows for batch reset workflowID1 := "test-batch-reset-1-" + uuid.NewString() workflowID2 := "test-batch-reset-2-" + uuid.NewString() - runs1 := s.setupRuns(ctx, workflowID1, 1, true) - runs2 := s.setupRuns(ctx, workflowID2, 1, true) + // Setup runs + versioningConfig := versioningConfig{Required: true, DeploymentName: deploymentName, BuildID: buildID} + runs1 := s.setupRuns(ctx, workflowID1, 1, true, versioningConfig) + runs2 := s.setupRuns(ctx, workflowID2, 1, true, versioningConfig) // Create versioning override for post-reset operations override := &workflowpb.VersioningOverride{ @@ -288,8 +315,8 @@ func (s *WorkflowResetSuite) TestBatchResetWithOptionsUpdate() { Pinned: &workflowpb.VersioningOverride_PinnedOverride{ Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, Version: &deploymentpb.WorkerDeploymentVersion{ - DeploymentName: "batch-testing", - BuildId: "v.456", + DeploymentName: deploymentName, + BuildId: buildID, }, }, }, @@ -378,8 +405,8 @@ func (s *WorkflowResetSuite) TestBatchResetWithOptionsUpdate() { Pinned: &workflowpb.VersioningOverride_PinnedOverride{ Behavior: workflowpb.VersioningOverride_PINNED_OVERRIDE_BEHAVIOR_PINNED, Version: &deploymentpb.WorkerDeploymentVersion{ - DeploymentName: "batch-testing", - BuildId: "v.456", + DeploymentName: deploymentName, + BuildId: buildID, }, }, }, @@ -441,18 +468,24 @@ func (s *WorkflowResetSuite) assertResetWorkflowLink(ctx context.Context, workfl } // helper method to setup the test run in the required configuration. It creates a total of n runs. If isCurrentRunning is true then the last run is kept open. -func (s *WorkflowResetSuite) setupRuns(ctx context.Context, workflowID string, n int, isCurrentRunning bool) []string { +func (s *WorkflowResetSuite) setupRuns(ctx context.Context, workflowID string, n int, isCurrentRunning bool, versioningConfig versioningConfig) []string { + taskQueueName := testcore.RandomizeStr(s.T().Name()) + + // If versioning is requested, start a versioned poller and validate version membership + if versioningConfig.Required { + s.startVersionedPollerAndValidate(ctx, taskQueueName, versioningConfig.DeploymentName, versioningConfig.BuildID) + } + runs := []string{} for i := 0; i < n-1; i++ { - runs = append(runs, s.prepareSingleRun(ctx, workflowID, false)) + runs = append(runs, s.prepareSingleRun(ctx, workflowID, taskQueueName, false)) } - runs = append(runs, s.prepareSingleRun(ctx, workflowID, isCurrentRunning)) + runs = append(runs, s.prepareSingleRun(ctx, workflowID, taskQueueName, isCurrentRunning)) return runs } -func (s *WorkflowResetSuite) prepareSingleRun(ctx context.Context, workflowID string, isRunning bool) string { +func (s *WorkflowResetSuite) prepareSingleRun(ctx context.Context, workflowID string, taskQueueName string, isRunning bool) string { identity := "worker-identity" - taskQueueName := testcore.RandomizeStr(s.T().Name()) taskQueue := &taskqueuepb.TaskQueue{ Name: taskQueueName, Kind: enumspb.TASK_QUEUE_KIND_NORMAL, @@ -525,6 +558,54 @@ func (s *WorkflowResetSuite) prepareSingleRun(ctx context.Context, workflowID st return run.GetRunID() } +// startVersionedPollerAndValidate starts a versioned poller for the given task queue +// and validates that the version is present in the task queue via matching RPC. +func (s *WorkflowResetSuite) startVersionedPollerAndValidate( + ctx context.Context, + taskQueueName string, + deploymentName string, + buildID string, +) { + taskQueue := &taskqueuepb.TaskQueue{ + Name: taskQueueName, + Kind: enumspb.TASK_QUEUE_KIND_NORMAL, + } + + // Start versioned poller in background + go func() { + _, _ = s.FrontendClient().PollWorkflowTaskQueue(ctx, &workflowservice.PollWorkflowTaskQueueRequest{ + Namespace: s.Namespace().String(), + TaskQueue: taskQueue, + Identity: "versioned-poller", + DeploymentOptions: &deploymentpb.WorkerDeploymentOptions{ + DeploymentName: deploymentName, + BuildId: buildID, + WorkerVersioningMode: enumspb.WORKER_VERSIONING_MODE_VERSIONED, + }, + }) + }() + + // Validate version is present via matching RPC + version := &deploymentspb.WorkerDeploymentVersion{ + DeploymentName: deploymentName, + BuildId: buildID, + } + s.EventuallyWithT(func(t *assert.CollectT) { + a := require.New(t) + resp, err := s.GetTestCluster().MatchingClient().CheckTaskQueueVersionMembership( + ctx, + &matchingservice.CheckTaskQueueVersionMembershipRequest{ + NamespaceId: s.NamespaceID().String(), + TaskQueue: taskQueueName, + TaskQueueType: enumspb.TASK_QUEUE_TYPE_WORKFLOW, + Version: version, + }, + ) + a.NoError(err) + a.True(resp.GetIsMember()) + }, 10*time.Second, 100*time.Millisecond) +} + // getLatestRunsForWorkflows gets the latest run IDs for the given workflow IDs func (s *WorkflowResetSuite) getLatestRunsForWorkflows(ctx context.Context, workflowIDs []string) []string { var runIDs []string