diff --git a/Makefile b/Makefile index ccb299f7f22..5f5625487a2 100644 --- a/Makefile +++ b/Makefile @@ -522,14 +522,18 @@ workflowcheck: $(WORKFLOWCHECK) check: lint shell-check ##### Tests ##### +# verify-test-log reads the whole file, so a log left behind by an earlier run +# would be judged as if it belonged to this one. clean-test-output: @printf $(COLOR) "Delete test output..." @rm -rf $(TEST_OUTPUT_ROOT) + @rm -f test.log @go clean -testcache build-tests: @printf $(COLOR) "Build tests..." - @CGO_ENABLED=$(CGO_ENABLED) go test $(TEST_TAG_FLAG) -exec="true" -count=0 $(TEST_DIRS) + @CGO_ENABLED=$(CGO_ENABLED) go test $(TEST_TAG_FLAG) -exec="true" -count=0 $(filter-out $(MIXED_BRAIN_TEST_ROOT)%,$(TEST_DIRS)) + @cd $(MIXED_BRAIN_TEST_ROOT) && CGO_ENABLED=1 go test $(TEST_TAG_FLAG) -exec="true" -count=0 ./... unit-test: clean-test-output @printf $(COLOR) "Run unit tests..." diff --git a/api/historyservice/v1/request_response.go-helpers.pb.go b/api/historyservice/v1/request_response.go-helpers.pb.go index 68cf73e2c50..33050f93afe 100644 --- a/api/historyservice/v1/request_response.go-helpers.pb.go +++ b/api/historyservice/v1/request_response.go-helpers.pb.go @@ -116,6 +116,80 @@ func (this *StartWorkflowExecutionResponse) Equal(that interface{}) bool { return proto.Equal(this, that1) } +// Marshal an object of type GetStreamReplaySlicesRequest to the protobuf v3 wire format +func (val *GetStreamReplaySlicesRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type GetStreamReplaySlicesRequest from the protobuf v3 wire format +func (val *GetStreamReplaySlicesRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *GetStreamReplaySlicesRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two GetStreamReplaySlicesRequest 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 *GetStreamReplaySlicesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *GetStreamReplaySlicesRequest + switch t := that.(type) { + case *GetStreamReplaySlicesRequest: + that1 = t + case GetStreamReplaySlicesRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type GetStreamReplaySlicesResponse to the protobuf v3 wire format +func (val *GetStreamReplaySlicesResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type GetStreamReplaySlicesResponse from the protobuf v3 wire format +func (val *GetStreamReplaySlicesResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *GetStreamReplaySlicesResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two GetStreamReplaySlicesResponse 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 *GetStreamReplaySlicesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *GetStreamReplaySlicesResponse + switch t := that.(type) { + case *GetStreamReplaySlicesResponse: + that1 = t + case GetStreamReplaySlicesResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + // Marshal an object of type GetMutableStateRequest to the protobuf v3 wire format func (val *GetMutableStateRequest) Marshal() ([]byte, error) { return proto.Marshal(val) diff --git a/api/historyservice/v1/request_response.pb.go b/api/historyservice/v1/request_response.pb.go index a7f13f19b10..d911cf62654 100644 --- a/api/historyservice/v1/request_response.pb.go +++ b/api/historyservice/v1/request_response.pb.go @@ -11,29 +11,30 @@ import ( sync "sync" unsafe "unsafe" - v123 "go.temporal.io/api/activity/v1" + v124 "go.temporal.io/api/activity/v1" v14 "go.temporal.io/api/common/v1" v16 "go.temporal.io/api/deployment/v1" v12 "go.temporal.io/api/enums/v1" v13 "go.temporal.io/api/failure/v1" v17 "go.temporal.io/api/history/v1" - v121 "go.temporal.io/api/nexus/v1" - v115 "go.temporal.io/api/protocol/v1" - v114 "go.temporal.io/api/query/v1" - v111 "go.temporal.io/api/taskqueue/v1" + v122 "go.temporal.io/api/nexus/v1" + v116 "go.temporal.io/api/protocol/v1" + v115 "go.temporal.io/api/query/v1" + v19 "go.temporal.io/api/stream/v1" + v112 "go.temporal.io/api/taskqueue/v1" v15 "go.temporal.io/api/workflow/v1" v1 "go.temporal.io/api/workflowservice/v1" - v118 "go.temporal.io/server/api/adminservice/v1" + v119 "go.temporal.io/server/api/adminservice/v1" v18 "go.temporal.io/server/api/clock/v1" - v119 "go.temporal.io/server/api/common/v1" - v112 "go.temporal.io/server/api/enums/v1" - v122 "go.temporal.io/server/api/health/v1" - v19 "go.temporal.io/server/api/history/v1" - v116 "go.temporal.io/server/api/namespace/v1" - v110 "go.temporal.io/server/api/persistence/v1" - v117 "go.temporal.io/server/api/replication/v1" - v113 "go.temporal.io/server/api/taskqueue/v1" - v120 "go.temporal.io/server/api/token/v1" + v120 "go.temporal.io/server/api/common/v1" + v113 "go.temporal.io/server/api/enums/v1" + v123 "go.temporal.io/server/api/health/v1" + v110 "go.temporal.io/server/api/history/v1" + v117 "go.temporal.io/server/api/namespace/v1" + v111 "go.temporal.io/server/api/persistence/v1" + v118 "go.temporal.io/server/api/replication/v1" + v114 "go.temporal.io/server/api/taskqueue/v1" + v121 "go.temporal.io/server/api/token/v1" v11 "go.temporal.io/server/api/workflow/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -458,21 +459,122 @@ func (x *StartWorkflowExecutionResponse) GetFirstExecutionRunId() string { return "" } +// Asks for the stream ranges a workflow's completed tasks recorded, re-read from +// their streams, for a task that is built without RecordWorkflowTaskStarted. +// A query dispatched straight through matching is the one such task. +type GetStreamReplaySlicesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetStreamReplaySlicesRequest) Reset() { + *x = GetStreamReplaySlicesRequest{} + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetStreamReplaySlicesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStreamReplaySlicesRequest) ProtoMessage() {} + +func (x *GetStreamReplaySlicesRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[3] + 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 GetStreamReplaySlicesRequest.ProtoReflect.Descriptor instead. +func (*GetStreamReplaySlicesRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{3} +} + +func (x *GetStreamReplaySlicesRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *GetStreamReplaySlicesRequest) GetExecution() *v14.WorkflowExecution { + if x != nil { + return x.Execution + } + return nil +} + +type GetStreamReplaySlicesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Every slice is tagged with the completed event that recorded its range. + // Empty when the workflow consumes no stream. + StreamSlices []*v19.StreamSlice `protobuf:"bytes,1,rep,name=stream_slices,json=streamSlices,proto3" json:"stream_slices,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetStreamReplaySlicesResponse) Reset() { + *x = GetStreamReplaySlicesResponse{} + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetStreamReplaySlicesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStreamReplaySlicesResponse) ProtoMessage() {} + +func (x *GetStreamReplaySlicesResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[4] + 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 GetStreamReplaySlicesResponse.ProtoReflect.Descriptor instead. +func (*GetStreamReplaySlicesResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{4} +} + +func (x *GetStreamReplaySlicesResponse) GetStreamSlices() []*v19.StreamSlice { + if x != nil { + return x.StreamSlices + } + return nil +} + type GetMutableStateRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` ExpectedNextEventId int64 `protobuf:"varint,3,opt,name=expected_next_event_id,json=expectedNextEventId,proto3" json:"expected_next_event_id,omitempty"` CurrentBranchToken []byte `protobuf:"bytes,4,opt,name=current_branch_token,json=currentBranchToken,proto3" json:"current_branch_token,omitempty"` - VersionHistoryItem *v19.VersionHistoryItem `protobuf:"bytes,5,opt,name=version_history_item,json=versionHistoryItem,proto3" json:"version_history_item,omitempty"` - VersionedTransition *v110.VersionedTransition `protobuf:"bytes,6,opt,name=versioned_transition,json=versionedTransition,proto3" json:"versioned_transition,omitempty"` + VersionHistoryItem *v110.VersionHistoryItem `protobuf:"bytes,5,opt,name=version_history_item,json=versionHistoryItem,proto3" json:"version_history_item,omitempty"` + VersionedTransition *v111.VersionedTransition `protobuf:"bytes,6,opt,name=versioned_transition,json=versionedTransition,proto3" json:"versioned_transition,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetMutableStateRequest) Reset() { *x = GetMutableStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[3] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -484,7 +586,7 @@ func (x *GetMutableStateRequest) String() string { func (*GetMutableStateRequest) ProtoMessage() {} func (x *GetMutableStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[3] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -497,7 +599,7 @@ func (x *GetMutableStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMutableStateRequest.ProtoReflect.Descriptor instead. func (*GetMutableStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{3} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{5} } func (x *GetMutableStateRequest) GetNamespaceId() string { @@ -528,14 +630,14 @@ func (x *GetMutableStateRequest) GetCurrentBranchToken() []byte { return nil } -func (x *GetMutableStateRequest) GetVersionHistoryItem() *v19.VersionHistoryItem { +func (x *GetMutableStateRequest) GetVersionHistoryItem() *v110.VersionHistoryItem { if x != nil { return x.VersionHistoryItem } return nil } -func (x *GetMutableStateRequest) GetVersionedTransition() *v110.VersionedTransition { +func (x *GetMutableStateRequest) GetVersionedTransition() *v111.VersionedTransition { if x != nil { return x.VersionedTransition } @@ -549,16 +651,16 @@ type GetMutableStateResponse struct { NextEventId int64 `protobuf:"varint,3,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` PreviousStartedEventId int64 `protobuf:"varint,4,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` LastFirstEventId int64 `protobuf:"varint,5,opt,name=last_first_event_id,json=lastFirstEventId,proto3" json:"last_first_event_id,omitempty"` - TaskQueue *v111.TaskQueue `protobuf:"bytes,6,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` - StickyTaskQueue *v111.TaskQueue `protobuf:"bytes,7,opt,name=sticky_task_queue,json=stickyTaskQueue,proto3" json:"sticky_task_queue,omitempty"` + TaskQueue *v112.TaskQueue `protobuf:"bytes,6,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` + StickyTaskQueue *v112.TaskQueue `protobuf:"bytes,7,opt,name=sticky_task_queue,json=stickyTaskQueue,proto3" json:"sticky_task_queue,omitempty"` // (-- api-linter: core::0140::prepositions=disabled // // aip.dev/not-precedent: "to" is used to indicate interval. --) StickyTaskQueueScheduleToStartTimeout *durationpb.Duration `protobuf:"bytes,11,opt,name=sticky_task_queue_schedule_to_start_timeout,json=stickyTaskQueueScheduleToStartTimeout,proto3" json:"sticky_task_queue_schedule_to_start_timeout,omitempty"` CurrentBranchToken []byte `protobuf:"bytes,13,opt,name=current_branch_token,json=currentBranchToken,proto3" json:"current_branch_token,omitempty"` - WorkflowState v112.WorkflowExecutionState `protobuf:"varint,15,opt,name=workflow_state,json=workflowState,proto3,enum=temporal.server.api.enums.v1.WorkflowExecutionState" json:"workflow_state,omitempty"` + WorkflowState v113.WorkflowExecutionState `protobuf:"varint,15,opt,name=workflow_state,json=workflowState,proto3,enum=temporal.server.api.enums.v1.WorkflowExecutionState" json:"workflow_state,omitempty"` WorkflowStatus v12.WorkflowExecutionStatus `protobuf:"varint,16,opt,name=workflow_status,json=workflowStatus,proto3,enum=temporal.api.enums.v1.WorkflowExecutionStatus" json:"workflow_status,omitempty"` - VersionHistories *v19.VersionHistories `protobuf:"bytes,17,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` + VersionHistories *v110.VersionHistories `protobuf:"bytes,17,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` IsStickyTaskQueueEnabled bool `protobuf:"varint,18,opt,name=is_sticky_task_queue_enabled,json=isStickyTaskQueueEnabled,proto3" json:"is_sticky_task_queue_enabled,omitempty"` LastFirstEventTxnId int64 `protobuf:"varint,19,opt,name=last_first_event_txn_id,json=lastFirstEventTxnId,proto3" json:"last_first_event_txn_id,omitempty"` FirstExecutionRunId string `protobuf:"bytes,20,opt,name=first_execution_run_id,json=firstExecutionRunId,proto3" json:"first_execution_run_id,omitempty"` @@ -569,18 +671,18 @@ type GetMutableStateResponse struct { // for this execution. AssignedBuildId string `protobuf:"bytes,22,opt,name=assigned_build_id,json=assignedBuildId,proto3" json:"assigned_build_id,omitempty"` InheritedBuildId string `protobuf:"bytes,23,opt,name=inherited_build_id,json=inheritedBuildId,proto3" json:"inherited_build_id,omitempty"` - TransitionHistory []*v110.VersionedTransition `protobuf:"bytes,24,rep,name=transition_history,json=transitionHistory,proto3" json:"transition_history,omitempty"` + TransitionHistory []*v111.VersionedTransition `protobuf:"bytes,24,rep,name=transition_history,json=transitionHistory,proto3" json:"transition_history,omitempty"` VersioningInfo *v15.WorkflowExecutionVersioningInfo `protobuf:"bytes,25,opt,name=versioning_info,json=versioningInfo,proto3" json:"versioning_info,omitempty"` // Transient or speculative workflow task events which are not yet persisted in the history. // These events should be appended to the history when it is returned to the worker. - TransientOrSpeculativeTasks *v19.TransientWorkflowTaskInfo `protobuf:"bytes,26,opt,name=transient_or_speculative_tasks,json=transientOrSpeculativeTasks,proto3" json:"transient_or_speculative_tasks,omitempty"` + TransientOrSpeculativeTasks *v110.TransientWorkflowTaskInfo `protobuf:"bytes,26,opt,name=transient_or_speculative_tasks,json=transientOrSpeculativeTasks,proto3" json:"transient_or_speculative_tasks,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetMutableStateResponse) Reset() { *x = GetMutableStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[4] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -592,7 +694,7 @@ func (x *GetMutableStateResponse) String() string { func (*GetMutableStateResponse) ProtoMessage() {} func (x *GetMutableStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[4] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -605,7 +707,7 @@ func (x *GetMutableStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMutableStateResponse.ProtoReflect.Descriptor instead. func (*GetMutableStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{4} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{6} } func (x *GetMutableStateResponse) GetExecution() *v14.WorkflowExecution { @@ -643,14 +745,14 @@ func (x *GetMutableStateResponse) GetLastFirstEventId() int64 { return 0 } -func (x *GetMutableStateResponse) GetTaskQueue() *v111.TaskQueue { +func (x *GetMutableStateResponse) GetTaskQueue() *v112.TaskQueue { if x != nil { return x.TaskQueue } return nil } -func (x *GetMutableStateResponse) GetStickyTaskQueue() *v111.TaskQueue { +func (x *GetMutableStateResponse) GetStickyTaskQueue() *v112.TaskQueue { if x != nil { return x.StickyTaskQueue } @@ -671,11 +773,11 @@ func (x *GetMutableStateResponse) GetCurrentBranchToken() []byte { return nil } -func (x *GetMutableStateResponse) GetWorkflowState() v112.WorkflowExecutionState { +func (x *GetMutableStateResponse) GetWorkflowState() v113.WorkflowExecutionState { if x != nil { return x.WorkflowState } - return v112.WorkflowExecutionState(0) + return v113.WorkflowExecutionState(0) } func (x *GetMutableStateResponse) GetWorkflowStatus() v12.WorkflowExecutionStatus { @@ -685,7 +787,7 @@ func (x *GetMutableStateResponse) GetWorkflowStatus() v12.WorkflowExecutionStatu return v12.WorkflowExecutionStatus(0) } -func (x *GetMutableStateResponse) GetVersionHistories() *v19.VersionHistories { +func (x *GetMutableStateResponse) GetVersionHistories() *v110.VersionHistories { if x != nil { return x.VersionHistories } @@ -734,7 +836,7 @@ func (x *GetMutableStateResponse) GetInheritedBuildId() string { return "" } -func (x *GetMutableStateResponse) GetTransitionHistory() []*v110.VersionedTransition { +func (x *GetMutableStateResponse) GetTransitionHistory() []*v111.VersionedTransition { if x != nil { return x.TransitionHistory } @@ -748,7 +850,7 @@ func (x *GetMutableStateResponse) GetVersioningInfo() *v15.WorkflowExecutionVers return nil } -func (x *GetMutableStateResponse) GetTransientOrSpeculativeTasks() *v19.TransientWorkflowTaskInfo { +func (x *GetMutableStateResponse) GetTransientOrSpeculativeTasks() *v110.TransientWorkflowTaskInfo { if x != nil { return x.TransientOrSpeculativeTasks } @@ -756,19 +858,19 @@ func (x *GetMutableStateResponse) GetTransientOrSpeculativeTasks() *v19.Transien } type PollMutableStateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` - ExpectedNextEventId int64 `protobuf:"varint,3,opt,name=expected_next_event_id,json=expectedNextEventId,proto3" json:"expected_next_event_id,omitempty"` - CurrentBranchToken []byte `protobuf:"bytes,4,opt,name=current_branch_token,json=currentBranchToken,proto3" json:"current_branch_token,omitempty"` - VersionHistoryItem *v19.VersionHistoryItem `protobuf:"bytes,5,opt,name=version_history_item,json=versionHistoryItem,proto3" json:"version_history_item,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` + ExpectedNextEventId int64 `protobuf:"varint,3,opt,name=expected_next_event_id,json=expectedNextEventId,proto3" json:"expected_next_event_id,omitempty"` + CurrentBranchToken []byte `protobuf:"bytes,4,opt,name=current_branch_token,json=currentBranchToken,proto3" json:"current_branch_token,omitempty"` + VersionHistoryItem *v110.VersionHistoryItem `protobuf:"bytes,5,opt,name=version_history_item,json=versionHistoryItem,proto3" json:"version_history_item,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *PollMutableStateRequest) Reset() { *x = PollMutableStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[5] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -780,7 +882,7 @@ func (x *PollMutableStateRequest) String() string { func (*PollMutableStateRequest) ProtoMessage() {} func (x *PollMutableStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[5] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +895,7 @@ func (x *PollMutableStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PollMutableStateRequest.ProtoReflect.Descriptor instead. func (*PollMutableStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{5} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{7} } func (x *PollMutableStateRequest) GetNamespaceId() string { @@ -824,7 +926,7 @@ func (x *PollMutableStateRequest) GetCurrentBranchToken() []byte { return nil } -func (x *PollMutableStateRequest) GetVersionHistoryItem() *v19.VersionHistoryItem { +func (x *PollMutableStateRequest) GetVersionHistoryItem() *v110.VersionHistoryItem { if x != nil { return x.VersionHistoryItem } @@ -838,15 +940,15 @@ type PollMutableStateResponse struct { NextEventId int64 `protobuf:"varint,3,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` PreviousStartedEventId int64 `protobuf:"varint,4,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` LastFirstEventId int64 `protobuf:"varint,5,opt,name=last_first_event_id,json=lastFirstEventId,proto3" json:"last_first_event_id,omitempty"` - TaskQueue *v111.TaskQueue `protobuf:"bytes,6,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` - StickyTaskQueue *v111.TaskQueue `protobuf:"bytes,7,opt,name=sticky_task_queue,json=stickyTaskQueue,proto3" json:"sticky_task_queue,omitempty"` + TaskQueue *v112.TaskQueue `protobuf:"bytes,6,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` + StickyTaskQueue *v112.TaskQueue `protobuf:"bytes,7,opt,name=sticky_task_queue,json=stickyTaskQueue,proto3" json:"sticky_task_queue,omitempty"` // (-- api-linter: core::0140::prepositions=disabled // // aip.dev/not-precedent: "to" is used to indicate interval. --) StickyTaskQueueScheduleToStartTimeout *durationpb.Duration `protobuf:"bytes,11,opt,name=sticky_task_queue_schedule_to_start_timeout,json=stickyTaskQueueScheduleToStartTimeout,proto3" json:"sticky_task_queue_schedule_to_start_timeout,omitempty"` CurrentBranchToken []byte `protobuf:"bytes,12,opt,name=current_branch_token,json=currentBranchToken,proto3" json:"current_branch_token,omitempty"` - VersionHistories *v19.VersionHistories `protobuf:"bytes,14,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` - WorkflowState v112.WorkflowExecutionState `protobuf:"varint,15,opt,name=workflow_state,json=workflowState,proto3,enum=temporal.server.api.enums.v1.WorkflowExecutionState" json:"workflow_state,omitempty"` + VersionHistories *v110.VersionHistories `protobuf:"bytes,14,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` + WorkflowState v113.WorkflowExecutionState `protobuf:"varint,15,opt,name=workflow_state,json=workflowState,proto3,enum=temporal.server.api.enums.v1.WorkflowExecutionState" json:"workflow_state,omitempty"` WorkflowStatus v12.WorkflowExecutionStatus `protobuf:"varint,16,opt,name=workflow_status,json=workflowStatus,proto3,enum=temporal.api.enums.v1.WorkflowExecutionStatus" json:"workflow_status,omitempty"` LastFirstEventTxnId int64 `protobuf:"varint,17,opt,name=last_first_event_txn_id,json=lastFirstEventTxnId,proto3" json:"last_first_event_txn_id,omitempty"` FirstExecutionRunId string `protobuf:"bytes,18,opt,name=first_execution_run_id,json=firstExecutionRunId,proto3" json:"first_execution_run_id,omitempty"` @@ -856,7 +958,7 @@ type PollMutableStateResponse struct { func (x *PollMutableStateResponse) Reset() { *x = PollMutableStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[6] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -868,7 +970,7 @@ func (x *PollMutableStateResponse) String() string { func (*PollMutableStateResponse) ProtoMessage() {} func (x *PollMutableStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[6] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -881,7 +983,7 @@ func (x *PollMutableStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PollMutableStateResponse.ProtoReflect.Descriptor instead. func (*PollMutableStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{6} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{8} } func (x *PollMutableStateResponse) GetExecution() *v14.WorkflowExecution { @@ -919,14 +1021,14 @@ func (x *PollMutableStateResponse) GetLastFirstEventId() int64 { return 0 } -func (x *PollMutableStateResponse) GetTaskQueue() *v111.TaskQueue { +func (x *PollMutableStateResponse) GetTaskQueue() *v112.TaskQueue { if x != nil { return x.TaskQueue } return nil } -func (x *PollMutableStateResponse) GetStickyTaskQueue() *v111.TaskQueue { +func (x *PollMutableStateResponse) GetStickyTaskQueue() *v112.TaskQueue { if x != nil { return x.StickyTaskQueue } @@ -947,18 +1049,18 @@ func (x *PollMutableStateResponse) GetCurrentBranchToken() []byte { return nil } -func (x *PollMutableStateResponse) GetVersionHistories() *v19.VersionHistories { +func (x *PollMutableStateResponse) GetVersionHistories() *v110.VersionHistories { if x != nil { return x.VersionHistories } return nil } -func (x *PollMutableStateResponse) GetWorkflowState() v112.WorkflowExecutionState { +func (x *PollMutableStateResponse) GetWorkflowState() v113.WorkflowExecutionState { if x != nil { return x.WorkflowState } - return v112.WorkflowExecutionState(0) + return v113.WorkflowExecutionState(0) } func (x *PollMutableStateResponse) GetWorkflowStatus() v12.WorkflowExecutionStatus { @@ -992,7 +1094,7 @@ type ResetStickyTaskQueueRequest struct { func (x *ResetStickyTaskQueueRequest) Reset() { *x = ResetStickyTaskQueueRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[7] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1004,7 +1106,7 @@ func (x *ResetStickyTaskQueueRequest) String() string { func (*ResetStickyTaskQueueRequest) ProtoMessage() {} func (x *ResetStickyTaskQueueRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[7] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1017,7 +1119,7 @@ func (x *ResetStickyTaskQueueRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetStickyTaskQueueRequest.ProtoReflect.Descriptor instead. func (*ResetStickyTaskQueueRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{7} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{9} } func (x *ResetStickyTaskQueueRequest) GetNamespaceId() string { @@ -1042,7 +1144,7 @@ type ResetStickyTaskQueueResponse struct { func (x *ResetStickyTaskQueueResponse) Reset() { *x = ResetStickyTaskQueueResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[8] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1054,7 +1156,7 @@ func (x *ResetStickyTaskQueueResponse) String() string { func (*ResetStickyTaskQueueResponse) ProtoMessage() {} func (x *ResetStickyTaskQueueResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[8] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1067,7 +1169,7 @@ func (x *ResetStickyTaskQueueResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetStickyTaskQueueResponse.ProtoReflect.Descriptor instead. func (*ResetStickyTaskQueueResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{8} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{10} } type ExecuteMultiOperationRequest struct { @@ -1081,7 +1183,7 @@ type ExecuteMultiOperationRequest struct { func (x *ExecuteMultiOperationRequest) Reset() { *x = ExecuteMultiOperationRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[9] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1093,7 +1195,7 @@ func (x *ExecuteMultiOperationRequest) String() string { func (*ExecuteMultiOperationRequest) ProtoMessage() {} func (x *ExecuteMultiOperationRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[9] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1106,7 +1208,7 @@ func (x *ExecuteMultiOperationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteMultiOperationRequest.ProtoReflect.Descriptor instead. func (*ExecuteMultiOperationRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{9} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{11} } func (x *ExecuteMultiOperationRequest) GetNamespaceId() string { @@ -1139,7 +1241,7 @@ type ExecuteMultiOperationResponse struct { func (x *ExecuteMultiOperationResponse) Reset() { *x = ExecuteMultiOperationResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[10] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1151,7 +1253,7 @@ func (x *ExecuteMultiOperationResponse) String() string { func (*ExecuteMultiOperationResponse) ProtoMessage() {} func (x *ExecuteMultiOperationResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[10] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1164,7 +1266,7 @@ func (x *ExecuteMultiOperationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteMultiOperationResponse.ProtoReflect.Descriptor instead. func (*ExecuteMultiOperationResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{10} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{12} } func (x *ExecuteMultiOperationResponse) GetResponses() []*ExecuteMultiOperationResponse_Response { @@ -1183,12 +1285,12 @@ type RecordWorkflowTaskStartedRequest struct { RequestId string `protobuf:"bytes,5,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` PollRequest *v1.PollWorkflowTaskQueueRequest `protobuf:"bytes,6,opt,name=poll_request,json=pollRequest,proto3" json:"poll_request,omitempty"` Clock *v18.VectorClock `protobuf:"bytes,7,opt,name=clock,proto3" json:"clock,omitempty"` - BuildIdRedirectInfo *v113.BuildIdRedirectInfo `protobuf:"bytes,8,opt,name=build_id_redirect_info,json=buildIdRedirectInfo,proto3" json:"build_id_redirect_info,omitempty"` + BuildIdRedirectInfo *v114.BuildIdRedirectInfo `protobuf:"bytes,8,opt,name=build_id_redirect_info,json=buildIdRedirectInfo,proto3" json:"build_id_redirect_info,omitempty"` // The deployment passed by History when the task was scheduled. // Deprecated. use `version_directive.deployment`. ScheduledDeployment *v16.Deployment `protobuf:"bytes,9,opt,name=scheduled_deployment,json=scheduledDeployment,proto3" json:"scheduled_deployment,omitempty"` // Versioning directive that was sent by history when scheduling the task. - VersionDirective *v113.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` + VersionDirective *v114.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` // Stamp value from when the workflow task was scheduled. Used to validate the task is still relevant. Stamp int32 `protobuf:"varint,11,opt,name=stamp,proto3" json:"stamp,omitempty"` // Revision number that was sent by matching when the task was dispatched. Used to resolve eventual consistency issues @@ -1204,7 +1306,7 @@ type RecordWorkflowTaskStartedRequest struct { func (x *RecordWorkflowTaskStartedRequest) Reset() { *x = RecordWorkflowTaskStartedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1216,7 +1318,7 @@ func (x *RecordWorkflowTaskStartedRequest) String() string { func (*RecordWorkflowTaskStartedRequest) ProtoMessage() {} func (x *RecordWorkflowTaskStartedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1229,7 +1331,7 @@ func (x *RecordWorkflowTaskStartedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RecordWorkflowTaskStartedRequest.ProtoReflect.Descriptor instead. func (*RecordWorkflowTaskStartedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{11} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{13} } func (x *RecordWorkflowTaskStartedRequest) GetNamespaceId() string { @@ -1274,7 +1376,7 @@ func (x *RecordWorkflowTaskStartedRequest) GetClock() *v18.VectorClock { return nil } -func (x *RecordWorkflowTaskStartedRequest) GetBuildIdRedirectInfo() *v113.BuildIdRedirectInfo { +func (x *RecordWorkflowTaskStartedRequest) GetBuildIdRedirectInfo() *v114.BuildIdRedirectInfo { if x != nil { return x.BuildIdRedirectInfo } @@ -1288,7 +1390,7 @@ func (x *RecordWorkflowTaskStartedRequest) GetScheduledDeployment() *v16.Deploym return nil } -func (x *RecordWorkflowTaskStartedRequest) GetVersionDirective() *v113.TaskVersionDirective { +func (x *RecordWorkflowTaskStartedRequest) GetVersionDirective() *v114.TaskVersionDirective { if x != nil { return x.VersionDirective } @@ -1317,25 +1419,25 @@ func (x *RecordWorkflowTaskStartedRequest) GetTargetDeploymentVersion() *v16.Wor } type RecordWorkflowTaskStartedResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - WorkflowType *v14.WorkflowType `protobuf:"bytes,1,opt,name=workflow_type,json=workflowType,proto3" json:"workflow_type,omitempty"` - PreviousStartedEventId int64 `protobuf:"varint,2,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` - ScheduledEventId int64 `protobuf:"varint,3,opt,name=scheduled_event_id,json=scheduledEventId,proto3" json:"scheduled_event_id,omitempty"` - StartedEventId int64 `protobuf:"varint,4,opt,name=started_event_id,json=startedEventId,proto3" json:"started_event_id,omitempty"` - NextEventId int64 `protobuf:"varint,5,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` - Attempt int32 `protobuf:"varint,6,opt,name=attempt,proto3" json:"attempt,omitempty"` - StickyExecutionEnabled bool `protobuf:"varint,7,opt,name=sticky_execution_enabled,json=stickyExecutionEnabled,proto3" json:"sticky_execution_enabled,omitempty"` - TransientWorkflowTask *v19.TransientWorkflowTaskInfo `protobuf:"bytes,8,opt,name=transient_workflow_task,json=transientWorkflowTask,proto3" json:"transient_workflow_task,omitempty"` - WorkflowExecutionTaskQueue *v111.TaskQueue `protobuf:"bytes,9,opt,name=workflow_execution_task_queue,json=workflowExecutionTaskQueue,proto3" json:"workflow_execution_task_queue,omitempty"` - BranchToken []byte `protobuf:"bytes,11,opt,name=branch_token,json=branchToken,proto3" json:"branch_token,omitempty"` - ScheduledTime *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=scheduled_time,json=scheduledTime,proto3" json:"scheduled_time,omitempty"` - StartedTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=started_time,json=startedTime,proto3" json:"started_time,omitempty"` - Queries map[string]*v114.WorkflowQuery `protobuf:"bytes,14,rep,name=queries,proto3" json:"queries,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Clock *v18.VectorClock `protobuf:"bytes,15,opt,name=clock,proto3" json:"clock,omitempty"` - Messages []*v115.Message `protobuf:"bytes,16,rep,name=messages,proto3" json:"messages,omitempty"` - Version int64 `protobuf:"varint,17,opt,name=version,proto3" json:"version,omitempty"` - History *v17.History `protobuf:"bytes,18,opt,name=history,proto3" json:"history,omitempty"` - NextPageToken []byte `protobuf:"bytes,19,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + WorkflowType *v14.WorkflowType `protobuf:"bytes,1,opt,name=workflow_type,json=workflowType,proto3" json:"workflow_type,omitempty"` + PreviousStartedEventId int64 `protobuf:"varint,2,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` + ScheduledEventId int64 `protobuf:"varint,3,opt,name=scheduled_event_id,json=scheduledEventId,proto3" json:"scheduled_event_id,omitempty"` + StartedEventId int64 `protobuf:"varint,4,opt,name=started_event_id,json=startedEventId,proto3" json:"started_event_id,omitempty"` + NextEventId int64 `protobuf:"varint,5,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` + Attempt int32 `protobuf:"varint,6,opt,name=attempt,proto3" json:"attempt,omitempty"` + StickyExecutionEnabled bool `protobuf:"varint,7,opt,name=sticky_execution_enabled,json=stickyExecutionEnabled,proto3" json:"sticky_execution_enabled,omitempty"` + TransientWorkflowTask *v110.TransientWorkflowTaskInfo `protobuf:"bytes,8,opt,name=transient_workflow_task,json=transientWorkflowTask,proto3" json:"transient_workflow_task,omitempty"` + WorkflowExecutionTaskQueue *v112.TaskQueue `protobuf:"bytes,9,opt,name=workflow_execution_task_queue,json=workflowExecutionTaskQueue,proto3" json:"workflow_execution_task_queue,omitempty"` + BranchToken []byte `protobuf:"bytes,11,opt,name=branch_token,json=branchToken,proto3" json:"branch_token,omitempty"` + ScheduledTime *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=scheduled_time,json=scheduledTime,proto3" json:"scheduled_time,omitempty"` + StartedTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=started_time,json=startedTime,proto3" json:"started_time,omitempty"` + Queries map[string]*v115.WorkflowQuery `protobuf:"bytes,14,rep,name=queries,proto3" json:"queries,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Clock *v18.VectorClock `protobuf:"bytes,15,opt,name=clock,proto3" json:"clock,omitempty"` + Messages []*v116.Message `protobuf:"bytes,16,rep,name=messages,proto3" json:"messages,omitempty"` + Version int64 `protobuf:"varint,17,opt,name=version,proto3" json:"version,omitempty"` + History *v17.History `protobuf:"bytes,18,opt,name=history,proto3" json:"history,omitempty"` + NextPageToken []byte `protobuf:"bytes,19,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // Deprecated: This field is being replaced by raw_history_bytes which sends raw bytes // instead of a proto-decoded History. This avoids matching service having to decode history. // TODO: PRATHYUSH @@ -1353,13 +1455,17 @@ type RecordWorkflowTaskStartedResponse struct { // Deprecated: Marked as deprecated in temporal/server/api/historyservice/v1/request_response.proto. RawHistory *v17.History `protobuf:"bytes,20,opt,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` RawHistoryBytes [][]byte `protobuf:"bytes,21,rep,name=raw_history_bytes,json=rawHistoryBytes,proto3" json:"raw_history_bytes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + StreamSlices []*v19.StreamSlice `protobuf:"bytes,22,rep,name=stream_slices,json=streamSlices,proto3" json:"stream_slices,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RecordWorkflowTaskStartedResponse) Reset() { *x = RecordWorkflowTaskStartedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1371,7 +1477,7 @@ func (x *RecordWorkflowTaskStartedResponse) String() string { func (*RecordWorkflowTaskStartedResponse) ProtoMessage() {} func (x *RecordWorkflowTaskStartedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1384,7 +1490,7 @@ func (x *RecordWorkflowTaskStartedResponse) ProtoReflect() protoreflect.Message // Deprecated: Use RecordWorkflowTaskStartedResponse.ProtoReflect.Descriptor instead. func (*RecordWorkflowTaskStartedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{12} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{14} } func (x *RecordWorkflowTaskStartedResponse) GetWorkflowType() *v14.WorkflowType { @@ -1436,14 +1542,14 @@ func (x *RecordWorkflowTaskStartedResponse) GetStickyExecutionEnabled() bool { return false } -func (x *RecordWorkflowTaskStartedResponse) GetTransientWorkflowTask() *v19.TransientWorkflowTaskInfo { +func (x *RecordWorkflowTaskStartedResponse) GetTransientWorkflowTask() *v110.TransientWorkflowTaskInfo { if x != nil { return x.TransientWorkflowTask } return nil } -func (x *RecordWorkflowTaskStartedResponse) GetWorkflowExecutionTaskQueue() *v111.TaskQueue { +func (x *RecordWorkflowTaskStartedResponse) GetWorkflowExecutionTaskQueue() *v112.TaskQueue { if x != nil { return x.WorkflowExecutionTaskQueue } @@ -1471,7 +1577,7 @@ func (x *RecordWorkflowTaskStartedResponse) GetStartedTime() *timestamppb.Timest return nil } -func (x *RecordWorkflowTaskStartedResponse) GetQueries() map[string]*v114.WorkflowQuery { +func (x *RecordWorkflowTaskStartedResponse) GetQueries() map[string]*v115.WorkflowQuery { if x != nil { return x.Queries } @@ -1485,7 +1591,7 @@ func (x *RecordWorkflowTaskStartedResponse) GetClock() *v18.VectorClock { return nil } -func (x *RecordWorkflowTaskStartedResponse) GetMessages() []*v115.Message { +func (x *RecordWorkflowTaskStartedResponse) GetMessages() []*v116.Message { if x != nil { return x.Messages } @@ -1528,6 +1634,13 @@ func (x *RecordWorkflowTaskStartedResponse) GetRawHistoryBytes() [][]byte { return nil } +func (x *RecordWorkflowTaskStartedResponse) GetStreamSlices() []*v19.StreamSlice { + if x != nil { + return x.StreamSlices + } + return nil +} + // RecordWorkflowTaskStartedResponseWithRawHistory is wire-compatible with RecordWorkflowTaskStartedResponse. // // WIRE COMPATIBILITY PATTERN: @@ -1547,38 +1660,42 @@ func (x *RecordWorkflowTaskStartedResponse) GetRawHistoryBytes() [][]byte { // IMPORTANT: Field numbers and all other fields must remain identical between these two messages. // Any change to RecordWorkflowTaskStartedResponse must be mirrored here. type RecordWorkflowTaskStartedResponseWithRawHistory struct { - state protoimpl.MessageState `protogen:"open.v1"` - WorkflowType *v14.WorkflowType `protobuf:"bytes,1,opt,name=workflow_type,json=workflowType,proto3" json:"workflow_type,omitempty"` - PreviousStartedEventId int64 `protobuf:"varint,2,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` - ScheduledEventId int64 `protobuf:"varint,3,opt,name=scheduled_event_id,json=scheduledEventId,proto3" json:"scheduled_event_id,omitempty"` - StartedEventId int64 `protobuf:"varint,4,opt,name=started_event_id,json=startedEventId,proto3" json:"started_event_id,omitempty"` - NextEventId int64 `protobuf:"varint,5,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` - Attempt int32 `protobuf:"varint,6,opt,name=attempt,proto3" json:"attempt,omitempty"` - StickyExecutionEnabled bool `protobuf:"varint,7,opt,name=sticky_execution_enabled,json=stickyExecutionEnabled,proto3" json:"sticky_execution_enabled,omitempty"` - TransientWorkflowTask *v19.TransientWorkflowTaskInfo `protobuf:"bytes,8,opt,name=transient_workflow_task,json=transientWorkflowTask,proto3" json:"transient_workflow_task,omitempty"` - WorkflowExecutionTaskQueue *v111.TaskQueue `protobuf:"bytes,9,opt,name=workflow_execution_task_queue,json=workflowExecutionTaskQueue,proto3" json:"workflow_execution_task_queue,omitempty"` - BranchToken []byte `protobuf:"bytes,11,opt,name=branch_token,json=branchToken,proto3" json:"branch_token,omitempty"` - ScheduledTime *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=scheduled_time,json=scheduledTime,proto3" json:"scheduled_time,omitempty"` - StartedTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=started_time,json=startedTime,proto3" json:"started_time,omitempty"` - Queries map[string]*v114.WorkflowQuery `protobuf:"bytes,14,rep,name=queries,proto3" json:"queries,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Clock *v18.VectorClock `protobuf:"bytes,15,opt,name=clock,proto3" json:"clock,omitempty"` - Messages []*v115.Message `protobuf:"bytes,16,rep,name=messages,proto3" json:"messages,omitempty"` - Version int64 `protobuf:"varint,17,opt,name=version,proto3" json:"version,omitempty"` - History *v17.History `protobuf:"bytes,18,opt,name=history,proto3" json:"history,omitempty"` - NextPageToken []byte `protobuf:"bytes,19,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + WorkflowType *v14.WorkflowType `protobuf:"bytes,1,opt,name=workflow_type,json=workflowType,proto3" json:"workflow_type,omitempty"` + PreviousStartedEventId int64 `protobuf:"varint,2,opt,name=previous_started_event_id,json=previousStartedEventId,proto3" json:"previous_started_event_id,omitempty"` + ScheduledEventId int64 `protobuf:"varint,3,opt,name=scheduled_event_id,json=scheduledEventId,proto3" json:"scheduled_event_id,omitempty"` + StartedEventId int64 `protobuf:"varint,4,opt,name=started_event_id,json=startedEventId,proto3" json:"started_event_id,omitempty"` + NextEventId int64 `protobuf:"varint,5,opt,name=next_event_id,json=nextEventId,proto3" json:"next_event_id,omitempty"` + Attempt int32 `protobuf:"varint,6,opt,name=attempt,proto3" json:"attempt,omitempty"` + StickyExecutionEnabled bool `protobuf:"varint,7,opt,name=sticky_execution_enabled,json=stickyExecutionEnabled,proto3" json:"sticky_execution_enabled,omitempty"` + TransientWorkflowTask *v110.TransientWorkflowTaskInfo `protobuf:"bytes,8,opt,name=transient_workflow_task,json=transientWorkflowTask,proto3" json:"transient_workflow_task,omitempty"` + WorkflowExecutionTaskQueue *v112.TaskQueue `protobuf:"bytes,9,opt,name=workflow_execution_task_queue,json=workflowExecutionTaskQueue,proto3" json:"workflow_execution_task_queue,omitempty"` + BranchToken []byte `protobuf:"bytes,11,opt,name=branch_token,json=branchToken,proto3" json:"branch_token,omitempty"` + ScheduledTime *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=scheduled_time,json=scheduledTime,proto3" json:"scheduled_time,omitempty"` + StartedTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=started_time,json=startedTime,proto3" json:"started_time,omitempty"` + Queries map[string]*v115.WorkflowQuery `protobuf:"bytes,14,rep,name=queries,proto3" json:"queries,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Clock *v18.VectorClock `protobuf:"bytes,15,opt,name=clock,proto3" json:"clock,omitempty"` + Messages []*v116.Message `protobuf:"bytes,16,rep,name=messages,proto3" json:"messages,omitempty"` + Version int64 `protobuf:"varint,17,opt,name=version,proto3" json:"version,omitempty"` + History *v17.History `protobuf:"bytes,18,opt,name=history,proto3" json:"history,omitempty"` + NextPageToken []byte `protobuf:"bytes,19,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // Deprecated: This field is being replaced by raw_history_bytes which sends raw bytes // instead of a proto-decoded History. This avoids matching service having to decode history. // // Deprecated: Marked as deprecated in temporal/server/api/historyservice/v1/request_response.proto. RawHistory [][]byte `protobuf:"bytes,20,rep,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` RawHistoryBytes [][]byte `protobuf:"bytes,21,rep,name=raw_history_bytes,json=rawHistoryBytes,proto3" json:"raw_history_bytes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + StreamSlices []*v19.StreamSlice `protobuf:"bytes,22,rep,name=stream_slices,json=streamSlices,proto3" json:"stream_slices,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RecordWorkflowTaskStartedResponseWithRawHistory) Reset() { *x = RecordWorkflowTaskStartedResponseWithRawHistory{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[13] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1590,7 +1707,7 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) String() string { func (*RecordWorkflowTaskStartedResponseWithRawHistory) ProtoMessage() {} func (x *RecordWorkflowTaskStartedResponseWithRawHistory) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[13] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1603,7 +1720,7 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) ProtoReflect() protore // Deprecated: Use RecordWorkflowTaskStartedResponseWithRawHistory.ProtoReflect.Descriptor instead. func (*RecordWorkflowTaskStartedResponseWithRawHistory) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{13} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{15} } func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetWorkflowType() *v14.WorkflowType { @@ -1655,14 +1772,14 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetStickyExecutionEnab return false } -func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetTransientWorkflowTask() *v19.TransientWorkflowTaskInfo { +func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetTransientWorkflowTask() *v110.TransientWorkflowTaskInfo { if x != nil { return x.TransientWorkflowTask } return nil } -func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetWorkflowExecutionTaskQueue() *v111.TaskQueue { +func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetWorkflowExecutionTaskQueue() *v112.TaskQueue { if x != nil { return x.WorkflowExecutionTaskQueue } @@ -1690,7 +1807,7 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetStartedTime() *time return nil } -func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetQueries() map[string]*v114.WorkflowQuery { +func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetQueries() map[string]*v115.WorkflowQuery { if x != nil { return x.Queries } @@ -1704,7 +1821,7 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetClock() *v18.Vector return nil } -func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetMessages() []*v115.Message { +func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetMessages() []*v116.Message { if x != nil { return x.Messages } @@ -1747,6 +1864,13 @@ func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetRawHistoryBytes() [ return nil } +func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetStreamSlices() []*v19.StreamSlice { + if x != nil { + return x.StreamSlices + } + return nil +} + type RecordActivityTaskStartedRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` @@ -1756,14 +1880,14 @@ type RecordActivityTaskStartedRequest struct { RequestId string `protobuf:"bytes,5,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` PollRequest *v1.PollActivityTaskQueueRequest `protobuf:"bytes,6,opt,name=poll_request,json=pollRequest,proto3" json:"poll_request,omitempty"` Clock *v18.VectorClock `protobuf:"bytes,7,opt,name=clock,proto3" json:"clock,omitempty"` - BuildIdRedirectInfo *v113.BuildIdRedirectInfo `protobuf:"bytes,8,opt,name=build_id_redirect_info,json=buildIdRedirectInfo,proto3" json:"build_id_redirect_info,omitempty"` + BuildIdRedirectInfo *v114.BuildIdRedirectInfo `protobuf:"bytes,8,opt,name=build_id_redirect_info,json=buildIdRedirectInfo,proto3" json:"build_id_redirect_info,omitempty"` // Stamp represents the internal “version” of the activity options and can/will be changed with Activity API. Stamp int32 `protobuf:"varint,9,opt,name=stamp,proto3" json:"stamp,omitempty"` // The deployment passed by History when the task was scheduled. // Deprecated. use `version_directive.deployment`. ScheduledDeployment *v16.Deployment `protobuf:"bytes,10,opt,name=scheduled_deployment,json=scheduledDeployment,proto3" json:"scheduled_deployment,omitempty"` // Versioning directive that was sent by history when scheduling the task. - VersionDirective *v113.TaskVersionDirective `protobuf:"bytes,12,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` + VersionDirective *v114.TaskVersionDirective `protobuf:"bytes,12,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` // Revision number that was sent by matching when the task was dispatched. Used to resolve eventual consistency issues // that may arise due to stale routing configs in task queue partitions. TaskDispatchRevisionNumber int64 `protobuf:"varint,13,opt,name=task_dispatch_revision_number,json=taskDispatchRevisionNumber,proto3" json:"task_dispatch_revision_number,omitempty"` @@ -1777,7 +1901,7 @@ type RecordActivityTaskStartedRequest struct { func (x *RecordActivityTaskStartedRequest) Reset() { *x = RecordActivityTaskStartedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[14] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1789,7 +1913,7 @@ func (x *RecordActivityTaskStartedRequest) String() string { func (*RecordActivityTaskStartedRequest) ProtoMessage() {} func (x *RecordActivityTaskStartedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[14] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1802,7 +1926,7 @@ func (x *RecordActivityTaskStartedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RecordActivityTaskStartedRequest.ProtoReflect.Descriptor instead. func (*RecordActivityTaskStartedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{14} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{16} } func (x *RecordActivityTaskStartedRequest) GetNamespaceId() string { @@ -1847,7 +1971,7 @@ func (x *RecordActivityTaskStartedRequest) GetClock() *v18.VectorClock { return nil } -func (x *RecordActivityTaskStartedRequest) GetBuildIdRedirectInfo() *v113.BuildIdRedirectInfo { +func (x *RecordActivityTaskStartedRequest) GetBuildIdRedirectInfo() *v114.BuildIdRedirectInfo { if x != nil { return x.BuildIdRedirectInfo } @@ -1868,7 +1992,7 @@ func (x *RecordActivityTaskStartedRequest) GetScheduledDeployment() *v16.Deploym return nil } -func (x *RecordActivityTaskStartedRequest) GetVersionDirective() *v113.TaskVersionDirective { +func (x *RecordActivityTaskStartedRequest) GetVersionDirective() *v114.TaskVersionDirective { if x != nil { return x.VersionDirective } @@ -1911,7 +2035,7 @@ type RecordActivityTaskStartedResponse struct { func (x *RecordActivityTaskStartedResponse) Reset() { *x = RecordActivityTaskStartedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[15] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1923,7 +2047,7 @@ func (x *RecordActivityTaskStartedResponse) String() string { func (*RecordActivityTaskStartedResponse) ProtoMessage() {} func (x *RecordActivityTaskStartedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[15] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1936,7 +2060,7 @@ func (x *RecordActivityTaskStartedResponse) ProtoReflect() protoreflect.Message // Deprecated: Use RecordActivityTaskStartedResponse.ProtoReflect.Descriptor instead. func (*RecordActivityTaskStartedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{15} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{17} } func (x *RecordActivityTaskStartedResponse) GetScheduledEvent() *v17.HistoryEvent { @@ -2040,7 +2164,7 @@ type RespondWorkflowTaskCompletedRequest struct { func (x *RespondWorkflowTaskCompletedRequest) Reset() { *x = RespondWorkflowTaskCompletedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2052,7 +2176,7 @@ func (x *RespondWorkflowTaskCompletedRequest) String() string { func (*RespondWorkflowTaskCompletedRequest) ProtoMessage() {} func (x *RespondWorkflowTaskCompletedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2065,7 +2189,7 @@ func (x *RespondWorkflowTaskCompletedRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use RespondWorkflowTaskCompletedRequest.ProtoReflect.Descriptor instead. func (*RespondWorkflowTaskCompletedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{16} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{18} } func (x *RespondWorkflowTaskCompletedRequest) GetNamespaceId() string { @@ -2095,7 +2219,7 @@ type RespondWorkflowTaskCompletedResponse struct { func (x *RespondWorkflowTaskCompletedResponse) Reset() { *x = RespondWorkflowTaskCompletedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2107,7 +2231,7 @@ func (x *RespondWorkflowTaskCompletedResponse) String() string { func (*RespondWorkflowTaskCompletedResponse) ProtoMessage() {} func (x *RespondWorkflowTaskCompletedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2120,7 +2244,7 @@ func (x *RespondWorkflowTaskCompletedResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use RespondWorkflowTaskCompletedResponse.ProtoReflect.Descriptor instead. func (*RespondWorkflowTaskCompletedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{17} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{19} } // Deprecated: Marked as deprecated in temporal/server/api/historyservice/v1/request_response.proto. @@ -2162,7 +2286,7 @@ type RespondWorkflowTaskFailedRequest struct { func (x *RespondWorkflowTaskFailedRequest) Reset() { *x = RespondWorkflowTaskFailedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[18] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2174,7 +2298,7 @@ func (x *RespondWorkflowTaskFailedRequest) String() string { func (*RespondWorkflowTaskFailedRequest) ProtoMessage() {} func (x *RespondWorkflowTaskFailedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[18] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2187,7 +2311,7 @@ func (x *RespondWorkflowTaskFailedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RespondWorkflowTaskFailedRequest.ProtoReflect.Descriptor instead. func (*RespondWorkflowTaskFailedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{18} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{20} } func (x *RespondWorkflowTaskFailedRequest) GetNamespaceId() string { @@ -2212,7 +2336,7 @@ type RespondWorkflowTaskFailedResponse struct { func (x *RespondWorkflowTaskFailedResponse) Reset() { *x = RespondWorkflowTaskFailedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[19] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2224,7 +2348,7 @@ func (x *RespondWorkflowTaskFailedResponse) String() string { func (*RespondWorkflowTaskFailedResponse) ProtoMessage() {} func (x *RespondWorkflowTaskFailedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[19] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2237,7 +2361,7 @@ func (x *RespondWorkflowTaskFailedResponse) ProtoReflect() protoreflect.Message // Deprecated: Use RespondWorkflowTaskFailedResponse.ProtoReflect.Descriptor instead. func (*RespondWorkflowTaskFailedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{19} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{21} } type IsWorkflowTaskValidRequest struct { @@ -2253,7 +2377,7 @@ type IsWorkflowTaskValidRequest struct { func (x *IsWorkflowTaskValidRequest) Reset() { *x = IsWorkflowTaskValidRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[20] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2265,7 +2389,7 @@ func (x *IsWorkflowTaskValidRequest) String() string { func (*IsWorkflowTaskValidRequest) ProtoMessage() {} func (x *IsWorkflowTaskValidRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[20] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2278,7 +2402,7 @@ func (x *IsWorkflowTaskValidRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IsWorkflowTaskValidRequest.ProtoReflect.Descriptor instead. func (*IsWorkflowTaskValidRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{20} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{22} } func (x *IsWorkflowTaskValidRequest) GetNamespaceId() string { @@ -2326,7 +2450,7 @@ type IsWorkflowTaskValidResponse struct { func (x *IsWorkflowTaskValidResponse) Reset() { *x = IsWorkflowTaskValidResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[21] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2338,7 +2462,7 @@ func (x *IsWorkflowTaskValidResponse) String() string { func (*IsWorkflowTaskValidResponse) ProtoMessage() {} func (x *IsWorkflowTaskValidResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[21] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2351,7 +2475,7 @@ func (x *IsWorkflowTaskValidResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IsWorkflowTaskValidResponse.ProtoReflect.Descriptor instead. func (*IsWorkflowTaskValidResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{21} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{23} } func (x *IsWorkflowTaskValidResponse) GetIsValid() bool { @@ -2371,7 +2495,7 @@ type RecordActivityTaskHeartbeatRequest struct { func (x *RecordActivityTaskHeartbeatRequest) Reset() { *x = RecordActivityTaskHeartbeatRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[22] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2383,7 +2507,7 @@ func (x *RecordActivityTaskHeartbeatRequest) String() string { func (*RecordActivityTaskHeartbeatRequest) ProtoMessage() {} func (x *RecordActivityTaskHeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[22] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2396,7 +2520,7 @@ func (x *RecordActivityTaskHeartbeatRequest) ProtoReflect() protoreflect.Message // Deprecated: Use RecordActivityTaskHeartbeatRequest.ProtoReflect.Descriptor instead. func (*RecordActivityTaskHeartbeatRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{22} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{24} } func (x *RecordActivityTaskHeartbeatRequest) GetNamespaceId() string { @@ -2424,7 +2548,7 @@ type RecordActivityTaskHeartbeatResponse struct { func (x *RecordActivityTaskHeartbeatResponse) Reset() { *x = RecordActivityTaskHeartbeatResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[23] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2436,7 +2560,7 @@ func (x *RecordActivityTaskHeartbeatResponse) String() string { func (*RecordActivityTaskHeartbeatResponse) ProtoMessage() {} func (x *RecordActivityTaskHeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[23] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2449,7 +2573,7 @@ func (x *RecordActivityTaskHeartbeatResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use RecordActivityTaskHeartbeatResponse.ProtoReflect.Descriptor instead. func (*RecordActivityTaskHeartbeatResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{23} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{25} } func (x *RecordActivityTaskHeartbeatResponse) GetCancelRequested() bool { @@ -2483,7 +2607,7 @@ type RespondActivityTaskCompletedRequest struct { func (x *RespondActivityTaskCompletedRequest) Reset() { *x = RespondActivityTaskCompletedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[24] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2495,7 +2619,7 @@ func (x *RespondActivityTaskCompletedRequest) String() string { func (*RespondActivityTaskCompletedRequest) ProtoMessage() {} func (x *RespondActivityTaskCompletedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[24] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2508,7 +2632,7 @@ func (x *RespondActivityTaskCompletedRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use RespondActivityTaskCompletedRequest.ProtoReflect.Descriptor instead. func (*RespondActivityTaskCompletedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{24} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{26} } func (x *RespondActivityTaskCompletedRequest) GetNamespaceId() string { @@ -2533,7 +2657,7 @@ type RespondActivityTaskCompletedResponse struct { func (x *RespondActivityTaskCompletedResponse) Reset() { *x = RespondActivityTaskCompletedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[25] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2545,7 +2669,7 @@ func (x *RespondActivityTaskCompletedResponse) String() string { func (*RespondActivityTaskCompletedResponse) ProtoMessage() {} func (x *RespondActivityTaskCompletedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[25] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2558,7 +2682,7 @@ func (x *RespondActivityTaskCompletedResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use RespondActivityTaskCompletedResponse.ProtoReflect.Descriptor instead. func (*RespondActivityTaskCompletedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{25} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{27} } type RespondActivityTaskFailedRequest struct { @@ -2571,7 +2695,7 @@ type RespondActivityTaskFailedRequest struct { func (x *RespondActivityTaskFailedRequest) Reset() { *x = RespondActivityTaskFailedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[26] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2583,7 +2707,7 @@ func (x *RespondActivityTaskFailedRequest) String() string { func (*RespondActivityTaskFailedRequest) ProtoMessage() {} func (x *RespondActivityTaskFailedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[26] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2596,7 +2720,7 @@ func (x *RespondActivityTaskFailedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RespondActivityTaskFailedRequest.ProtoReflect.Descriptor instead. func (*RespondActivityTaskFailedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{26} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{28} } func (x *RespondActivityTaskFailedRequest) GetNamespaceId() string { @@ -2621,7 +2745,7 @@ type RespondActivityTaskFailedResponse struct { func (x *RespondActivityTaskFailedResponse) Reset() { *x = RespondActivityTaskFailedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[27] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2633,7 +2757,7 @@ func (x *RespondActivityTaskFailedResponse) String() string { func (*RespondActivityTaskFailedResponse) ProtoMessage() {} func (x *RespondActivityTaskFailedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[27] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2646,7 +2770,7 @@ func (x *RespondActivityTaskFailedResponse) ProtoReflect() protoreflect.Message // Deprecated: Use RespondActivityTaskFailedResponse.ProtoReflect.Descriptor instead. func (*RespondActivityTaskFailedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{27} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{29} } type RespondActivityTaskCanceledRequest struct { @@ -2659,7 +2783,7 @@ type RespondActivityTaskCanceledRequest struct { func (x *RespondActivityTaskCanceledRequest) Reset() { *x = RespondActivityTaskCanceledRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[28] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2671,7 +2795,7 @@ func (x *RespondActivityTaskCanceledRequest) String() string { func (*RespondActivityTaskCanceledRequest) ProtoMessage() {} func (x *RespondActivityTaskCanceledRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[28] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2684,7 +2808,7 @@ func (x *RespondActivityTaskCanceledRequest) ProtoReflect() protoreflect.Message // Deprecated: Use RespondActivityTaskCanceledRequest.ProtoReflect.Descriptor instead. func (*RespondActivityTaskCanceledRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{28} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{30} } func (x *RespondActivityTaskCanceledRequest) GetNamespaceId() string { @@ -2709,7 +2833,7 @@ type RespondActivityTaskCanceledResponse struct { func (x *RespondActivityTaskCanceledResponse) Reset() { *x = RespondActivityTaskCanceledResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[29] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2721,7 +2845,7 @@ func (x *RespondActivityTaskCanceledResponse) String() string { func (*RespondActivityTaskCanceledResponse) ProtoMessage() {} func (x *RespondActivityTaskCanceledResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[29] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2734,7 +2858,7 @@ func (x *RespondActivityTaskCanceledResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use RespondActivityTaskCanceledResponse.ProtoReflect.Descriptor instead. func (*RespondActivityTaskCanceledResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{29} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{31} } type IsActivityTaskValidRequest struct { @@ -2751,7 +2875,7 @@ type IsActivityTaskValidRequest struct { func (x *IsActivityTaskValidRequest) Reset() { *x = IsActivityTaskValidRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[30] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2763,7 +2887,7 @@ func (x *IsActivityTaskValidRequest) String() string { func (*IsActivityTaskValidRequest) ProtoMessage() {} func (x *IsActivityTaskValidRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[30] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2776,7 +2900,7 @@ func (x *IsActivityTaskValidRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IsActivityTaskValidRequest.ProtoReflect.Descriptor instead. func (*IsActivityTaskValidRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{30} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{32} } func (x *IsActivityTaskValidRequest) GetNamespaceId() string { @@ -2824,7 +2948,7 @@ type IsActivityTaskValidResponse struct { func (x *IsActivityTaskValidResponse) Reset() { *x = IsActivityTaskValidResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[31] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2836,7 +2960,7 @@ func (x *IsActivityTaskValidResponse) String() string { func (*IsActivityTaskValidResponse) ProtoMessage() {} func (x *IsActivityTaskValidResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[31] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2849,7 +2973,7 @@ func (x *IsActivityTaskValidResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IsActivityTaskValidResponse.ProtoReflect.Descriptor instead. func (*IsActivityTaskValidResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{31} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{33} } func (x *IsActivityTaskValidResponse) GetIsValid() bool { @@ -2871,7 +2995,7 @@ type SignalWorkflowExecutionRequest struct { func (x *SignalWorkflowExecutionRequest) Reset() { *x = SignalWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[32] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2883,7 +3007,7 @@ func (x *SignalWorkflowExecutionRequest) String() string { func (*SignalWorkflowExecutionRequest) ProtoMessage() {} func (x *SignalWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[32] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2896,7 +3020,7 @@ func (x *SignalWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SignalWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*SignalWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{32} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{34} } func (x *SignalWorkflowExecutionRequest) GetNamespaceId() string { @@ -2936,7 +3060,7 @@ type SignalWorkflowExecutionResponse struct { func (x *SignalWorkflowExecutionResponse) Reset() { *x = SignalWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[33] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2948,7 +3072,7 @@ func (x *SignalWorkflowExecutionResponse) String() string { func (*SignalWorkflowExecutionResponse) ProtoMessage() {} func (x *SignalWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[33] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2961,7 +3085,7 @@ func (x *SignalWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SignalWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*SignalWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{33} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{35} } func (x *SignalWorkflowExecutionResponse) GetLink() *v14.Link { @@ -2984,7 +3108,7 @@ type SignalWithStartWorkflowExecutionRequest struct { func (x *SignalWithStartWorkflowExecutionRequest) Reset() { *x = SignalWithStartWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[34] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2996,7 +3120,7 @@ func (x *SignalWithStartWorkflowExecutionRequest) String() string { func (*SignalWithStartWorkflowExecutionRequest) ProtoMessage() {} func (x *SignalWithStartWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[34] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3009,7 +3133,7 @@ func (x *SignalWithStartWorkflowExecutionRequest) ProtoReflect() protoreflect.Me // Deprecated: Use SignalWithStartWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*SignalWithStartWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{34} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{36} } func (x *SignalWithStartWorkflowExecutionRequest) GetNamespaceId() string { @@ -3041,7 +3165,7 @@ type SignalWithStartWorkflowExecutionResponse struct { func (x *SignalWithStartWorkflowExecutionResponse) Reset() { *x = SignalWithStartWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[35] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3053,7 +3177,7 @@ func (x *SignalWithStartWorkflowExecutionResponse) String() string { func (*SignalWithStartWorkflowExecutionResponse) ProtoMessage() {} func (x *SignalWithStartWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[35] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3066,7 +3190,7 @@ func (x *SignalWithStartWorkflowExecutionResponse) ProtoReflect() protoreflect.M // Deprecated: Use SignalWithStartWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*SignalWithStartWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{35} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{37} } func (x *SignalWithStartWorkflowExecutionResponse) GetRunId() string { @@ -3108,7 +3232,7 @@ type RemoveSignalMutableStateRequest struct { func (x *RemoveSignalMutableStateRequest) Reset() { *x = RemoveSignalMutableStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[36] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3120,7 +3244,7 @@ func (x *RemoveSignalMutableStateRequest) String() string { func (*RemoveSignalMutableStateRequest) ProtoMessage() {} func (x *RemoveSignalMutableStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[36] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3133,7 +3257,7 @@ func (x *RemoveSignalMutableStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveSignalMutableStateRequest.ProtoReflect.Descriptor instead. func (*RemoveSignalMutableStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{36} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{38} } func (x *RemoveSignalMutableStateRequest) GetNamespaceId() string { @@ -3165,7 +3289,7 @@ type RemoveSignalMutableStateResponse struct { func (x *RemoveSignalMutableStateResponse) Reset() { *x = RemoveSignalMutableStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[37] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3177,7 +3301,7 @@ func (x *RemoveSignalMutableStateResponse) String() string { func (*RemoveSignalMutableStateResponse) ProtoMessage() {} func (x *RemoveSignalMutableStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[37] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3190,7 +3314,7 @@ func (x *RemoveSignalMutableStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveSignalMutableStateResponse.ProtoReflect.Descriptor instead. func (*RemoveSignalMutableStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{37} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{39} } type TerminateWorkflowExecutionRequest struct { @@ -3205,7 +3329,7 @@ type TerminateWorkflowExecutionRequest struct { func (x *TerminateWorkflowExecutionRequest) Reset() { *x = TerminateWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[38] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3217,7 +3341,7 @@ func (x *TerminateWorkflowExecutionRequest) String() string { func (*TerminateWorkflowExecutionRequest) ProtoMessage() {} func (x *TerminateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[38] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3230,7 +3354,7 @@ func (x *TerminateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message // Deprecated: Use TerminateWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*TerminateWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{38} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{40} } func (x *TerminateWorkflowExecutionRequest) GetNamespaceId() string { @@ -3269,7 +3393,7 @@ type TerminateWorkflowExecutionResponse struct { func (x *TerminateWorkflowExecutionResponse) Reset() { *x = TerminateWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[39] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3281,7 +3405,7 @@ func (x *TerminateWorkflowExecutionResponse) String() string { func (*TerminateWorkflowExecutionResponse) ProtoMessage() {} func (x *TerminateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[39] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3294,7 +3418,7 @@ func (x *TerminateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message // Deprecated: Use TerminateWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*TerminateWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{39} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{41} } type DeleteWorkflowExecutionRequest struct { @@ -3308,7 +3432,7 @@ type DeleteWorkflowExecutionRequest struct { func (x *DeleteWorkflowExecutionRequest) Reset() { *x = DeleteWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[40] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3320,7 +3444,7 @@ func (x *DeleteWorkflowExecutionRequest) String() string { func (*DeleteWorkflowExecutionRequest) ProtoMessage() {} func (x *DeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[40] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3333,7 +3457,7 @@ func (x *DeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*DeleteWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{40} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{42} } func (x *DeleteWorkflowExecutionRequest) GetNamespaceId() string { @@ -3365,7 +3489,7 @@ type DeleteWorkflowExecutionResponse struct { func (x *DeleteWorkflowExecutionResponse) Reset() { *x = DeleteWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[41] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3377,7 +3501,7 @@ func (x *DeleteWorkflowExecutionResponse) String() string { func (*DeleteWorkflowExecutionResponse) ProtoMessage() {} func (x *DeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[41] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3390,7 +3514,7 @@ func (x *DeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*DeleteWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{41} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{43} } type ResetWorkflowExecutionRequest struct { @@ -3403,7 +3527,7 @@ type ResetWorkflowExecutionRequest struct { func (x *ResetWorkflowExecutionRequest) Reset() { *x = ResetWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[42] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3415,7 +3539,7 @@ func (x *ResetWorkflowExecutionRequest) String() string { func (*ResetWorkflowExecutionRequest) ProtoMessage() {} func (x *ResetWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[42] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3428,7 +3552,7 @@ func (x *ResetWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*ResetWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{42} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{44} } func (x *ResetWorkflowExecutionRequest) GetNamespaceId() string { @@ -3454,7 +3578,7 @@ type ResetWorkflowExecutionResponse struct { func (x *ResetWorkflowExecutionResponse) Reset() { *x = ResetWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[43] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3466,7 +3590,7 @@ func (x *ResetWorkflowExecutionResponse) String() string { func (*ResetWorkflowExecutionResponse) ProtoMessage() {} func (x *ResetWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[43] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3479,7 +3603,7 @@ func (x *ResetWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*ResetWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{43} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{45} } func (x *ResetWorkflowExecutionResponse) GetRunId() string { @@ -3502,7 +3626,7 @@ type RequestCancelWorkflowExecutionRequest struct { func (x *RequestCancelWorkflowExecutionRequest) Reset() { *x = RequestCancelWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[44] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3514,7 +3638,7 @@ func (x *RequestCancelWorkflowExecutionRequest) String() string { func (*RequestCancelWorkflowExecutionRequest) ProtoMessage() {} func (x *RequestCancelWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[44] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3527,7 +3651,7 @@ func (x *RequestCancelWorkflowExecutionRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use RequestCancelWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*RequestCancelWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{44} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{46} } func (x *RequestCancelWorkflowExecutionRequest) GetNamespaceId() string { @@ -3573,7 +3697,7 @@ type RequestCancelWorkflowExecutionResponse struct { func (x *RequestCancelWorkflowExecutionResponse) Reset() { *x = RequestCancelWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[45] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3585,7 +3709,7 @@ func (x *RequestCancelWorkflowExecutionResponse) String() string { func (*RequestCancelWorkflowExecutionResponse) ProtoMessage() {} func (x *RequestCancelWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[45] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3598,7 +3722,7 @@ func (x *RequestCancelWorkflowExecutionResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use RequestCancelWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*RequestCancelWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{45} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{47} } type ScheduleWorkflowTaskRequest struct { @@ -3614,7 +3738,7 @@ type ScheduleWorkflowTaskRequest struct { func (x *ScheduleWorkflowTaskRequest) Reset() { *x = ScheduleWorkflowTaskRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[46] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3626,7 +3750,7 @@ func (x *ScheduleWorkflowTaskRequest) String() string { func (*ScheduleWorkflowTaskRequest) ProtoMessage() {} func (x *ScheduleWorkflowTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[46] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3639,7 +3763,7 @@ func (x *ScheduleWorkflowTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ScheduleWorkflowTaskRequest.ProtoReflect.Descriptor instead. func (*ScheduleWorkflowTaskRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{46} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{48} } func (x *ScheduleWorkflowTaskRequest) GetNamespaceId() string { @@ -3685,7 +3809,7 @@ type ScheduleWorkflowTaskResponse struct { func (x *ScheduleWorkflowTaskResponse) Reset() { *x = ScheduleWorkflowTaskResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[47] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3697,7 +3821,7 @@ func (x *ScheduleWorkflowTaskResponse) String() string { func (*ScheduleWorkflowTaskResponse) ProtoMessage() {} func (x *ScheduleWorkflowTaskResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[47] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3710,7 +3834,7 @@ func (x *ScheduleWorkflowTaskResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ScheduleWorkflowTaskResponse.ProtoReflect.Descriptor instead. func (*ScheduleWorkflowTaskResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{47} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{49} } type VerifyFirstWorkflowTaskScheduledRequest struct { @@ -3725,7 +3849,7 @@ type VerifyFirstWorkflowTaskScheduledRequest struct { func (x *VerifyFirstWorkflowTaskScheduledRequest) Reset() { *x = VerifyFirstWorkflowTaskScheduledRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[48] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3737,7 +3861,7 @@ func (x *VerifyFirstWorkflowTaskScheduledRequest) String() string { func (*VerifyFirstWorkflowTaskScheduledRequest) ProtoMessage() {} func (x *VerifyFirstWorkflowTaskScheduledRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[48] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3750,7 +3874,7 @@ func (x *VerifyFirstWorkflowTaskScheduledRequest) ProtoReflect() protoreflect.Me // Deprecated: Use VerifyFirstWorkflowTaskScheduledRequest.ProtoReflect.Descriptor instead. func (*VerifyFirstWorkflowTaskScheduledRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{48} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{50} } func (x *VerifyFirstWorkflowTaskScheduledRequest) GetNamespaceId() string { @@ -3789,7 +3913,7 @@ type VerifyFirstWorkflowTaskScheduledResponse struct { func (x *VerifyFirstWorkflowTaskScheduledResponse) Reset() { *x = VerifyFirstWorkflowTaskScheduledResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[49] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3801,7 +3925,7 @@ func (x *VerifyFirstWorkflowTaskScheduledResponse) String() string { func (*VerifyFirstWorkflowTaskScheduledResponse) ProtoMessage() {} func (x *VerifyFirstWorkflowTaskScheduledResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[49] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3814,7 +3938,7 @@ func (x *VerifyFirstWorkflowTaskScheduledResponse) ProtoReflect() protoreflect.M // Deprecated: Use VerifyFirstWorkflowTaskScheduledResponse.ProtoReflect.Descriptor instead. func (*VerifyFirstWorkflowTaskScheduledResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{49} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{51} } // * @@ -3839,7 +3963,7 @@ type RecordChildExecutionCompletedRequest struct { func (x *RecordChildExecutionCompletedRequest) Reset() { *x = RecordChildExecutionCompletedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[50] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3851,7 +3975,7 @@ func (x *RecordChildExecutionCompletedRequest) String() string { func (*RecordChildExecutionCompletedRequest) ProtoMessage() {} func (x *RecordChildExecutionCompletedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[50] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3864,7 +3988,7 @@ func (x *RecordChildExecutionCompletedRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use RecordChildExecutionCompletedRequest.ProtoReflect.Descriptor instead. func (*RecordChildExecutionCompletedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{50} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{52} } func (x *RecordChildExecutionCompletedRequest) GetNamespaceId() string { @@ -3931,7 +4055,7 @@ type RecordChildExecutionCompletedResponse struct { func (x *RecordChildExecutionCompletedResponse) Reset() { *x = RecordChildExecutionCompletedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[51] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3943,7 +4067,7 @@ func (x *RecordChildExecutionCompletedResponse) String() string { func (*RecordChildExecutionCompletedResponse) ProtoMessage() {} func (x *RecordChildExecutionCompletedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[51] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3956,7 +4080,7 @@ func (x *RecordChildExecutionCompletedResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use RecordChildExecutionCompletedResponse.ProtoReflect.Descriptor instead. func (*RecordChildExecutionCompletedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{51} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{53} } type VerifyChildExecutionCompletionRecordedRequest struct { @@ -3974,7 +4098,7 @@ type VerifyChildExecutionCompletionRecordedRequest struct { func (x *VerifyChildExecutionCompletionRecordedRequest) Reset() { *x = VerifyChildExecutionCompletionRecordedRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[52] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3986,7 +4110,7 @@ func (x *VerifyChildExecutionCompletionRecordedRequest) String() string { func (*VerifyChildExecutionCompletionRecordedRequest) ProtoMessage() {} func (x *VerifyChildExecutionCompletionRecordedRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[52] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3999,7 +4123,7 @@ func (x *VerifyChildExecutionCompletionRecordedRequest) ProtoReflect() protorefl // Deprecated: Use VerifyChildExecutionCompletionRecordedRequest.ProtoReflect.Descriptor instead. func (*VerifyChildExecutionCompletionRecordedRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{52} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{54} } func (x *VerifyChildExecutionCompletionRecordedRequest) GetNamespaceId() string { @@ -4059,7 +4183,7 @@ type VerifyChildExecutionCompletionRecordedResponse struct { func (x *VerifyChildExecutionCompletionRecordedResponse) Reset() { *x = VerifyChildExecutionCompletionRecordedResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[53] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4071,7 +4195,7 @@ func (x *VerifyChildExecutionCompletionRecordedResponse) String() string { func (*VerifyChildExecutionCompletionRecordedResponse) ProtoMessage() {} func (x *VerifyChildExecutionCompletionRecordedResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[53] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4084,7 +4208,7 @@ func (x *VerifyChildExecutionCompletionRecordedResponse) ProtoReflect() protoref // Deprecated: Use VerifyChildExecutionCompletionRecordedResponse.ProtoReflect.Descriptor instead. func (*VerifyChildExecutionCompletionRecordedResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{53} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{55} } type DescribeWorkflowExecutionRequest struct { @@ -4097,7 +4221,7 @@ type DescribeWorkflowExecutionRequest struct { func (x *DescribeWorkflowExecutionRequest) Reset() { *x = DescribeWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[54] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4109,7 +4233,7 @@ func (x *DescribeWorkflowExecutionRequest) String() string { func (*DescribeWorkflowExecutionRequest) ProtoMessage() {} func (x *DescribeWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[54] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4122,7 +4246,7 @@ func (x *DescribeWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*DescribeWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{54} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{56} } func (x *DescribeWorkflowExecutionRequest) GetNamespaceId() string { @@ -4155,7 +4279,7 @@ type DescribeWorkflowExecutionResponse struct { func (x *DescribeWorkflowExecutionResponse) Reset() { *x = DescribeWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[55] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4167,7 +4291,7 @@ func (x *DescribeWorkflowExecutionResponse) String() string { func (*DescribeWorkflowExecutionResponse) ProtoMessage() {} func (x *DescribeWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[55] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4180,7 +4304,7 @@ func (x *DescribeWorkflowExecutionResponse) ProtoReflect() protoreflect.Message // Deprecated: Use DescribeWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*DescribeWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{55} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{57} } func (x *DescribeWorkflowExecutionResponse) GetExecutionConfig() *v15.WorkflowExecutionConfig { @@ -4240,11 +4364,11 @@ func (x *DescribeWorkflowExecutionResponse) GetWorkflowExtendedInfo() *v15.Workf } type ReplicateEventsV2Request struct { - state protoimpl.MessageState `protogen:"open.v1"` - NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - WorkflowExecution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=workflow_execution,json=workflowExecution,proto3" json:"workflow_execution,omitempty"` - VersionHistoryItems []*v19.VersionHistoryItem `protobuf:"bytes,3,rep,name=version_history_items,json=versionHistoryItems,proto3" json:"version_history_items,omitempty"` - Events *v14.DataBlob `protobuf:"bytes,4,opt,name=events,proto3" json:"events,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + WorkflowExecution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=workflow_execution,json=workflowExecution,proto3" json:"workflow_execution,omitempty"` + VersionHistoryItems []*v110.VersionHistoryItem `protobuf:"bytes,3,rep,name=version_history_items,json=versionHistoryItems,proto3" json:"version_history_items,omitempty"` + Events *v14.DataBlob `protobuf:"bytes,4,opt,name=events,proto3" json:"events,omitempty"` // New run events does not need version history since there is no prior events. NewRunEvents *v14.DataBlob `protobuf:"bytes,5,opt,name=new_run_events,json=newRunEvents,proto3" json:"new_run_events,omitempty"` BaseExecutionInfo *v11.BaseExecutionInfo `protobuf:"bytes,6,opt,name=base_execution_info,json=baseExecutionInfo,proto3" json:"base_execution_info,omitempty"` @@ -4255,7 +4379,7 @@ type ReplicateEventsV2Request struct { func (x *ReplicateEventsV2Request) Reset() { *x = ReplicateEventsV2Request{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[56] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4267,7 +4391,7 @@ func (x *ReplicateEventsV2Request) String() string { func (*ReplicateEventsV2Request) ProtoMessage() {} func (x *ReplicateEventsV2Request) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[56] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4280,7 +4404,7 @@ func (x *ReplicateEventsV2Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateEventsV2Request.ProtoReflect.Descriptor instead. func (*ReplicateEventsV2Request) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{56} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{58} } func (x *ReplicateEventsV2Request) GetNamespaceId() string { @@ -4297,7 +4421,7 @@ func (x *ReplicateEventsV2Request) GetWorkflowExecution() *v14.WorkflowExecution return nil } -func (x *ReplicateEventsV2Request) GetVersionHistoryItems() []*v19.VersionHistoryItem { +func (x *ReplicateEventsV2Request) GetVersionHistoryItems() []*v110.VersionHistoryItem { if x != nil { return x.VersionHistoryItems } @@ -4340,7 +4464,7 @@ type ReplicateEventsV2Response struct { func (x *ReplicateEventsV2Response) Reset() { *x = ReplicateEventsV2Response{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[57] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4352,7 +4476,7 @@ func (x *ReplicateEventsV2Response) String() string { func (*ReplicateEventsV2Response) ProtoMessage() {} func (x *ReplicateEventsV2Response) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[57] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4365,12 +4489,12 @@ func (x *ReplicateEventsV2Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateEventsV2Response.ProtoReflect.Descriptor instead. func (*ReplicateEventsV2Response) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{57} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{59} } type ReplicateWorkflowStateRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - WorkflowState *v110.WorkflowMutableState `protobuf:"bytes,1,opt,name=workflow_state,json=workflowState,proto3" json:"workflow_state,omitempty"` + WorkflowState *v111.WorkflowMutableState `protobuf:"bytes,1,opt,name=workflow_state,json=workflowState,proto3" json:"workflow_state,omitempty"` RemoteCluster string `protobuf:"bytes,2,opt,name=remote_cluster,json=remoteCluster,proto3" json:"remote_cluster,omitempty"` NamespaceId string `protobuf:"bytes,3,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` IsForceReplication bool `protobuf:"varint,4,opt,name=is_force_replication,json=isForceReplication,proto3" json:"is_force_replication,omitempty"` @@ -4381,7 +4505,7 @@ type ReplicateWorkflowStateRequest struct { func (x *ReplicateWorkflowStateRequest) Reset() { *x = ReplicateWorkflowStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[58] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4393,7 +4517,7 @@ func (x *ReplicateWorkflowStateRequest) String() string { func (*ReplicateWorkflowStateRequest) ProtoMessage() {} func (x *ReplicateWorkflowStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[58] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4406,10 +4530,10 @@ func (x *ReplicateWorkflowStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateWorkflowStateRequest.ProtoReflect.Descriptor instead. func (*ReplicateWorkflowStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{58} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{60} } -func (x *ReplicateWorkflowStateRequest) GetWorkflowState() *v110.WorkflowMutableState { +func (x *ReplicateWorkflowStateRequest) GetWorkflowState() *v111.WorkflowMutableState { if x != nil { return x.WorkflowState } @@ -4452,7 +4576,7 @@ type ReplicateWorkflowStateResponse struct { func (x *ReplicateWorkflowStateResponse) Reset() { *x = ReplicateWorkflowStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[59] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4464,7 +4588,7 @@ func (x *ReplicateWorkflowStateResponse) String() string { func (*ReplicateWorkflowStateResponse) ProtoMessage() {} func (x *ReplicateWorkflowStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[59] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4477,7 +4601,7 @@ func (x *ReplicateWorkflowStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateWorkflowStateResponse.ProtoReflect.Descriptor instead. func (*ReplicateWorkflowStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{59} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{61} } type SyncShardStatusRequest struct { @@ -4491,7 +4615,7 @@ type SyncShardStatusRequest struct { func (x *SyncShardStatusRequest) Reset() { *x = SyncShardStatusRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[60] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4503,7 +4627,7 @@ func (x *SyncShardStatusRequest) String() string { func (*SyncShardStatusRequest) ProtoMessage() {} func (x *SyncShardStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[60] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4516,7 +4640,7 @@ func (x *SyncShardStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncShardStatusRequest.ProtoReflect.Descriptor instead. func (*SyncShardStatusRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{60} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{62} } func (x *SyncShardStatusRequest) GetSourceCluster() string { @@ -4548,7 +4672,7 @@ type SyncShardStatusResponse struct { func (x *SyncShardStatusResponse) Reset() { *x = SyncShardStatusResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[61] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4560,7 +4684,7 @@ func (x *SyncShardStatusResponse) String() string { func (*SyncShardStatusResponse) ProtoMessage() {} func (x *SyncShardStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[61] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4573,7 +4697,7 @@ func (x *SyncShardStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncShardStatusResponse.ProtoReflect.Descriptor instead. func (*SyncShardStatusResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{61} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{63} } type SyncActivityRequest struct { @@ -4591,7 +4715,7 @@ type SyncActivityRequest struct { Attempt int32 `protobuf:"varint,11,opt,name=attempt,proto3" json:"attempt,omitempty"` LastFailure *v13.Failure `protobuf:"bytes,12,opt,name=last_failure,json=lastFailure,proto3" json:"last_failure,omitempty"` LastWorkerIdentity string `protobuf:"bytes,13,opt,name=last_worker_identity,json=lastWorkerIdentity,proto3" json:"last_worker_identity,omitempty"` - VersionHistory *v19.VersionHistory `protobuf:"bytes,14,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` + VersionHistory *v110.VersionHistory `protobuf:"bytes,14,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` BaseExecutionInfo *v11.BaseExecutionInfo `protobuf:"bytes,15,opt,name=base_execution_info,json=baseExecutionInfo,proto3" json:"base_execution_info,omitempty"` // build ID of the worker who received this activity last time LastStartedBuildId string `protobuf:"bytes,16,opt,name=last_started_build_id,json=lastStartedBuildId,proto3" json:"last_started_build_id,omitempty"` @@ -4617,7 +4741,7 @@ type SyncActivityRequest struct { func (x *SyncActivityRequest) Reset() { *x = SyncActivityRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[62] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4629,7 +4753,7 @@ func (x *SyncActivityRequest) String() string { func (*SyncActivityRequest) ProtoMessage() {} func (x *SyncActivityRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[62] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4642,7 +4766,7 @@ func (x *SyncActivityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncActivityRequest.ProtoReflect.Descriptor instead. func (*SyncActivityRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{62} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{64} } func (x *SyncActivityRequest) GetNamespaceId() string { @@ -4736,7 +4860,7 @@ func (x *SyncActivityRequest) GetLastWorkerIdentity() string { return "" } -func (x *SyncActivityRequest) GetVersionHistory() *v19.VersionHistory { +func (x *SyncActivityRequest) GetVersionHistory() *v110.VersionHistory { if x != nil { return x.VersionHistory } @@ -4839,7 +4963,7 @@ type SyncActivitiesRequest struct { func (x *SyncActivitiesRequest) Reset() { *x = SyncActivitiesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[63] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4851,7 +4975,7 @@ func (x *SyncActivitiesRequest) String() string { func (*SyncActivitiesRequest) ProtoMessage() {} func (x *SyncActivitiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[63] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4864,7 +4988,7 @@ func (x *SyncActivitiesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncActivitiesRequest.ProtoReflect.Descriptor instead. func (*SyncActivitiesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{63} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{65} } func (x *SyncActivitiesRequest) GetNamespaceId() string { @@ -4907,7 +5031,7 @@ type ActivitySyncInfo struct { Attempt int32 `protobuf:"varint,8,opt,name=attempt,proto3" json:"attempt,omitempty"` LastFailure *v13.Failure `protobuf:"bytes,9,opt,name=last_failure,json=lastFailure,proto3" json:"last_failure,omitempty"` LastWorkerIdentity string `protobuf:"bytes,10,opt,name=last_worker_identity,json=lastWorkerIdentity,proto3" json:"last_worker_identity,omitempty"` - VersionHistory *v19.VersionHistory `protobuf:"bytes,11,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` + VersionHistory *v110.VersionHistory `protobuf:"bytes,11,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` // build ID of the worker who received this activity last time LastStartedBuildId string `protobuf:"bytes,12,opt,name=last_started_build_id,json=lastStartedBuildId,proto3" json:"last_started_build_id,omitempty"` // workflows redirect_counter value when this activity started last time @@ -4932,7 +5056,7 @@ type ActivitySyncInfo struct { func (x *ActivitySyncInfo) Reset() { *x = ActivitySyncInfo{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[64] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4944,7 +5068,7 @@ func (x *ActivitySyncInfo) String() string { func (*ActivitySyncInfo) ProtoMessage() {} func (x *ActivitySyncInfo) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[64] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4957,7 +5081,7 @@ func (x *ActivitySyncInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ActivitySyncInfo.ProtoReflect.Descriptor instead. func (*ActivitySyncInfo) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{64} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{66} } func (x *ActivitySyncInfo) GetVersion() int64 { @@ -5030,7 +5154,7 @@ func (x *ActivitySyncInfo) GetLastWorkerIdentity() string { return "" } -func (x *ActivitySyncInfo) GetVersionHistory() *v19.VersionHistory { +func (x *ActivitySyncInfo) GetVersionHistory() *v110.VersionHistory { if x != nil { return x.VersionHistory } @@ -5122,7 +5246,7 @@ type SyncActivityResponse struct { func (x *SyncActivityResponse) Reset() { *x = SyncActivityResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[65] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5134,7 +5258,7 @@ func (x *SyncActivityResponse) String() string { func (*SyncActivityResponse) ProtoMessage() {} func (x *SyncActivityResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[65] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5147,7 +5271,7 @@ func (x *SyncActivityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncActivityResponse.ProtoReflect.Descriptor instead. func (*SyncActivityResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{65} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{67} } type DescribeMutableStateRequest struct { @@ -5163,7 +5287,7 @@ type DescribeMutableStateRequest struct { func (x *DescribeMutableStateRequest) Reset() { *x = DescribeMutableStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[66] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5175,7 +5299,7 @@ func (x *DescribeMutableStateRequest) String() string { func (*DescribeMutableStateRequest) ProtoMessage() {} func (x *DescribeMutableStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[66] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5188,7 +5312,7 @@ func (x *DescribeMutableStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeMutableStateRequest.ProtoReflect.Descriptor instead. func (*DescribeMutableStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{66} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{68} } func (x *DescribeMutableStateRequest) GetNamespaceId() string { @@ -5222,17 +5346,17 @@ func (x *DescribeMutableStateRequest) GetArchetypeId() uint32 { type DescribeMutableStateResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // CacheMutableState is only available when mutable state is in cache. - CacheMutableState *v110.WorkflowMutableState `protobuf:"bytes,1,opt,name=cache_mutable_state,json=cacheMutableState,proto3" json:"cache_mutable_state,omitempty"` + CacheMutableState *v111.WorkflowMutableState `protobuf:"bytes,1,opt,name=cache_mutable_state,json=cacheMutableState,proto3" json:"cache_mutable_state,omitempty"` // DatabaseMutableState is always available, // but only loaded from database when mutable state is NOT in cache or skip_force_reload is false. - DatabaseMutableState *v110.WorkflowMutableState `protobuf:"bytes,2,opt,name=database_mutable_state,json=databaseMutableState,proto3" json:"database_mutable_state,omitempty"` + DatabaseMutableState *v111.WorkflowMutableState `protobuf:"bytes,2,opt,name=database_mutable_state,json=databaseMutableState,proto3" json:"database_mutable_state,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *DescribeMutableStateResponse) Reset() { *x = DescribeMutableStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[67] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5244,7 +5368,7 @@ func (x *DescribeMutableStateResponse) String() string { func (*DescribeMutableStateResponse) ProtoMessage() {} func (x *DescribeMutableStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[67] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5257,17 +5381,17 @@ func (x *DescribeMutableStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeMutableStateResponse.ProtoReflect.Descriptor instead. func (*DescribeMutableStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{67} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{69} } -func (x *DescribeMutableStateResponse) GetCacheMutableState() *v110.WorkflowMutableState { +func (x *DescribeMutableStateResponse) GetCacheMutableState() *v111.WorkflowMutableState { if x != nil { return x.CacheMutableState } return nil } -func (x *DescribeMutableStateResponse) GetDatabaseMutableState() *v110.WorkflowMutableState { +func (x *DescribeMutableStateResponse) GetDatabaseMutableState() *v111.WorkflowMutableState { if x != nil { return x.DatabaseMutableState } @@ -5288,7 +5412,7 @@ type DescribeHistoryHostRequest struct { func (x *DescribeHistoryHostRequest) Reset() { *x = DescribeHistoryHostRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[68] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5300,7 +5424,7 @@ func (x *DescribeHistoryHostRequest) String() string { func (*DescribeHistoryHostRequest) ProtoMessage() {} func (x *DescribeHistoryHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[68] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5313,7 +5437,7 @@ func (x *DescribeHistoryHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeHistoryHostRequest.ProtoReflect.Descriptor instead. func (*DescribeHistoryHostRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{68} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{70} } func (x *DescribeHistoryHostRequest) GetHostAddress() string { @@ -5348,7 +5472,7 @@ type DescribeHistoryHostResponse struct { state protoimpl.MessageState `protogen:"open.v1"` ShardsNumber int32 `protobuf:"varint,1,opt,name=shards_number,json=shardsNumber,proto3" json:"shards_number,omitempty"` ShardIds []int32 `protobuf:"varint,2,rep,packed,name=shard_ids,json=shardIds,proto3" json:"shard_ids,omitempty"` - NamespaceCache *v116.NamespaceCacheInfo `protobuf:"bytes,3,opt,name=namespace_cache,json=namespaceCache,proto3" json:"namespace_cache,omitempty"` + NamespaceCache *v117.NamespaceCacheInfo `protobuf:"bytes,3,opt,name=namespace_cache,json=namespaceCache,proto3" json:"namespace_cache,omitempty"` Address string `protobuf:"bytes,5,opt,name=address,proto3" json:"address,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -5356,7 +5480,7 @@ type DescribeHistoryHostResponse struct { func (x *DescribeHistoryHostResponse) Reset() { *x = DescribeHistoryHostResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[69] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5368,7 +5492,7 @@ func (x *DescribeHistoryHostResponse) String() string { func (*DescribeHistoryHostResponse) ProtoMessage() {} func (x *DescribeHistoryHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[69] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5381,7 +5505,7 @@ func (x *DescribeHistoryHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeHistoryHostResponse.ProtoReflect.Descriptor instead. func (*DescribeHistoryHostResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{69} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{71} } func (x *DescribeHistoryHostResponse) GetShardsNumber() int32 { @@ -5398,7 +5522,7 @@ func (x *DescribeHistoryHostResponse) GetShardIds() []int32 { return nil } -func (x *DescribeHistoryHostResponse) GetNamespaceCache() *v116.NamespaceCacheInfo { +func (x *DescribeHistoryHostResponse) GetNamespaceCache() *v117.NamespaceCacheInfo { if x != nil { return x.NamespaceCache } @@ -5421,7 +5545,7 @@ type CloseShardRequest struct { func (x *CloseShardRequest) Reset() { *x = CloseShardRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[70] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5433,7 +5557,7 @@ func (x *CloseShardRequest) String() string { func (*CloseShardRequest) ProtoMessage() {} func (x *CloseShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[70] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5446,7 +5570,7 @@ func (x *CloseShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseShardRequest.ProtoReflect.Descriptor instead. func (*CloseShardRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{70} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{72} } func (x *CloseShardRequest) GetShardId() int32 { @@ -5464,7 +5588,7 @@ type CloseShardResponse struct { func (x *CloseShardResponse) Reset() { *x = CloseShardResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[71] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5476,7 +5600,7 @@ func (x *CloseShardResponse) String() string { func (*CloseShardResponse) ProtoMessage() {} func (x *CloseShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[71] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5489,7 +5613,7 @@ func (x *CloseShardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseShardResponse.ProtoReflect.Descriptor instead. func (*CloseShardResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{71} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{73} } type GetShardRequest struct { @@ -5501,7 +5625,7 @@ type GetShardRequest struct { func (x *GetShardRequest) Reset() { *x = GetShardRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[72] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5513,7 +5637,7 @@ func (x *GetShardRequest) String() string { func (*GetShardRequest) ProtoMessage() {} func (x *GetShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[72] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5526,7 +5650,7 @@ func (x *GetShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetShardRequest.ProtoReflect.Descriptor instead. func (*GetShardRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{72} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{74} } func (x *GetShardRequest) GetShardId() int32 { @@ -5538,14 +5662,14 @@ func (x *GetShardRequest) GetShardId() int32 { type GetShardResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - ShardInfo *v110.ShardInfo `protobuf:"bytes,1,opt,name=shard_info,json=shardInfo,proto3" json:"shard_info,omitempty"` + ShardInfo *v111.ShardInfo `protobuf:"bytes,1,opt,name=shard_info,json=shardInfo,proto3" json:"shard_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetShardResponse) Reset() { *x = GetShardResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[73] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5557,7 +5681,7 @@ func (x *GetShardResponse) String() string { func (*GetShardResponse) ProtoMessage() {} func (x *GetShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[73] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5570,10 +5694,10 @@ func (x *GetShardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetShardResponse.ProtoReflect.Descriptor instead. func (*GetShardResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{73} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{75} } -func (x *GetShardResponse) GetShardInfo() *v110.ShardInfo { +func (x *GetShardResponse) GetShardInfo() *v111.ShardInfo { if x != nil { return x.ShardInfo } @@ -5593,7 +5717,7 @@ type RemoveTaskRequest struct { func (x *RemoveTaskRequest) Reset() { *x = RemoveTaskRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[74] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5605,7 +5729,7 @@ func (x *RemoveTaskRequest) String() string { func (*RemoveTaskRequest) ProtoMessage() {} func (x *RemoveTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[74] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5618,7 +5742,7 @@ func (x *RemoveTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveTaskRequest.ProtoReflect.Descriptor instead. func (*RemoveTaskRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{74} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{76} } func (x *RemoveTaskRequest) GetShardId() int32 { @@ -5657,7 +5781,7 @@ type RemoveTaskResponse struct { func (x *RemoveTaskResponse) Reset() { *x = RemoveTaskResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[75] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5669,7 +5793,7 @@ func (x *RemoveTaskResponse) String() string { func (*RemoveTaskResponse) ProtoMessage() {} func (x *RemoveTaskResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[75] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5682,12 +5806,12 @@ func (x *RemoveTaskResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveTaskResponse.ProtoReflect.Descriptor instead. func (*RemoveTaskResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{75} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{77} } type GetReplicationMessagesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Tokens []*v117.ReplicationToken `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens,omitempty"` + Tokens []*v118.ReplicationToken `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens,omitempty"` ClusterName string `protobuf:"bytes,2,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -5695,7 +5819,7 @@ type GetReplicationMessagesRequest struct { func (x *GetReplicationMessagesRequest) Reset() { *x = GetReplicationMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[76] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5707,7 +5831,7 @@ func (x *GetReplicationMessagesRequest) String() string { func (*GetReplicationMessagesRequest) ProtoMessage() {} func (x *GetReplicationMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[76] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5720,10 +5844,10 @@ func (x *GetReplicationMessagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetReplicationMessagesRequest.ProtoReflect.Descriptor instead. func (*GetReplicationMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{76} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{78} } -func (x *GetReplicationMessagesRequest) GetTokens() []*v117.ReplicationToken { +func (x *GetReplicationMessagesRequest) GetTokens() []*v118.ReplicationToken { if x != nil { return x.Tokens } @@ -5739,14 +5863,14 @@ func (x *GetReplicationMessagesRequest) GetClusterName() string { type GetReplicationMessagesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - ShardMessages map[int32]*v117.ReplicationMessages `protobuf:"bytes,1,rep,name=shard_messages,json=shardMessages,proto3" json:"shard_messages,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + ShardMessages map[int32]*v118.ReplicationMessages `protobuf:"bytes,1,rep,name=shard_messages,json=shardMessages,proto3" json:"shard_messages,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetReplicationMessagesResponse) Reset() { *x = GetReplicationMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[77] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5758,7 +5882,7 @@ func (x *GetReplicationMessagesResponse) String() string { func (*GetReplicationMessagesResponse) ProtoMessage() {} func (x *GetReplicationMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[77] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5771,10 +5895,10 @@ func (x *GetReplicationMessagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetReplicationMessagesResponse.ProtoReflect.Descriptor instead. func (*GetReplicationMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{77} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{79} } -func (x *GetReplicationMessagesResponse) GetShardMessages() map[int32]*v117.ReplicationMessages { +func (x *GetReplicationMessagesResponse) GetShardMessages() map[int32]*v118.ReplicationMessages { if x != nil { return x.ShardMessages } @@ -5783,14 +5907,14 @@ func (x *GetReplicationMessagesResponse) GetShardMessages() map[int32]*v117.Repl type GetDLQReplicationMessagesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - TaskInfos []*v117.ReplicationTaskInfo `protobuf:"bytes,1,rep,name=task_infos,json=taskInfos,proto3" json:"task_infos,omitempty"` + TaskInfos []*v118.ReplicationTaskInfo `protobuf:"bytes,1,rep,name=task_infos,json=taskInfos,proto3" json:"task_infos,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetDLQReplicationMessagesRequest) Reset() { *x = GetDLQReplicationMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[78] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5802,7 +5926,7 @@ func (x *GetDLQReplicationMessagesRequest) String() string { func (*GetDLQReplicationMessagesRequest) ProtoMessage() {} func (x *GetDLQReplicationMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[78] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5815,10 +5939,10 @@ func (x *GetDLQReplicationMessagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDLQReplicationMessagesRequest.ProtoReflect.Descriptor instead. func (*GetDLQReplicationMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{78} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{80} } -func (x *GetDLQReplicationMessagesRequest) GetTaskInfos() []*v117.ReplicationTaskInfo { +func (x *GetDLQReplicationMessagesRequest) GetTaskInfos() []*v118.ReplicationTaskInfo { if x != nil { return x.TaskInfos } @@ -5827,14 +5951,14 @@ func (x *GetDLQReplicationMessagesRequest) GetTaskInfos() []*v117.ReplicationTas type GetDLQReplicationMessagesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - ReplicationTasks []*v117.ReplicationTask `protobuf:"bytes,1,rep,name=replication_tasks,json=replicationTasks,proto3" json:"replication_tasks,omitempty"` + ReplicationTasks []*v118.ReplicationTask `protobuf:"bytes,1,rep,name=replication_tasks,json=replicationTasks,proto3" json:"replication_tasks,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetDLQReplicationMessagesResponse) Reset() { *x = GetDLQReplicationMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[79] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5846,7 +5970,7 @@ func (x *GetDLQReplicationMessagesResponse) String() string { func (*GetDLQReplicationMessagesResponse) ProtoMessage() {} func (x *GetDLQReplicationMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[79] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5859,10 +5983,10 @@ func (x *GetDLQReplicationMessagesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use GetDLQReplicationMessagesResponse.ProtoReflect.Descriptor instead. func (*GetDLQReplicationMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{79} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{81} } -func (x *GetDLQReplicationMessagesResponse) GetReplicationTasks() []*v117.ReplicationTask { +func (x *GetDLQReplicationMessagesResponse) GetReplicationTasks() []*v118.ReplicationTask { if x != nil { return x.ReplicationTasks } @@ -5879,7 +6003,7 @@ type QueryWorkflowRequest struct { func (x *QueryWorkflowRequest) Reset() { *x = QueryWorkflowRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[80] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5891,7 +6015,7 @@ func (x *QueryWorkflowRequest) String() string { func (*QueryWorkflowRequest) ProtoMessage() {} func (x *QueryWorkflowRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[80] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5904,7 +6028,7 @@ func (x *QueryWorkflowRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryWorkflowRequest.ProtoReflect.Descriptor instead. func (*QueryWorkflowRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{80} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{82} } func (x *QueryWorkflowRequest) GetNamespaceId() string { @@ -5930,7 +6054,7 @@ type QueryWorkflowResponse struct { func (x *QueryWorkflowResponse) Reset() { *x = QueryWorkflowResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[81] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5942,7 +6066,7 @@ func (x *QueryWorkflowResponse) String() string { func (*QueryWorkflowResponse) ProtoMessage() {} func (x *QueryWorkflowResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[81] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5955,7 +6079,7 @@ func (x *QueryWorkflowResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryWorkflowResponse.ProtoReflect.Descriptor instead. func (*QueryWorkflowResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{81} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{83} } func (x *QueryWorkflowResponse) GetResponse() *v1.QueryWorkflowResponse { @@ -5968,14 +6092,14 @@ func (x *QueryWorkflowResponse) GetResponse() *v1.QueryWorkflowResponse { type ReapplyEventsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Request *v118.ReapplyEventsRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.ReapplyEventsRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ReapplyEventsRequest) Reset() { *x = ReapplyEventsRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[82] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5987,7 +6111,7 @@ func (x *ReapplyEventsRequest) String() string { func (*ReapplyEventsRequest) ProtoMessage() {} func (x *ReapplyEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[82] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6000,7 +6124,7 @@ func (x *ReapplyEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReapplyEventsRequest.ProtoReflect.Descriptor instead. func (*ReapplyEventsRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{82} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{84} } func (x *ReapplyEventsRequest) GetNamespaceId() string { @@ -6010,7 +6134,7 @@ func (x *ReapplyEventsRequest) GetNamespaceId() string { return "" } -func (x *ReapplyEventsRequest) GetRequest() *v118.ReapplyEventsRequest { +func (x *ReapplyEventsRequest) GetRequest() *v119.ReapplyEventsRequest { if x != nil { return x.Request } @@ -6025,7 +6149,7 @@ type ReapplyEventsResponse struct { func (x *ReapplyEventsResponse) Reset() { *x = ReapplyEventsResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[83] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6037,7 +6161,7 @@ func (x *ReapplyEventsResponse) String() string { func (*ReapplyEventsResponse) ProtoMessage() {} func (x *ReapplyEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[83] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6050,12 +6174,12 @@ func (x *ReapplyEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReapplyEventsResponse.ProtoReflect.Descriptor instead. func (*ReapplyEventsResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{83} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{85} } type GetDLQMessagesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Type v112.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` + Type v113.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` ShardId int32 `protobuf:"varint,2,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` SourceCluster string `protobuf:"bytes,3,opt,name=source_cluster,json=sourceCluster,proto3" json:"source_cluster,omitempty"` InclusiveEndMessageId int64 `protobuf:"varint,4,opt,name=inclusive_end_message_id,json=inclusiveEndMessageId,proto3" json:"inclusive_end_message_id,omitempty"` @@ -6067,7 +6191,7 @@ type GetDLQMessagesRequest struct { func (x *GetDLQMessagesRequest) Reset() { *x = GetDLQMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[84] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6079,7 +6203,7 @@ func (x *GetDLQMessagesRequest) String() string { func (*GetDLQMessagesRequest) ProtoMessage() {} func (x *GetDLQMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[84] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6092,14 +6216,14 @@ func (x *GetDLQMessagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDLQMessagesRequest.ProtoReflect.Descriptor instead. func (*GetDLQMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{84} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{86} } -func (x *GetDLQMessagesRequest) GetType() v112.DeadLetterQueueType { +func (x *GetDLQMessagesRequest) GetType() v113.DeadLetterQueueType { if x != nil { return x.Type } - return v112.DeadLetterQueueType(0) + return v113.DeadLetterQueueType(0) } func (x *GetDLQMessagesRequest) GetShardId() int32 { @@ -6139,17 +6263,17 @@ func (x *GetDLQMessagesRequest) GetNextPageToken() []byte { type GetDLQMessagesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Type v112.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` - ReplicationTasks []*v117.ReplicationTask `protobuf:"bytes,2,rep,name=replication_tasks,json=replicationTasks,proto3" json:"replication_tasks,omitempty"` + Type v113.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` + ReplicationTasks []*v118.ReplicationTask `protobuf:"bytes,2,rep,name=replication_tasks,json=replicationTasks,proto3" json:"replication_tasks,omitempty"` NextPageToken []byte `protobuf:"bytes,3,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - ReplicationTasksInfo []*v117.ReplicationTaskInfo `protobuf:"bytes,4,rep,name=replication_tasks_info,json=replicationTasksInfo,proto3" json:"replication_tasks_info,omitempty"` + ReplicationTasksInfo []*v118.ReplicationTaskInfo `protobuf:"bytes,4,rep,name=replication_tasks_info,json=replicationTasksInfo,proto3" json:"replication_tasks_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetDLQMessagesResponse) Reset() { *x = GetDLQMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[85] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6161,7 +6285,7 @@ func (x *GetDLQMessagesResponse) String() string { func (*GetDLQMessagesResponse) ProtoMessage() {} func (x *GetDLQMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[85] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6174,17 +6298,17 @@ func (x *GetDLQMessagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDLQMessagesResponse.ProtoReflect.Descriptor instead. func (*GetDLQMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{85} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{87} } -func (x *GetDLQMessagesResponse) GetType() v112.DeadLetterQueueType { +func (x *GetDLQMessagesResponse) GetType() v113.DeadLetterQueueType { if x != nil { return x.Type } - return v112.DeadLetterQueueType(0) + return v113.DeadLetterQueueType(0) } -func (x *GetDLQMessagesResponse) GetReplicationTasks() []*v117.ReplicationTask { +func (x *GetDLQMessagesResponse) GetReplicationTasks() []*v118.ReplicationTask { if x != nil { return x.ReplicationTasks } @@ -6198,7 +6322,7 @@ func (x *GetDLQMessagesResponse) GetNextPageToken() []byte { return nil } -func (x *GetDLQMessagesResponse) GetReplicationTasksInfo() []*v117.ReplicationTaskInfo { +func (x *GetDLQMessagesResponse) GetReplicationTasksInfo() []*v118.ReplicationTaskInfo { if x != nil { return x.ReplicationTasksInfo } @@ -6207,7 +6331,7 @@ func (x *GetDLQMessagesResponse) GetReplicationTasksInfo() []*v117.ReplicationTa type PurgeDLQMessagesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Type v112.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` + Type v113.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` ShardId int32 `protobuf:"varint,2,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` SourceCluster string `protobuf:"bytes,3,opt,name=source_cluster,json=sourceCluster,proto3" json:"source_cluster,omitempty"` InclusiveEndMessageId int64 `protobuf:"varint,4,opt,name=inclusive_end_message_id,json=inclusiveEndMessageId,proto3" json:"inclusive_end_message_id,omitempty"` @@ -6217,7 +6341,7 @@ type PurgeDLQMessagesRequest struct { func (x *PurgeDLQMessagesRequest) Reset() { *x = PurgeDLQMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[86] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6229,7 +6353,7 @@ func (x *PurgeDLQMessagesRequest) String() string { func (*PurgeDLQMessagesRequest) ProtoMessage() {} func (x *PurgeDLQMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[86] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6242,14 +6366,14 @@ func (x *PurgeDLQMessagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurgeDLQMessagesRequest.ProtoReflect.Descriptor instead. func (*PurgeDLQMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{86} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{88} } -func (x *PurgeDLQMessagesRequest) GetType() v112.DeadLetterQueueType { +func (x *PurgeDLQMessagesRequest) GetType() v113.DeadLetterQueueType { if x != nil { return x.Type } - return v112.DeadLetterQueueType(0) + return v113.DeadLetterQueueType(0) } func (x *PurgeDLQMessagesRequest) GetShardId() int32 { @@ -6281,7 +6405,7 @@ type PurgeDLQMessagesResponse struct { func (x *PurgeDLQMessagesResponse) Reset() { *x = PurgeDLQMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[87] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6293,7 +6417,7 @@ func (x *PurgeDLQMessagesResponse) String() string { func (*PurgeDLQMessagesResponse) ProtoMessage() {} func (x *PurgeDLQMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[87] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6306,12 +6430,12 @@ func (x *PurgeDLQMessagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurgeDLQMessagesResponse.ProtoReflect.Descriptor instead. func (*PurgeDLQMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{87} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{89} } type MergeDLQMessagesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Type v112.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` + Type v113.DeadLetterQueueType `protobuf:"varint,1,opt,name=type,proto3,enum=temporal.server.api.enums.v1.DeadLetterQueueType" json:"type,omitempty"` ShardId int32 `protobuf:"varint,2,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` SourceCluster string `protobuf:"bytes,3,opt,name=source_cluster,json=sourceCluster,proto3" json:"source_cluster,omitempty"` InclusiveEndMessageId int64 `protobuf:"varint,4,opt,name=inclusive_end_message_id,json=inclusiveEndMessageId,proto3" json:"inclusive_end_message_id,omitempty"` @@ -6323,7 +6447,7 @@ type MergeDLQMessagesRequest struct { func (x *MergeDLQMessagesRequest) Reset() { *x = MergeDLQMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[88] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6335,7 +6459,7 @@ func (x *MergeDLQMessagesRequest) String() string { func (*MergeDLQMessagesRequest) ProtoMessage() {} func (x *MergeDLQMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[88] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6348,14 +6472,14 @@ func (x *MergeDLQMessagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeDLQMessagesRequest.ProtoReflect.Descriptor instead. func (*MergeDLQMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{88} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{90} } -func (x *MergeDLQMessagesRequest) GetType() v112.DeadLetterQueueType { +func (x *MergeDLQMessagesRequest) GetType() v113.DeadLetterQueueType { if x != nil { return x.Type } - return v112.DeadLetterQueueType(0) + return v113.DeadLetterQueueType(0) } func (x *MergeDLQMessagesRequest) GetShardId() int32 { @@ -6402,7 +6526,7 @@ type MergeDLQMessagesResponse struct { func (x *MergeDLQMessagesResponse) Reset() { *x = MergeDLQMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[89] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6414,7 +6538,7 @@ func (x *MergeDLQMessagesResponse) String() string { func (*MergeDLQMessagesResponse) ProtoMessage() {} func (x *MergeDLQMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[89] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6427,7 +6551,7 @@ func (x *MergeDLQMessagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeDLQMessagesResponse.ProtoReflect.Descriptor instead. func (*MergeDLQMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{89} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{91} } func (x *MergeDLQMessagesResponse) GetNextPageToken() []byte { @@ -6442,14 +6566,14 @@ type RefreshWorkflowTasksRequest struct { NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` // (-- api-linter: core::0141::forbidden-types=disabled --) ArchetypeId uint32 `protobuf:"varint,3,opt,name=archetype_id,json=archetypeId,proto3" json:"archetype_id,omitempty"` - Request *v118.RefreshWorkflowTasksRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.RefreshWorkflowTasksRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *RefreshWorkflowTasksRequest) Reset() { *x = RefreshWorkflowTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[90] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6461,7 +6585,7 @@ func (x *RefreshWorkflowTasksRequest) String() string { func (*RefreshWorkflowTasksRequest) ProtoMessage() {} func (x *RefreshWorkflowTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[90] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6474,7 +6598,7 @@ func (x *RefreshWorkflowTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshWorkflowTasksRequest.ProtoReflect.Descriptor instead. func (*RefreshWorkflowTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{90} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{92} } func (x *RefreshWorkflowTasksRequest) GetNamespaceId() string { @@ -6491,7 +6615,7 @@ func (x *RefreshWorkflowTasksRequest) GetArchetypeId() uint32 { return 0 } -func (x *RefreshWorkflowTasksRequest) GetRequest() *v118.RefreshWorkflowTasksRequest { +func (x *RefreshWorkflowTasksRequest) GetRequest() *v119.RefreshWorkflowTasksRequest { if x != nil { return x.Request } @@ -6506,7 +6630,7 @@ type RefreshWorkflowTasksResponse struct { func (x *RefreshWorkflowTasksResponse) Reset() { *x = RefreshWorkflowTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[91] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6518,7 +6642,7 @@ func (x *RefreshWorkflowTasksResponse) String() string { func (*RefreshWorkflowTasksResponse) ProtoMessage() {} func (x *RefreshWorkflowTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[91] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6531,7 +6655,7 @@ func (x *RefreshWorkflowTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshWorkflowTasksResponse.ProtoReflect.Descriptor instead. func (*RefreshWorkflowTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{91} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{93} } type GenerateLastHistoryReplicationTasksRequest struct { @@ -6547,7 +6671,7 @@ type GenerateLastHistoryReplicationTasksRequest struct { func (x *GenerateLastHistoryReplicationTasksRequest) Reset() { *x = GenerateLastHistoryReplicationTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[92] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6559,7 +6683,7 @@ func (x *GenerateLastHistoryReplicationTasksRequest) String() string { func (*GenerateLastHistoryReplicationTasksRequest) ProtoMessage() {} func (x *GenerateLastHistoryReplicationTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[92] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6572,7 +6696,7 @@ func (x *GenerateLastHistoryReplicationTasksRequest) ProtoReflect() protoreflect // Deprecated: Use GenerateLastHistoryReplicationTasksRequest.ProtoReflect.Descriptor instead. func (*GenerateLastHistoryReplicationTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{92} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{94} } func (x *GenerateLastHistoryReplicationTasksRequest) GetNamespaceId() string { @@ -6613,7 +6737,7 @@ type GenerateLastHistoryReplicationTasksResponse struct { func (x *GenerateLastHistoryReplicationTasksResponse) Reset() { *x = GenerateLastHistoryReplicationTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[93] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6625,7 +6749,7 @@ func (x *GenerateLastHistoryReplicationTasksResponse) String() string { func (*GenerateLastHistoryReplicationTasksResponse) ProtoMessage() {} func (x *GenerateLastHistoryReplicationTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[93] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6638,7 +6762,7 @@ func (x *GenerateLastHistoryReplicationTasksResponse) ProtoReflect() protoreflec // Deprecated: Use GenerateLastHistoryReplicationTasksResponse.ProtoReflect.Descriptor instead. func (*GenerateLastHistoryReplicationTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{93} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{95} } func (x *GenerateLastHistoryReplicationTasksResponse) GetStateTransitionCount() int64 { @@ -6665,7 +6789,7 @@ type GetReplicationStatusRequest struct { func (x *GetReplicationStatusRequest) Reset() { *x = GetReplicationStatusRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[94] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6677,7 +6801,7 @@ func (x *GetReplicationStatusRequest) String() string { func (*GetReplicationStatusRequest) ProtoMessage() {} func (x *GetReplicationStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[94] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6690,7 +6814,7 @@ func (x *GetReplicationStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetReplicationStatusRequest.ProtoReflect.Descriptor instead. func (*GetReplicationStatusRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{94} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{96} } func (x *GetReplicationStatusRequest) GetRemoteClusters() []string { @@ -6709,7 +6833,7 @@ type GetReplicationStatusResponse struct { func (x *GetReplicationStatusResponse) Reset() { *x = GetReplicationStatusResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[95] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6721,7 +6845,7 @@ func (x *GetReplicationStatusResponse) String() string { func (*GetReplicationStatusResponse) ProtoMessage() {} func (x *GetReplicationStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[95] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6734,7 +6858,7 @@ func (x *GetReplicationStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetReplicationStatusResponse.ProtoReflect.Descriptor instead. func (*GetReplicationStatusResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{95} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{97} } func (x *GetReplicationStatusResponse) GetShards() []*ShardReplicationStatus { @@ -6760,7 +6884,7 @@ type ShardReplicationStatus struct { func (x *ShardReplicationStatus) Reset() { *x = ShardReplicationStatus{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[96] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6772,7 +6896,7 @@ func (x *ShardReplicationStatus) String() string { func (*ShardReplicationStatus) ProtoMessage() {} func (x *ShardReplicationStatus) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[96] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6785,7 +6909,7 @@ func (x *ShardReplicationStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ShardReplicationStatus.ProtoReflect.Descriptor instead. func (*ShardReplicationStatus) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{96} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{98} } func (x *ShardReplicationStatus) GetShardId() int32 { @@ -6840,7 +6964,7 @@ type HandoverNamespaceInfo struct { func (x *HandoverNamespaceInfo) Reset() { *x = HandoverNamespaceInfo{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[97] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6852,7 +6976,7 @@ func (x *HandoverNamespaceInfo) String() string { func (*HandoverNamespaceInfo) ProtoMessage() {} func (x *HandoverNamespaceInfo) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[97] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6865,7 +6989,7 @@ func (x *HandoverNamespaceInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use HandoverNamespaceInfo.ProtoReflect.Descriptor instead. func (*HandoverNamespaceInfo) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{97} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{99} } func (x *HandoverNamespaceInfo) GetHandoverReplicationTaskId() int64 { @@ -6887,7 +7011,7 @@ type ShardReplicationStatusPerCluster struct { func (x *ShardReplicationStatusPerCluster) Reset() { *x = ShardReplicationStatusPerCluster{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[98] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6899,7 +7023,7 @@ func (x *ShardReplicationStatusPerCluster) String() string { func (*ShardReplicationStatusPerCluster) ProtoMessage() {} func (x *ShardReplicationStatusPerCluster) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[98] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6912,7 +7036,7 @@ func (x *ShardReplicationStatusPerCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use ShardReplicationStatusPerCluster.ProtoReflect.Descriptor instead. func (*ShardReplicationStatusPerCluster) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{98} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{100} } func (x *ShardReplicationStatusPerCluster) GetAckedTaskId() int64 { @@ -6939,7 +7063,7 @@ type RebuildMutableStateRequest struct { func (x *RebuildMutableStateRequest) Reset() { *x = RebuildMutableStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[99] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6951,7 +7075,7 @@ func (x *RebuildMutableStateRequest) String() string { func (*RebuildMutableStateRequest) ProtoMessage() {} func (x *RebuildMutableStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[99] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6964,7 +7088,7 @@ func (x *RebuildMutableStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RebuildMutableStateRequest.ProtoReflect.Descriptor instead. func (*RebuildMutableStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{99} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{101} } func (x *RebuildMutableStateRequest) GetNamespaceId() string { @@ -6989,7 +7113,7 @@ type RebuildMutableStateResponse struct { func (x *RebuildMutableStateResponse) Reset() { *x = RebuildMutableStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[100] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7001,7 +7125,7 @@ func (x *RebuildMutableStateResponse) String() string { func (*RebuildMutableStateResponse) ProtoMessage() {} func (x *RebuildMutableStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[100] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7014,7 +7138,7 @@ func (x *RebuildMutableStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RebuildMutableStateResponse.ProtoReflect.Descriptor instead. func (*RebuildMutableStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{100} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{102} } type ImportWorkflowExecutionRequest struct { @@ -7022,7 +7146,7 @@ type ImportWorkflowExecutionRequest struct { NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` HistoryBatches []*v14.DataBlob `protobuf:"bytes,3,rep,name=history_batches,json=historyBatches,proto3" json:"history_batches,omitempty"` - VersionHistory *v19.VersionHistory `protobuf:"bytes,4,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` + VersionHistory *v110.VersionHistory `protobuf:"bytes,4,opt,name=version_history,json=versionHistory,proto3" json:"version_history,omitempty"` Token []byte `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -7030,7 +7154,7 @@ type ImportWorkflowExecutionRequest struct { func (x *ImportWorkflowExecutionRequest) Reset() { *x = ImportWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[101] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7042,7 +7166,7 @@ func (x *ImportWorkflowExecutionRequest) String() string { func (*ImportWorkflowExecutionRequest) ProtoMessage() {} func (x *ImportWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[101] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7055,7 +7179,7 @@ func (x *ImportWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*ImportWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{101} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{103} } func (x *ImportWorkflowExecutionRequest) GetNamespaceId() string { @@ -7079,7 +7203,7 @@ func (x *ImportWorkflowExecutionRequest) GetHistoryBatches() []*v14.DataBlob { return nil } -func (x *ImportWorkflowExecutionRequest) GetVersionHistory() *v19.VersionHistory { +func (x *ImportWorkflowExecutionRequest) GetVersionHistory() *v110.VersionHistory { if x != nil { return x.VersionHistory } @@ -7103,7 +7227,7 @@ type ImportWorkflowExecutionResponse struct { func (x *ImportWorkflowExecutionResponse) Reset() { *x = ImportWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[102] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7115,7 +7239,7 @@ func (x *ImportWorkflowExecutionResponse) String() string { func (*ImportWorkflowExecutionResponse) ProtoMessage() {} func (x *ImportWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[102] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7128,7 +7252,7 @@ func (x *ImportWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*ImportWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{102} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{104} } func (x *ImportWorkflowExecutionResponse) GetToken() []byte { @@ -7157,7 +7281,7 @@ type DeleteWorkflowVisibilityRecordRequest struct { func (x *DeleteWorkflowVisibilityRecordRequest) Reset() { *x = DeleteWorkflowVisibilityRecordRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[103] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7169,7 +7293,7 @@ func (x *DeleteWorkflowVisibilityRecordRequest) String() string { func (*DeleteWorkflowVisibilityRecordRequest) ProtoMessage() {} func (x *DeleteWorkflowVisibilityRecordRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[103] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7182,7 +7306,7 @@ func (x *DeleteWorkflowVisibilityRecordRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use DeleteWorkflowVisibilityRecordRequest.ProtoReflect.Descriptor instead. func (*DeleteWorkflowVisibilityRecordRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{103} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{105} } func (x *DeleteWorkflowVisibilityRecordRequest) GetNamespaceId() string { @@ -7221,7 +7345,7 @@ type DeleteWorkflowVisibilityRecordResponse struct { func (x *DeleteWorkflowVisibilityRecordResponse) Reset() { *x = DeleteWorkflowVisibilityRecordResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[104] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7233,7 +7357,7 @@ func (x *DeleteWorkflowVisibilityRecordResponse) String() string { func (*DeleteWorkflowVisibilityRecordResponse) ProtoMessage() {} func (x *DeleteWorkflowVisibilityRecordResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[104] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7246,7 +7370,7 @@ func (x *DeleteWorkflowVisibilityRecordResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use DeleteWorkflowVisibilityRecordResponse.ProtoReflect.Descriptor instead. func (*DeleteWorkflowVisibilityRecordResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{104} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{106} } // (-- api-linter: core::0134=disabled @@ -7262,7 +7386,7 @@ type UpdateWorkflowExecutionRequest struct { func (x *UpdateWorkflowExecutionRequest) Reset() { *x = UpdateWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[105] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7274,7 +7398,7 @@ func (x *UpdateWorkflowExecutionRequest) String() string { func (*UpdateWorkflowExecutionRequest) ProtoMessage() {} func (x *UpdateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[105] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7287,7 +7411,7 @@ func (x *UpdateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*UpdateWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{105} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{107} } func (x *UpdateWorkflowExecutionRequest) GetNamespaceId() string { @@ -7313,7 +7437,7 @@ type UpdateWorkflowExecutionResponse struct { func (x *UpdateWorkflowExecutionResponse) Reset() { *x = UpdateWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[106] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7325,7 +7449,7 @@ func (x *UpdateWorkflowExecutionResponse) String() string { func (*UpdateWorkflowExecutionResponse) ProtoMessage() {} func (x *UpdateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[106] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7338,7 +7462,7 @@ func (x *UpdateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*UpdateWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{106} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{108} } func (x *UpdateWorkflowExecutionResponse) GetResponse() *v1.UpdateWorkflowExecutionResponse { @@ -7360,7 +7484,7 @@ type StreamWorkflowReplicationMessagesRequest struct { func (x *StreamWorkflowReplicationMessagesRequest) Reset() { *x = StreamWorkflowReplicationMessagesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7372,7 +7496,7 @@ func (x *StreamWorkflowReplicationMessagesRequest) String() string { func (*StreamWorkflowReplicationMessagesRequest) ProtoMessage() {} func (x *StreamWorkflowReplicationMessagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7385,7 +7509,7 @@ func (x *StreamWorkflowReplicationMessagesRequest) ProtoReflect() protoreflect.M // Deprecated: Use StreamWorkflowReplicationMessagesRequest.ProtoReflect.Descriptor instead. func (*StreamWorkflowReplicationMessagesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{107} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{109} } func (x *StreamWorkflowReplicationMessagesRequest) GetAttributes() isStreamWorkflowReplicationMessagesRequest_Attributes { @@ -7395,7 +7519,7 @@ func (x *StreamWorkflowReplicationMessagesRequest) GetAttributes() isStreamWorkf return nil } -func (x *StreamWorkflowReplicationMessagesRequest) GetSyncReplicationState() *v117.SyncReplicationState { +func (x *StreamWorkflowReplicationMessagesRequest) GetSyncReplicationState() *v118.SyncReplicationState { if x != nil { if x, ok := x.Attributes.(*StreamWorkflowReplicationMessagesRequest_SyncReplicationState); ok { return x.SyncReplicationState @@ -7409,7 +7533,7 @@ type isStreamWorkflowReplicationMessagesRequest_Attributes interface { } type StreamWorkflowReplicationMessagesRequest_SyncReplicationState struct { - SyncReplicationState *v117.SyncReplicationState `protobuf:"bytes,1,opt,name=sync_replication_state,json=syncReplicationState,proto3,oneof"` + SyncReplicationState *v118.SyncReplicationState `protobuf:"bytes,1,opt,name=sync_replication_state,json=syncReplicationState,proto3,oneof"` } func (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState) isStreamWorkflowReplicationMessagesRequest_Attributes() { @@ -7427,7 +7551,7 @@ type StreamWorkflowReplicationMessagesResponse struct { func (x *StreamWorkflowReplicationMessagesResponse) Reset() { *x = StreamWorkflowReplicationMessagesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7439,7 +7563,7 @@ func (x *StreamWorkflowReplicationMessagesResponse) String() string { func (*StreamWorkflowReplicationMessagesResponse) ProtoMessage() {} func (x *StreamWorkflowReplicationMessagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7452,7 +7576,7 @@ func (x *StreamWorkflowReplicationMessagesResponse) ProtoReflect() protoreflect. // Deprecated: Use StreamWorkflowReplicationMessagesResponse.ProtoReflect.Descriptor instead. func (*StreamWorkflowReplicationMessagesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{108} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{110} } func (x *StreamWorkflowReplicationMessagesResponse) GetAttributes() isStreamWorkflowReplicationMessagesResponse_Attributes { @@ -7462,7 +7586,7 @@ func (x *StreamWorkflowReplicationMessagesResponse) GetAttributes() isStreamWork return nil } -func (x *StreamWorkflowReplicationMessagesResponse) GetMessages() *v117.WorkflowReplicationMessages { +func (x *StreamWorkflowReplicationMessagesResponse) GetMessages() *v118.WorkflowReplicationMessages { if x != nil { if x, ok := x.Attributes.(*StreamWorkflowReplicationMessagesResponse_Messages); ok { return x.Messages @@ -7476,7 +7600,7 @@ type isStreamWorkflowReplicationMessagesResponse_Attributes interface { } type StreamWorkflowReplicationMessagesResponse_Messages struct { - Messages *v117.WorkflowReplicationMessages `protobuf:"bytes,1,opt,name=messages,proto3,oneof"` + Messages *v118.WorkflowReplicationMessages `protobuf:"bytes,1,opt,name=messages,proto3,oneof"` } func (*StreamWorkflowReplicationMessagesResponse_Messages) isStreamWorkflowReplicationMessagesResponse_Attributes() { @@ -7492,7 +7616,7 @@ type PollWorkflowExecutionUpdateRequest struct { func (x *PollWorkflowExecutionUpdateRequest) Reset() { *x = PollWorkflowExecutionUpdateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7504,7 +7628,7 @@ func (x *PollWorkflowExecutionUpdateRequest) String() string { func (*PollWorkflowExecutionUpdateRequest) ProtoMessage() {} func (x *PollWorkflowExecutionUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7517,7 +7641,7 @@ func (x *PollWorkflowExecutionUpdateRequest) ProtoReflect() protoreflect.Message // Deprecated: Use PollWorkflowExecutionUpdateRequest.ProtoReflect.Descriptor instead. func (*PollWorkflowExecutionUpdateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{109} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{111} } func (x *PollWorkflowExecutionUpdateRequest) GetNamespaceId() string { @@ -7543,7 +7667,7 @@ type PollWorkflowExecutionUpdateResponse struct { func (x *PollWorkflowExecutionUpdateResponse) Reset() { *x = PollWorkflowExecutionUpdateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7555,7 +7679,7 @@ func (x *PollWorkflowExecutionUpdateResponse) String() string { func (*PollWorkflowExecutionUpdateResponse) ProtoMessage() {} func (x *PollWorkflowExecutionUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7568,7 +7692,7 @@ func (x *PollWorkflowExecutionUpdateResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use PollWorkflowExecutionUpdateResponse.ProtoReflect.Descriptor instead. func (*PollWorkflowExecutionUpdateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{110} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{112} } func (x *PollWorkflowExecutionUpdateResponse) GetResponse() *v1.PollWorkflowExecutionUpdateResponse { @@ -7588,7 +7712,7 @@ type GetWorkflowExecutionHistoryRequest struct { func (x *GetWorkflowExecutionHistoryRequest) Reset() { *x = GetWorkflowExecutionHistoryRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7600,7 +7724,7 @@ func (x *GetWorkflowExecutionHistoryRequest) String() string { func (*GetWorkflowExecutionHistoryRequest) ProtoMessage() {} func (x *GetWorkflowExecutionHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7613,7 +7737,7 @@ func (x *GetWorkflowExecutionHistoryRequest) ProtoReflect() protoreflect.Message // Deprecated: Use GetWorkflowExecutionHistoryRequest.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionHistoryRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{111} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{113} } func (x *GetWorkflowExecutionHistoryRequest) GetNamespaceId() string { @@ -7640,7 +7764,7 @@ type GetWorkflowExecutionHistoryResponse struct { func (x *GetWorkflowExecutionHistoryResponse) Reset() { *x = GetWorkflowExecutionHistoryResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7652,7 +7776,7 @@ func (x *GetWorkflowExecutionHistoryResponse) String() string { func (*GetWorkflowExecutionHistoryResponse) ProtoMessage() {} func (x *GetWorkflowExecutionHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7665,7 +7789,7 @@ func (x *GetWorkflowExecutionHistoryResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use GetWorkflowExecutionHistoryResponse.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionHistoryResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{112} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{114} } func (x *GetWorkflowExecutionHistoryResponse) GetResponse() *v1.GetWorkflowExecutionHistoryResponse { @@ -7693,7 +7817,7 @@ type GetWorkflowExecutionHistoryResponseWithRaw struct { func (x *GetWorkflowExecutionHistoryResponseWithRaw) Reset() { *x = GetWorkflowExecutionHistoryResponseWithRaw{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[113] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7705,7 +7829,7 @@ func (x *GetWorkflowExecutionHistoryResponseWithRaw) String() string { func (*GetWorkflowExecutionHistoryResponseWithRaw) ProtoMessage() {} func (x *GetWorkflowExecutionHistoryResponseWithRaw) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[113] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7718,7 +7842,7 @@ func (x *GetWorkflowExecutionHistoryResponseWithRaw) ProtoReflect() protoreflect // Deprecated: Use GetWorkflowExecutionHistoryResponseWithRaw.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionHistoryResponseWithRaw) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{113} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{115} } func (x *GetWorkflowExecutionHistoryResponseWithRaw) GetResponse() *v1.GetWorkflowExecutionHistoryResponse { @@ -7745,7 +7869,7 @@ type GetWorkflowExecutionHistoryReverseRequest struct { func (x *GetWorkflowExecutionHistoryReverseRequest) Reset() { *x = GetWorkflowExecutionHistoryReverseRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[114] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7757,7 +7881,7 @@ func (x *GetWorkflowExecutionHistoryReverseRequest) String() string { func (*GetWorkflowExecutionHistoryReverseRequest) ProtoMessage() {} func (x *GetWorkflowExecutionHistoryReverseRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[114] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7770,7 +7894,7 @@ func (x *GetWorkflowExecutionHistoryReverseRequest) ProtoReflect() protoreflect. // Deprecated: Use GetWorkflowExecutionHistoryReverseRequest.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionHistoryReverseRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{114} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{116} } func (x *GetWorkflowExecutionHistoryReverseRequest) GetNamespaceId() string { @@ -7796,7 +7920,7 @@ type GetWorkflowExecutionHistoryReverseResponse struct { func (x *GetWorkflowExecutionHistoryReverseResponse) Reset() { *x = GetWorkflowExecutionHistoryReverseResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[115] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7808,7 +7932,7 @@ func (x *GetWorkflowExecutionHistoryReverseResponse) String() string { func (*GetWorkflowExecutionHistoryReverseResponse) ProtoMessage() {} func (x *GetWorkflowExecutionHistoryReverseResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[115] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7821,7 +7945,7 @@ func (x *GetWorkflowExecutionHistoryReverseResponse) ProtoReflect() protoreflect // Deprecated: Use GetWorkflowExecutionHistoryReverseResponse.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionHistoryReverseResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{115} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{117} } func (x *GetWorkflowExecutionHistoryReverseResponse) GetResponse() *v1.GetWorkflowExecutionHistoryReverseResponse { @@ -7837,14 +7961,14 @@ func (x *GetWorkflowExecutionHistoryReverseResponse) GetResponse() *v1.GetWorkfl type GetWorkflowExecutionRawHistoryV2Request struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Request *v118.GetWorkflowExecutionRawHistoryV2Request `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.GetWorkflowExecutionRawHistoryV2Request `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetWorkflowExecutionRawHistoryV2Request) Reset() { *x = GetWorkflowExecutionRawHistoryV2Request{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[116] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7856,7 +7980,7 @@ func (x *GetWorkflowExecutionRawHistoryV2Request) String() string { func (*GetWorkflowExecutionRawHistoryV2Request) ProtoMessage() {} func (x *GetWorkflowExecutionRawHistoryV2Request) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[116] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7869,7 +7993,7 @@ func (x *GetWorkflowExecutionRawHistoryV2Request) ProtoReflect() protoreflect.Me // Deprecated: Use GetWorkflowExecutionRawHistoryV2Request.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionRawHistoryV2Request) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{116} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{118} } func (x *GetWorkflowExecutionRawHistoryV2Request) GetNamespaceId() string { @@ -7879,7 +8003,7 @@ func (x *GetWorkflowExecutionRawHistoryV2Request) GetNamespaceId() string { return "" } -func (x *GetWorkflowExecutionRawHistoryV2Request) GetRequest() *v118.GetWorkflowExecutionRawHistoryV2Request { +func (x *GetWorkflowExecutionRawHistoryV2Request) GetRequest() *v119.GetWorkflowExecutionRawHistoryV2Request { if x != nil { return x.Request } @@ -7888,14 +8012,14 @@ func (x *GetWorkflowExecutionRawHistoryV2Request) GetRequest() *v118.GetWorkflow type GetWorkflowExecutionRawHistoryV2Response struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v118.GetWorkflowExecutionRawHistoryV2Response `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v119.GetWorkflowExecutionRawHistoryV2Response `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetWorkflowExecutionRawHistoryV2Response) Reset() { *x = GetWorkflowExecutionRawHistoryV2Response{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[117] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7907,7 +8031,7 @@ func (x *GetWorkflowExecutionRawHistoryV2Response) String() string { func (*GetWorkflowExecutionRawHistoryV2Response) ProtoMessage() {} func (x *GetWorkflowExecutionRawHistoryV2Response) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[117] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7920,10 +8044,10 @@ func (x *GetWorkflowExecutionRawHistoryV2Response) ProtoReflect() protoreflect.M // Deprecated: Use GetWorkflowExecutionRawHistoryV2Response.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionRawHistoryV2Response) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{117} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{119} } -func (x *GetWorkflowExecutionRawHistoryV2Response) GetResponse() *v118.GetWorkflowExecutionRawHistoryV2Response { +func (x *GetWorkflowExecutionRawHistoryV2Response) GetResponse() *v119.GetWorkflowExecutionRawHistoryV2Response { if x != nil { return x.Response } @@ -7933,14 +8057,14 @@ func (x *GetWorkflowExecutionRawHistoryV2Response) GetResponse() *v118.GetWorkfl type GetWorkflowExecutionRawHistoryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Request *v118.GetWorkflowExecutionRawHistoryRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.GetWorkflowExecutionRawHistoryRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetWorkflowExecutionRawHistoryRequest) Reset() { *x = GetWorkflowExecutionRawHistoryRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[118] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7952,7 +8076,7 @@ func (x *GetWorkflowExecutionRawHistoryRequest) String() string { func (*GetWorkflowExecutionRawHistoryRequest) ProtoMessage() {} func (x *GetWorkflowExecutionRawHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[118] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7965,7 +8089,7 @@ func (x *GetWorkflowExecutionRawHistoryRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use GetWorkflowExecutionRawHistoryRequest.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionRawHistoryRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{118} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{120} } func (x *GetWorkflowExecutionRawHistoryRequest) GetNamespaceId() string { @@ -7975,7 +8099,7 @@ func (x *GetWorkflowExecutionRawHistoryRequest) GetNamespaceId() string { return "" } -func (x *GetWorkflowExecutionRawHistoryRequest) GetRequest() *v118.GetWorkflowExecutionRawHistoryRequest { +func (x *GetWorkflowExecutionRawHistoryRequest) GetRequest() *v119.GetWorkflowExecutionRawHistoryRequest { if x != nil { return x.Request } @@ -7984,14 +8108,14 @@ func (x *GetWorkflowExecutionRawHistoryRequest) GetRequest() *v118.GetWorkflowEx type GetWorkflowExecutionRawHistoryResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v118.GetWorkflowExecutionRawHistoryResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v119.GetWorkflowExecutionRawHistoryResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GetWorkflowExecutionRawHistoryResponse) Reset() { *x = GetWorkflowExecutionRawHistoryResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[119] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8003,7 +8127,7 @@ func (x *GetWorkflowExecutionRawHistoryResponse) String() string { func (*GetWorkflowExecutionRawHistoryResponse) ProtoMessage() {} func (x *GetWorkflowExecutionRawHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[119] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8016,10 +8140,10 @@ func (x *GetWorkflowExecutionRawHistoryResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use GetWorkflowExecutionRawHistoryResponse.ProtoReflect.Descriptor instead. func (*GetWorkflowExecutionRawHistoryResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{119} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{121} } -func (x *GetWorkflowExecutionRawHistoryResponse) GetResponse() *v118.GetWorkflowExecutionRawHistoryResponse { +func (x *GetWorkflowExecutionRawHistoryResponse) GetResponse() *v119.GetWorkflowExecutionRawHistoryResponse { if x != nil { return x.Response } @@ -8031,14 +8155,14 @@ type ForceDeleteWorkflowExecutionRequest struct { NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` // (-- api-linter: core::0141::forbidden-types=disabled --) ArchetypeId uint32 `protobuf:"varint,3,opt,name=archetype_id,json=archetypeId,proto3" json:"archetype_id,omitempty"` - Request *v118.DeleteWorkflowExecutionRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.DeleteWorkflowExecutionRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ForceDeleteWorkflowExecutionRequest) Reset() { *x = ForceDeleteWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[120] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8050,7 +8174,7 @@ func (x *ForceDeleteWorkflowExecutionRequest) String() string { func (*ForceDeleteWorkflowExecutionRequest) ProtoMessage() {} func (x *ForceDeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[120] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8063,7 +8187,7 @@ func (x *ForceDeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ForceDeleteWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*ForceDeleteWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{120} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{122} } func (x *ForceDeleteWorkflowExecutionRequest) GetNamespaceId() string { @@ -8080,7 +8204,7 @@ func (x *ForceDeleteWorkflowExecutionRequest) GetArchetypeId() uint32 { return 0 } -func (x *ForceDeleteWorkflowExecutionRequest) GetRequest() *v118.DeleteWorkflowExecutionRequest { +func (x *ForceDeleteWorkflowExecutionRequest) GetRequest() *v119.DeleteWorkflowExecutionRequest { if x != nil { return x.Request } @@ -8089,14 +8213,14 @@ func (x *ForceDeleteWorkflowExecutionRequest) GetRequest() *v118.DeleteWorkflowE type ForceDeleteWorkflowExecutionResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v118.DeleteWorkflowExecutionResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v119.DeleteWorkflowExecutionResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ForceDeleteWorkflowExecutionResponse) Reset() { *x = ForceDeleteWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[121] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8108,7 +8232,7 @@ func (x *ForceDeleteWorkflowExecutionResponse) String() string { func (*ForceDeleteWorkflowExecutionResponse) ProtoMessage() {} func (x *ForceDeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[121] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8121,10 +8245,10 @@ func (x *ForceDeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ForceDeleteWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*ForceDeleteWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{121} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{123} } -func (x *ForceDeleteWorkflowExecutionResponse) GetResponse() *v118.DeleteWorkflowExecutionResponse { +func (x *ForceDeleteWorkflowExecutionResponse) GetResponse() *v119.DeleteWorkflowExecutionResponse { if x != nil { return x.Response } @@ -8145,7 +8269,7 @@ type DeleteExecutionRequest struct { func (x *DeleteExecutionRequest) Reset() { *x = DeleteExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[122] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8157,7 +8281,7 @@ func (x *DeleteExecutionRequest) String() string { func (*DeleteExecutionRequest) ProtoMessage() {} func (x *DeleteExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[122] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8170,7 +8294,7 @@ func (x *DeleteExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteExecutionRequest.ProtoReflect.Descriptor instead. func (*DeleteExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{122} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{124} } func (x *DeleteExecutionRequest) GetNamespaceId() string { @@ -8216,7 +8340,7 @@ type DeleteExecutionResponse struct { func (x *DeleteExecutionResponse) Reset() { *x = DeleteExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[123] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8228,7 +8352,7 @@ func (x *DeleteExecutionResponse) String() string { func (*DeleteExecutionResponse) ProtoMessage() {} func (x *DeleteExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[123] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8241,12 +8365,12 @@ func (x *DeleteExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteExecutionResponse.ProtoReflect.Descriptor instead. func (*DeleteExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{123} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{125} } type GetDLQTasksRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - DlqKey *v119.HistoryDLQKey `protobuf:"bytes,1,opt,name=dlq_key,json=dlqKey,proto3" json:"dlq_key,omitempty"` + DlqKey *v120.HistoryDLQKey `protobuf:"bytes,1,opt,name=dlq_key,json=dlqKey,proto3" json:"dlq_key,omitempty"` // page_size must be positive. Up to this many tasks will be returned. PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` NextPageToken []byte `protobuf:"bytes,3,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` @@ -8256,7 +8380,7 @@ type GetDLQTasksRequest struct { func (x *GetDLQTasksRequest) Reset() { *x = GetDLQTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[124] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8268,7 +8392,7 @@ func (x *GetDLQTasksRequest) String() string { func (*GetDLQTasksRequest) ProtoMessage() {} func (x *GetDLQTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[124] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8281,10 +8405,10 @@ func (x *GetDLQTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDLQTasksRequest.ProtoReflect.Descriptor instead. func (*GetDLQTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{124} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{126} } -func (x *GetDLQTasksRequest) GetDlqKey() *v119.HistoryDLQKey { +func (x *GetDLQTasksRequest) GetDlqKey() *v120.HistoryDLQKey { if x != nil { return x.DlqKey } @@ -8307,7 +8431,7 @@ func (x *GetDLQTasksRequest) GetNextPageToken() []byte { type GetDLQTasksResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - DlqTasks []*v119.HistoryDLQTask `protobuf:"bytes,1,rep,name=dlq_tasks,json=dlqTasks,proto3" json:"dlq_tasks,omitempty"` + DlqTasks []*v120.HistoryDLQTask `protobuf:"bytes,1,rep,name=dlq_tasks,json=dlqTasks,proto3" json:"dlq_tasks,omitempty"` // next_page_token is empty if there are no more results. However, the converse is not true. If there are no more // results, this field may still be non-empty. This is to avoid having to do a count query to determine whether // there are more results. @@ -8318,7 +8442,7 @@ type GetDLQTasksResponse struct { func (x *GetDLQTasksResponse) Reset() { *x = GetDLQTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[125] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8330,7 +8454,7 @@ func (x *GetDLQTasksResponse) String() string { func (*GetDLQTasksResponse) ProtoMessage() {} func (x *GetDLQTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[125] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8343,10 +8467,10 @@ func (x *GetDLQTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDLQTasksResponse.ProtoReflect.Descriptor instead. func (*GetDLQTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{125} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{127} } -func (x *GetDLQTasksResponse) GetDlqTasks() []*v119.HistoryDLQTask { +func (x *GetDLQTasksResponse) GetDlqTasks() []*v120.HistoryDLQTask { if x != nil { return x.DlqTasks } @@ -8362,15 +8486,15 @@ func (x *GetDLQTasksResponse) GetNextPageToken() []byte { type DeleteDLQTasksRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - DlqKey *v119.HistoryDLQKey `protobuf:"bytes,1,opt,name=dlq_key,json=dlqKey,proto3" json:"dlq_key,omitempty"` - InclusiveMaxTaskMetadata *v119.HistoryDLQTaskMetadata `protobuf:"bytes,2,opt,name=inclusive_max_task_metadata,json=inclusiveMaxTaskMetadata,proto3" json:"inclusive_max_task_metadata,omitempty"` + DlqKey *v120.HistoryDLQKey `protobuf:"bytes,1,opt,name=dlq_key,json=dlqKey,proto3" json:"dlq_key,omitempty"` + InclusiveMaxTaskMetadata *v120.HistoryDLQTaskMetadata `protobuf:"bytes,2,opt,name=inclusive_max_task_metadata,json=inclusiveMaxTaskMetadata,proto3" json:"inclusive_max_task_metadata,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *DeleteDLQTasksRequest) Reset() { *x = DeleteDLQTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[126] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8382,7 +8506,7 @@ func (x *DeleteDLQTasksRequest) String() string { func (*DeleteDLQTasksRequest) ProtoMessage() {} func (x *DeleteDLQTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[126] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8395,17 +8519,17 @@ func (x *DeleteDLQTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteDLQTasksRequest.ProtoReflect.Descriptor instead. func (*DeleteDLQTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{126} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{128} } -func (x *DeleteDLQTasksRequest) GetDlqKey() *v119.HistoryDLQKey { +func (x *DeleteDLQTasksRequest) GetDlqKey() *v120.HistoryDLQKey { if x != nil { return x.DlqKey } return nil } -func (x *DeleteDLQTasksRequest) GetInclusiveMaxTaskMetadata() *v119.HistoryDLQTaskMetadata { +func (x *DeleteDLQTasksRequest) GetInclusiveMaxTaskMetadata() *v120.HistoryDLQTaskMetadata { if x != nil { return x.InclusiveMaxTaskMetadata } @@ -8422,7 +8546,7 @@ type DeleteDLQTasksResponse struct { func (x *DeleteDLQTasksResponse) Reset() { *x = DeleteDLQTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[127] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8434,7 +8558,7 @@ func (x *DeleteDLQTasksResponse) String() string { func (*DeleteDLQTasksResponse) ProtoMessage() {} func (x *DeleteDLQTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[127] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8447,7 +8571,7 @@ func (x *DeleteDLQTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteDLQTasksResponse.ProtoReflect.Descriptor instead. func (*DeleteDLQTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{127} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{129} } func (x *DeleteDLQTasksResponse) GetMessagesDeleted() int64 { @@ -8468,7 +8592,7 @@ type ListQueuesRequest struct { func (x *ListQueuesRequest) Reset() { *x = ListQueuesRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[128] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8480,7 +8604,7 @@ func (x *ListQueuesRequest) String() string { func (*ListQueuesRequest) ProtoMessage() {} func (x *ListQueuesRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[128] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8493,7 +8617,7 @@ func (x *ListQueuesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListQueuesRequest.ProtoReflect.Descriptor instead. func (*ListQueuesRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{128} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{130} } func (x *ListQueuesRequest) GetQueueType() int32 { @@ -8527,7 +8651,7 @@ type ListQueuesResponse struct { func (x *ListQueuesResponse) Reset() { *x = ListQueuesResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[129] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8539,7 +8663,7 @@ func (x *ListQueuesResponse) String() string { func (*ListQueuesResponse) ProtoMessage() {} func (x *ListQueuesResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[129] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8552,7 +8676,7 @@ func (x *ListQueuesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListQueuesResponse.ProtoReflect.Descriptor instead. func (*ListQueuesResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{129} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{131} } func (x *ListQueuesResponse) GetQueues() []*ListQueuesResponse_QueueInfo { @@ -8583,7 +8707,7 @@ type AddTasksRequest struct { func (x *AddTasksRequest) Reset() { *x = AddTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[130] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8595,7 +8719,7 @@ func (x *AddTasksRequest) String() string { func (*AddTasksRequest) ProtoMessage() {} func (x *AddTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[130] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8608,7 +8732,7 @@ func (x *AddTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTasksRequest.ProtoReflect.Descriptor instead. func (*AddTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{130} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{132} } func (x *AddTasksRequest) GetShardId() int32 { @@ -8633,7 +8757,7 @@ type AddTasksResponse struct { func (x *AddTasksResponse) Reset() { *x = AddTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[131] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8645,7 +8769,7 @@ func (x *AddTasksResponse) String() string { func (*AddTasksResponse) ProtoMessage() {} func (x *AddTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[131] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8658,19 +8782,19 @@ func (x *AddTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTasksResponse.ProtoReflect.Descriptor instead. func (*AddTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{131} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{133} } type ListTasksRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Request *v118.ListHistoryTasksRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` + Request *v119.ListHistoryTasksRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ListTasksRequest) Reset() { *x = ListTasksRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[132] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8682,7 +8806,7 @@ func (x *ListTasksRequest) String() string { func (*ListTasksRequest) ProtoMessage() {} func (x *ListTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[132] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8695,10 +8819,10 @@ func (x *ListTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTasksRequest.ProtoReflect.Descriptor instead. func (*ListTasksRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{132} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{134} } -func (x *ListTasksRequest) GetRequest() *v118.ListHistoryTasksRequest { +func (x *ListTasksRequest) GetRequest() *v119.ListHistoryTasksRequest { if x != nil { return x.Request } @@ -8707,14 +8831,14 @@ func (x *ListTasksRequest) GetRequest() *v118.ListHistoryTasksRequest { type ListTasksResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v118.ListHistoryTasksResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v119.ListHistoryTasksResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ListTasksResponse) Reset() { *x = ListTasksResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[133] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8726,7 +8850,7 @@ func (x *ListTasksResponse) String() string { func (*ListTasksResponse) ProtoMessage() {} func (x *ListTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[133] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8739,10 +8863,10 @@ func (x *ListTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTasksResponse.ProtoReflect.Descriptor instead. func (*ListTasksResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{133} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{135} } -func (x *ListTasksResponse) GetResponse() *v118.ListHistoryTasksResponse { +func (x *ListTasksResponse) GetResponse() *v119.ListHistoryTasksResponse { if x != nil { return x.Response } @@ -8752,7 +8876,7 @@ func (x *ListTasksResponse) GetResponse() *v118.ListHistoryTasksResponse { type CompleteNexusOperationChasmRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Completion token - holds information for locating an entity and the corresponding component. - Completion *v120.NexusOperationCompletion `protobuf:"bytes,1,opt,name=completion,proto3" json:"completion,omitempty"` + Completion *v121.NexusOperationCompletion `protobuf:"bytes,1,opt,name=completion,proto3" json:"completion,omitempty"` // Types that are valid to be assigned to Outcome: // // *CompleteNexusOperationChasmRequest_Success @@ -8773,7 +8897,7 @@ type CompleteNexusOperationChasmRequest struct { func (x *CompleteNexusOperationChasmRequest) Reset() { *x = CompleteNexusOperationChasmRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8785,7 +8909,7 @@ func (x *CompleteNexusOperationChasmRequest) String() string { func (*CompleteNexusOperationChasmRequest) ProtoMessage() {} func (x *CompleteNexusOperationChasmRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8798,10 +8922,10 @@ func (x *CompleteNexusOperationChasmRequest) ProtoReflect() protoreflect.Message // Deprecated: Use CompleteNexusOperationChasmRequest.ProtoReflect.Descriptor instead. func (*CompleteNexusOperationChasmRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{134} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{136} } -func (x *CompleteNexusOperationChasmRequest) GetCompletion() *v120.NexusOperationCompletion { +func (x *CompleteNexusOperationChasmRequest) GetCompletion() *v121.NexusOperationCompletion { if x != nil { return x.Completion } @@ -8887,7 +9011,7 @@ type CompleteNexusOperationChasmResponse struct { func (x *CompleteNexusOperationChasmResponse) Reset() { *x = CompleteNexusOperationChasmResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[135] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8899,7 +9023,7 @@ func (x *CompleteNexusOperationChasmResponse) String() string { func (*CompleteNexusOperationChasmResponse) ProtoMessage() {} func (x *CompleteNexusOperationChasmResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[135] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8912,13 +9036,13 @@ func (x *CompleteNexusOperationChasmResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use CompleteNexusOperationChasmResponse.ProtoReflect.Descriptor instead. func (*CompleteNexusOperationChasmResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{135} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{137} } type CompleteNexusOperationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Completion token - holds information for locating a run and the corresponding operation state machine. - Completion *v120.NexusOperationCompletion `protobuf:"bytes,1,opt,name=completion,proto3" json:"completion,omitempty"` + Completion *v121.NexusOperationCompletion `protobuf:"bytes,1,opt,name=completion,proto3" json:"completion,omitempty"` // Operation state - may only be successful / failed / canceled. State string `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` // Types that are valid to be assigned to Outcome: @@ -8938,7 +9062,7 @@ type CompleteNexusOperationRequest struct { func (x *CompleteNexusOperationRequest) Reset() { *x = CompleteNexusOperationRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8950,7 +9074,7 @@ func (x *CompleteNexusOperationRequest) String() string { func (*CompleteNexusOperationRequest) ProtoMessage() {} func (x *CompleteNexusOperationRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8963,10 +9087,10 @@ func (x *CompleteNexusOperationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteNexusOperationRequest.ProtoReflect.Descriptor instead. func (*CompleteNexusOperationRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{136} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{138} } -func (x *CompleteNexusOperationRequest) GetCompletion() *v120.NexusOperationCompletion { +func (x *CompleteNexusOperationRequest) GetCompletion() *v121.NexusOperationCompletion { if x != nil { return x.Completion } @@ -8996,7 +9120,7 @@ func (x *CompleteNexusOperationRequest) GetSuccess() *v14.Payload { return nil } -func (x *CompleteNexusOperationRequest) GetFailure() *v121.Failure { +func (x *CompleteNexusOperationRequest) GetFailure() *v122.Failure { if x != nil { if x, ok := x.Outcome.(*CompleteNexusOperationRequest_Failure); ok { return x.Failure @@ -9037,7 +9161,7 @@ type CompleteNexusOperationRequest_Success struct { type CompleteNexusOperationRequest_Failure struct { // Operation failure, only set if state != successful. - Failure *v121.Failure `protobuf:"bytes,4,opt,name=failure,proto3,oneof"` + Failure *v122.Failure `protobuf:"bytes,4,opt,name=failure,proto3,oneof"` } func (*CompleteNexusOperationRequest_Success) isCompleteNexusOperationRequest_Outcome() {} @@ -9052,7 +9176,7 @@ type CompleteNexusOperationResponse struct { func (x *CompleteNexusOperationResponse) Reset() { *x = CompleteNexusOperationResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[137] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9064,7 +9188,7 @@ func (x *CompleteNexusOperationResponse) String() string { func (*CompleteNexusOperationResponse) ProtoMessage() {} func (x *CompleteNexusOperationResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[137] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9077,7 +9201,7 @@ func (x *CompleteNexusOperationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteNexusOperationResponse.ProtoReflect.Descriptor instead. func (*CompleteNexusOperationResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{137} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{139} } type InvokeStateMachineMethodRequest struct { @@ -9092,7 +9216,7 @@ type InvokeStateMachineMethodRequest struct { RunId string `protobuf:"bytes,3,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` // Reference including the path to the backing Operation state machine and a version + transition count for // staleness checks. - Ref *v110.StateMachineRef `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"` + Ref *v111.StateMachineRef `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"` // The method name to invoke. Methods must be explicitly registered for the target state machine in the state // machine registry, and accept an argument type of HistoryEvent that is the completion event of the completed // workflow. @@ -9105,7 +9229,7 @@ type InvokeStateMachineMethodRequest struct { func (x *InvokeStateMachineMethodRequest) Reset() { *x = InvokeStateMachineMethodRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9117,7 +9241,7 @@ func (x *InvokeStateMachineMethodRequest) String() string { func (*InvokeStateMachineMethodRequest) ProtoMessage() {} func (x *InvokeStateMachineMethodRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9130,7 +9254,7 @@ func (x *InvokeStateMachineMethodRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeStateMachineMethodRequest.ProtoReflect.Descriptor instead. func (*InvokeStateMachineMethodRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{138} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{140} } func (x *InvokeStateMachineMethodRequest) GetNamespaceId() string { @@ -9154,7 +9278,7 @@ func (x *InvokeStateMachineMethodRequest) GetRunId() string { return "" } -func (x *InvokeStateMachineMethodRequest) GetRef() *v110.StateMachineRef { +func (x *InvokeStateMachineMethodRequest) GetRef() *v111.StateMachineRef { if x != nil { return x.Ref } @@ -9185,7 +9309,7 @@ type InvokeStateMachineMethodResponse struct { func (x *InvokeStateMachineMethodResponse) Reset() { *x = InvokeStateMachineMethodResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[139] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9197,7 +9321,7 @@ func (x *InvokeStateMachineMethodResponse) String() string { func (*InvokeStateMachineMethodResponse) ProtoMessage() {} func (x *InvokeStateMachineMethodResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[139] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9210,7 +9334,7 @@ func (x *InvokeStateMachineMethodResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeStateMachineMethodResponse.ProtoReflect.Descriptor instead. func (*InvokeStateMachineMethodResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{139} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{141} } func (x *InvokeStateMachineMethodResponse) GetOutput() []byte { @@ -9229,7 +9353,7 @@ type DeepHealthCheckRequest struct { func (x *DeepHealthCheckRequest) Reset() { *x = DeepHealthCheckRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[140] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9241,7 +9365,7 @@ func (x *DeepHealthCheckRequest) String() string { func (*DeepHealthCheckRequest) ProtoMessage() {} func (x *DeepHealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[140] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9254,7 +9378,7 @@ func (x *DeepHealthCheckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeepHealthCheckRequest.ProtoReflect.Descriptor instead. func (*DeepHealthCheckRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{140} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{142} } func (x *DeepHealthCheckRequest) GetHostAddress() string { @@ -9266,16 +9390,16 @@ func (x *DeepHealthCheckRequest) GetHostAddress() string { type DeepHealthCheckResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - State v112.HealthState `protobuf:"varint,1,opt,name=state,proto3,enum=temporal.server.api.enums.v1.HealthState" json:"state,omitempty"` + State v113.HealthState `protobuf:"varint,1,opt,name=state,proto3,enum=temporal.server.api.enums.v1.HealthState" json:"state,omitempty"` // Per-check diagnostic results. Populated for all checks regardless of state. - Checks []*v122.HealthCheck `protobuf:"bytes,2,rep,name=checks,proto3" json:"checks,omitempty"` + Checks []*v123.HealthCheck `protobuf:"bytes,2,rep,name=checks,proto3" json:"checks,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *DeepHealthCheckResponse) Reset() { *x = DeepHealthCheckResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[141] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9287,7 +9411,7 @@ func (x *DeepHealthCheckResponse) String() string { func (*DeepHealthCheckResponse) ProtoMessage() {} func (x *DeepHealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[141] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9300,17 +9424,17 @@ func (x *DeepHealthCheckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeepHealthCheckResponse.ProtoReflect.Descriptor instead. func (*DeepHealthCheckResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{141} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{143} } -func (x *DeepHealthCheckResponse) GetState() v112.HealthState { +func (x *DeepHealthCheckResponse) GetState() v113.HealthState { if x != nil { return x.State } - return v112.HealthState(0) + return v113.HealthState(0) } -func (x *DeepHealthCheckResponse) GetChecks() []*v122.HealthCheck { +func (x *DeepHealthCheckResponse) GetChecks() []*v123.HealthCheck { if x != nil { return x.Checks } @@ -9321,8 +9445,8 @@ type SyncWorkflowStateRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` Execution *v14.WorkflowExecution `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` - VersionedTransition *v110.VersionedTransition `protobuf:"bytes,3,opt,name=versioned_transition,json=versionedTransition,proto3" json:"versioned_transition,omitempty"` - VersionHistories *v19.VersionHistories `protobuf:"bytes,4,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` + VersionedTransition *v111.VersionedTransition `protobuf:"bytes,3,opt,name=versioned_transition,json=versionedTransition,proto3" json:"versioned_transition,omitempty"` + VersionHistories *v110.VersionHistories `protobuf:"bytes,4,opt,name=version_histories,json=versionHistories,proto3" json:"version_histories,omitempty"` TargetClusterId int32 `protobuf:"varint,5,opt,name=target_cluster_id,json=targetClusterId,proto3" json:"target_cluster_id,omitempty"` // (-- api-linter: core::0141::forbidden-types=disabled --) ArchetypeId uint32 `protobuf:"varint,6,opt,name=archetype_id,json=archetypeId,proto3" json:"archetype_id,omitempty"` @@ -9332,7 +9456,7 @@ type SyncWorkflowStateRequest struct { func (x *SyncWorkflowStateRequest) Reset() { *x = SyncWorkflowStateRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[142] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9344,7 +9468,7 @@ func (x *SyncWorkflowStateRequest) String() string { func (*SyncWorkflowStateRequest) ProtoMessage() {} func (x *SyncWorkflowStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[142] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9357,7 +9481,7 @@ func (x *SyncWorkflowStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncWorkflowStateRequest.ProtoReflect.Descriptor instead. func (*SyncWorkflowStateRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{142} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{144} } func (x *SyncWorkflowStateRequest) GetNamespaceId() string { @@ -9374,14 +9498,14 @@ func (x *SyncWorkflowStateRequest) GetExecution() *v14.WorkflowExecution { return nil } -func (x *SyncWorkflowStateRequest) GetVersionedTransition() *v110.VersionedTransition { +func (x *SyncWorkflowStateRequest) GetVersionedTransition() *v111.VersionedTransition { if x != nil { return x.VersionedTransition } return nil } -func (x *SyncWorkflowStateRequest) GetVersionHistories() *v19.VersionHistories { +func (x *SyncWorkflowStateRequest) GetVersionHistories() *v110.VersionHistories { if x != nil { return x.VersionHistories } @@ -9404,14 +9528,14 @@ func (x *SyncWorkflowStateRequest) GetArchetypeId() uint32 { type SyncWorkflowStateResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - VersionedTransitionArtifact *v117.VersionedTransitionArtifact `protobuf:"bytes,5,opt,name=versioned_transition_artifact,json=versionedTransitionArtifact,proto3" json:"versioned_transition_artifact,omitempty"` + VersionedTransitionArtifact *v118.VersionedTransitionArtifact `protobuf:"bytes,5,opt,name=versioned_transition_artifact,json=versionedTransitionArtifact,proto3" json:"versioned_transition_artifact,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *SyncWorkflowStateResponse) Reset() { *x = SyncWorkflowStateResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[143] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9423,7 +9547,7 @@ func (x *SyncWorkflowStateResponse) String() string { func (*SyncWorkflowStateResponse) ProtoMessage() {} func (x *SyncWorkflowStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[143] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9436,10 +9560,10 @@ func (x *SyncWorkflowStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncWorkflowStateResponse.ProtoReflect.Descriptor instead. func (*SyncWorkflowStateResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{143} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{145} } -func (x *SyncWorkflowStateResponse) GetVersionedTransitionArtifact() *v117.VersionedTransitionArtifact { +func (x *SyncWorkflowStateResponse) GetVersionedTransitionArtifact() *v118.VersionedTransitionArtifact { if x != nil { return x.VersionedTransitionArtifact } @@ -9459,7 +9583,7 @@ type UpdateActivityOptionsRequest struct { func (x *UpdateActivityOptionsRequest) Reset() { *x = UpdateActivityOptionsRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[144] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9471,7 +9595,7 @@ func (x *UpdateActivityOptionsRequest) String() string { func (*UpdateActivityOptionsRequest) ProtoMessage() {} func (x *UpdateActivityOptionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[144] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9484,7 +9608,7 @@ func (x *UpdateActivityOptionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateActivityOptionsRequest.ProtoReflect.Descriptor instead. func (*UpdateActivityOptionsRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{144} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{146} } func (x *UpdateActivityOptionsRequest) GetNamespaceId() string { @@ -9504,14 +9628,14 @@ func (x *UpdateActivityOptionsRequest) GetUpdateRequest() *v1.UpdateActivityOpti type UpdateActivityOptionsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Activity options after an update - ActivityOptions *v123.ActivityOptions `protobuf:"bytes,1,opt,name=activity_options,json=activityOptions,proto3" json:"activity_options,omitempty"` + ActivityOptions *v124.ActivityOptions `protobuf:"bytes,1,opt,name=activity_options,json=activityOptions,proto3" json:"activity_options,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *UpdateActivityOptionsResponse) Reset() { *x = UpdateActivityOptionsResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[145] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9523,7 +9647,7 @@ func (x *UpdateActivityOptionsResponse) String() string { func (*UpdateActivityOptionsResponse) ProtoMessage() {} func (x *UpdateActivityOptionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[145] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9536,10 +9660,10 @@ func (x *UpdateActivityOptionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateActivityOptionsResponse.ProtoReflect.Descriptor instead. func (*UpdateActivityOptionsResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{145} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{147} } -func (x *UpdateActivityOptionsResponse) GetActivityOptions() *v123.ActivityOptions { +func (x *UpdateActivityOptionsResponse) GetActivityOptions() *v124.ActivityOptions { if x != nil { return x.ActivityOptions } @@ -9557,7 +9681,7 @@ type PauseActivityRequest struct { func (x *PauseActivityRequest) Reset() { *x = PauseActivityRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[146] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9569,7 +9693,7 @@ func (x *PauseActivityRequest) String() string { func (*PauseActivityRequest) ProtoMessage() {} func (x *PauseActivityRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[146] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9582,7 +9706,7 @@ func (x *PauseActivityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseActivityRequest.ProtoReflect.Descriptor instead. func (*PauseActivityRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{146} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{148} } func (x *PauseActivityRequest) GetNamespaceId() string { @@ -9607,7 +9731,7 @@ type PauseActivityResponse struct { func (x *PauseActivityResponse) Reset() { *x = PauseActivityResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[147] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9619,7 +9743,7 @@ func (x *PauseActivityResponse) String() string { func (*PauseActivityResponse) ProtoMessage() {} func (x *PauseActivityResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[147] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9632,7 +9756,7 @@ func (x *PauseActivityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseActivityResponse.ProtoReflect.Descriptor instead. func (*PauseActivityResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{147} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{149} } type UnpauseActivityRequest struct { @@ -9646,7 +9770,7 @@ type UnpauseActivityRequest struct { func (x *UnpauseActivityRequest) Reset() { *x = UnpauseActivityRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[148] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9658,7 +9782,7 @@ func (x *UnpauseActivityRequest) String() string { func (*UnpauseActivityRequest) ProtoMessage() {} func (x *UnpauseActivityRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[148] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9671,7 +9795,7 @@ func (x *UnpauseActivityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnpauseActivityRequest.ProtoReflect.Descriptor instead. func (*UnpauseActivityRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{148} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{150} } func (x *UnpauseActivityRequest) GetNamespaceId() string { @@ -9696,7 +9820,7 @@ type UnpauseActivityResponse struct { func (x *UnpauseActivityResponse) Reset() { *x = UnpauseActivityResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[149] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9708,7 +9832,7 @@ func (x *UnpauseActivityResponse) String() string { func (*UnpauseActivityResponse) ProtoMessage() {} func (x *UnpauseActivityResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[149] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9721,7 +9845,7 @@ func (x *UnpauseActivityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnpauseActivityResponse.ProtoReflect.Descriptor instead. func (*UnpauseActivityResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{149} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{151} } type ResetActivityRequest struct { @@ -9735,7 +9859,7 @@ type ResetActivityRequest struct { func (x *ResetActivityRequest) Reset() { *x = ResetActivityRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[150] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9747,7 +9871,7 @@ func (x *ResetActivityRequest) String() string { func (*ResetActivityRequest) ProtoMessage() {} func (x *ResetActivityRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[150] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9760,7 +9884,7 @@ func (x *ResetActivityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetActivityRequest.ProtoReflect.Descriptor instead. func (*ResetActivityRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{150} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{152} } func (x *ResetActivityRequest) GetNamespaceId() string { @@ -9785,7 +9909,7 @@ type ResetActivityResponse struct { func (x *ResetActivityResponse) Reset() { *x = ResetActivityResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[151] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9797,7 +9921,7 @@ func (x *ResetActivityResponse) String() string { func (*ResetActivityResponse) ProtoMessage() {} func (x *ResetActivityResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[151] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9810,7 +9934,7 @@ func (x *ResetActivityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetActivityResponse.ProtoReflect.Descriptor instead. func (*ResetActivityResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{151} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{153} } // (-- api-linter: core::0134::request-mask-required=disabled @@ -9825,7 +9949,7 @@ type UpdateWorkflowExecutionOptionsRequest struct { func (x *UpdateWorkflowExecutionOptionsRequest) Reset() { *x = UpdateWorkflowExecutionOptionsRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[152] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9837,7 +9961,7 @@ func (x *UpdateWorkflowExecutionOptionsRequest) String() string { func (*UpdateWorkflowExecutionOptionsRequest) ProtoMessage() {} func (x *UpdateWorkflowExecutionOptionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[152] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9850,7 +9974,7 @@ func (x *UpdateWorkflowExecutionOptionsRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use UpdateWorkflowExecutionOptionsRequest.ProtoReflect.Descriptor instead. func (*UpdateWorkflowExecutionOptionsRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{152} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{154} } func (x *UpdateWorkflowExecutionOptionsRequest) GetNamespaceId() string { @@ -9880,7 +10004,7 @@ type UpdateWorkflowExecutionOptionsResponse struct { func (x *UpdateWorkflowExecutionOptionsResponse) Reset() { *x = UpdateWorkflowExecutionOptionsResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[153] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9892,7 +10016,7 @@ func (x *UpdateWorkflowExecutionOptionsResponse) String() string { func (*UpdateWorkflowExecutionOptionsResponse) ProtoMessage() {} func (x *UpdateWorkflowExecutionOptionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[153] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9905,7 +10029,7 @@ func (x *UpdateWorkflowExecutionOptionsResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use UpdateWorkflowExecutionOptionsResponse.ProtoReflect.Descriptor instead. func (*UpdateWorkflowExecutionOptionsResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{153} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{155} } func (x *UpdateWorkflowExecutionOptionsResponse) GetWorkflowExecutionOptions() *v15.WorkflowExecutionOptions { @@ -9933,7 +10057,7 @@ type PauseWorkflowExecutionRequest struct { func (x *PauseWorkflowExecutionRequest) Reset() { *x = PauseWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[154] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9945,7 +10069,7 @@ func (x *PauseWorkflowExecutionRequest) String() string { func (*PauseWorkflowExecutionRequest) ProtoMessage() {} func (x *PauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[154] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9958,7 +10082,7 @@ func (x *PauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*PauseWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{154} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{156} } func (x *PauseWorkflowExecutionRequest) GetNamespaceId() string { @@ -9983,7 +10107,7 @@ type PauseWorkflowExecutionResponse struct { func (x *PauseWorkflowExecutionResponse) Reset() { *x = PauseWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[155] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9995,7 +10119,7 @@ func (x *PauseWorkflowExecutionResponse) String() string { func (*PauseWorkflowExecutionResponse) ProtoMessage() {} func (x *PauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[155] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10008,7 +10132,7 @@ func (x *PauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*PauseWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{155} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{157} } type UnpauseWorkflowExecutionRequest struct { @@ -10022,7 +10146,7 @@ type UnpauseWorkflowExecutionRequest struct { func (x *UnpauseWorkflowExecutionRequest) Reset() { *x = UnpauseWorkflowExecutionRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[156] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10034,7 +10158,7 @@ func (x *UnpauseWorkflowExecutionRequest) String() string { func (*UnpauseWorkflowExecutionRequest) ProtoMessage() {} func (x *UnpauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[156] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10047,7 +10171,7 @@ func (x *UnpauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnpauseWorkflowExecutionRequest.ProtoReflect.Descriptor instead. func (*UnpauseWorkflowExecutionRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{156} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{158} } func (x *UnpauseWorkflowExecutionRequest) GetNamespaceId() string { @@ -10072,7 +10196,7 @@ type UnpauseWorkflowExecutionResponse struct { func (x *UnpauseWorkflowExecutionResponse) Reset() { *x = UnpauseWorkflowExecutionResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[157] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10084,7 +10208,7 @@ func (x *UnpauseWorkflowExecutionResponse) String() string { func (*UnpauseWorkflowExecutionResponse) ProtoMessage() {} func (x *UnpauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[157] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10097,21 +10221,21 @@ func (x *UnpauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnpauseWorkflowExecutionResponse.ProtoReflect.Descriptor instead. func (*UnpauseWorkflowExecutionResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{157} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{159} } type StartNexusOperationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` ShardId int32 `protobuf:"varint,2,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` - Request *v121.StartOperationRequest `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` + Request *v122.StartOperationRequest `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *StartNexusOperationRequest) Reset() { *x = StartNexusOperationRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[158] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10123,7 +10247,7 @@ func (x *StartNexusOperationRequest) String() string { func (*StartNexusOperationRequest) ProtoMessage() {} func (x *StartNexusOperationRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[158] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10136,7 +10260,7 @@ func (x *StartNexusOperationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartNexusOperationRequest.ProtoReflect.Descriptor instead. func (*StartNexusOperationRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{158} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{160} } func (x *StartNexusOperationRequest) GetNamespaceId() string { @@ -10153,7 +10277,7 @@ func (x *StartNexusOperationRequest) GetShardId() int32 { return 0 } -func (x *StartNexusOperationRequest) GetRequest() *v121.StartOperationRequest { +func (x *StartNexusOperationRequest) GetRequest() *v122.StartOperationRequest { if x != nil { return x.Request } @@ -10162,14 +10286,14 @@ func (x *StartNexusOperationRequest) GetRequest() *v121.StartOperationRequest { type StartNexusOperationResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v121.StartOperationResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v122.StartOperationResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *StartNexusOperationResponse) Reset() { *x = StartNexusOperationResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[159] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10181,7 +10305,7 @@ func (x *StartNexusOperationResponse) String() string { func (*StartNexusOperationResponse) ProtoMessage() {} func (x *StartNexusOperationResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[159] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10194,10 +10318,10 @@ func (x *StartNexusOperationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartNexusOperationResponse.ProtoReflect.Descriptor instead. func (*StartNexusOperationResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{159} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{161} } -func (x *StartNexusOperationResponse) GetResponse() *v121.StartOperationResponse { +func (x *StartNexusOperationResponse) GetResponse() *v122.StartOperationResponse { if x != nil { return x.Response } @@ -10208,14 +10332,14 @@ type CancelNexusOperationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` ShardId int32 `protobuf:"varint,2,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` - Request *v121.CancelOperationRequest `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` + Request *v122.CancelOperationRequest `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *CancelNexusOperationRequest) Reset() { *x = CancelNexusOperationRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[160] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10227,7 +10351,7 @@ func (x *CancelNexusOperationRequest) String() string { func (*CancelNexusOperationRequest) ProtoMessage() {} func (x *CancelNexusOperationRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[160] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10240,7 +10364,7 @@ func (x *CancelNexusOperationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CancelNexusOperationRequest.ProtoReflect.Descriptor instead. func (*CancelNexusOperationRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{160} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{162} } func (x *CancelNexusOperationRequest) GetNamespaceId() string { @@ -10257,7 +10381,7 @@ func (x *CancelNexusOperationRequest) GetShardId() int32 { return 0 } -func (x *CancelNexusOperationRequest) GetRequest() *v121.CancelOperationRequest { +func (x *CancelNexusOperationRequest) GetRequest() *v122.CancelOperationRequest { if x != nil { return x.Request } @@ -10266,14 +10390,14 @@ func (x *CancelNexusOperationRequest) GetRequest() *v121.CancelOperationRequest type CancelNexusOperationResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Response *v121.CancelOperationResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + Response *v122.CancelOperationResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *CancelNexusOperationResponse) Reset() { *x = CancelNexusOperationResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[161] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10285,7 +10409,7 @@ func (x *CancelNexusOperationResponse) String() string { func (*CancelNexusOperationResponse) ProtoMessage() {} func (x *CancelNexusOperationResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[161] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10298,10 +10422,10 @@ func (x *CancelNexusOperationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CancelNexusOperationResponse.ProtoReflect.Descriptor instead. func (*CancelNexusOperationResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{161} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{163} } -func (x *CancelNexusOperationResponse) GetResponse() *v121.CancelOperationResponse { +func (x *CancelNexusOperationResponse) GetResponse() *v122.CancelOperationResponse { if x != nil { return x.Response } @@ -10318,7 +10442,7 @@ type PollWorkflowExecutionTimeSkippingRequest struct { func (x *PollWorkflowExecutionTimeSkippingRequest) Reset() { *x = PollWorkflowExecutionTimeSkippingRequest{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10330,7 +10454,7 @@ func (x *PollWorkflowExecutionTimeSkippingRequest) String() string { func (*PollWorkflowExecutionTimeSkippingRequest) ProtoMessage() {} func (x *PollWorkflowExecutionTimeSkippingRequest) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10343,7 +10467,7 @@ func (x *PollWorkflowExecutionTimeSkippingRequest) ProtoReflect() protoreflect.M // Deprecated: Use PollWorkflowExecutionTimeSkippingRequest.ProtoReflect.Descriptor instead. func (*PollWorkflowExecutionTimeSkippingRequest) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{162} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{164} } func (x *PollWorkflowExecutionTimeSkippingRequest) GetNamespaceId() string { @@ -10369,7 +10493,7 @@ type PollWorkflowExecutionTimeSkippingResponse struct { func (x *PollWorkflowExecutionTimeSkippingResponse) Reset() { *x = PollWorkflowExecutionTimeSkippingResponse{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10381,7 +10505,7 @@ func (x *PollWorkflowExecutionTimeSkippingResponse) String() string { func (*PollWorkflowExecutionTimeSkippingResponse) ProtoMessage() {} func (x *PollWorkflowExecutionTimeSkippingResponse) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10394,7 +10518,7 @@ func (x *PollWorkflowExecutionTimeSkippingResponse) ProtoReflect() protoreflect. // Deprecated: Use PollWorkflowExecutionTimeSkippingResponse.ProtoReflect.Descriptor instead. func (*PollWorkflowExecutionTimeSkippingResponse) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{163} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{165} } func (x *PollWorkflowExecutionTimeSkippingResponse) GetResponse() *v1.PollWorkflowExecutionTimeSkippingResponse { @@ -10417,7 +10541,7 @@ type ExecuteMultiOperationRequest_Operation struct { func (x *ExecuteMultiOperationRequest_Operation) Reset() { *x = ExecuteMultiOperationRequest_Operation{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[164] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10429,7 +10553,7 @@ func (x *ExecuteMultiOperationRequest_Operation) String() string { func (*ExecuteMultiOperationRequest_Operation) ProtoMessage() {} func (x *ExecuteMultiOperationRequest_Operation) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[164] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10442,7 +10566,7 @@ func (x *ExecuteMultiOperationRequest_Operation) ProtoReflect() protoreflect.Mes // Deprecated: Use ExecuteMultiOperationRequest_Operation.ProtoReflect.Descriptor instead. func (*ExecuteMultiOperationRequest_Operation) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{9, 0} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{11, 0} } func (x *ExecuteMultiOperationRequest_Operation) GetOperation() isExecuteMultiOperationRequest_Operation_Operation { @@ -10501,7 +10625,7 @@ type ExecuteMultiOperationResponse_Response struct { func (x *ExecuteMultiOperationResponse_Response) Reset() { *x = ExecuteMultiOperationResponse_Response{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[165] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10513,7 +10637,7 @@ func (x *ExecuteMultiOperationResponse_Response) String() string { func (*ExecuteMultiOperationResponse_Response) ProtoMessage() {} func (x *ExecuteMultiOperationResponse_Response) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[165] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10526,7 +10650,7 @@ func (x *ExecuteMultiOperationResponse_Response) ProtoReflect() protoreflect.Mes // Deprecated: Use ExecuteMultiOperationResponse_Response.ProtoReflect.Descriptor instead. func (*ExecuteMultiOperationResponse_Response) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{10, 0} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{12, 0} } func (x *ExecuteMultiOperationResponse_Response) GetResponse() isExecuteMultiOperationResponse_Response_Response { @@ -10583,7 +10707,7 @@ type ListQueuesResponse_QueueInfo struct { func (x *ListQueuesResponse_QueueInfo) Reset() { *x = ListQueuesResponse_QueueInfo{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[171] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10595,7 +10719,7 @@ func (x *ListQueuesResponse_QueueInfo) String() string { func (*ListQueuesResponse_QueueInfo) ProtoMessage() {} func (x *ListQueuesResponse_QueueInfo) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[171] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10608,7 +10732,7 @@ func (x *ListQueuesResponse_QueueInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ListQueuesResponse_QueueInfo.ProtoReflect.Descriptor instead. func (*ListQueuesResponse_QueueInfo) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{129, 0} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{131, 0} } func (x *ListQueuesResponse_QueueInfo) GetQueueName() string { @@ -10646,7 +10770,7 @@ type AddTasksRequest_Task struct { func (x *AddTasksRequest_Task) Reset() { *x = AddTasksRequest_Task{} - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[172] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10658,7 +10782,7 @@ func (x *AddTasksRequest_Task) String() string { func (*AddTasksRequest_Task) ProtoMessage() {} func (x *AddTasksRequest_Task) ProtoReflect() protoreflect.Message { - mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[172] + mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10671,7 +10795,7 @@ func (x *AddTasksRequest_Task) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTasksRequest_Task.ProtoReflect.Descriptor instead. func (*AddTasksRequest_Task) Descriptor() ([]byte, []int) { - return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{130, 0} + return file_temporal_server_api_historyservice_v1_request_response_proto_rawDescGZIP(), []int{132, 0} } func (x *AddTasksRequest_Task) GetCategoryId() int32 { @@ -10709,7 +10833,7 @@ var File_temporal_server_api_historyservice_v1_request_response_proto protorefle const file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc = "" + "\n" + - " temporal.api.workflowservice.v1.StartWorkflowExecutionRequest - 174, // 1: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.parent_execution_info:type_name -> temporal.server.api.workflow.v1.ParentExecutionInfo - 175, // 2: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.workflow_execution_expiration_time:type_name -> google.protobuf.Timestamp - 176, // 3: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.continue_as_new_initiator:type_name -> temporal.api.enums.v1.ContinueAsNewInitiator - 177, // 4: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.continued_failure:type_name -> temporal.api.failure.v1.Failure - 178, // 5: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.last_completion_result:type_name -> temporal.api.common.v1.Payloads - 179, // 6: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.first_workflow_task_backoff:type_name -> google.protobuf.Duration - 180, // 7: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.source_version_stamp:type_name -> temporal.api.common.v1.WorkerVersionStamp - 181, // 8: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.root_execution_info:type_name -> temporal.server.api.workflow.v1.RootExecutionInfo - 182, // 9: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.versioning_override:type_name -> temporal.api.workflow.v1.VersioningOverride - 183, // 10: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.inherited_pinned_version:type_name -> temporal.api.deployment.v1.WorkerDeploymentVersion - 184, // 11: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.inherited_auto_upgrade_info:type_name -> temporal.api.deployment.v1.InheritedAutoUpgradeInfo - 185, // 12: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.declined_target_version_upgrade:type_name -> temporal.api.history.v1.DeclinedTargetVersionUpgrade - 186, // 13: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.time_skipping_state_propagation:type_name -> temporal.api.common.v1.TimeSkippingStatePropagation - 187, // 14: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 188, // 15: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.eager_workflow_task:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse - 189, // 16: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus - 190, // 17: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.link:type_name -> temporal.api.common.v1.Link - 191, // 18: temporal.server.api.historyservice.v1.GetMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 192, // 19: temporal.server.api.historyservice.v1.GetMutableStateRequest.version_history_item:type_name -> temporal.server.api.history.v1.VersionHistoryItem - 193, // 20: temporal.server.api.historyservice.v1.GetMutableStateRequest.versioned_transition:type_name -> temporal.server.api.persistence.v1.VersionedTransition - 191, // 21: temporal.server.api.historyservice.v1.GetMutableStateResponse.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 194, // 22: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 195, // 23: temporal.server.api.historyservice.v1.GetMutableStateResponse.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 195, // 24: temporal.server.api.historyservice.v1.GetMutableStateResponse.sticky_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 179, // 25: temporal.server.api.historyservice.v1.GetMutableStateResponse.sticky_task_queue_schedule_to_start_timeout:type_name -> google.protobuf.Duration - 196, // 26: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_state:type_name -> temporal.server.api.enums.v1.WorkflowExecutionState - 189, // 27: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus - 197, // 28: temporal.server.api.historyservice.v1.GetMutableStateResponse.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories - 180, // 29: temporal.server.api.historyservice.v1.GetMutableStateResponse.most_recent_worker_version_stamp:type_name -> temporal.api.common.v1.WorkerVersionStamp - 193, // 30: temporal.server.api.historyservice.v1.GetMutableStateResponse.transition_history:type_name -> temporal.server.api.persistence.v1.VersionedTransition - 198, // 31: temporal.server.api.historyservice.v1.GetMutableStateResponse.versioning_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionVersioningInfo - 199, // 32: temporal.server.api.historyservice.v1.GetMutableStateResponse.transient_or_speculative_tasks:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo - 191, // 33: temporal.server.api.historyservice.v1.PollMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 192, // 34: temporal.server.api.historyservice.v1.PollMutableStateRequest.version_history_item:type_name -> temporal.server.api.history.v1.VersionHistoryItem - 191, // 35: temporal.server.api.historyservice.v1.PollMutableStateResponse.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 194, // 36: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 195, // 37: temporal.server.api.historyservice.v1.PollMutableStateResponse.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 195, // 38: temporal.server.api.historyservice.v1.PollMutableStateResponse.sticky_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 179, // 39: temporal.server.api.historyservice.v1.PollMutableStateResponse.sticky_task_queue_schedule_to_start_timeout:type_name -> google.protobuf.Duration - 197, // 40: temporal.server.api.historyservice.v1.PollMutableStateResponse.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories - 196, // 41: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_state:type_name -> temporal.server.api.enums.v1.WorkflowExecutionState - 189, // 42: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus - 191, // 43: temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 164, // 44: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.operations:type_name -> temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation - 165, // 45: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.responses:type_name -> temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response - 191, // 46: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 200, // 47: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest - 187, // 48: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 201, // 49: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.build_id_redirect_info:type_name -> temporal.server.api.taskqueue.v1.BuildIdRedirectInfo - 202, // 50: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.scheduled_deployment:type_name -> temporal.api.deployment.v1.Deployment - 203, // 51: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 183, // 52: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.target_deployment_version:type_name -> temporal.api.deployment.v1.WorkerDeploymentVersion - 194, // 53: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 199, // 54: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo - 195, // 55: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 175, // 56: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 57: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.started_time:type_name -> google.protobuf.Timestamp - 166, // 58: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.queries:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.QueriesEntry - 187, // 59: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 204, // 60: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.messages:type_name -> temporal.api.protocol.v1.Message - 205, // 61: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.history:type_name -> temporal.api.history.v1.History - 205, // 62: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.raw_history:type_name -> temporal.api.history.v1.History - 194, // 63: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 199, // 64: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo - 195, // 65: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 175, // 66: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 67: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.started_time:type_name -> google.protobuf.Timestamp - 167, // 68: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.queries:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.QueriesEntry - 187, // 69: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 204, // 70: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.messages:type_name -> temporal.api.protocol.v1.Message - 205, // 71: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.history:type_name -> temporal.api.history.v1.History - 191, // 72: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 206, // 73: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest - 187, // 74: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 201, // 75: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.build_id_redirect_info:type_name -> temporal.server.api.taskqueue.v1.BuildIdRedirectInfo - 202, // 76: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.scheduled_deployment:type_name -> temporal.api.deployment.v1.Deployment - 203, // 77: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 207, // 78: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.scheduled_event:type_name -> temporal.api.history.v1.HistoryEvent - 175, // 79: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.started_time:type_name -> google.protobuf.Timestamp - 175, // 80: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp - 178, // 81: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads - 194, // 82: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 187, // 83: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 208, // 84: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.priority:type_name -> temporal.api.common.v1.Priority - 209, // 85: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy - 210, // 86: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest.complete_request:type_name -> temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest - 12, // 87: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.started_response:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse - 211, // 88: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.activity_tasks:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueResponse - 188, // 89: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.new_workflow_task:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse - 212, // 90: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest.failed_request:type_name -> temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest - 191, // 91: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 187, // 92: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 213, // 93: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest.heartbeat_request:type_name -> temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest - 214, // 94: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest.complete_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest - 215, // 95: temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest.failed_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest - 216, // 96: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest.cancel_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskCanceledRequest - 191, // 97: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 187, // 98: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 217, // 99: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest.signal_request:type_name -> temporal.api.workflowservice.v1.SignalWorkflowExecutionRequest - 191, // 100: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 190, // 101: temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse.link:type_name -> temporal.api.common.v1.Link - 218, // 102: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest.signal_with_start_request:type_name -> temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest - 190, // 103: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse.signal_link:type_name -> temporal.api.common.v1.Link - 191, // 104: temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 219, // 105: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest.terminate_request:type_name -> temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest - 191, // 106: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 191, // 107: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 220, // 108: temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest.reset_request:type_name -> temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest - 221, // 109: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest.cancel_request:type_name -> temporal.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest - 191, // 110: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 191, // 111: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 187, // 112: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.child_clock:type_name -> temporal.server.api.clock.v1.VectorClock - 187, // 113: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.parent_clock:type_name -> temporal.server.api.clock.v1.VectorClock - 191, // 114: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 187, // 115: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 191, // 116: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.parent_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 191, // 117: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.child_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 207, // 118: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.completion_event:type_name -> temporal.api.history.v1.HistoryEvent - 187, // 119: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 191, // 120: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.parent_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 191, // 121: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.child_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 187, // 122: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 222, // 123: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest - 223, // 124: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.execution_config:type_name -> temporal.api.workflow.v1.WorkflowExecutionConfig - 224, // 125: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.workflow_execution_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionInfo - 225, // 126: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_activities:type_name -> temporal.api.workflow.v1.PendingActivityInfo - 226, // 127: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_children:type_name -> temporal.api.workflow.v1.PendingChildExecutionInfo - 227, // 128: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_workflow_task:type_name -> temporal.api.workflow.v1.PendingWorkflowTaskInfo - 228, // 129: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.callbacks:type_name -> temporal.api.workflow.v1.CallbackInfo - 229, // 130: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_nexus_operations:type_name -> temporal.api.workflow.v1.PendingNexusOperationInfo - 230, // 131: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.workflow_extended_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionExtendedInfo - 191, // 132: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 192, // 133: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.version_history_items:type_name -> temporal.server.api.history.v1.VersionHistoryItem - 231, // 134: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.events:type_name -> temporal.api.common.v1.DataBlob - 231, // 135: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.new_run_events:type_name -> temporal.api.common.v1.DataBlob - 232, // 136: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.base_execution_info:type_name -> temporal.server.api.workflow.v1.BaseExecutionInfo - 233, // 137: temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest.workflow_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState - 175, // 138: temporal.server.api.historyservice.v1.SyncShardStatusRequest.status_time:type_name -> google.protobuf.Timestamp - 175, // 139: temporal.server.api.historyservice.v1.SyncActivityRequest.scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 140: temporal.server.api.historyservice.v1.SyncActivityRequest.started_time:type_name -> google.protobuf.Timestamp - 175, // 141: temporal.server.api.historyservice.v1.SyncActivityRequest.last_heartbeat_time:type_name -> google.protobuf.Timestamp - 178, // 142: temporal.server.api.historyservice.v1.SyncActivityRequest.details:type_name -> temporal.api.common.v1.Payloads - 177, // 143: temporal.server.api.historyservice.v1.SyncActivityRequest.last_failure:type_name -> temporal.api.failure.v1.Failure - 234, // 144: temporal.server.api.historyservice.v1.SyncActivityRequest.version_history:type_name -> temporal.server.api.history.v1.VersionHistory - 232, // 145: temporal.server.api.historyservice.v1.SyncActivityRequest.base_execution_info:type_name -> temporal.server.api.workflow.v1.BaseExecutionInfo - 175, // 146: temporal.server.api.historyservice.v1.SyncActivityRequest.first_scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 147: temporal.server.api.historyservice.v1.SyncActivityRequest.last_attempt_complete_time:type_name -> google.protobuf.Timestamp - 179, // 148: temporal.server.api.historyservice.v1.SyncActivityRequest.retry_initial_interval:type_name -> google.protobuf.Duration - 179, // 149: temporal.server.api.historyservice.v1.SyncActivityRequest.retry_maximum_interval:type_name -> google.protobuf.Duration - 64, // 150: temporal.server.api.historyservice.v1.SyncActivitiesRequest.activities_info:type_name -> temporal.server.api.historyservice.v1.ActivitySyncInfo - 175, // 151: temporal.server.api.historyservice.v1.ActivitySyncInfo.scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 152: temporal.server.api.historyservice.v1.ActivitySyncInfo.started_time:type_name -> google.protobuf.Timestamp - 175, // 153: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_heartbeat_time:type_name -> google.protobuf.Timestamp - 178, // 154: temporal.server.api.historyservice.v1.ActivitySyncInfo.details:type_name -> temporal.api.common.v1.Payloads - 177, // 155: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_failure:type_name -> temporal.api.failure.v1.Failure - 234, // 156: temporal.server.api.historyservice.v1.ActivitySyncInfo.version_history:type_name -> temporal.server.api.history.v1.VersionHistory - 175, // 157: temporal.server.api.historyservice.v1.ActivitySyncInfo.first_scheduled_time:type_name -> google.protobuf.Timestamp - 175, // 158: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_attempt_complete_time:type_name -> google.protobuf.Timestamp - 179, // 159: temporal.server.api.historyservice.v1.ActivitySyncInfo.retry_initial_interval:type_name -> google.protobuf.Duration - 179, // 160: temporal.server.api.historyservice.v1.ActivitySyncInfo.retry_maximum_interval:type_name -> google.protobuf.Duration - 191, // 161: temporal.server.api.historyservice.v1.DescribeMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 233, // 162: temporal.server.api.historyservice.v1.DescribeMutableStateResponse.cache_mutable_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState - 233, // 163: temporal.server.api.historyservice.v1.DescribeMutableStateResponse.database_mutable_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState - 191, // 164: temporal.server.api.historyservice.v1.DescribeHistoryHostRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 235, // 165: temporal.server.api.historyservice.v1.DescribeHistoryHostResponse.namespace_cache:type_name -> temporal.server.api.namespace.v1.NamespaceCacheInfo - 236, // 166: temporal.server.api.historyservice.v1.GetShardResponse.shard_info:type_name -> temporal.server.api.persistence.v1.ShardInfo - 175, // 167: temporal.server.api.historyservice.v1.RemoveTaskRequest.visibility_time:type_name -> google.protobuf.Timestamp - 237, // 168: temporal.server.api.historyservice.v1.GetReplicationMessagesRequest.tokens:type_name -> temporal.server.api.replication.v1.ReplicationToken - 168, // 169: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.shard_messages:type_name -> temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.ShardMessagesEntry - 238, // 170: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest.task_infos:type_name -> temporal.server.api.replication.v1.ReplicationTaskInfo - 239, // 171: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse.replication_tasks:type_name -> temporal.server.api.replication.v1.ReplicationTask - 240, // 172: temporal.server.api.historyservice.v1.QueryWorkflowRequest.request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest - 241, // 173: temporal.server.api.historyservice.v1.QueryWorkflowResponse.response:type_name -> temporal.api.workflowservice.v1.QueryWorkflowResponse - 242, // 174: temporal.server.api.historyservice.v1.ReapplyEventsRequest.request:type_name -> temporal.server.api.adminservice.v1.ReapplyEventsRequest - 243, // 175: temporal.server.api.historyservice.v1.GetDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType - 243, // 176: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType - 239, // 177: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.replication_tasks:type_name -> temporal.server.api.replication.v1.ReplicationTask - 238, // 178: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.replication_tasks_info:type_name -> temporal.server.api.replication.v1.ReplicationTaskInfo - 243, // 179: temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType - 243, // 180: temporal.server.api.historyservice.v1.MergeDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType - 244, // 181: temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest.request:type_name -> temporal.server.api.adminservice.v1.RefreshWorkflowTasksRequest - 191, // 182: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 96, // 183: temporal.server.api.historyservice.v1.GetReplicationStatusResponse.shards:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus - 175, // 184: temporal.server.api.historyservice.v1.ShardReplicationStatus.shard_local_time:type_name -> google.protobuf.Timestamp - 169, // 185: temporal.server.api.historyservice.v1.ShardReplicationStatus.remote_clusters:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus.RemoteClustersEntry - 170, // 186: temporal.server.api.historyservice.v1.ShardReplicationStatus.handover_namespaces:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus.HandoverNamespacesEntry - 175, // 187: temporal.server.api.historyservice.v1.ShardReplicationStatus.max_replication_task_visibility_time:type_name -> google.protobuf.Timestamp - 175, // 188: temporal.server.api.historyservice.v1.ShardReplicationStatusPerCluster.acked_task_visibility_time:type_name -> google.protobuf.Timestamp - 191, // 189: temporal.server.api.historyservice.v1.RebuildMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 191, // 190: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 231, // 191: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.history_batches:type_name -> temporal.api.common.v1.DataBlob - 234, // 192: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.version_history:type_name -> temporal.server.api.history.v1.VersionHistory - 191, // 193: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 175, // 194: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.workflow_start_time:type_name -> google.protobuf.Timestamp - 175, // 195: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.workflow_close_time:type_name -> google.protobuf.Timestamp - 245, // 196: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequest - 246, // 197: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse - 247, // 198: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest.sync_replication_state:type_name -> temporal.server.api.replication.v1.SyncReplicationState - 248, // 199: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse.messages:type_name -> temporal.server.api.replication.v1.WorkflowReplicationMessages - 249, // 200: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest.request:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest - 250, // 201: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse.response:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateResponse - 251, // 202: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest - 252, // 203: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse - 205, // 204: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse.history:type_name -> temporal.api.history.v1.History - 252, // 205: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponseWithRaw.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse - 253, // 206: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest - 254, // 207: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse - 255, // 208: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request.request:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryV2Request - 256, // 209: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response.response:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryV2Response - 257, // 210: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest.request:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryRequest - 258, // 211: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse.response:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryResponse - 259, // 212: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest.request:type_name -> temporal.server.api.adminservice.v1.DeleteWorkflowExecutionRequest - 260, // 213: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse.response:type_name -> temporal.server.api.adminservice.v1.DeleteWorkflowExecutionResponse - 191, // 214: temporal.server.api.historyservice.v1.DeleteExecutionRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 261, // 215: temporal.server.api.historyservice.v1.GetDLQTasksRequest.dlq_key:type_name -> temporal.server.api.common.v1.HistoryDLQKey - 262, // 216: temporal.server.api.historyservice.v1.GetDLQTasksResponse.dlq_tasks:type_name -> temporal.server.api.common.v1.HistoryDLQTask - 261, // 217: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest.dlq_key:type_name -> temporal.server.api.common.v1.HistoryDLQKey - 263, // 218: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest.inclusive_max_task_metadata:type_name -> temporal.server.api.common.v1.HistoryDLQTaskMetadata - 171, // 219: temporal.server.api.historyservice.v1.ListQueuesResponse.queues:type_name -> temporal.server.api.historyservice.v1.ListQueuesResponse.QueueInfo - 172, // 220: temporal.server.api.historyservice.v1.AddTasksRequest.tasks:type_name -> temporal.server.api.historyservice.v1.AddTasksRequest.Task - 264, // 221: temporal.server.api.historyservice.v1.ListTasksRequest.request:type_name -> temporal.server.api.adminservice.v1.ListHistoryTasksRequest - 265, // 222: temporal.server.api.historyservice.v1.ListTasksResponse.response:type_name -> temporal.server.api.adminservice.v1.ListHistoryTasksResponse - 266, // 223: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.completion:type_name -> temporal.server.api.token.v1.NexusOperationCompletion - 267, // 224: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.success:type_name -> temporal.api.common.v1.Payload - 177, // 225: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.failure:type_name -> temporal.api.failure.v1.Failure - 175, // 226: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.close_time:type_name -> google.protobuf.Timestamp - 190, // 227: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.links:type_name -> temporal.api.common.v1.Link - 175, // 228: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.start_time:type_name -> google.protobuf.Timestamp - 266, // 229: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.completion:type_name -> temporal.server.api.token.v1.NexusOperationCompletion - 267, // 230: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.success:type_name -> temporal.api.common.v1.Payload - 268, // 231: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.failure:type_name -> temporal.api.nexus.v1.Failure - 175, // 232: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.start_time:type_name -> google.protobuf.Timestamp - 190, // 233: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.links:type_name -> temporal.api.common.v1.Link - 269, // 234: temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest.ref:type_name -> temporal.server.api.persistence.v1.StateMachineRef - 270, // 235: temporal.server.api.historyservice.v1.DeepHealthCheckResponse.state:type_name -> temporal.server.api.enums.v1.HealthState - 271, // 236: temporal.server.api.historyservice.v1.DeepHealthCheckResponse.checks:type_name -> temporal.server.api.health.v1.HealthCheck - 191, // 237: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 193, // 238: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.versioned_transition:type_name -> temporal.server.api.persistence.v1.VersionedTransition - 197, // 239: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories - 272, // 240: temporal.server.api.historyservice.v1.SyncWorkflowStateResponse.versioned_transition_artifact:type_name -> temporal.server.api.replication.v1.VersionedTransitionArtifact - 273, // 241: temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest.update_request:type_name -> temporal.api.workflowservice.v1.UpdateActivityOptionsRequest - 274, // 242: temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse.activity_options:type_name -> temporal.api.activity.v1.ActivityOptions - 275, // 243: temporal.server.api.historyservice.v1.PauseActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.PauseActivityRequest - 276, // 244: temporal.server.api.historyservice.v1.UnpauseActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.UnpauseActivityRequest - 277, // 245: temporal.server.api.historyservice.v1.ResetActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.ResetActivityRequest - 278, // 246: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest.update_request:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionOptionsRequest - 279, // 247: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse.workflow_execution_options:type_name -> temporal.api.workflow.v1.WorkflowExecutionOptions - 175, // 248: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse.update_time:type_name -> google.protobuf.Timestamp - 280, // 249: temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest.pause_request:type_name -> temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest - 281, // 250: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest.unpause_request:type_name -> temporal.api.workflowservice.v1.UnpauseWorkflowExecutionRequest - 282, // 251: temporal.server.api.historyservice.v1.StartNexusOperationRequest.request:type_name -> temporal.api.nexus.v1.StartOperationRequest - 283, // 252: temporal.server.api.historyservice.v1.StartNexusOperationResponse.response:type_name -> temporal.api.nexus.v1.StartOperationResponse - 284, // 253: temporal.server.api.historyservice.v1.CancelNexusOperationRequest.request:type_name -> temporal.api.nexus.v1.CancelOperationRequest - 285, // 254: temporal.server.api.historyservice.v1.CancelNexusOperationResponse.response:type_name -> temporal.api.nexus.v1.CancelOperationResponse - 286, // 255: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest.request:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingRequest - 287, // 256: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse.response:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse - 1, // 257: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation.start_workflow:type_name -> temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest - 105, // 258: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation.update_workflow:type_name -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest - 2, // 259: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response.start_workflow:type_name -> temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse - 106, // 260: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response.update_workflow:type_name -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse - 288, // 261: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery - 288, // 262: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery - 289, // 263: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.ShardMessagesEntry.value:type_name -> temporal.server.api.replication.v1.ReplicationMessages - 98, // 264: temporal.server.api.historyservice.v1.ShardReplicationStatus.RemoteClustersEntry.value:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatusPerCluster - 97, // 265: temporal.server.api.historyservice.v1.ShardReplicationStatus.HandoverNamespacesEntry.value:type_name -> temporal.server.api.historyservice.v1.HandoverNamespaceInfo - 231, // 266: temporal.server.api.historyservice.v1.AddTasksRequest.Task.blob:type_name -> temporal.api.common.v1.DataBlob - 290, // 267: temporal.server.api.historyservice.v1.routing:extendee -> google.protobuf.MessageOptions - 0, // 268: temporal.server.api.historyservice.v1.routing:type_name -> temporal.server.api.historyservice.v1.RoutingOptions - 269, // [269:269] is the sub-list for method output_type - 269, // [269:269] is the sub-list for method input_type - 268, // [268:269] is the sub-list for extension type_name - 267, // [267:268] is the sub-list for extension extendee - 0, // [0:267] is the sub-list for field type_name + 175, // 0: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.start_request:type_name -> temporal.api.workflowservice.v1.StartWorkflowExecutionRequest + 176, // 1: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.parent_execution_info:type_name -> temporal.server.api.workflow.v1.ParentExecutionInfo + 177, // 2: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.workflow_execution_expiration_time:type_name -> google.protobuf.Timestamp + 178, // 3: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.continue_as_new_initiator:type_name -> temporal.api.enums.v1.ContinueAsNewInitiator + 179, // 4: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.continued_failure:type_name -> temporal.api.failure.v1.Failure + 180, // 5: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.last_completion_result:type_name -> temporal.api.common.v1.Payloads + 181, // 6: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.first_workflow_task_backoff:type_name -> google.protobuf.Duration + 182, // 7: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.source_version_stamp:type_name -> temporal.api.common.v1.WorkerVersionStamp + 183, // 8: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.root_execution_info:type_name -> temporal.server.api.workflow.v1.RootExecutionInfo + 184, // 9: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.versioning_override:type_name -> temporal.api.workflow.v1.VersioningOverride + 185, // 10: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.inherited_pinned_version:type_name -> temporal.api.deployment.v1.WorkerDeploymentVersion + 186, // 11: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.inherited_auto_upgrade_info:type_name -> temporal.api.deployment.v1.InheritedAutoUpgradeInfo + 187, // 12: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.declined_target_version_upgrade:type_name -> temporal.api.history.v1.DeclinedTargetVersionUpgrade + 188, // 13: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest.time_skipping_state_propagation:type_name -> temporal.api.common.v1.TimeSkippingStatePropagation + 189, // 14: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 190, // 15: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.eager_workflow_task:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse + 191, // 16: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus + 192, // 17: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse.link:type_name -> temporal.api.common.v1.Link + 193, // 18: temporal.server.api.historyservice.v1.GetStreamReplaySlicesRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 194, // 19: temporal.server.api.historyservice.v1.GetStreamReplaySlicesResponse.stream_slices:type_name -> temporal.api.stream.v1.StreamSlice + 193, // 20: temporal.server.api.historyservice.v1.GetMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 195, // 21: temporal.server.api.historyservice.v1.GetMutableStateRequest.version_history_item:type_name -> temporal.server.api.history.v1.VersionHistoryItem + 196, // 22: temporal.server.api.historyservice.v1.GetMutableStateRequest.versioned_transition:type_name -> temporal.server.api.persistence.v1.VersionedTransition + 193, // 23: temporal.server.api.historyservice.v1.GetMutableStateResponse.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 197, // 24: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 198, // 25: temporal.server.api.historyservice.v1.GetMutableStateResponse.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 198, // 26: temporal.server.api.historyservice.v1.GetMutableStateResponse.sticky_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 181, // 27: temporal.server.api.historyservice.v1.GetMutableStateResponse.sticky_task_queue_schedule_to_start_timeout:type_name -> google.protobuf.Duration + 199, // 28: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_state:type_name -> temporal.server.api.enums.v1.WorkflowExecutionState + 191, // 29: temporal.server.api.historyservice.v1.GetMutableStateResponse.workflow_status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus + 200, // 30: temporal.server.api.historyservice.v1.GetMutableStateResponse.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories + 182, // 31: temporal.server.api.historyservice.v1.GetMutableStateResponse.most_recent_worker_version_stamp:type_name -> temporal.api.common.v1.WorkerVersionStamp + 196, // 32: temporal.server.api.historyservice.v1.GetMutableStateResponse.transition_history:type_name -> temporal.server.api.persistence.v1.VersionedTransition + 201, // 33: temporal.server.api.historyservice.v1.GetMutableStateResponse.versioning_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionVersioningInfo + 202, // 34: temporal.server.api.historyservice.v1.GetMutableStateResponse.transient_or_speculative_tasks:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo + 193, // 35: temporal.server.api.historyservice.v1.PollMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 195, // 36: temporal.server.api.historyservice.v1.PollMutableStateRequest.version_history_item:type_name -> temporal.server.api.history.v1.VersionHistoryItem + 193, // 37: temporal.server.api.historyservice.v1.PollMutableStateResponse.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 197, // 38: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 198, // 39: temporal.server.api.historyservice.v1.PollMutableStateResponse.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 198, // 40: temporal.server.api.historyservice.v1.PollMutableStateResponse.sticky_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 181, // 41: temporal.server.api.historyservice.v1.PollMutableStateResponse.sticky_task_queue_schedule_to_start_timeout:type_name -> google.protobuf.Duration + 200, // 42: temporal.server.api.historyservice.v1.PollMutableStateResponse.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories + 199, // 43: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_state:type_name -> temporal.server.api.enums.v1.WorkflowExecutionState + 191, // 44: temporal.server.api.historyservice.v1.PollMutableStateResponse.workflow_status:type_name -> temporal.api.enums.v1.WorkflowExecutionStatus + 193, // 45: temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 166, // 46: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.operations:type_name -> temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation + 167, // 47: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.responses:type_name -> temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response + 193, // 48: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 203, // 49: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest + 189, // 50: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 204, // 51: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.build_id_redirect_info:type_name -> temporal.server.api.taskqueue.v1.BuildIdRedirectInfo + 205, // 52: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.scheduled_deployment:type_name -> temporal.api.deployment.v1.Deployment + 206, // 53: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 185, // 54: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest.target_deployment_version:type_name -> temporal.api.deployment.v1.WorkerDeploymentVersion + 197, // 55: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 202, // 56: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo + 198, // 57: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 177, // 58: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 59: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.started_time:type_name -> google.protobuf.Timestamp + 168, // 60: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.queries:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.QueriesEntry + 189, // 61: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 207, // 62: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.messages:type_name -> temporal.api.protocol.v1.Message + 208, // 63: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.history:type_name -> temporal.api.history.v1.History + 208, // 64: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.raw_history:type_name -> temporal.api.history.v1.History + 194, // 65: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.stream_slices:type_name -> temporal.api.stream.v1.StreamSlice + 197, // 66: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 202, // 67: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo + 198, // 68: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 177, // 69: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 70: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.started_time:type_name -> google.protobuf.Timestamp + 169, // 71: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.queries:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.QueriesEntry + 189, // 72: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 207, // 73: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.messages:type_name -> temporal.api.protocol.v1.Message + 208, // 74: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.history:type_name -> temporal.api.history.v1.History + 194, // 75: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.stream_slices:type_name -> temporal.api.stream.v1.StreamSlice + 193, // 76: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 209, // 77: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest + 189, // 78: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 204, // 79: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.build_id_redirect_info:type_name -> temporal.server.api.taskqueue.v1.BuildIdRedirectInfo + 205, // 80: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.scheduled_deployment:type_name -> temporal.api.deployment.v1.Deployment + 206, // 81: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 210, // 82: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.scheduled_event:type_name -> temporal.api.history.v1.HistoryEvent + 177, // 83: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.started_time:type_name -> google.protobuf.Timestamp + 177, // 84: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp + 180, // 85: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads + 197, // 86: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 189, // 87: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 211, // 88: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.priority:type_name -> temporal.api.common.v1.Priority + 212, // 89: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy + 213, // 90: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest.complete_request:type_name -> temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedRequest + 14, // 91: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.started_response:type_name -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse + 214, // 92: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.activity_tasks:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueResponse + 190, // 93: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse.new_workflow_task:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse + 215, // 94: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest.failed_request:type_name -> temporal.api.workflowservice.v1.RespondWorkflowTaskFailedRequest + 193, // 95: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 189, // 96: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 216, // 97: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest.heartbeat_request:type_name -> temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatRequest + 217, // 98: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest.complete_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskCompletedRequest + 218, // 99: temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest.failed_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskFailedRequest + 219, // 100: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest.cancel_request:type_name -> temporal.api.workflowservice.v1.RespondActivityTaskCanceledRequest + 193, // 101: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 189, // 102: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 220, // 103: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest.signal_request:type_name -> temporal.api.workflowservice.v1.SignalWorkflowExecutionRequest + 193, // 104: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 192, // 105: temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse.link:type_name -> temporal.api.common.v1.Link + 221, // 106: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest.signal_with_start_request:type_name -> temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest + 192, // 107: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse.signal_link:type_name -> temporal.api.common.v1.Link + 193, // 108: temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 222, // 109: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest.terminate_request:type_name -> temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest + 193, // 110: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 193, // 111: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 223, // 112: temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest.reset_request:type_name -> temporal.api.workflowservice.v1.ResetWorkflowExecutionRequest + 224, // 113: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest.cancel_request:type_name -> temporal.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest + 193, // 114: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest.external_workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 193, // 115: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 189, // 116: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.child_clock:type_name -> temporal.server.api.clock.v1.VectorClock + 189, // 117: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest.parent_clock:type_name -> temporal.server.api.clock.v1.VectorClock + 193, // 118: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 189, // 119: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 193, // 120: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.parent_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 193, // 121: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.child_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 210, // 122: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.completion_event:type_name -> temporal.api.history.v1.HistoryEvent + 189, // 123: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 193, // 124: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.parent_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 193, // 125: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.child_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 189, // 126: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 225, // 127: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest + 226, // 128: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.execution_config:type_name -> temporal.api.workflow.v1.WorkflowExecutionConfig + 227, // 129: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.workflow_execution_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionInfo + 228, // 130: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_activities:type_name -> temporal.api.workflow.v1.PendingActivityInfo + 229, // 131: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_children:type_name -> temporal.api.workflow.v1.PendingChildExecutionInfo + 230, // 132: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_workflow_task:type_name -> temporal.api.workflow.v1.PendingWorkflowTaskInfo + 231, // 133: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.callbacks:type_name -> temporal.api.workflow.v1.CallbackInfo + 232, // 134: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.pending_nexus_operations:type_name -> temporal.api.workflow.v1.PendingNexusOperationInfo + 233, // 135: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse.workflow_extended_info:type_name -> temporal.api.workflow.v1.WorkflowExecutionExtendedInfo + 193, // 136: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 195, // 137: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.version_history_items:type_name -> temporal.server.api.history.v1.VersionHistoryItem + 234, // 138: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.events:type_name -> temporal.api.common.v1.DataBlob + 234, // 139: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.new_run_events:type_name -> temporal.api.common.v1.DataBlob + 235, // 140: temporal.server.api.historyservice.v1.ReplicateEventsV2Request.base_execution_info:type_name -> temporal.server.api.workflow.v1.BaseExecutionInfo + 236, // 141: temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest.workflow_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState + 177, // 142: temporal.server.api.historyservice.v1.SyncShardStatusRequest.status_time:type_name -> google.protobuf.Timestamp + 177, // 143: temporal.server.api.historyservice.v1.SyncActivityRequest.scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 144: temporal.server.api.historyservice.v1.SyncActivityRequest.started_time:type_name -> google.protobuf.Timestamp + 177, // 145: temporal.server.api.historyservice.v1.SyncActivityRequest.last_heartbeat_time:type_name -> google.protobuf.Timestamp + 180, // 146: temporal.server.api.historyservice.v1.SyncActivityRequest.details:type_name -> temporal.api.common.v1.Payloads + 179, // 147: temporal.server.api.historyservice.v1.SyncActivityRequest.last_failure:type_name -> temporal.api.failure.v1.Failure + 237, // 148: temporal.server.api.historyservice.v1.SyncActivityRequest.version_history:type_name -> temporal.server.api.history.v1.VersionHistory + 235, // 149: temporal.server.api.historyservice.v1.SyncActivityRequest.base_execution_info:type_name -> temporal.server.api.workflow.v1.BaseExecutionInfo + 177, // 150: temporal.server.api.historyservice.v1.SyncActivityRequest.first_scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 151: temporal.server.api.historyservice.v1.SyncActivityRequest.last_attempt_complete_time:type_name -> google.protobuf.Timestamp + 181, // 152: temporal.server.api.historyservice.v1.SyncActivityRequest.retry_initial_interval:type_name -> google.protobuf.Duration + 181, // 153: temporal.server.api.historyservice.v1.SyncActivityRequest.retry_maximum_interval:type_name -> google.protobuf.Duration + 66, // 154: temporal.server.api.historyservice.v1.SyncActivitiesRequest.activities_info:type_name -> temporal.server.api.historyservice.v1.ActivitySyncInfo + 177, // 155: temporal.server.api.historyservice.v1.ActivitySyncInfo.scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 156: temporal.server.api.historyservice.v1.ActivitySyncInfo.started_time:type_name -> google.protobuf.Timestamp + 177, // 157: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_heartbeat_time:type_name -> google.protobuf.Timestamp + 180, // 158: temporal.server.api.historyservice.v1.ActivitySyncInfo.details:type_name -> temporal.api.common.v1.Payloads + 179, // 159: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_failure:type_name -> temporal.api.failure.v1.Failure + 237, // 160: temporal.server.api.historyservice.v1.ActivitySyncInfo.version_history:type_name -> temporal.server.api.history.v1.VersionHistory + 177, // 161: temporal.server.api.historyservice.v1.ActivitySyncInfo.first_scheduled_time:type_name -> google.protobuf.Timestamp + 177, // 162: temporal.server.api.historyservice.v1.ActivitySyncInfo.last_attempt_complete_time:type_name -> google.protobuf.Timestamp + 181, // 163: temporal.server.api.historyservice.v1.ActivitySyncInfo.retry_initial_interval:type_name -> google.protobuf.Duration + 181, // 164: temporal.server.api.historyservice.v1.ActivitySyncInfo.retry_maximum_interval:type_name -> google.protobuf.Duration + 193, // 165: temporal.server.api.historyservice.v1.DescribeMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 236, // 166: temporal.server.api.historyservice.v1.DescribeMutableStateResponse.cache_mutable_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState + 236, // 167: temporal.server.api.historyservice.v1.DescribeMutableStateResponse.database_mutable_state:type_name -> temporal.server.api.persistence.v1.WorkflowMutableState + 193, // 168: temporal.server.api.historyservice.v1.DescribeHistoryHostRequest.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 238, // 169: temporal.server.api.historyservice.v1.DescribeHistoryHostResponse.namespace_cache:type_name -> temporal.server.api.namespace.v1.NamespaceCacheInfo + 239, // 170: temporal.server.api.historyservice.v1.GetShardResponse.shard_info:type_name -> temporal.server.api.persistence.v1.ShardInfo + 177, // 171: temporal.server.api.historyservice.v1.RemoveTaskRequest.visibility_time:type_name -> google.protobuf.Timestamp + 240, // 172: temporal.server.api.historyservice.v1.GetReplicationMessagesRequest.tokens:type_name -> temporal.server.api.replication.v1.ReplicationToken + 170, // 173: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.shard_messages:type_name -> temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.ShardMessagesEntry + 241, // 174: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest.task_infos:type_name -> temporal.server.api.replication.v1.ReplicationTaskInfo + 242, // 175: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse.replication_tasks:type_name -> temporal.server.api.replication.v1.ReplicationTask + 243, // 176: temporal.server.api.historyservice.v1.QueryWorkflowRequest.request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest + 244, // 177: temporal.server.api.historyservice.v1.QueryWorkflowResponse.response:type_name -> temporal.api.workflowservice.v1.QueryWorkflowResponse + 245, // 178: temporal.server.api.historyservice.v1.ReapplyEventsRequest.request:type_name -> temporal.server.api.adminservice.v1.ReapplyEventsRequest + 246, // 179: temporal.server.api.historyservice.v1.GetDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType + 246, // 180: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType + 242, // 181: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.replication_tasks:type_name -> temporal.server.api.replication.v1.ReplicationTask + 241, // 182: temporal.server.api.historyservice.v1.GetDLQMessagesResponse.replication_tasks_info:type_name -> temporal.server.api.replication.v1.ReplicationTaskInfo + 246, // 183: temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType + 246, // 184: temporal.server.api.historyservice.v1.MergeDLQMessagesRequest.type:type_name -> temporal.server.api.enums.v1.DeadLetterQueueType + 247, // 185: temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest.request:type_name -> temporal.server.api.adminservice.v1.RefreshWorkflowTasksRequest + 193, // 186: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 98, // 187: temporal.server.api.historyservice.v1.GetReplicationStatusResponse.shards:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus + 177, // 188: temporal.server.api.historyservice.v1.ShardReplicationStatus.shard_local_time:type_name -> google.protobuf.Timestamp + 171, // 189: temporal.server.api.historyservice.v1.ShardReplicationStatus.remote_clusters:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus.RemoteClustersEntry + 172, // 190: temporal.server.api.historyservice.v1.ShardReplicationStatus.handover_namespaces:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatus.HandoverNamespacesEntry + 177, // 191: temporal.server.api.historyservice.v1.ShardReplicationStatus.max_replication_task_visibility_time:type_name -> google.protobuf.Timestamp + 177, // 192: temporal.server.api.historyservice.v1.ShardReplicationStatusPerCluster.acked_task_visibility_time:type_name -> google.protobuf.Timestamp + 193, // 193: temporal.server.api.historyservice.v1.RebuildMutableStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 193, // 194: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 234, // 195: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.history_batches:type_name -> temporal.api.common.v1.DataBlob + 237, // 196: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest.version_history:type_name -> temporal.server.api.history.v1.VersionHistory + 193, // 197: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 177, // 198: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.workflow_start_time:type_name -> google.protobuf.Timestamp + 177, // 199: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest.workflow_close_time:type_name -> google.protobuf.Timestamp + 248, // 200: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionRequest + 249, // 201: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse + 250, // 202: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest.sync_replication_state:type_name -> temporal.server.api.replication.v1.SyncReplicationState + 251, // 203: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse.messages:type_name -> temporal.server.api.replication.v1.WorkflowReplicationMessages + 252, // 204: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest.request:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateRequest + 253, // 205: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse.response:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionUpdateResponse + 254, // 206: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryRequest + 255, // 207: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse + 208, // 208: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse.history:type_name -> temporal.api.history.v1.History + 255, // 209: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponseWithRaw.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse + 256, // 210: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseRequest + 257, // 211: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryReverseResponse + 258, // 212: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request.request:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryV2Request + 259, // 213: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response.response:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryV2Response + 260, // 214: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest.request:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryRequest + 261, // 215: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse.response:type_name -> temporal.server.api.adminservice.v1.GetWorkflowExecutionRawHistoryResponse + 262, // 216: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest.request:type_name -> temporal.server.api.adminservice.v1.DeleteWorkflowExecutionRequest + 263, // 217: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse.response:type_name -> temporal.server.api.adminservice.v1.DeleteWorkflowExecutionResponse + 193, // 218: temporal.server.api.historyservice.v1.DeleteExecutionRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 264, // 219: temporal.server.api.historyservice.v1.GetDLQTasksRequest.dlq_key:type_name -> temporal.server.api.common.v1.HistoryDLQKey + 265, // 220: temporal.server.api.historyservice.v1.GetDLQTasksResponse.dlq_tasks:type_name -> temporal.server.api.common.v1.HistoryDLQTask + 264, // 221: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest.dlq_key:type_name -> temporal.server.api.common.v1.HistoryDLQKey + 266, // 222: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest.inclusive_max_task_metadata:type_name -> temporal.server.api.common.v1.HistoryDLQTaskMetadata + 173, // 223: temporal.server.api.historyservice.v1.ListQueuesResponse.queues:type_name -> temporal.server.api.historyservice.v1.ListQueuesResponse.QueueInfo + 174, // 224: temporal.server.api.historyservice.v1.AddTasksRequest.tasks:type_name -> temporal.server.api.historyservice.v1.AddTasksRequest.Task + 267, // 225: temporal.server.api.historyservice.v1.ListTasksRequest.request:type_name -> temporal.server.api.adminservice.v1.ListHistoryTasksRequest + 268, // 226: temporal.server.api.historyservice.v1.ListTasksResponse.response:type_name -> temporal.server.api.adminservice.v1.ListHistoryTasksResponse + 269, // 227: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.completion:type_name -> temporal.server.api.token.v1.NexusOperationCompletion + 270, // 228: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.success:type_name -> temporal.api.common.v1.Payload + 179, // 229: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.failure:type_name -> temporal.api.failure.v1.Failure + 177, // 230: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.close_time:type_name -> google.protobuf.Timestamp + 192, // 231: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.links:type_name -> temporal.api.common.v1.Link + 177, // 232: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest.start_time:type_name -> google.protobuf.Timestamp + 269, // 233: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.completion:type_name -> temporal.server.api.token.v1.NexusOperationCompletion + 270, // 234: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.success:type_name -> temporal.api.common.v1.Payload + 271, // 235: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.failure:type_name -> temporal.api.nexus.v1.Failure + 177, // 236: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.start_time:type_name -> google.protobuf.Timestamp + 192, // 237: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest.links:type_name -> temporal.api.common.v1.Link + 272, // 238: temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest.ref:type_name -> temporal.server.api.persistence.v1.StateMachineRef + 273, // 239: temporal.server.api.historyservice.v1.DeepHealthCheckResponse.state:type_name -> temporal.server.api.enums.v1.HealthState + 274, // 240: temporal.server.api.historyservice.v1.DeepHealthCheckResponse.checks:type_name -> temporal.server.api.health.v1.HealthCheck + 193, // 241: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 196, // 242: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.versioned_transition:type_name -> temporal.server.api.persistence.v1.VersionedTransition + 200, // 243: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest.version_histories:type_name -> temporal.server.api.history.v1.VersionHistories + 275, // 244: temporal.server.api.historyservice.v1.SyncWorkflowStateResponse.versioned_transition_artifact:type_name -> temporal.server.api.replication.v1.VersionedTransitionArtifact + 276, // 245: temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest.update_request:type_name -> temporal.api.workflowservice.v1.UpdateActivityOptionsRequest + 277, // 246: temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse.activity_options:type_name -> temporal.api.activity.v1.ActivityOptions + 278, // 247: temporal.server.api.historyservice.v1.PauseActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.PauseActivityRequest + 279, // 248: temporal.server.api.historyservice.v1.UnpauseActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.UnpauseActivityRequest + 280, // 249: temporal.server.api.historyservice.v1.ResetActivityRequest.frontend_request:type_name -> temporal.api.workflowservice.v1.ResetActivityRequest + 281, // 250: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest.update_request:type_name -> temporal.api.workflowservice.v1.UpdateWorkflowExecutionOptionsRequest + 282, // 251: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse.workflow_execution_options:type_name -> temporal.api.workflow.v1.WorkflowExecutionOptions + 177, // 252: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse.update_time:type_name -> google.protobuf.Timestamp + 283, // 253: temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest.pause_request:type_name -> temporal.api.workflowservice.v1.PauseWorkflowExecutionRequest + 284, // 254: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest.unpause_request:type_name -> temporal.api.workflowservice.v1.UnpauseWorkflowExecutionRequest + 285, // 255: temporal.server.api.historyservice.v1.StartNexusOperationRequest.request:type_name -> temporal.api.nexus.v1.StartOperationRequest + 286, // 256: temporal.server.api.historyservice.v1.StartNexusOperationResponse.response:type_name -> temporal.api.nexus.v1.StartOperationResponse + 287, // 257: temporal.server.api.historyservice.v1.CancelNexusOperationRequest.request:type_name -> temporal.api.nexus.v1.CancelOperationRequest + 288, // 258: temporal.server.api.historyservice.v1.CancelNexusOperationResponse.response:type_name -> temporal.api.nexus.v1.CancelOperationResponse + 289, // 259: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest.request:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingRequest + 290, // 260: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse.response:type_name -> temporal.api.workflowservice.v1.PollWorkflowExecutionTimeSkippingResponse + 1, // 261: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation.start_workflow:type_name -> temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest + 107, // 262: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest.Operation.update_workflow:type_name -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest + 2, // 263: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response.start_workflow:type_name -> temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse + 108, // 264: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse.Response.update_workflow:type_name -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse + 291, // 265: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery + 291, // 266: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponseWithRawHistory.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery + 292, // 267: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse.ShardMessagesEntry.value:type_name -> temporal.server.api.replication.v1.ReplicationMessages + 100, // 268: temporal.server.api.historyservice.v1.ShardReplicationStatus.RemoteClustersEntry.value:type_name -> temporal.server.api.historyservice.v1.ShardReplicationStatusPerCluster + 99, // 269: temporal.server.api.historyservice.v1.ShardReplicationStatus.HandoverNamespacesEntry.value:type_name -> temporal.server.api.historyservice.v1.HandoverNamespaceInfo + 234, // 270: temporal.server.api.historyservice.v1.AddTasksRequest.Task.blob:type_name -> temporal.api.common.v1.DataBlob + 293, // 271: temporal.server.api.historyservice.v1.routing:extendee -> google.protobuf.MessageOptions + 0, // 272: temporal.server.api.historyservice.v1.routing:type_name -> temporal.server.api.historyservice.v1.RoutingOptions + 273, // [273:273] is the sub-list for method output_type + 273, // [273:273] is the sub-list for method input_type + 272, // [272:273] is the sub-list for extension type_name + 271, // [271:272] is the sub-list for extension extendee + 0, // [0:271] is the sub-list for field type_name } func init() { file_temporal_server_api_historyservice_v1_request_response_proto_init() } @@ -12076,25 +12212,25 @@ func file_temporal_server_api_historyservice_v1_request_response_proto_init() { if File_temporal_server_api_historyservice_v1_request_response_proto != nil { return } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109].OneofWrappers = []any{ (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState)(nil), } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110].OneofWrappers = []any{ (*StreamWorkflowReplicationMessagesResponse_Messages)(nil), } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136].OneofWrappers = []any{ (*CompleteNexusOperationChasmRequest_Success)(nil), (*CompleteNexusOperationChasmRequest_Failure)(nil), } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138].OneofWrappers = []any{ (*CompleteNexusOperationRequest_Success)(nil), (*CompleteNexusOperationRequest_Failure)(nil), } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[164].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[166].OneofWrappers = []any{ (*ExecuteMultiOperationRequest_Operation_StartWorkflow)(nil), (*ExecuteMultiOperationRequest_Operation_UpdateWorkflow)(nil), } - file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[165].OneofWrappers = []any{ + file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[167].OneofWrappers = []any{ (*ExecuteMultiOperationResponse_Response_StartWorkflow)(nil), (*ExecuteMultiOperationResponse_Response_UpdateWorkflow)(nil), } @@ -12104,7 +12240,7 @@ func file_temporal_server_api_historyservice_v1_request_response_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc)), NumEnums: 0, - NumMessages: 173, + NumMessages: 175, NumExtensions: 1, NumServices: 0, }, diff --git a/api/historyservice/v1/service.pb.go b/api/historyservice/v1/service.pb.go index 640fef3b4d4..bee88cf6888 100644 --- a/api/historyservice/v1/service.pb.go +++ b/api/historyservice/v1/service.pb.go @@ -26,11 +26,12 @@ var File_temporal_server_api_historyservice_v1_service_proto protoreflect.FileDe const file_temporal_server_api_historyservice_v1_service_proto_rawDesc = "" + "\n" + - "3temporal/server/api/historyservice/v1/service.proto\x12%temporal.server.api.historyservice.v1\x1a0temporal/server/api/common/v1/api_category.proto\x1a.temporal.server.api.historyservice.v1.GetMutableStateResponse\"\x06\x8a\xb5\x18\x02\b\x01\x12\x9b\x01\n" + - "\x10PollMutableState\x12>.temporal.server.api.historyservice.v1.PollMutableStateRequest\x1a?.temporal.server.api.historyservice.v1.PollMutableStateResponse\"\x06\x8a\xb5\x18\x02\b\x02\x12\xa7\x01\n" + + "\x10PollMutableState\x12>.temporal.server.api.historyservice.v1.PollMutableStateRequest\x1a?.temporal.server.api.historyservice.v1.PollMutableStateResponse\"\x06\x8a\xb5\x18\x02\b\x02\x12\xaa\x01\n" + + "\x15GetStreamReplaySlices\x12C.temporal.server.api.historyservice.v1.GetStreamReplaySlicesRequest\x1aD.temporal.server.api.historyservice.v1.GetStreamReplaySlicesResponse\"\x06\x8a\xb5\x18\x02\b\x01\x12\xa7\x01\n" + "\x14ResetStickyTaskQueue\x12B.temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest\x1aC.temporal.server.api.historyservice.v1.ResetStickyTaskQueueResponse\"\x06\x8a\xb5\x18\x02\b\x01\x12\xb6\x01\n" + "\x19RecordWorkflowTaskStarted\x12G.temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest\x1aH.temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse\"\x06\x8a\xb5\x18\x02\b\x01\x12\xb6\x01\n" + "\x19RecordActivityTaskStarted\x12G.temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest\x1aH.temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse\"\x06\x8a\xb5\x18\x02\b\x01\x12\xbf\x01\n" + @@ -114,319 +115,323 @@ var file_temporal_server_api_historyservice_v1_service_proto_goTypes = []any{ (*StartWorkflowExecutionRequest)(nil), // 0: temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest (*GetMutableStateRequest)(nil), // 1: temporal.server.api.historyservice.v1.GetMutableStateRequest (*PollMutableStateRequest)(nil), // 2: temporal.server.api.historyservice.v1.PollMutableStateRequest - (*ResetStickyTaskQueueRequest)(nil), // 3: temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest - (*RecordWorkflowTaskStartedRequest)(nil), // 4: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest - (*RecordActivityTaskStartedRequest)(nil), // 5: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest - (*RespondWorkflowTaskCompletedRequest)(nil), // 6: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest - (*RespondWorkflowTaskFailedRequest)(nil), // 7: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest - (*IsWorkflowTaskValidRequest)(nil), // 8: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest - (*RecordActivityTaskHeartbeatRequest)(nil), // 9: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest - (*RespondActivityTaskCompletedRequest)(nil), // 10: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest - (*RespondActivityTaskFailedRequest)(nil), // 11: temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest - (*RespondActivityTaskCanceledRequest)(nil), // 12: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest - (*IsActivityTaskValidRequest)(nil), // 13: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest - (*SignalWorkflowExecutionRequest)(nil), // 14: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest - (*SignalWithStartWorkflowExecutionRequest)(nil), // 15: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest - (*ExecuteMultiOperationRequest)(nil), // 16: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest - (*RemoveSignalMutableStateRequest)(nil), // 17: temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest - (*TerminateWorkflowExecutionRequest)(nil), // 18: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest - (*DeleteWorkflowExecutionRequest)(nil), // 19: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest - (*ResetWorkflowExecutionRequest)(nil), // 20: temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest - (*UpdateWorkflowExecutionOptionsRequest)(nil), // 21: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest - (*RequestCancelWorkflowExecutionRequest)(nil), // 22: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest - (*ScheduleWorkflowTaskRequest)(nil), // 23: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest - (*VerifyFirstWorkflowTaskScheduledRequest)(nil), // 24: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest - (*RecordChildExecutionCompletedRequest)(nil), // 25: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest - (*VerifyChildExecutionCompletionRecordedRequest)(nil), // 26: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest - (*DescribeWorkflowExecutionRequest)(nil), // 27: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest - (*ReplicateEventsV2Request)(nil), // 28: temporal.server.api.historyservice.v1.ReplicateEventsV2Request - (*ReplicateWorkflowStateRequest)(nil), // 29: temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest - (*SyncShardStatusRequest)(nil), // 30: temporal.server.api.historyservice.v1.SyncShardStatusRequest - (*SyncActivityRequest)(nil), // 31: temporal.server.api.historyservice.v1.SyncActivityRequest - (*DescribeMutableStateRequest)(nil), // 32: temporal.server.api.historyservice.v1.DescribeMutableStateRequest - (*DescribeHistoryHostRequest)(nil), // 33: temporal.server.api.historyservice.v1.DescribeHistoryHostRequest - (*CloseShardRequest)(nil), // 34: temporal.server.api.historyservice.v1.CloseShardRequest - (*GetShardRequest)(nil), // 35: temporal.server.api.historyservice.v1.GetShardRequest - (*RemoveTaskRequest)(nil), // 36: temporal.server.api.historyservice.v1.RemoveTaskRequest - (*GetReplicationMessagesRequest)(nil), // 37: temporal.server.api.historyservice.v1.GetReplicationMessagesRequest - (*GetDLQReplicationMessagesRequest)(nil), // 38: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest - (*QueryWorkflowRequest)(nil), // 39: temporal.server.api.historyservice.v1.QueryWorkflowRequest - (*ReapplyEventsRequest)(nil), // 40: temporal.server.api.historyservice.v1.ReapplyEventsRequest - (*GetDLQMessagesRequest)(nil), // 41: temporal.server.api.historyservice.v1.GetDLQMessagesRequest - (*PurgeDLQMessagesRequest)(nil), // 42: temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest - (*MergeDLQMessagesRequest)(nil), // 43: temporal.server.api.historyservice.v1.MergeDLQMessagesRequest - (*RefreshWorkflowTasksRequest)(nil), // 44: temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest - (*GenerateLastHistoryReplicationTasksRequest)(nil), // 45: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest - (*GetReplicationStatusRequest)(nil), // 46: temporal.server.api.historyservice.v1.GetReplicationStatusRequest - (*RebuildMutableStateRequest)(nil), // 47: temporal.server.api.historyservice.v1.RebuildMutableStateRequest - (*ImportWorkflowExecutionRequest)(nil), // 48: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest - (*DeleteWorkflowVisibilityRecordRequest)(nil), // 49: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest - (*UpdateWorkflowExecutionRequest)(nil), // 50: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest - (*PollWorkflowExecutionUpdateRequest)(nil), // 51: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest - (*StreamWorkflowReplicationMessagesRequest)(nil), // 52: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest - (*GetWorkflowExecutionHistoryRequest)(nil), // 53: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest - (*GetWorkflowExecutionHistoryReverseRequest)(nil), // 54: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest - (*GetWorkflowExecutionRawHistoryV2Request)(nil), // 55: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request - (*GetWorkflowExecutionRawHistoryRequest)(nil), // 56: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest - (*ForceDeleteWorkflowExecutionRequest)(nil), // 57: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest - (*DeleteExecutionRequest)(nil), // 58: temporal.server.api.historyservice.v1.DeleteExecutionRequest - (*GetDLQTasksRequest)(nil), // 59: temporal.server.api.historyservice.v1.GetDLQTasksRequest - (*DeleteDLQTasksRequest)(nil), // 60: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest - (*ListQueuesRequest)(nil), // 61: temporal.server.api.historyservice.v1.ListQueuesRequest - (*AddTasksRequest)(nil), // 62: temporal.server.api.historyservice.v1.AddTasksRequest - (*ListTasksRequest)(nil), // 63: temporal.server.api.historyservice.v1.ListTasksRequest - (*CompleteNexusOperationRequest)(nil), // 64: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest - (*CompleteNexusOperationChasmRequest)(nil), // 65: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest - (*InvokeStateMachineMethodRequest)(nil), // 66: temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest - (*DeepHealthCheckRequest)(nil), // 67: temporal.server.api.historyservice.v1.DeepHealthCheckRequest - (*SyncWorkflowStateRequest)(nil), // 68: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest - (*UpdateActivityOptionsRequest)(nil), // 69: temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest - (*PauseActivityRequest)(nil), // 70: temporal.server.api.historyservice.v1.PauseActivityRequest - (*UnpauseActivityRequest)(nil), // 71: temporal.server.api.historyservice.v1.UnpauseActivityRequest - (*ResetActivityRequest)(nil), // 72: temporal.server.api.historyservice.v1.ResetActivityRequest - (*PauseWorkflowExecutionRequest)(nil), // 73: temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest - (*UnpauseWorkflowExecutionRequest)(nil), // 74: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest - (*StartNexusOperationRequest)(nil), // 75: temporal.server.api.historyservice.v1.StartNexusOperationRequest - (*CancelNexusOperationRequest)(nil), // 76: temporal.server.api.historyservice.v1.CancelNexusOperationRequest - (*PollWorkflowExecutionTimeSkippingRequest)(nil), // 77: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest - (*StartWorkflowExecutionResponse)(nil), // 78: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse - (*GetMutableStateResponse)(nil), // 79: temporal.server.api.historyservice.v1.GetMutableStateResponse - (*PollMutableStateResponse)(nil), // 80: temporal.server.api.historyservice.v1.PollMutableStateResponse - (*ResetStickyTaskQueueResponse)(nil), // 81: temporal.server.api.historyservice.v1.ResetStickyTaskQueueResponse - (*RecordWorkflowTaskStartedResponse)(nil), // 82: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse - (*RecordActivityTaskStartedResponse)(nil), // 83: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse - (*RespondWorkflowTaskCompletedResponse)(nil), // 84: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse - (*RespondWorkflowTaskFailedResponse)(nil), // 85: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedResponse - (*IsWorkflowTaskValidResponse)(nil), // 86: temporal.server.api.historyservice.v1.IsWorkflowTaskValidResponse - (*RecordActivityTaskHeartbeatResponse)(nil), // 87: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatResponse - (*RespondActivityTaskCompletedResponse)(nil), // 88: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedResponse - (*RespondActivityTaskFailedResponse)(nil), // 89: temporal.server.api.historyservice.v1.RespondActivityTaskFailedResponse - (*RespondActivityTaskCanceledResponse)(nil), // 90: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledResponse - (*IsActivityTaskValidResponse)(nil), // 91: temporal.server.api.historyservice.v1.IsActivityTaskValidResponse - (*SignalWorkflowExecutionResponse)(nil), // 92: temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse - (*SignalWithStartWorkflowExecutionResponse)(nil), // 93: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse - (*ExecuteMultiOperationResponse)(nil), // 94: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse - (*RemoveSignalMutableStateResponse)(nil), // 95: temporal.server.api.historyservice.v1.RemoveSignalMutableStateResponse - (*TerminateWorkflowExecutionResponse)(nil), // 96: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionResponse - (*DeleteWorkflowExecutionResponse)(nil), // 97: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionResponse - (*ResetWorkflowExecutionResponse)(nil), // 98: temporal.server.api.historyservice.v1.ResetWorkflowExecutionResponse - (*UpdateWorkflowExecutionOptionsResponse)(nil), // 99: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse - (*RequestCancelWorkflowExecutionResponse)(nil), // 100: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionResponse - (*ScheduleWorkflowTaskResponse)(nil), // 101: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskResponse - (*VerifyFirstWorkflowTaskScheduledResponse)(nil), // 102: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledResponse - (*RecordChildExecutionCompletedResponse)(nil), // 103: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedResponse - (*VerifyChildExecutionCompletionRecordedResponse)(nil), // 104: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedResponse - (*DescribeWorkflowExecutionResponse)(nil), // 105: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse - (*ReplicateEventsV2Response)(nil), // 106: temporal.server.api.historyservice.v1.ReplicateEventsV2Response - (*ReplicateWorkflowStateResponse)(nil), // 107: temporal.server.api.historyservice.v1.ReplicateWorkflowStateResponse - (*SyncShardStatusResponse)(nil), // 108: temporal.server.api.historyservice.v1.SyncShardStatusResponse - (*SyncActivityResponse)(nil), // 109: temporal.server.api.historyservice.v1.SyncActivityResponse - (*DescribeMutableStateResponse)(nil), // 110: temporal.server.api.historyservice.v1.DescribeMutableStateResponse - (*DescribeHistoryHostResponse)(nil), // 111: temporal.server.api.historyservice.v1.DescribeHistoryHostResponse - (*CloseShardResponse)(nil), // 112: temporal.server.api.historyservice.v1.CloseShardResponse - (*GetShardResponse)(nil), // 113: temporal.server.api.historyservice.v1.GetShardResponse - (*RemoveTaskResponse)(nil), // 114: temporal.server.api.historyservice.v1.RemoveTaskResponse - (*GetReplicationMessagesResponse)(nil), // 115: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse - (*GetDLQReplicationMessagesResponse)(nil), // 116: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse - (*QueryWorkflowResponse)(nil), // 117: temporal.server.api.historyservice.v1.QueryWorkflowResponse - (*ReapplyEventsResponse)(nil), // 118: temporal.server.api.historyservice.v1.ReapplyEventsResponse - (*GetDLQMessagesResponse)(nil), // 119: temporal.server.api.historyservice.v1.GetDLQMessagesResponse - (*PurgeDLQMessagesResponse)(nil), // 120: temporal.server.api.historyservice.v1.PurgeDLQMessagesResponse - (*MergeDLQMessagesResponse)(nil), // 121: temporal.server.api.historyservice.v1.MergeDLQMessagesResponse - (*RefreshWorkflowTasksResponse)(nil), // 122: temporal.server.api.historyservice.v1.RefreshWorkflowTasksResponse - (*GenerateLastHistoryReplicationTasksResponse)(nil), // 123: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksResponse - (*GetReplicationStatusResponse)(nil), // 124: temporal.server.api.historyservice.v1.GetReplicationStatusResponse - (*RebuildMutableStateResponse)(nil), // 125: temporal.server.api.historyservice.v1.RebuildMutableStateResponse - (*ImportWorkflowExecutionResponse)(nil), // 126: temporal.server.api.historyservice.v1.ImportWorkflowExecutionResponse - (*DeleteWorkflowVisibilityRecordResponse)(nil), // 127: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordResponse - (*UpdateWorkflowExecutionResponse)(nil), // 128: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse - (*PollWorkflowExecutionUpdateResponse)(nil), // 129: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse - (*StreamWorkflowReplicationMessagesResponse)(nil), // 130: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse - (*GetWorkflowExecutionHistoryResponse)(nil), // 131: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse - (*GetWorkflowExecutionHistoryReverseResponse)(nil), // 132: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse - (*GetWorkflowExecutionRawHistoryV2Response)(nil), // 133: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response - (*GetWorkflowExecutionRawHistoryResponse)(nil), // 134: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse - (*ForceDeleteWorkflowExecutionResponse)(nil), // 135: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse - (*DeleteExecutionResponse)(nil), // 136: temporal.server.api.historyservice.v1.DeleteExecutionResponse - (*GetDLQTasksResponse)(nil), // 137: temporal.server.api.historyservice.v1.GetDLQTasksResponse - (*DeleteDLQTasksResponse)(nil), // 138: temporal.server.api.historyservice.v1.DeleteDLQTasksResponse - (*ListQueuesResponse)(nil), // 139: temporal.server.api.historyservice.v1.ListQueuesResponse - (*AddTasksResponse)(nil), // 140: temporal.server.api.historyservice.v1.AddTasksResponse - (*ListTasksResponse)(nil), // 141: temporal.server.api.historyservice.v1.ListTasksResponse - (*CompleteNexusOperationResponse)(nil), // 142: temporal.server.api.historyservice.v1.CompleteNexusOperationResponse - (*CompleteNexusOperationChasmResponse)(nil), // 143: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmResponse - (*InvokeStateMachineMethodResponse)(nil), // 144: temporal.server.api.historyservice.v1.InvokeStateMachineMethodResponse - (*DeepHealthCheckResponse)(nil), // 145: temporal.server.api.historyservice.v1.DeepHealthCheckResponse - (*SyncWorkflowStateResponse)(nil), // 146: temporal.server.api.historyservice.v1.SyncWorkflowStateResponse - (*UpdateActivityOptionsResponse)(nil), // 147: temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse - (*PauseActivityResponse)(nil), // 148: temporal.server.api.historyservice.v1.PauseActivityResponse - (*UnpauseActivityResponse)(nil), // 149: temporal.server.api.historyservice.v1.UnpauseActivityResponse - (*ResetActivityResponse)(nil), // 150: temporal.server.api.historyservice.v1.ResetActivityResponse - (*PauseWorkflowExecutionResponse)(nil), // 151: temporal.server.api.historyservice.v1.PauseWorkflowExecutionResponse - (*UnpauseWorkflowExecutionResponse)(nil), // 152: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionResponse - (*StartNexusOperationResponse)(nil), // 153: temporal.server.api.historyservice.v1.StartNexusOperationResponse - (*CancelNexusOperationResponse)(nil), // 154: temporal.server.api.historyservice.v1.CancelNexusOperationResponse - (*PollWorkflowExecutionTimeSkippingResponse)(nil), // 155: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse + (*GetStreamReplaySlicesRequest)(nil), // 3: temporal.server.api.historyservice.v1.GetStreamReplaySlicesRequest + (*ResetStickyTaskQueueRequest)(nil), // 4: temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest + (*RecordWorkflowTaskStartedRequest)(nil), // 5: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest + (*RecordActivityTaskStartedRequest)(nil), // 6: temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest + (*RespondWorkflowTaskCompletedRequest)(nil), // 7: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest + (*RespondWorkflowTaskFailedRequest)(nil), // 8: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest + (*IsWorkflowTaskValidRequest)(nil), // 9: temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest + (*RecordActivityTaskHeartbeatRequest)(nil), // 10: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest + (*RespondActivityTaskCompletedRequest)(nil), // 11: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest + (*RespondActivityTaskFailedRequest)(nil), // 12: temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest + (*RespondActivityTaskCanceledRequest)(nil), // 13: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest + (*IsActivityTaskValidRequest)(nil), // 14: temporal.server.api.historyservice.v1.IsActivityTaskValidRequest + (*SignalWorkflowExecutionRequest)(nil), // 15: temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest + (*SignalWithStartWorkflowExecutionRequest)(nil), // 16: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest + (*ExecuteMultiOperationRequest)(nil), // 17: temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest + (*RemoveSignalMutableStateRequest)(nil), // 18: temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest + (*TerminateWorkflowExecutionRequest)(nil), // 19: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest + (*DeleteWorkflowExecutionRequest)(nil), // 20: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest + (*ResetWorkflowExecutionRequest)(nil), // 21: temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest + (*UpdateWorkflowExecutionOptionsRequest)(nil), // 22: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest + (*RequestCancelWorkflowExecutionRequest)(nil), // 23: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest + (*ScheduleWorkflowTaskRequest)(nil), // 24: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest + (*VerifyFirstWorkflowTaskScheduledRequest)(nil), // 25: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest + (*RecordChildExecutionCompletedRequest)(nil), // 26: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest + (*VerifyChildExecutionCompletionRecordedRequest)(nil), // 27: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest + (*DescribeWorkflowExecutionRequest)(nil), // 28: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest + (*ReplicateEventsV2Request)(nil), // 29: temporal.server.api.historyservice.v1.ReplicateEventsV2Request + (*ReplicateWorkflowStateRequest)(nil), // 30: temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest + (*SyncShardStatusRequest)(nil), // 31: temporal.server.api.historyservice.v1.SyncShardStatusRequest + (*SyncActivityRequest)(nil), // 32: temporal.server.api.historyservice.v1.SyncActivityRequest + (*DescribeMutableStateRequest)(nil), // 33: temporal.server.api.historyservice.v1.DescribeMutableStateRequest + (*DescribeHistoryHostRequest)(nil), // 34: temporal.server.api.historyservice.v1.DescribeHistoryHostRequest + (*CloseShardRequest)(nil), // 35: temporal.server.api.historyservice.v1.CloseShardRequest + (*GetShardRequest)(nil), // 36: temporal.server.api.historyservice.v1.GetShardRequest + (*RemoveTaskRequest)(nil), // 37: temporal.server.api.historyservice.v1.RemoveTaskRequest + (*GetReplicationMessagesRequest)(nil), // 38: temporal.server.api.historyservice.v1.GetReplicationMessagesRequest + (*GetDLQReplicationMessagesRequest)(nil), // 39: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest + (*QueryWorkflowRequest)(nil), // 40: temporal.server.api.historyservice.v1.QueryWorkflowRequest + (*ReapplyEventsRequest)(nil), // 41: temporal.server.api.historyservice.v1.ReapplyEventsRequest + (*GetDLQMessagesRequest)(nil), // 42: temporal.server.api.historyservice.v1.GetDLQMessagesRequest + (*PurgeDLQMessagesRequest)(nil), // 43: temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest + (*MergeDLQMessagesRequest)(nil), // 44: temporal.server.api.historyservice.v1.MergeDLQMessagesRequest + (*RefreshWorkflowTasksRequest)(nil), // 45: temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest + (*GenerateLastHistoryReplicationTasksRequest)(nil), // 46: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest + (*GetReplicationStatusRequest)(nil), // 47: temporal.server.api.historyservice.v1.GetReplicationStatusRequest + (*RebuildMutableStateRequest)(nil), // 48: temporal.server.api.historyservice.v1.RebuildMutableStateRequest + (*ImportWorkflowExecutionRequest)(nil), // 49: temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest + (*DeleteWorkflowVisibilityRecordRequest)(nil), // 50: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest + (*UpdateWorkflowExecutionRequest)(nil), // 51: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest + (*PollWorkflowExecutionUpdateRequest)(nil), // 52: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest + (*StreamWorkflowReplicationMessagesRequest)(nil), // 53: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest + (*GetWorkflowExecutionHistoryRequest)(nil), // 54: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest + (*GetWorkflowExecutionHistoryReverseRequest)(nil), // 55: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest + (*GetWorkflowExecutionRawHistoryV2Request)(nil), // 56: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request + (*GetWorkflowExecutionRawHistoryRequest)(nil), // 57: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest + (*ForceDeleteWorkflowExecutionRequest)(nil), // 58: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest + (*DeleteExecutionRequest)(nil), // 59: temporal.server.api.historyservice.v1.DeleteExecutionRequest + (*GetDLQTasksRequest)(nil), // 60: temporal.server.api.historyservice.v1.GetDLQTasksRequest + (*DeleteDLQTasksRequest)(nil), // 61: temporal.server.api.historyservice.v1.DeleteDLQTasksRequest + (*ListQueuesRequest)(nil), // 62: temporal.server.api.historyservice.v1.ListQueuesRequest + (*AddTasksRequest)(nil), // 63: temporal.server.api.historyservice.v1.AddTasksRequest + (*ListTasksRequest)(nil), // 64: temporal.server.api.historyservice.v1.ListTasksRequest + (*CompleteNexusOperationRequest)(nil), // 65: temporal.server.api.historyservice.v1.CompleteNexusOperationRequest + (*CompleteNexusOperationChasmRequest)(nil), // 66: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest + (*InvokeStateMachineMethodRequest)(nil), // 67: temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest + (*DeepHealthCheckRequest)(nil), // 68: temporal.server.api.historyservice.v1.DeepHealthCheckRequest + (*SyncWorkflowStateRequest)(nil), // 69: temporal.server.api.historyservice.v1.SyncWorkflowStateRequest + (*UpdateActivityOptionsRequest)(nil), // 70: temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest + (*PauseActivityRequest)(nil), // 71: temporal.server.api.historyservice.v1.PauseActivityRequest + (*UnpauseActivityRequest)(nil), // 72: temporal.server.api.historyservice.v1.UnpauseActivityRequest + (*ResetActivityRequest)(nil), // 73: temporal.server.api.historyservice.v1.ResetActivityRequest + (*PauseWorkflowExecutionRequest)(nil), // 74: temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest + (*UnpauseWorkflowExecutionRequest)(nil), // 75: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest + (*StartNexusOperationRequest)(nil), // 76: temporal.server.api.historyservice.v1.StartNexusOperationRequest + (*CancelNexusOperationRequest)(nil), // 77: temporal.server.api.historyservice.v1.CancelNexusOperationRequest + (*PollWorkflowExecutionTimeSkippingRequest)(nil), // 78: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest + (*StartWorkflowExecutionResponse)(nil), // 79: temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse + (*GetMutableStateResponse)(nil), // 80: temporal.server.api.historyservice.v1.GetMutableStateResponse + (*PollMutableStateResponse)(nil), // 81: temporal.server.api.historyservice.v1.PollMutableStateResponse + (*GetStreamReplaySlicesResponse)(nil), // 82: temporal.server.api.historyservice.v1.GetStreamReplaySlicesResponse + (*ResetStickyTaskQueueResponse)(nil), // 83: temporal.server.api.historyservice.v1.ResetStickyTaskQueueResponse + (*RecordWorkflowTaskStartedResponse)(nil), // 84: temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse + (*RecordActivityTaskStartedResponse)(nil), // 85: temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse + (*RespondWorkflowTaskCompletedResponse)(nil), // 86: temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse + (*RespondWorkflowTaskFailedResponse)(nil), // 87: temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedResponse + (*IsWorkflowTaskValidResponse)(nil), // 88: temporal.server.api.historyservice.v1.IsWorkflowTaskValidResponse + (*RecordActivityTaskHeartbeatResponse)(nil), // 89: temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatResponse + (*RespondActivityTaskCompletedResponse)(nil), // 90: temporal.server.api.historyservice.v1.RespondActivityTaskCompletedResponse + (*RespondActivityTaskFailedResponse)(nil), // 91: temporal.server.api.historyservice.v1.RespondActivityTaskFailedResponse + (*RespondActivityTaskCanceledResponse)(nil), // 92: temporal.server.api.historyservice.v1.RespondActivityTaskCanceledResponse + (*IsActivityTaskValidResponse)(nil), // 93: temporal.server.api.historyservice.v1.IsActivityTaskValidResponse + (*SignalWorkflowExecutionResponse)(nil), // 94: temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse + (*SignalWithStartWorkflowExecutionResponse)(nil), // 95: temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse + (*ExecuteMultiOperationResponse)(nil), // 96: temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse + (*RemoveSignalMutableStateResponse)(nil), // 97: temporal.server.api.historyservice.v1.RemoveSignalMutableStateResponse + (*TerminateWorkflowExecutionResponse)(nil), // 98: temporal.server.api.historyservice.v1.TerminateWorkflowExecutionResponse + (*DeleteWorkflowExecutionResponse)(nil), // 99: temporal.server.api.historyservice.v1.DeleteWorkflowExecutionResponse + (*ResetWorkflowExecutionResponse)(nil), // 100: temporal.server.api.historyservice.v1.ResetWorkflowExecutionResponse + (*UpdateWorkflowExecutionOptionsResponse)(nil), // 101: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse + (*RequestCancelWorkflowExecutionResponse)(nil), // 102: temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionResponse + (*ScheduleWorkflowTaskResponse)(nil), // 103: temporal.server.api.historyservice.v1.ScheduleWorkflowTaskResponse + (*VerifyFirstWorkflowTaskScheduledResponse)(nil), // 104: temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledResponse + (*RecordChildExecutionCompletedResponse)(nil), // 105: temporal.server.api.historyservice.v1.RecordChildExecutionCompletedResponse + (*VerifyChildExecutionCompletionRecordedResponse)(nil), // 106: temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedResponse + (*DescribeWorkflowExecutionResponse)(nil), // 107: temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse + (*ReplicateEventsV2Response)(nil), // 108: temporal.server.api.historyservice.v1.ReplicateEventsV2Response + (*ReplicateWorkflowStateResponse)(nil), // 109: temporal.server.api.historyservice.v1.ReplicateWorkflowStateResponse + (*SyncShardStatusResponse)(nil), // 110: temporal.server.api.historyservice.v1.SyncShardStatusResponse + (*SyncActivityResponse)(nil), // 111: temporal.server.api.historyservice.v1.SyncActivityResponse + (*DescribeMutableStateResponse)(nil), // 112: temporal.server.api.historyservice.v1.DescribeMutableStateResponse + (*DescribeHistoryHostResponse)(nil), // 113: temporal.server.api.historyservice.v1.DescribeHistoryHostResponse + (*CloseShardResponse)(nil), // 114: temporal.server.api.historyservice.v1.CloseShardResponse + (*GetShardResponse)(nil), // 115: temporal.server.api.historyservice.v1.GetShardResponse + (*RemoveTaskResponse)(nil), // 116: temporal.server.api.historyservice.v1.RemoveTaskResponse + (*GetReplicationMessagesResponse)(nil), // 117: temporal.server.api.historyservice.v1.GetReplicationMessagesResponse + (*GetDLQReplicationMessagesResponse)(nil), // 118: temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse + (*QueryWorkflowResponse)(nil), // 119: temporal.server.api.historyservice.v1.QueryWorkflowResponse + (*ReapplyEventsResponse)(nil), // 120: temporal.server.api.historyservice.v1.ReapplyEventsResponse + (*GetDLQMessagesResponse)(nil), // 121: temporal.server.api.historyservice.v1.GetDLQMessagesResponse + (*PurgeDLQMessagesResponse)(nil), // 122: temporal.server.api.historyservice.v1.PurgeDLQMessagesResponse + (*MergeDLQMessagesResponse)(nil), // 123: temporal.server.api.historyservice.v1.MergeDLQMessagesResponse + (*RefreshWorkflowTasksResponse)(nil), // 124: temporal.server.api.historyservice.v1.RefreshWorkflowTasksResponse + (*GenerateLastHistoryReplicationTasksResponse)(nil), // 125: temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksResponse + (*GetReplicationStatusResponse)(nil), // 126: temporal.server.api.historyservice.v1.GetReplicationStatusResponse + (*RebuildMutableStateResponse)(nil), // 127: temporal.server.api.historyservice.v1.RebuildMutableStateResponse + (*ImportWorkflowExecutionResponse)(nil), // 128: temporal.server.api.historyservice.v1.ImportWorkflowExecutionResponse + (*DeleteWorkflowVisibilityRecordResponse)(nil), // 129: temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordResponse + (*UpdateWorkflowExecutionResponse)(nil), // 130: temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse + (*PollWorkflowExecutionUpdateResponse)(nil), // 131: temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse + (*StreamWorkflowReplicationMessagesResponse)(nil), // 132: temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse + (*GetWorkflowExecutionHistoryResponse)(nil), // 133: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse + (*GetWorkflowExecutionHistoryReverseResponse)(nil), // 134: temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse + (*GetWorkflowExecutionRawHistoryV2Response)(nil), // 135: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response + (*GetWorkflowExecutionRawHistoryResponse)(nil), // 136: temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse + (*ForceDeleteWorkflowExecutionResponse)(nil), // 137: temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse + (*DeleteExecutionResponse)(nil), // 138: temporal.server.api.historyservice.v1.DeleteExecutionResponse + (*GetDLQTasksResponse)(nil), // 139: temporal.server.api.historyservice.v1.GetDLQTasksResponse + (*DeleteDLQTasksResponse)(nil), // 140: temporal.server.api.historyservice.v1.DeleteDLQTasksResponse + (*ListQueuesResponse)(nil), // 141: temporal.server.api.historyservice.v1.ListQueuesResponse + (*AddTasksResponse)(nil), // 142: temporal.server.api.historyservice.v1.AddTasksResponse + (*ListTasksResponse)(nil), // 143: temporal.server.api.historyservice.v1.ListTasksResponse + (*CompleteNexusOperationResponse)(nil), // 144: temporal.server.api.historyservice.v1.CompleteNexusOperationResponse + (*CompleteNexusOperationChasmResponse)(nil), // 145: temporal.server.api.historyservice.v1.CompleteNexusOperationChasmResponse + (*InvokeStateMachineMethodResponse)(nil), // 146: temporal.server.api.historyservice.v1.InvokeStateMachineMethodResponse + (*DeepHealthCheckResponse)(nil), // 147: temporal.server.api.historyservice.v1.DeepHealthCheckResponse + (*SyncWorkflowStateResponse)(nil), // 148: temporal.server.api.historyservice.v1.SyncWorkflowStateResponse + (*UpdateActivityOptionsResponse)(nil), // 149: temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse + (*PauseActivityResponse)(nil), // 150: temporal.server.api.historyservice.v1.PauseActivityResponse + (*UnpauseActivityResponse)(nil), // 151: temporal.server.api.historyservice.v1.UnpauseActivityResponse + (*ResetActivityResponse)(nil), // 152: temporal.server.api.historyservice.v1.ResetActivityResponse + (*PauseWorkflowExecutionResponse)(nil), // 153: temporal.server.api.historyservice.v1.PauseWorkflowExecutionResponse + (*UnpauseWorkflowExecutionResponse)(nil), // 154: temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionResponse + (*StartNexusOperationResponse)(nil), // 155: temporal.server.api.historyservice.v1.StartNexusOperationResponse + (*CancelNexusOperationResponse)(nil), // 156: temporal.server.api.historyservice.v1.CancelNexusOperationResponse + (*PollWorkflowExecutionTimeSkippingResponse)(nil), // 157: temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse } var file_temporal_server_api_historyservice_v1_service_proto_depIdxs = []int32{ 0, // 0: temporal.server.api.historyservice.v1.HistoryService.StartWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.StartWorkflowExecutionRequest 1, // 1: temporal.server.api.historyservice.v1.HistoryService.GetMutableState:input_type -> temporal.server.api.historyservice.v1.GetMutableStateRequest 2, // 2: temporal.server.api.historyservice.v1.HistoryService.PollMutableState:input_type -> temporal.server.api.historyservice.v1.PollMutableStateRequest - 3, // 3: temporal.server.api.historyservice.v1.HistoryService.ResetStickyTaskQueue:input_type -> temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest - 4, // 4: temporal.server.api.historyservice.v1.HistoryService.RecordWorkflowTaskStarted:input_type -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest - 5, // 5: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskStarted:input_type -> temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest - 6, // 6: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskCompleted:input_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest - 7, // 7: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskFailed:input_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest - 8, // 8: temporal.server.api.historyservice.v1.HistoryService.IsWorkflowTaskValid:input_type -> temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest - 9, // 9: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskHeartbeat:input_type -> temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest - 10, // 10: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCompleted:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest - 11, // 11: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskFailed:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest - 12, // 12: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCanceled:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest - 13, // 13: temporal.server.api.historyservice.v1.HistoryService.IsActivityTaskValid:input_type -> temporal.server.api.historyservice.v1.IsActivityTaskValidRequest - 14, // 14: temporal.server.api.historyservice.v1.HistoryService.SignalWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest - 15, // 15: temporal.server.api.historyservice.v1.HistoryService.SignalWithStartWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest - 16, // 16: temporal.server.api.historyservice.v1.HistoryService.ExecuteMultiOperation:input_type -> temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest - 17, // 17: temporal.server.api.historyservice.v1.HistoryService.RemoveSignalMutableState:input_type -> temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest - 18, // 18: temporal.server.api.historyservice.v1.HistoryService.TerminateWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest - 19, // 19: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest - 20, // 20: temporal.server.api.historyservice.v1.HistoryService.ResetWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest - 21, // 21: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecutionOptions:input_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest - 22, // 22: temporal.server.api.historyservice.v1.HistoryService.RequestCancelWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest - 23, // 23: temporal.server.api.historyservice.v1.HistoryService.ScheduleWorkflowTask:input_type -> temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest - 24, // 24: temporal.server.api.historyservice.v1.HistoryService.VerifyFirstWorkflowTaskScheduled:input_type -> temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest - 25, // 25: temporal.server.api.historyservice.v1.HistoryService.RecordChildExecutionCompleted:input_type -> temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest - 26, // 26: temporal.server.api.historyservice.v1.HistoryService.VerifyChildExecutionCompletionRecorded:input_type -> temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest - 27, // 27: temporal.server.api.historyservice.v1.HistoryService.DescribeWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest - 28, // 28: temporal.server.api.historyservice.v1.HistoryService.ReplicateEventsV2:input_type -> temporal.server.api.historyservice.v1.ReplicateEventsV2Request - 29, // 29: temporal.server.api.historyservice.v1.HistoryService.ReplicateWorkflowState:input_type -> temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest - 30, // 30: temporal.server.api.historyservice.v1.HistoryService.SyncShardStatus:input_type -> temporal.server.api.historyservice.v1.SyncShardStatusRequest - 31, // 31: temporal.server.api.historyservice.v1.HistoryService.SyncActivity:input_type -> temporal.server.api.historyservice.v1.SyncActivityRequest - 32, // 32: temporal.server.api.historyservice.v1.HistoryService.DescribeMutableState:input_type -> temporal.server.api.historyservice.v1.DescribeMutableStateRequest - 33, // 33: temporal.server.api.historyservice.v1.HistoryService.DescribeHistoryHost:input_type -> temporal.server.api.historyservice.v1.DescribeHistoryHostRequest - 34, // 34: temporal.server.api.historyservice.v1.HistoryService.CloseShard:input_type -> temporal.server.api.historyservice.v1.CloseShardRequest - 35, // 35: temporal.server.api.historyservice.v1.HistoryService.GetShard:input_type -> temporal.server.api.historyservice.v1.GetShardRequest - 36, // 36: temporal.server.api.historyservice.v1.HistoryService.RemoveTask:input_type -> temporal.server.api.historyservice.v1.RemoveTaskRequest - 37, // 37: temporal.server.api.historyservice.v1.HistoryService.GetReplicationMessages:input_type -> temporal.server.api.historyservice.v1.GetReplicationMessagesRequest - 38, // 38: temporal.server.api.historyservice.v1.HistoryService.GetDLQReplicationMessages:input_type -> temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest - 39, // 39: temporal.server.api.historyservice.v1.HistoryService.QueryWorkflow:input_type -> temporal.server.api.historyservice.v1.QueryWorkflowRequest - 40, // 40: temporal.server.api.historyservice.v1.HistoryService.ReapplyEvents:input_type -> temporal.server.api.historyservice.v1.ReapplyEventsRequest - 41, // 41: temporal.server.api.historyservice.v1.HistoryService.GetDLQMessages:input_type -> temporal.server.api.historyservice.v1.GetDLQMessagesRequest - 42, // 42: temporal.server.api.historyservice.v1.HistoryService.PurgeDLQMessages:input_type -> temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest - 43, // 43: temporal.server.api.historyservice.v1.HistoryService.MergeDLQMessages:input_type -> temporal.server.api.historyservice.v1.MergeDLQMessagesRequest - 44, // 44: temporal.server.api.historyservice.v1.HistoryService.RefreshWorkflowTasks:input_type -> temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest - 45, // 45: temporal.server.api.historyservice.v1.HistoryService.GenerateLastHistoryReplicationTasks:input_type -> temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest - 46, // 46: temporal.server.api.historyservice.v1.HistoryService.GetReplicationStatus:input_type -> temporal.server.api.historyservice.v1.GetReplicationStatusRequest - 47, // 47: temporal.server.api.historyservice.v1.HistoryService.RebuildMutableState:input_type -> temporal.server.api.historyservice.v1.RebuildMutableStateRequest - 48, // 48: temporal.server.api.historyservice.v1.HistoryService.ImportWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest - 49, // 49: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowVisibilityRecord:input_type -> temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest - 50, // 50: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest - 51, // 51: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionUpdate:input_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest - 52, // 52: temporal.server.api.historyservice.v1.HistoryService.StreamWorkflowReplicationMessages:input_type -> temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest - 53, // 53: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistory:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest - 54, // 54: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistoryReverse:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest - 55, // 55: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistoryV2:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request - 56, // 56: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistory:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest - 57, // 57: temporal.server.api.historyservice.v1.HistoryService.ForceDeleteWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest - 58, // 58: temporal.server.api.historyservice.v1.HistoryService.DeleteExecution:input_type -> temporal.server.api.historyservice.v1.DeleteExecutionRequest - 59, // 59: temporal.server.api.historyservice.v1.HistoryService.GetDLQTasks:input_type -> temporal.server.api.historyservice.v1.GetDLQTasksRequest - 60, // 60: temporal.server.api.historyservice.v1.HistoryService.DeleteDLQTasks:input_type -> temporal.server.api.historyservice.v1.DeleteDLQTasksRequest - 61, // 61: temporal.server.api.historyservice.v1.HistoryService.ListQueues:input_type -> temporal.server.api.historyservice.v1.ListQueuesRequest - 62, // 62: temporal.server.api.historyservice.v1.HistoryService.AddTasks:input_type -> temporal.server.api.historyservice.v1.AddTasksRequest - 63, // 63: temporal.server.api.historyservice.v1.HistoryService.ListTasks:input_type -> temporal.server.api.historyservice.v1.ListTasksRequest - 64, // 64: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperation:input_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationRequest - 65, // 65: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperationChasm:input_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest - 66, // 66: temporal.server.api.historyservice.v1.HistoryService.InvokeStateMachineMethod:input_type -> temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest - 67, // 67: temporal.server.api.historyservice.v1.HistoryService.DeepHealthCheck:input_type -> temporal.server.api.historyservice.v1.DeepHealthCheckRequest - 68, // 68: temporal.server.api.historyservice.v1.HistoryService.SyncWorkflowState:input_type -> temporal.server.api.historyservice.v1.SyncWorkflowStateRequest - 69, // 69: temporal.server.api.historyservice.v1.HistoryService.UpdateActivityOptions:input_type -> temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest - 70, // 70: temporal.server.api.historyservice.v1.HistoryService.PauseActivity:input_type -> temporal.server.api.historyservice.v1.PauseActivityRequest - 71, // 71: temporal.server.api.historyservice.v1.HistoryService.UnpauseActivity:input_type -> temporal.server.api.historyservice.v1.UnpauseActivityRequest - 72, // 72: temporal.server.api.historyservice.v1.HistoryService.ResetActivity:input_type -> temporal.server.api.historyservice.v1.ResetActivityRequest - 73, // 73: temporal.server.api.historyservice.v1.HistoryService.PauseWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest - 74, // 74: temporal.server.api.historyservice.v1.HistoryService.UnpauseWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest - 75, // 75: temporal.server.api.historyservice.v1.HistoryService.StartNexusOperation:input_type -> temporal.server.api.historyservice.v1.StartNexusOperationRequest - 76, // 76: temporal.server.api.historyservice.v1.HistoryService.CancelNexusOperation:input_type -> temporal.server.api.historyservice.v1.CancelNexusOperationRequest - 77, // 77: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionTimeSkipping:input_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest - 78, // 78: temporal.server.api.historyservice.v1.HistoryService.StartWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse - 79, // 79: temporal.server.api.historyservice.v1.HistoryService.GetMutableState:output_type -> temporal.server.api.historyservice.v1.GetMutableStateResponse - 80, // 80: temporal.server.api.historyservice.v1.HistoryService.PollMutableState:output_type -> temporal.server.api.historyservice.v1.PollMutableStateResponse - 81, // 81: temporal.server.api.historyservice.v1.HistoryService.ResetStickyTaskQueue:output_type -> temporal.server.api.historyservice.v1.ResetStickyTaskQueueResponse - 82, // 82: temporal.server.api.historyservice.v1.HistoryService.RecordWorkflowTaskStarted:output_type -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse - 83, // 83: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskStarted:output_type -> temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse - 84, // 84: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskCompleted:output_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse - 85, // 85: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskFailed:output_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedResponse - 86, // 86: temporal.server.api.historyservice.v1.HistoryService.IsWorkflowTaskValid:output_type -> temporal.server.api.historyservice.v1.IsWorkflowTaskValidResponse - 87, // 87: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskHeartbeat:output_type -> temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatResponse - 88, // 88: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCompleted:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCompletedResponse - 89, // 89: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskFailed:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskFailedResponse - 90, // 90: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCanceled:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCanceledResponse - 91, // 91: temporal.server.api.historyservice.v1.HistoryService.IsActivityTaskValid:output_type -> temporal.server.api.historyservice.v1.IsActivityTaskValidResponse - 92, // 92: temporal.server.api.historyservice.v1.HistoryService.SignalWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse - 93, // 93: temporal.server.api.historyservice.v1.HistoryService.SignalWithStartWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse - 94, // 94: temporal.server.api.historyservice.v1.HistoryService.ExecuteMultiOperation:output_type -> temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse - 95, // 95: temporal.server.api.historyservice.v1.HistoryService.RemoveSignalMutableState:output_type -> temporal.server.api.historyservice.v1.RemoveSignalMutableStateResponse - 96, // 96: temporal.server.api.historyservice.v1.HistoryService.TerminateWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.TerminateWorkflowExecutionResponse - 97, // 97: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.DeleteWorkflowExecutionResponse - 98, // 98: temporal.server.api.historyservice.v1.HistoryService.ResetWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ResetWorkflowExecutionResponse - 99, // 99: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecutionOptions:output_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse - 100, // 100: temporal.server.api.historyservice.v1.HistoryService.RequestCancelWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionResponse - 101, // 101: temporal.server.api.historyservice.v1.HistoryService.ScheduleWorkflowTask:output_type -> temporal.server.api.historyservice.v1.ScheduleWorkflowTaskResponse - 102, // 102: temporal.server.api.historyservice.v1.HistoryService.VerifyFirstWorkflowTaskScheduled:output_type -> temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledResponse - 103, // 103: temporal.server.api.historyservice.v1.HistoryService.RecordChildExecutionCompleted:output_type -> temporal.server.api.historyservice.v1.RecordChildExecutionCompletedResponse - 104, // 104: temporal.server.api.historyservice.v1.HistoryService.VerifyChildExecutionCompletionRecorded:output_type -> temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedResponse - 105, // 105: temporal.server.api.historyservice.v1.HistoryService.DescribeWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse - 106, // 106: temporal.server.api.historyservice.v1.HistoryService.ReplicateEventsV2:output_type -> temporal.server.api.historyservice.v1.ReplicateEventsV2Response - 107, // 107: temporal.server.api.historyservice.v1.HistoryService.ReplicateWorkflowState:output_type -> temporal.server.api.historyservice.v1.ReplicateWorkflowStateResponse - 108, // 108: temporal.server.api.historyservice.v1.HistoryService.SyncShardStatus:output_type -> temporal.server.api.historyservice.v1.SyncShardStatusResponse - 109, // 109: temporal.server.api.historyservice.v1.HistoryService.SyncActivity:output_type -> temporal.server.api.historyservice.v1.SyncActivityResponse - 110, // 110: temporal.server.api.historyservice.v1.HistoryService.DescribeMutableState:output_type -> temporal.server.api.historyservice.v1.DescribeMutableStateResponse - 111, // 111: temporal.server.api.historyservice.v1.HistoryService.DescribeHistoryHost:output_type -> temporal.server.api.historyservice.v1.DescribeHistoryHostResponse - 112, // 112: temporal.server.api.historyservice.v1.HistoryService.CloseShard:output_type -> temporal.server.api.historyservice.v1.CloseShardResponse - 113, // 113: temporal.server.api.historyservice.v1.HistoryService.GetShard:output_type -> temporal.server.api.historyservice.v1.GetShardResponse - 114, // 114: temporal.server.api.historyservice.v1.HistoryService.RemoveTask:output_type -> temporal.server.api.historyservice.v1.RemoveTaskResponse - 115, // 115: temporal.server.api.historyservice.v1.HistoryService.GetReplicationMessages:output_type -> temporal.server.api.historyservice.v1.GetReplicationMessagesResponse - 116, // 116: temporal.server.api.historyservice.v1.HistoryService.GetDLQReplicationMessages:output_type -> temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse - 117, // 117: temporal.server.api.historyservice.v1.HistoryService.QueryWorkflow:output_type -> temporal.server.api.historyservice.v1.QueryWorkflowResponse - 118, // 118: temporal.server.api.historyservice.v1.HistoryService.ReapplyEvents:output_type -> temporal.server.api.historyservice.v1.ReapplyEventsResponse - 119, // 119: temporal.server.api.historyservice.v1.HistoryService.GetDLQMessages:output_type -> temporal.server.api.historyservice.v1.GetDLQMessagesResponse - 120, // 120: temporal.server.api.historyservice.v1.HistoryService.PurgeDLQMessages:output_type -> temporal.server.api.historyservice.v1.PurgeDLQMessagesResponse - 121, // 121: temporal.server.api.historyservice.v1.HistoryService.MergeDLQMessages:output_type -> temporal.server.api.historyservice.v1.MergeDLQMessagesResponse - 122, // 122: temporal.server.api.historyservice.v1.HistoryService.RefreshWorkflowTasks:output_type -> temporal.server.api.historyservice.v1.RefreshWorkflowTasksResponse - 123, // 123: temporal.server.api.historyservice.v1.HistoryService.GenerateLastHistoryReplicationTasks:output_type -> temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksResponse - 124, // 124: temporal.server.api.historyservice.v1.HistoryService.GetReplicationStatus:output_type -> temporal.server.api.historyservice.v1.GetReplicationStatusResponse - 125, // 125: temporal.server.api.historyservice.v1.HistoryService.RebuildMutableState:output_type -> temporal.server.api.historyservice.v1.RebuildMutableStateResponse - 126, // 126: temporal.server.api.historyservice.v1.HistoryService.ImportWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ImportWorkflowExecutionResponse - 127, // 127: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowVisibilityRecord:output_type -> temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordResponse - 128, // 128: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse - 129, // 129: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionUpdate:output_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse - 130, // 130: temporal.server.api.historyservice.v1.HistoryService.StreamWorkflowReplicationMessages:output_type -> temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse - 131, // 131: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistory:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse - 132, // 132: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistoryReverse:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse - 133, // 133: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistoryV2:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response - 134, // 134: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistory:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse - 135, // 135: temporal.server.api.historyservice.v1.HistoryService.ForceDeleteWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse - 136, // 136: temporal.server.api.historyservice.v1.HistoryService.DeleteExecution:output_type -> temporal.server.api.historyservice.v1.DeleteExecutionResponse - 137, // 137: temporal.server.api.historyservice.v1.HistoryService.GetDLQTasks:output_type -> temporal.server.api.historyservice.v1.GetDLQTasksResponse - 138, // 138: temporal.server.api.historyservice.v1.HistoryService.DeleteDLQTasks:output_type -> temporal.server.api.historyservice.v1.DeleteDLQTasksResponse - 139, // 139: temporal.server.api.historyservice.v1.HistoryService.ListQueues:output_type -> temporal.server.api.historyservice.v1.ListQueuesResponse - 140, // 140: temporal.server.api.historyservice.v1.HistoryService.AddTasks:output_type -> temporal.server.api.historyservice.v1.AddTasksResponse - 141, // 141: temporal.server.api.historyservice.v1.HistoryService.ListTasks:output_type -> temporal.server.api.historyservice.v1.ListTasksResponse - 142, // 142: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperation:output_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationResponse - 143, // 143: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperationChasm:output_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationChasmResponse - 144, // 144: temporal.server.api.historyservice.v1.HistoryService.InvokeStateMachineMethod:output_type -> temporal.server.api.historyservice.v1.InvokeStateMachineMethodResponse - 145, // 145: temporal.server.api.historyservice.v1.HistoryService.DeepHealthCheck:output_type -> temporal.server.api.historyservice.v1.DeepHealthCheckResponse - 146, // 146: temporal.server.api.historyservice.v1.HistoryService.SyncWorkflowState:output_type -> temporal.server.api.historyservice.v1.SyncWorkflowStateResponse - 147, // 147: temporal.server.api.historyservice.v1.HistoryService.UpdateActivityOptions:output_type -> temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse - 148, // 148: temporal.server.api.historyservice.v1.HistoryService.PauseActivity:output_type -> temporal.server.api.historyservice.v1.PauseActivityResponse - 149, // 149: temporal.server.api.historyservice.v1.HistoryService.UnpauseActivity:output_type -> temporal.server.api.historyservice.v1.UnpauseActivityResponse - 150, // 150: temporal.server.api.historyservice.v1.HistoryService.ResetActivity:output_type -> temporal.server.api.historyservice.v1.ResetActivityResponse - 151, // 151: temporal.server.api.historyservice.v1.HistoryService.PauseWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.PauseWorkflowExecutionResponse - 152, // 152: temporal.server.api.historyservice.v1.HistoryService.UnpauseWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionResponse - 153, // 153: temporal.server.api.historyservice.v1.HistoryService.StartNexusOperation:output_type -> temporal.server.api.historyservice.v1.StartNexusOperationResponse - 154, // 154: temporal.server.api.historyservice.v1.HistoryService.CancelNexusOperation:output_type -> temporal.server.api.historyservice.v1.CancelNexusOperationResponse - 155, // 155: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionTimeSkipping:output_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse - 78, // [78:156] is the sub-list for method output_type - 0, // [0:78] is the sub-list for method input_type + 3, // 3: temporal.server.api.historyservice.v1.HistoryService.GetStreamReplaySlices:input_type -> temporal.server.api.historyservice.v1.GetStreamReplaySlicesRequest + 4, // 4: temporal.server.api.historyservice.v1.HistoryService.ResetStickyTaskQueue:input_type -> temporal.server.api.historyservice.v1.ResetStickyTaskQueueRequest + 5, // 5: temporal.server.api.historyservice.v1.HistoryService.RecordWorkflowTaskStarted:input_type -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedRequest + 6, // 6: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskStarted:input_type -> temporal.server.api.historyservice.v1.RecordActivityTaskStartedRequest + 7, // 7: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskCompleted:input_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedRequest + 8, // 8: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskFailed:input_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedRequest + 9, // 9: temporal.server.api.historyservice.v1.HistoryService.IsWorkflowTaskValid:input_type -> temporal.server.api.historyservice.v1.IsWorkflowTaskValidRequest + 10, // 10: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskHeartbeat:input_type -> temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatRequest + 11, // 11: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCompleted:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCompletedRequest + 12, // 12: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskFailed:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskFailedRequest + 13, // 13: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCanceled:input_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCanceledRequest + 14, // 14: temporal.server.api.historyservice.v1.HistoryService.IsActivityTaskValid:input_type -> temporal.server.api.historyservice.v1.IsActivityTaskValidRequest + 15, // 15: temporal.server.api.historyservice.v1.HistoryService.SignalWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.SignalWorkflowExecutionRequest + 16, // 16: temporal.server.api.historyservice.v1.HistoryService.SignalWithStartWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionRequest + 17, // 17: temporal.server.api.historyservice.v1.HistoryService.ExecuteMultiOperation:input_type -> temporal.server.api.historyservice.v1.ExecuteMultiOperationRequest + 18, // 18: temporal.server.api.historyservice.v1.HistoryService.RemoveSignalMutableState:input_type -> temporal.server.api.historyservice.v1.RemoveSignalMutableStateRequest + 19, // 19: temporal.server.api.historyservice.v1.HistoryService.TerminateWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.TerminateWorkflowExecutionRequest + 20, // 20: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.DeleteWorkflowExecutionRequest + 21, // 21: temporal.server.api.historyservice.v1.HistoryService.ResetWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ResetWorkflowExecutionRequest + 22, // 22: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecutionOptions:input_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsRequest + 23, // 23: temporal.server.api.historyservice.v1.HistoryService.RequestCancelWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionRequest + 24, // 24: temporal.server.api.historyservice.v1.HistoryService.ScheduleWorkflowTask:input_type -> temporal.server.api.historyservice.v1.ScheduleWorkflowTaskRequest + 25, // 25: temporal.server.api.historyservice.v1.HistoryService.VerifyFirstWorkflowTaskScheduled:input_type -> temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledRequest + 26, // 26: temporal.server.api.historyservice.v1.HistoryService.RecordChildExecutionCompleted:input_type -> temporal.server.api.historyservice.v1.RecordChildExecutionCompletedRequest + 27, // 27: temporal.server.api.historyservice.v1.HistoryService.VerifyChildExecutionCompletionRecorded:input_type -> temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedRequest + 28, // 28: temporal.server.api.historyservice.v1.HistoryService.DescribeWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.DescribeWorkflowExecutionRequest + 29, // 29: temporal.server.api.historyservice.v1.HistoryService.ReplicateEventsV2:input_type -> temporal.server.api.historyservice.v1.ReplicateEventsV2Request + 30, // 30: temporal.server.api.historyservice.v1.HistoryService.ReplicateWorkflowState:input_type -> temporal.server.api.historyservice.v1.ReplicateWorkflowStateRequest + 31, // 31: temporal.server.api.historyservice.v1.HistoryService.SyncShardStatus:input_type -> temporal.server.api.historyservice.v1.SyncShardStatusRequest + 32, // 32: temporal.server.api.historyservice.v1.HistoryService.SyncActivity:input_type -> temporal.server.api.historyservice.v1.SyncActivityRequest + 33, // 33: temporal.server.api.historyservice.v1.HistoryService.DescribeMutableState:input_type -> temporal.server.api.historyservice.v1.DescribeMutableStateRequest + 34, // 34: temporal.server.api.historyservice.v1.HistoryService.DescribeHistoryHost:input_type -> temporal.server.api.historyservice.v1.DescribeHistoryHostRequest + 35, // 35: temporal.server.api.historyservice.v1.HistoryService.CloseShard:input_type -> temporal.server.api.historyservice.v1.CloseShardRequest + 36, // 36: temporal.server.api.historyservice.v1.HistoryService.GetShard:input_type -> temporal.server.api.historyservice.v1.GetShardRequest + 37, // 37: temporal.server.api.historyservice.v1.HistoryService.RemoveTask:input_type -> temporal.server.api.historyservice.v1.RemoveTaskRequest + 38, // 38: temporal.server.api.historyservice.v1.HistoryService.GetReplicationMessages:input_type -> temporal.server.api.historyservice.v1.GetReplicationMessagesRequest + 39, // 39: temporal.server.api.historyservice.v1.HistoryService.GetDLQReplicationMessages:input_type -> temporal.server.api.historyservice.v1.GetDLQReplicationMessagesRequest + 40, // 40: temporal.server.api.historyservice.v1.HistoryService.QueryWorkflow:input_type -> temporal.server.api.historyservice.v1.QueryWorkflowRequest + 41, // 41: temporal.server.api.historyservice.v1.HistoryService.ReapplyEvents:input_type -> temporal.server.api.historyservice.v1.ReapplyEventsRequest + 42, // 42: temporal.server.api.historyservice.v1.HistoryService.GetDLQMessages:input_type -> temporal.server.api.historyservice.v1.GetDLQMessagesRequest + 43, // 43: temporal.server.api.historyservice.v1.HistoryService.PurgeDLQMessages:input_type -> temporal.server.api.historyservice.v1.PurgeDLQMessagesRequest + 44, // 44: temporal.server.api.historyservice.v1.HistoryService.MergeDLQMessages:input_type -> temporal.server.api.historyservice.v1.MergeDLQMessagesRequest + 45, // 45: temporal.server.api.historyservice.v1.HistoryService.RefreshWorkflowTasks:input_type -> temporal.server.api.historyservice.v1.RefreshWorkflowTasksRequest + 46, // 46: temporal.server.api.historyservice.v1.HistoryService.GenerateLastHistoryReplicationTasks:input_type -> temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksRequest + 47, // 47: temporal.server.api.historyservice.v1.HistoryService.GetReplicationStatus:input_type -> temporal.server.api.historyservice.v1.GetReplicationStatusRequest + 48, // 48: temporal.server.api.historyservice.v1.HistoryService.RebuildMutableState:input_type -> temporal.server.api.historyservice.v1.RebuildMutableStateRequest + 49, // 49: temporal.server.api.historyservice.v1.HistoryService.ImportWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ImportWorkflowExecutionRequest + 50, // 50: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowVisibilityRecord:input_type -> temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordRequest + 51, // 51: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionRequest + 52, // 52: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionUpdate:input_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateRequest + 53, // 53: temporal.server.api.historyservice.v1.HistoryService.StreamWorkflowReplicationMessages:input_type -> temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesRequest + 54, // 54: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistory:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryRequest + 55, // 55: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistoryReverse:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseRequest + 56, // 56: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistoryV2:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Request + 57, // 57: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistory:input_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryRequest + 58, // 58: temporal.server.api.historyservice.v1.HistoryService.ForceDeleteWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionRequest + 59, // 59: temporal.server.api.historyservice.v1.HistoryService.DeleteExecution:input_type -> temporal.server.api.historyservice.v1.DeleteExecutionRequest + 60, // 60: temporal.server.api.historyservice.v1.HistoryService.GetDLQTasks:input_type -> temporal.server.api.historyservice.v1.GetDLQTasksRequest + 61, // 61: temporal.server.api.historyservice.v1.HistoryService.DeleteDLQTasks:input_type -> temporal.server.api.historyservice.v1.DeleteDLQTasksRequest + 62, // 62: temporal.server.api.historyservice.v1.HistoryService.ListQueues:input_type -> temporal.server.api.historyservice.v1.ListQueuesRequest + 63, // 63: temporal.server.api.historyservice.v1.HistoryService.AddTasks:input_type -> temporal.server.api.historyservice.v1.AddTasksRequest + 64, // 64: temporal.server.api.historyservice.v1.HistoryService.ListTasks:input_type -> temporal.server.api.historyservice.v1.ListTasksRequest + 65, // 65: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperation:input_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationRequest + 66, // 66: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperationChasm:input_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationChasmRequest + 67, // 67: temporal.server.api.historyservice.v1.HistoryService.InvokeStateMachineMethod:input_type -> temporal.server.api.historyservice.v1.InvokeStateMachineMethodRequest + 68, // 68: temporal.server.api.historyservice.v1.HistoryService.DeepHealthCheck:input_type -> temporal.server.api.historyservice.v1.DeepHealthCheckRequest + 69, // 69: temporal.server.api.historyservice.v1.HistoryService.SyncWorkflowState:input_type -> temporal.server.api.historyservice.v1.SyncWorkflowStateRequest + 70, // 70: temporal.server.api.historyservice.v1.HistoryService.UpdateActivityOptions:input_type -> temporal.server.api.historyservice.v1.UpdateActivityOptionsRequest + 71, // 71: temporal.server.api.historyservice.v1.HistoryService.PauseActivity:input_type -> temporal.server.api.historyservice.v1.PauseActivityRequest + 72, // 72: temporal.server.api.historyservice.v1.HistoryService.UnpauseActivity:input_type -> temporal.server.api.historyservice.v1.UnpauseActivityRequest + 73, // 73: temporal.server.api.historyservice.v1.HistoryService.ResetActivity:input_type -> temporal.server.api.historyservice.v1.ResetActivityRequest + 74, // 74: temporal.server.api.historyservice.v1.HistoryService.PauseWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.PauseWorkflowExecutionRequest + 75, // 75: temporal.server.api.historyservice.v1.HistoryService.UnpauseWorkflowExecution:input_type -> temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionRequest + 76, // 76: temporal.server.api.historyservice.v1.HistoryService.StartNexusOperation:input_type -> temporal.server.api.historyservice.v1.StartNexusOperationRequest + 77, // 77: temporal.server.api.historyservice.v1.HistoryService.CancelNexusOperation:input_type -> temporal.server.api.historyservice.v1.CancelNexusOperationRequest + 78, // 78: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionTimeSkipping:input_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingRequest + 79, // 79: temporal.server.api.historyservice.v1.HistoryService.StartWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.StartWorkflowExecutionResponse + 80, // 80: temporal.server.api.historyservice.v1.HistoryService.GetMutableState:output_type -> temporal.server.api.historyservice.v1.GetMutableStateResponse + 81, // 81: temporal.server.api.historyservice.v1.HistoryService.PollMutableState:output_type -> temporal.server.api.historyservice.v1.PollMutableStateResponse + 82, // 82: temporal.server.api.historyservice.v1.HistoryService.GetStreamReplaySlices:output_type -> temporal.server.api.historyservice.v1.GetStreamReplaySlicesResponse + 83, // 83: temporal.server.api.historyservice.v1.HistoryService.ResetStickyTaskQueue:output_type -> temporal.server.api.historyservice.v1.ResetStickyTaskQueueResponse + 84, // 84: temporal.server.api.historyservice.v1.HistoryService.RecordWorkflowTaskStarted:output_type -> temporal.server.api.historyservice.v1.RecordWorkflowTaskStartedResponse + 85, // 85: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskStarted:output_type -> temporal.server.api.historyservice.v1.RecordActivityTaskStartedResponse + 86, // 86: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskCompleted:output_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskCompletedResponse + 87, // 87: temporal.server.api.historyservice.v1.HistoryService.RespondWorkflowTaskFailed:output_type -> temporal.server.api.historyservice.v1.RespondWorkflowTaskFailedResponse + 88, // 88: temporal.server.api.historyservice.v1.HistoryService.IsWorkflowTaskValid:output_type -> temporal.server.api.historyservice.v1.IsWorkflowTaskValidResponse + 89, // 89: temporal.server.api.historyservice.v1.HistoryService.RecordActivityTaskHeartbeat:output_type -> temporal.server.api.historyservice.v1.RecordActivityTaskHeartbeatResponse + 90, // 90: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCompleted:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCompletedResponse + 91, // 91: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskFailed:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskFailedResponse + 92, // 92: temporal.server.api.historyservice.v1.HistoryService.RespondActivityTaskCanceled:output_type -> temporal.server.api.historyservice.v1.RespondActivityTaskCanceledResponse + 93, // 93: temporal.server.api.historyservice.v1.HistoryService.IsActivityTaskValid:output_type -> temporal.server.api.historyservice.v1.IsActivityTaskValidResponse + 94, // 94: temporal.server.api.historyservice.v1.HistoryService.SignalWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.SignalWorkflowExecutionResponse + 95, // 95: temporal.server.api.historyservice.v1.HistoryService.SignalWithStartWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.SignalWithStartWorkflowExecutionResponse + 96, // 96: temporal.server.api.historyservice.v1.HistoryService.ExecuteMultiOperation:output_type -> temporal.server.api.historyservice.v1.ExecuteMultiOperationResponse + 97, // 97: temporal.server.api.historyservice.v1.HistoryService.RemoveSignalMutableState:output_type -> temporal.server.api.historyservice.v1.RemoveSignalMutableStateResponse + 98, // 98: temporal.server.api.historyservice.v1.HistoryService.TerminateWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.TerminateWorkflowExecutionResponse + 99, // 99: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.DeleteWorkflowExecutionResponse + 100, // 100: temporal.server.api.historyservice.v1.HistoryService.ResetWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ResetWorkflowExecutionResponse + 101, // 101: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecutionOptions:output_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionOptionsResponse + 102, // 102: temporal.server.api.historyservice.v1.HistoryService.RequestCancelWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.RequestCancelWorkflowExecutionResponse + 103, // 103: temporal.server.api.historyservice.v1.HistoryService.ScheduleWorkflowTask:output_type -> temporal.server.api.historyservice.v1.ScheduleWorkflowTaskResponse + 104, // 104: temporal.server.api.historyservice.v1.HistoryService.VerifyFirstWorkflowTaskScheduled:output_type -> temporal.server.api.historyservice.v1.VerifyFirstWorkflowTaskScheduledResponse + 105, // 105: temporal.server.api.historyservice.v1.HistoryService.RecordChildExecutionCompleted:output_type -> temporal.server.api.historyservice.v1.RecordChildExecutionCompletedResponse + 106, // 106: temporal.server.api.historyservice.v1.HistoryService.VerifyChildExecutionCompletionRecorded:output_type -> temporal.server.api.historyservice.v1.VerifyChildExecutionCompletionRecordedResponse + 107, // 107: temporal.server.api.historyservice.v1.HistoryService.DescribeWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.DescribeWorkflowExecutionResponse + 108, // 108: temporal.server.api.historyservice.v1.HistoryService.ReplicateEventsV2:output_type -> temporal.server.api.historyservice.v1.ReplicateEventsV2Response + 109, // 109: temporal.server.api.historyservice.v1.HistoryService.ReplicateWorkflowState:output_type -> temporal.server.api.historyservice.v1.ReplicateWorkflowStateResponse + 110, // 110: temporal.server.api.historyservice.v1.HistoryService.SyncShardStatus:output_type -> temporal.server.api.historyservice.v1.SyncShardStatusResponse + 111, // 111: temporal.server.api.historyservice.v1.HistoryService.SyncActivity:output_type -> temporal.server.api.historyservice.v1.SyncActivityResponse + 112, // 112: temporal.server.api.historyservice.v1.HistoryService.DescribeMutableState:output_type -> temporal.server.api.historyservice.v1.DescribeMutableStateResponse + 113, // 113: temporal.server.api.historyservice.v1.HistoryService.DescribeHistoryHost:output_type -> temporal.server.api.historyservice.v1.DescribeHistoryHostResponse + 114, // 114: temporal.server.api.historyservice.v1.HistoryService.CloseShard:output_type -> temporal.server.api.historyservice.v1.CloseShardResponse + 115, // 115: temporal.server.api.historyservice.v1.HistoryService.GetShard:output_type -> temporal.server.api.historyservice.v1.GetShardResponse + 116, // 116: temporal.server.api.historyservice.v1.HistoryService.RemoveTask:output_type -> temporal.server.api.historyservice.v1.RemoveTaskResponse + 117, // 117: temporal.server.api.historyservice.v1.HistoryService.GetReplicationMessages:output_type -> temporal.server.api.historyservice.v1.GetReplicationMessagesResponse + 118, // 118: temporal.server.api.historyservice.v1.HistoryService.GetDLQReplicationMessages:output_type -> temporal.server.api.historyservice.v1.GetDLQReplicationMessagesResponse + 119, // 119: temporal.server.api.historyservice.v1.HistoryService.QueryWorkflow:output_type -> temporal.server.api.historyservice.v1.QueryWorkflowResponse + 120, // 120: temporal.server.api.historyservice.v1.HistoryService.ReapplyEvents:output_type -> temporal.server.api.historyservice.v1.ReapplyEventsResponse + 121, // 121: temporal.server.api.historyservice.v1.HistoryService.GetDLQMessages:output_type -> temporal.server.api.historyservice.v1.GetDLQMessagesResponse + 122, // 122: temporal.server.api.historyservice.v1.HistoryService.PurgeDLQMessages:output_type -> temporal.server.api.historyservice.v1.PurgeDLQMessagesResponse + 123, // 123: temporal.server.api.historyservice.v1.HistoryService.MergeDLQMessages:output_type -> temporal.server.api.historyservice.v1.MergeDLQMessagesResponse + 124, // 124: temporal.server.api.historyservice.v1.HistoryService.RefreshWorkflowTasks:output_type -> temporal.server.api.historyservice.v1.RefreshWorkflowTasksResponse + 125, // 125: temporal.server.api.historyservice.v1.HistoryService.GenerateLastHistoryReplicationTasks:output_type -> temporal.server.api.historyservice.v1.GenerateLastHistoryReplicationTasksResponse + 126, // 126: temporal.server.api.historyservice.v1.HistoryService.GetReplicationStatus:output_type -> temporal.server.api.historyservice.v1.GetReplicationStatusResponse + 127, // 127: temporal.server.api.historyservice.v1.HistoryService.RebuildMutableState:output_type -> temporal.server.api.historyservice.v1.RebuildMutableStateResponse + 128, // 128: temporal.server.api.historyservice.v1.HistoryService.ImportWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ImportWorkflowExecutionResponse + 129, // 129: temporal.server.api.historyservice.v1.HistoryService.DeleteWorkflowVisibilityRecord:output_type -> temporal.server.api.historyservice.v1.DeleteWorkflowVisibilityRecordResponse + 130, // 130: temporal.server.api.historyservice.v1.HistoryService.UpdateWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.UpdateWorkflowExecutionResponse + 131, // 131: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionUpdate:output_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionUpdateResponse + 132, // 132: temporal.server.api.historyservice.v1.HistoryService.StreamWorkflowReplicationMessages:output_type -> temporal.server.api.historyservice.v1.StreamWorkflowReplicationMessagesResponse + 133, // 133: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistory:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryResponse + 134, // 134: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionHistoryReverse:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionHistoryReverseResponse + 135, // 135: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistoryV2:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryV2Response + 136, // 136: temporal.server.api.historyservice.v1.HistoryService.GetWorkflowExecutionRawHistory:output_type -> temporal.server.api.historyservice.v1.GetWorkflowExecutionRawHistoryResponse + 137, // 137: temporal.server.api.historyservice.v1.HistoryService.ForceDeleteWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.ForceDeleteWorkflowExecutionResponse + 138, // 138: temporal.server.api.historyservice.v1.HistoryService.DeleteExecution:output_type -> temporal.server.api.historyservice.v1.DeleteExecutionResponse + 139, // 139: temporal.server.api.historyservice.v1.HistoryService.GetDLQTasks:output_type -> temporal.server.api.historyservice.v1.GetDLQTasksResponse + 140, // 140: temporal.server.api.historyservice.v1.HistoryService.DeleteDLQTasks:output_type -> temporal.server.api.historyservice.v1.DeleteDLQTasksResponse + 141, // 141: temporal.server.api.historyservice.v1.HistoryService.ListQueues:output_type -> temporal.server.api.historyservice.v1.ListQueuesResponse + 142, // 142: temporal.server.api.historyservice.v1.HistoryService.AddTasks:output_type -> temporal.server.api.historyservice.v1.AddTasksResponse + 143, // 143: temporal.server.api.historyservice.v1.HistoryService.ListTasks:output_type -> temporal.server.api.historyservice.v1.ListTasksResponse + 144, // 144: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperation:output_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationResponse + 145, // 145: temporal.server.api.historyservice.v1.HistoryService.CompleteNexusOperationChasm:output_type -> temporal.server.api.historyservice.v1.CompleteNexusOperationChasmResponse + 146, // 146: temporal.server.api.historyservice.v1.HistoryService.InvokeStateMachineMethod:output_type -> temporal.server.api.historyservice.v1.InvokeStateMachineMethodResponse + 147, // 147: temporal.server.api.historyservice.v1.HistoryService.DeepHealthCheck:output_type -> temporal.server.api.historyservice.v1.DeepHealthCheckResponse + 148, // 148: temporal.server.api.historyservice.v1.HistoryService.SyncWorkflowState:output_type -> temporal.server.api.historyservice.v1.SyncWorkflowStateResponse + 149, // 149: temporal.server.api.historyservice.v1.HistoryService.UpdateActivityOptions:output_type -> temporal.server.api.historyservice.v1.UpdateActivityOptionsResponse + 150, // 150: temporal.server.api.historyservice.v1.HistoryService.PauseActivity:output_type -> temporal.server.api.historyservice.v1.PauseActivityResponse + 151, // 151: temporal.server.api.historyservice.v1.HistoryService.UnpauseActivity:output_type -> temporal.server.api.historyservice.v1.UnpauseActivityResponse + 152, // 152: temporal.server.api.historyservice.v1.HistoryService.ResetActivity:output_type -> temporal.server.api.historyservice.v1.ResetActivityResponse + 153, // 153: temporal.server.api.historyservice.v1.HistoryService.PauseWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.PauseWorkflowExecutionResponse + 154, // 154: temporal.server.api.historyservice.v1.HistoryService.UnpauseWorkflowExecution:output_type -> temporal.server.api.historyservice.v1.UnpauseWorkflowExecutionResponse + 155, // 155: temporal.server.api.historyservice.v1.HistoryService.StartNexusOperation:output_type -> temporal.server.api.historyservice.v1.StartNexusOperationResponse + 156, // 156: temporal.server.api.historyservice.v1.HistoryService.CancelNexusOperation:output_type -> temporal.server.api.historyservice.v1.CancelNexusOperationResponse + 157, // 157: temporal.server.api.historyservice.v1.HistoryService.PollWorkflowExecutionTimeSkipping:output_type -> temporal.server.api.historyservice.v1.PollWorkflowExecutionTimeSkippingResponse + 79, // [79:158] is the sub-list for method output_type + 0, // [0:79] 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/historyservice/v1/service_grpc.pb.go b/api/historyservice/v1/service_grpc.pb.go index 79e609f4a33..a6c13f620cd 100644 --- a/api/historyservice/v1/service_grpc.pb.go +++ b/api/historyservice/v1/service_grpc.pb.go @@ -23,6 +23,7 @@ const ( HistoryService_StartWorkflowExecution_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/StartWorkflowExecution" HistoryService_GetMutableState_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/GetMutableState" HistoryService_PollMutableState_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/PollMutableState" + HistoryService_GetStreamReplaySlices_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/GetStreamReplaySlices" HistoryService_ResetStickyTaskQueue_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/ResetStickyTaskQueue" HistoryService_RecordWorkflowTaskStarted_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/RecordWorkflowTaskStarted" HistoryService_RecordActivityTaskStarted_FullMethodName = "/temporal.server.api.historyservice.v1.HistoryService/RecordActivityTaskStarted" @@ -117,6 +118,10 @@ type HistoryServiceClient interface { // It fails with 'EntityNotExistError' if specified workflow execution in unknown to the service. // It returns CurrentBranchChangedError if the workflow version branch has changed. PollMutableState(ctx context.Context, in *PollMutableStateRequest, opts ...grpc.CallOption) (*PollMutableStateResponse, error) + // Returns the stream ranges the workflow's completed tasks recorded, re-read + // from their streams and tagged with the event that recorded each, so a task + // built without RecordWorkflowTaskStarted can still replay a consumer. + GetStreamReplaySlices(ctx context.Context, in *GetStreamReplaySlicesRequest, opts ...grpc.CallOption) (*GetStreamReplaySlicesResponse, error) // Reset the sticky task queue related information in mutable state of a given workflow. // Things cleared are: // 1. StickyTaskQueue @@ -428,6 +433,15 @@ func (c *historyServiceClient) PollMutableState(ctx context.Context, in *PollMut return out, nil } +func (c *historyServiceClient) GetStreamReplaySlices(ctx context.Context, in *GetStreamReplaySlicesRequest, opts ...grpc.CallOption) (*GetStreamReplaySlicesResponse, error) { + out := new(GetStreamReplaySlicesResponse) + err := c.cc.Invoke(ctx, HistoryService_GetStreamReplaySlices_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *historyServiceClient) ResetStickyTaskQueue(ctx context.Context, in *ResetStickyTaskQueueRequest, opts ...grpc.CallOption) (*ResetStickyTaskQueueResponse, error) { out := new(ResetStickyTaskQueueResponse) err := c.cc.Invoke(ctx, HistoryService_ResetStickyTaskQueue_FullMethodName, in, out, opts...) @@ -1142,6 +1156,10 @@ type HistoryServiceServer interface { // It fails with 'EntityNotExistError' if specified workflow execution in unknown to the service. // It returns CurrentBranchChangedError if the workflow version branch has changed. PollMutableState(context.Context, *PollMutableStateRequest) (*PollMutableStateResponse, error) + // Returns the stream ranges the workflow's completed tasks recorded, re-read + // from their streams and tagged with the event that recorded each, so a task + // built without RecordWorkflowTaskStarted can still replay a consumer. + GetStreamReplaySlices(context.Context, *GetStreamReplaySlicesRequest) (*GetStreamReplaySlicesResponse, error) // Reset the sticky task queue related information in mutable state of a given workflow. // Things cleared are: // 1. StickyTaskQueue @@ -1432,6 +1450,9 @@ func (UnimplementedHistoryServiceServer) GetMutableState(context.Context, *GetMu func (UnimplementedHistoryServiceServer) PollMutableState(context.Context, *PollMutableStateRequest) (*PollMutableStateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PollMutableState not implemented") } +func (UnimplementedHistoryServiceServer) GetStreamReplaySlices(context.Context, *GetStreamReplaySlicesRequest) (*GetStreamReplaySlicesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStreamReplaySlices not implemented") +} func (UnimplementedHistoryServiceServer) ResetStickyTaskQueue(context.Context, *ResetStickyTaskQueueRequest) (*ResetStickyTaskQueueResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ResetStickyTaskQueue not implemented") } @@ -1724,6 +1745,24 @@ func _HistoryService_PollMutableState_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _HistoryService_GetStreamReplaySlices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetStreamReplaySlicesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HistoryServiceServer).GetStreamReplaySlices(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: HistoryService_GetStreamReplaySlices_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HistoryServiceServer).GetStreamReplaySlices(ctx, req.(*GetStreamReplaySlicesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _HistoryService_ResetStickyTaskQueue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ResetStickyTaskQueueRequest) if err := dec(in); err != nil { @@ -3101,6 +3140,10 @@ var HistoryService_ServiceDesc = grpc.ServiceDesc{ MethodName: "PollMutableState", Handler: _HistoryService_PollMutableState_Handler, }, + { + MethodName: "GetStreamReplaySlices", + Handler: _HistoryService_GetStreamReplaySlices_Handler, + }, { MethodName: "ResetStickyTaskQueue", Handler: _HistoryService_ResetStickyTaskQueue_Handler, diff --git a/api/historyservicemock/v1/service_grpc.pb.mock.go b/api/historyservicemock/v1/service_grpc.pb.mock.go index 6f4d8d32ff7..421c6c539fa 100644 --- a/api/historyservicemock/v1/service_grpc.pb.mock.go +++ b/api/historyservicemock/v1/service_grpc.pb.mock.go @@ -503,6 +503,26 @@ func (mr *MockHistoryServiceClientMockRecorder) GetShard(ctx, in any, opts ...an return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShard", reflect.TypeOf((*MockHistoryServiceClient)(nil).GetShard), varargs...) } +// GetStreamReplaySlices mocks base method. +func (m *MockHistoryServiceClient) GetStreamReplaySlices(ctx context.Context, in *historyservice.GetStreamReplaySlicesRequest, opts ...grpc.CallOption) (*historyservice.GetStreamReplaySlicesResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, in} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "GetStreamReplaySlices", varargs...) + ret0, _ := ret[0].(*historyservice.GetStreamReplaySlicesResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStreamReplaySlices indicates an expected call of GetStreamReplaySlices. +func (mr *MockHistoryServiceClientMockRecorder) GetStreamReplaySlices(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, "GetStreamReplaySlices", reflect.TypeOf((*MockHistoryServiceClient)(nil).GetStreamReplaySlices), varargs...) +} + // GetWorkflowExecutionHistory mocks base method. func (m *MockHistoryServiceClient) GetWorkflowExecutionHistory(ctx context.Context, in *historyservice.GetWorkflowExecutionHistoryRequest, opts ...grpc.CallOption) (*historyservice.GetWorkflowExecutionHistoryResponse, error) { m.ctrl.T.Helper() @@ -2110,6 +2130,21 @@ func (mr *MockHistoryServiceServerMockRecorder) GetShard(arg0, arg1 any) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShard", reflect.TypeOf((*MockHistoryServiceServer)(nil).GetShard), arg0, arg1) } +// GetStreamReplaySlices mocks base method. +func (m *MockHistoryServiceServer) GetStreamReplaySlices(arg0 context.Context, arg1 *historyservice.GetStreamReplaySlicesRequest) (*historyservice.GetStreamReplaySlicesResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStreamReplaySlices", arg0, arg1) + ret0, _ := ret[0].(*historyservice.GetStreamReplaySlicesResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStreamReplaySlices indicates an expected call of GetStreamReplaySlices. +func (mr *MockHistoryServiceServerMockRecorder) GetStreamReplaySlices(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStreamReplaySlices", reflect.TypeOf((*MockHistoryServiceServer)(nil).GetStreamReplaySlices), arg0, arg1) +} + // GetWorkflowExecutionHistory mocks base method. func (m *MockHistoryServiceServer) GetWorkflowExecutionHistory(arg0 context.Context, arg1 *historyservice.GetWorkflowExecutionHistoryRequest) (*historyservice.GetWorkflowExecutionHistoryResponse, error) { m.ctrl.T.Helper() diff --git a/api/matchingservice/v1/request_response.pb.go b/api/matchingservice/v1/request_response.pb.go index 4a2f7325773..bbdbe0254c9 100644 --- a/api/matchingservice/v1/request_response.pb.go +++ b/api/matchingservice/v1/request_response.pb.go @@ -12,22 +12,23 @@ import ( unsafe "unsafe" v11 "go.temporal.io/api/common/v1" - v112 "go.temporal.io/api/deployment/v1" - v19 "go.temporal.io/api/enums/v1" - v114 "go.temporal.io/api/failure/v1" + v113 "go.temporal.io/api/deployment/v1" + v110 "go.temporal.io/api/enums/v1" + v115 "go.temporal.io/api/failure/v1" v16 "go.temporal.io/api/history/v1" - v113 "go.temporal.io/api/nexus/v1" + v114 "go.temporal.io/api/nexus/v1" v15 "go.temporal.io/api/protocol/v1" v12 "go.temporal.io/api/query/v1" + v17 "go.temporal.io/api/stream/v1" v14 "go.temporal.io/api/taskqueue/v1" - v115 "go.temporal.io/api/worker/v1" + v116 "go.temporal.io/api/worker/v1" v1 "go.temporal.io/api/workflowservice/v1" - v17 "go.temporal.io/server/api/clock/v1" - v110 "go.temporal.io/server/api/deployment/v1" - v116 "go.temporal.io/server/api/enums/v1" + v18 "go.temporal.io/server/api/clock/v1" + v111 "go.temporal.io/server/api/deployment/v1" + v117 "go.temporal.io/server/api/enums/v1" v13 "go.temporal.io/server/api/history/v1" - v111 "go.temporal.io/server/api/persistence/v1" - v18 "go.temporal.io/server/api/taskqueue/v1" + v112 "go.temporal.io/server/api/persistence/v1" + v19 "go.temporal.io/server/api/taskqueue/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" @@ -145,7 +146,11 @@ type PollWorkflowTaskQueueResponse struct { PollerScalingDecision *v14.PollerScalingDecision `protobuf:"bytes,21,opt,name=poller_scaling_decision,json=pollerScalingDecision,proto3" json:"poller_scaling_decision,omitempty"` // Raw history bytes sent from matching service when history.sendRawHistoryBetweenInternalServices is enabled. // Matching client will deserialize this to History when it receives the response. - RawHistory *v16.History `protobuf:"bytes,22,opt,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` + RawHistory *v16.History `protobuf:"bytes,22,opt,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + StreamSlices []*v17.StreamSlice `protobuf:"bytes,23,rep,name=stream_slices,json=streamSlices,proto3" json:"stream_slices,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -327,6 +332,13 @@ func (x *PollWorkflowTaskQueueResponse) GetRawHistory() *v16.History { return nil } +func (x *PollWorkflowTaskQueueResponse) GetStreamSlices() []*v17.StreamSlice { + if x != nil { + return x.StreamSlices + } + return nil +} + // PollWorkflowTaskQueueResponseWithRawHistory is wire-compatible with PollWorkflowTaskQueueResponse. // // WIRE COMPATIBILITY PATTERN: @@ -374,7 +386,11 @@ type PollWorkflowTaskQueueResponseWithRawHistory struct { // Raw history bytes. Each element is a proto-encoded batch of history events. // When matching client deserializes this to PollWorkflowTaskQueueResponse, this field // will be automatically deserialized to the raw_history field as History. - RawHistory [][]byte `protobuf:"bytes,22,rep,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` + RawHistory [][]byte `protobuf:"bytes,22,rep,name=raw_history,json=rawHistory,proto3" json:"raw_history,omitempty"` + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + StreamSlices []*v17.StreamSlice `protobuf:"bytes,23,rep,name=stream_slices,json=streamSlices,proto3" json:"stream_slices,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -556,6 +572,13 @@ func (x *PollWorkflowTaskQueueResponseWithRawHistory) GetRawHistory() [][]byte { return nil } +func (x *PollWorkflowTaskQueueResponseWithRawHistory) GetStreamSlices() []*v17.StreamSlice { + if x != nil { + return x.StreamSlices + } + return nil +} + type PollActivityTaskQueueRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` @@ -846,11 +869,11 @@ type AddWorkflowTaskRequest struct { // // aip.dev/not-precedent: "to" is used to indicate interval. --) ScheduleToStartTimeout *durationpb.Duration `protobuf:"bytes,5,opt,name=schedule_to_start_timeout,json=scheduleToStartTimeout,proto3" json:"schedule_to_start_timeout,omitempty"` - Clock *v17.VectorClock `protobuf:"bytes,9,opt,name=clock,proto3" json:"clock,omitempty"` + Clock *v18.VectorClock `protobuf:"bytes,9,opt,name=clock,proto3" json:"clock,omitempty"` // How this task should be directed by matching. (Missing means the default // for TaskVersionDirective, which is unversioned.) - VersionDirective *v18.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` - ForwardInfo *v18.TaskForwardInfo `protobuf:"bytes,11,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` + VersionDirective *v19.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` + ForwardInfo *v19.TaskForwardInfo `protobuf:"bytes,11,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` Priority *v11.Priority `protobuf:"bytes,12,opt,name=priority,proto3" json:"priority,omitempty"` // Stamp value from when the workflow task was scheduled. Used to validate the task is still relevant. Stamp int32 `protobuf:"varint,13,opt,name=stamp,proto3" json:"stamp,omitempty"` @@ -923,21 +946,21 @@ func (x *AddWorkflowTaskRequest) GetScheduleToStartTimeout() *durationpb.Duratio return nil } -func (x *AddWorkflowTaskRequest) GetClock() *v17.VectorClock { +func (x *AddWorkflowTaskRequest) GetClock() *v18.VectorClock { if x != nil { return x.Clock } return nil } -func (x *AddWorkflowTaskRequest) GetVersionDirective() *v18.TaskVersionDirective { +func (x *AddWorkflowTaskRequest) GetVersionDirective() *v19.TaskVersionDirective { if x != nil { return x.VersionDirective } return nil } -func (x *AddWorkflowTaskRequest) GetForwardInfo() *v18.TaskForwardInfo { +func (x *AddWorkflowTaskRequest) GetForwardInfo() *v19.TaskForwardInfo { if x != nil { return x.ForwardInfo } @@ -1014,11 +1037,11 @@ type AddActivityTaskRequest struct { // // aip.dev/not-precedent: "to" is used to indicate interval. --) ScheduleToStartTimeout *durationpb.Duration `protobuf:"bytes,6,opt,name=schedule_to_start_timeout,json=scheduleToStartTimeout,proto3" json:"schedule_to_start_timeout,omitempty"` - Clock *v17.VectorClock `protobuf:"bytes,9,opt,name=clock,proto3" json:"clock,omitempty"` + Clock *v18.VectorClock `protobuf:"bytes,9,opt,name=clock,proto3" json:"clock,omitempty"` // How this task should be directed by matching. (Missing means the default // for TaskVersionDirective, which is unversioned.) - VersionDirective *v18.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` - ForwardInfo *v18.TaskForwardInfo `protobuf:"bytes,11,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` + VersionDirective *v19.TaskVersionDirective `protobuf:"bytes,10,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` + ForwardInfo *v19.TaskForwardInfo `protobuf:"bytes,11,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` Stamp int32 `protobuf:"varint,12,opt,name=stamp,proto3" json:"stamp,omitempty"` Priority *v11.Priority `protobuf:"bytes,13,opt,name=priority,proto3" json:"priority,omitempty"` // Reference to the Chasm component for activity execution (if applicable). For standalone activities, all @@ -1094,21 +1117,21 @@ func (x *AddActivityTaskRequest) GetScheduleToStartTimeout() *durationpb.Duratio return nil } -func (x *AddActivityTaskRequest) GetClock() *v17.VectorClock { +func (x *AddActivityTaskRequest) GetClock() *v18.VectorClock { if x != nil { return x.Clock } return nil } -func (x *AddActivityTaskRequest) GetVersionDirective() *v18.TaskVersionDirective { +func (x *AddActivityTaskRequest) GetVersionDirective() *v19.TaskVersionDirective { if x != nil { return x.VersionDirective } return nil } -func (x *AddActivityTaskRequest) GetForwardInfo() *v18.TaskForwardInfo { +func (x *AddActivityTaskRequest) GetForwardInfo() *v19.TaskForwardInfo { if x != nil { return x.ForwardInfo } @@ -1189,8 +1212,8 @@ type QueryWorkflowRequest struct { QueryRequest *v1.QueryWorkflowRequest `protobuf:"bytes,3,opt,name=query_request,json=queryRequest,proto3" json:"query_request,omitempty"` // How this task should be directed by matching. (Missing means the default // for TaskVersionDirective, which is unversioned.) - VersionDirective *v18.TaskVersionDirective `protobuf:"bytes,5,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` - ForwardInfo *v18.TaskForwardInfo `protobuf:"bytes,6,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` + VersionDirective *v19.TaskVersionDirective `protobuf:"bytes,5,opt,name=version_directive,json=versionDirective,proto3" json:"version_directive,omitempty"` + ForwardInfo *v19.TaskForwardInfo `protobuf:"bytes,6,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` Priority *v11.Priority `protobuf:"bytes,7,opt,name=priority,proto3" json:"priority,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1247,14 +1270,14 @@ func (x *QueryWorkflowRequest) GetQueryRequest() *v1.QueryWorkflowRequest { return nil } -func (x *QueryWorkflowRequest) GetVersionDirective() *v18.TaskVersionDirective { +func (x *QueryWorkflowRequest) GetVersionDirective() *v19.TaskVersionDirective { if x != nil { return x.VersionDirective } return nil } -func (x *QueryWorkflowRequest) GetForwardInfo() *v18.TaskForwardInfo { +func (x *QueryWorkflowRequest) GetForwardInfo() *v19.TaskForwardInfo { if x != nil { return x.ForwardInfo } @@ -1427,7 +1450,7 @@ func (*RespondQueryTaskCompletedResponse) Descriptor() ([]byte, []int) { type CancelOutstandingPollRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - TaskQueueType v19.TaskQueueType `protobuf:"varint,2,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,2,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` TaskQueue *v14.TaskQueue `protobuf:"bytes,3,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` PollerId string `protobuf:"bytes,4,opt,name=poller_id,json=pollerId,proto3" json:"poller_id,omitempty"` unknownFields protoimpl.UnknownFields @@ -1471,11 +1494,11 @@ func (x *CancelOutstandingPollRequest) GetNamespaceId() string { return "" } -func (x *CancelOutstandingPollRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *CancelOutstandingPollRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } func (x *CancelOutstandingPollRequest) GetTaskQueue() *v14.TaskQueue { @@ -1533,7 +1556,7 @@ type CancelOutstandingWorkerPollsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` TaskQueue *v14.TaskQueue `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"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,3,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` WorkerInstanceKey string `protobuf:"bytes,4,opt,name=worker_instance_key,json=workerInstanceKey,proto3" json:"worker_instance_key,omitempty"` // Worker identity string (e.g., "pid@hostname"). Used to eagerly remove the worker // from pollerHistory so DescribeTaskQueue doesn't show stale pollers. @@ -1588,11 +1611,11 @@ func (x *CancelOutstandingWorkerPollsRequest) GetTaskQueue() *v14.TaskQueue { return nil } -func (x *CancelOutstandingWorkerPollsRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *CancelOutstandingWorkerPollsRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } func (x *CancelOutstandingWorkerPollsRequest) GetWorkerInstanceKey() string { @@ -1661,9 +1684,9 @@ type CancelOutstandingWorkerPollsPartitionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` // Used for RPC routing only. Set to any partition on the target host. - TaskQueuePartition *v18.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` + TaskQueuePartition *v19.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` // Partitions to process on this host. - Partitions []*v18.TaskQueuePartition `protobuf:"bytes,3,rep,name=partitions,proto3" json:"partitions,omitempty"` + Partitions []*v19.TaskQueuePartition `protobuf:"bytes,3,rep,name=partitions,proto3" json:"partitions,omitempty"` // Workers to cancel polls for. Workers []*CancelOutstandingWorkerPollsPartitionRequest_WorkerEntry `protobuf:"bytes,4,rep,name=workers,proto3" json:"workers,omitempty"` unknownFields protoimpl.UnknownFields @@ -1707,14 +1730,14 @@ func (x *CancelOutstandingWorkerPollsPartitionRequest) GetNamespaceId() string { return "" } -func (x *CancelOutstandingWorkerPollsPartitionRequest) GetTaskQueuePartition() *v18.TaskQueuePartition { +func (x *CancelOutstandingWorkerPollsPartitionRequest) GetTaskQueuePartition() *v19.TaskQueuePartition { if x != nil { return x.TaskQueuePartition } return nil } -func (x *CancelOutstandingWorkerPollsPartitionRequest) GetPartitions() []*v18.TaskQueuePartition { +func (x *CancelOutstandingWorkerPollsPartitionRequest) GetPartitions() []*v19.TaskQueuePartition { if x != nil { return x.Partitions } @@ -1776,7 +1799,7 @@ type DescribeTaskQueueRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` DescRequest *v1.DescribeTaskQueueRequest `protobuf:"bytes,2,opt,name=desc_request,json=descRequest,proto3" json:"desc_request,omitempty"` - Version *v110.WorkerDeploymentVersion `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Version *v111.WorkerDeploymentVersion `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1825,7 +1848,7 @@ func (x *DescribeTaskQueueRequest) GetDescRequest() *v1.DescribeTaskQueueRequest return nil } -func (x *DescribeTaskQueueRequest) GetVersion() *v110.WorkerDeploymentVersion { +func (x *DescribeTaskQueueRequest) GetVersion() *v111.WorkerDeploymentVersion { if x != nil { return x.Version } @@ -1880,9 +1903,9 @@ type DescribeVersionedTaskQueuesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` // This task queue is for routing purposes. - TaskQueueType v19.TaskQueueType `protobuf:"varint,2,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,2,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` TaskQueue *v14.TaskQueue `protobuf:"bytes,3,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` - Version *v110.WorkerDeploymentVersion `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + Version *v111.WorkerDeploymentVersion `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` // List of task queues to describe. VersionTaskQueues []*DescribeVersionedTaskQueuesRequest_VersionTaskQueue `protobuf:"bytes,5,rep,name=version_task_queues,json=versionTaskQueues,proto3" json:"version_task_queues,omitempty"` unknownFields protoimpl.UnknownFields @@ -1926,11 +1949,11 @@ func (x *DescribeVersionedTaskQueuesRequest) GetNamespaceId() string { return "" } -func (x *DescribeVersionedTaskQueuesRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *DescribeVersionedTaskQueuesRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } func (x *DescribeVersionedTaskQueuesRequest) GetTaskQueue() *v14.TaskQueue { @@ -1940,7 +1963,7 @@ func (x *DescribeVersionedTaskQueuesRequest) GetTaskQueue() *v14.TaskQueue { return nil } -func (x *DescribeVersionedTaskQueuesRequest) GetVersion() *v110.WorkerDeploymentVersion { +func (x *DescribeVersionedTaskQueuesRequest) GetVersion() *v111.WorkerDeploymentVersion { if x != nil { return x.Version } @@ -2001,7 +2024,7 @@ func (x *DescribeVersionedTaskQueuesResponse) GetVersionTaskQueues() []*Describe type DescribeTaskQueuePartitionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - TaskQueuePartition *v18.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` + TaskQueuePartition *v19.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` Versions *v14.TaskQueueVersionSelection `protobuf:"bytes,3,opt,name=versions,proto3" json:"versions,omitempty"` // Report task queue stats for the requested task queue types and versions ReportStats bool `protobuf:"varint,4,opt,name=report_stats,json=reportStats,proto3" json:"report_stats,omitempty"` @@ -2053,7 +2076,7 @@ func (x *DescribeTaskQueuePartitionRequest) GetNamespaceId() string { return "" } -func (x *DescribeTaskQueuePartitionRequest) GetTaskQueuePartition() *v18.TaskQueuePartition { +func (x *DescribeTaskQueuePartitionRequest) GetTaskQueuePartition() *v19.TaskQueuePartition { if x != nil { return x.TaskQueuePartition } @@ -2097,8 +2120,8 @@ func (x *DescribeTaskQueuePartitionRequest) GetOnlyIfLoaded() bool { type DescribeTaskQueuePartitionResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - VersionsInfoInternal map[string]*v18.TaskQueueVersionInfoInternal `protobuf:"bytes,1,rep,name=versions_info_internal,json=versionsInfoInternal,proto3" json:"versions_info_internal,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - ScaleInfo *v18.PartitionScaleInfo `protobuf:"bytes,2,opt,name=scale_info,json=scaleInfo,proto3" json:"scale_info,omitempty"` + VersionsInfoInternal map[string]*v19.TaskQueueVersionInfoInternal `protobuf:"bytes,1,rep,name=versions_info_internal,json=versionsInfoInternal,proto3" json:"versions_info_internal,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + ScaleInfo *v19.PartitionScaleInfo `protobuf:"bytes,2,opt,name=scale_info,json=scaleInfo,proto3" json:"scale_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2133,14 +2156,14 @@ func (*DescribeTaskQueuePartitionResponse) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{24} } -func (x *DescribeTaskQueuePartitionResponse) GetVersionsInfoInternal() map[string]*v18.TaskQueueVersionInfoInternal { +func (x *DescribeTaskQueuePartitionResponse) GetVersionsInfoInternal() map[string]*v19.TaskQueueVersionInfoInternal { if x != nil { return x.VersionsInfoInternal } return nil } -func (x *DescribeTaskQueuePartitionResponse) GetScaleInfo() *v18.PartitionScaleInfo { +func (x *DescribeTaskQueuePartitionResponse) GetScaleInfo() *v19.PartitionScaleInfo { if x != nil { return x.ScaleInfo } @@ -2779,8 +2802,8 @@ type GetTaskQueueUserDataRequest struct { NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` // The task queue to fetch data from. The task queue is always considered as a normal // queue, since sticky queues have no user data. - TaskQueue string `protobuf:"bytes,2,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` - TaskQueueType v19.TaskQueueType `protobuf:"varint,5,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + TaskQueue string `protobuf:"bytes,2,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,5,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` // The value of the last known user data version. // If the requester has no data, it should set this to 0. // This value must not be set to a negative number (note that our linter suggests avoiding uint64). @@ -2843,11 +2866,11 @@ func (x *GetTaskQueueUserDataRequest) GetTaskQueue() string { return "" } -func (x *GetTaskQueueUserDataRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *GetTaskQueueUserDataRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } func (x *GetTaskQueueUserDataRequest) GetLastKnownUserDataVersion() int64 { @@ -2882,8 +2905,8 @@ type GetTaskQueueUserDataResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Versioned user data, set if the task queue has user data and the request's last_known_user_data_version is less // than the version cached in the root partition. - UserData *v111.VersionedTaskQueueUserData `protobuf:"bytes,2,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` - EphemeralData *v18.VersionedEphemeralData `protobuf:"bytes,3,opt,name=ephemeral_data,json=ephemeralData,proto3" json:"ephemeral_data,omitempty"` + UserData *v112.VersionedTaskQueueUserData `protobuf:"bytes,2,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` + EphemeralData *v19.VersionedEphemeralData `protobuf:"bytes,3,opt,name=ephemeral_data,json=ephemeralData,proto3" json:"ephemeral_data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2918,14 +2941,14 @@ func (*GetTaskQueueUserDataResponse) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{36} } -func (x *GetTaskQueueUserDataResponse) GetUserData() *v111.VersionedTaskQueueUserData { +func (x *GetTaskQueueUserDataResponse) GetUserData() *v112.VersionedTaskQueueUserData { if x != nil { return x.UserData } return nil } -func (x *GetTaskQueueUserDataResponse) GetEphemeralData() *v18.VersionedEphemeralData { +func (x *GetTaskQueueUserDataResponse) GetEphemeralData() *v19.VersionedEphemeralData { if x != nil { return x.EphemeralData } @@ -2940,8 +2963,8 @@ type SyncDeploymentUserDataRequest struct { // (-- api-linter: core::0203::required=disabled // // aip.dev/not-precedent: Not following Google API format --) - DeploymentName string `protobuf:"bytes,9,opt,name=deployment_name,json=deploymentName,proto3" json:"deployment_name,omitempty"` - TaskQueueTypes []v19.TaskQueueType `protobuf:"varint,8,rep,packed,name=task_queue_types,json=taskQueueTypes,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_types,omitempty"` + DeploymentName string `protobuf:"bytes,9,opt,name=deployment_name,json=deploymentName,proto3" json:"deployment_name,omitempty"` + TaskQueueTypes []v110.TaskQueueType `protobuf:"varint,8,rep,packed,name=task_queue_types,json=taskQueueTypes,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_types,omitempty"` // Types that are valid to be assigned to Operation: // // *SyncDeploymentUserDataRequest_UpdateVersionData @@ -2949,12 +2972,12 @@ type SyncDeploymentUserDataRequest struct { Operation isSyncDeploymentUserDataRequest_Operation `protobuf_oneof:"operation"` // Absent means no change. // Ignored by the task queue if new revision number is not greater that what it has. - UpdateRoutingConfig *v112.RoutingConfig `protobuf:"bytes,10,opt,name=update_routing_config,json=updateRoutingConfig,proto3" json:"update_routing_config,omitempty"` + UpdateRoutingConfig *v113.RoutingConfig `protobuf:"bytes,10,opt,name=update_routing_config,json=updateRoutingConfig,proto3" json:"update_routing_config,omitempty"` // Optional map of build id to upsert version data. // (-- api-linter: core::0203::required=disabled // // aip.dev/not-precedent: Not following Google API format --) - UpsertVersionsData map[string]*v110.WorkerDeploymentVersionData `protobuf:"bytes,11,rep,name=upsert_versions_data,json=upsertVersionsData,proto3" json:"upsert_versions_data,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + UpsertVersionsData map[string]*v111.WorkerDeploymentVersionData `protobuf:"bytes,11,rep,name=upsert_versions_data,json=upsertVersionsData,proto3" json:"upsert_versions_data,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // List of build ids to forget from task queue. ForgetVersions []string `protobuf:"bytes,12,rep,name=forget_versions,json=forgetVersions,proto3" json:"forget_versions,omitempty"` unknownFields protoimpl.UnknownFields @@ -3012,7 +3035,7 @@ func (x *SyncDeploymentUserDataRequest) GetDeploymentName() string { return "" } -func (x *SyncDeploymentUserDataRequest) GetTaskQueueTypes() []v19.TaskQueueType { +func (x *SyncDeploymentUserDataRequest) GetTaskQueueTypes() []v110.TaskQueueType { if x != nil { return x.TaskQueueTypes } @@ -3027,7 +3050,7 @@ func (x *SyncDeploymentUserDataRequest) GetOperation() isSyncDeploymentUserDataR } // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. -func (x *SyncDeploymentUserDataRequest) GetUpdateVersionData() *v110.DeploymentVersionData { +func (x *SyncDeploymentUserDataRequest) GetUpdateVersionData() *v111.DeploymentVersionData { if x != nil { if x, ok := x.Operation.(*SyncDeploymentUserDataRequest_UpdateVersionData); ok { return x.UpdateVersionData @@ -3037,7 +3060,7 @@ func (x *SyncDeploymentUserDataRequest) GetUpdateVersionData() *v110.DeploymentV } // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. -func (x *SyncDeploymentUserDataRequest) GetForgetVersion() *v110.WorkerDeploymentVersion { +func (x *SyncDeploymentUserDataRequest) GetForgetVersion() *v111.WorkerDeploymentVersion { if x != nil { if x, ok := x.Operation.(*SyncDeploymentUserDataRequest_ForgetVersion); ok { return x.ForgetVersion @@ -3046,14 +3069,14 @@ func (x *SyncDeploymentUserDataRequest) GetForgetVersion() *v110.WorkerDeploymen return nil } -func (x *SyncDeploymentUserDataRequest) GetUpdateRoutingConfig() *v112.RoutingConfig { +func (x *SyncDeploymentUserDataRequest) GetUpdateRoutingConfig() *v113.RoutingConfig { if x != nil { return x.UpdateRoutingConfig } return nil } -func (x *SyncDeploymentUserDataRequest) GetUpsertVersionsData() map[string]*v110.WorkerDeploymentVersionData { +func (x *SyncDeploymentUserDataRequest) GetUpsertVersionsData() map[string]*v111.WorkerDeploymentVersionData { if x != nil { return x.UpsertVersionsData } @@ -3075,14 +3098,14 @@ type SyncDeploymentUserDataRequest_UpdateVersionData struct { // The deployment version and its data that is being updated. // // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. - UpdateVersionData *v110.DeploymentVersionData `protobuf:"bytes,6,opt,name=update_version_data,json=updateVersionData,proto3,oneof"` + UpdateVersionData *v111.DeploymentVersionData `protobuf:"bytes,6,opt,name=update_version_data,json=updateVersionData,proto3,oneof"` } type SyncDeploymentUserDataRequest_ForgetVersion struct { // The version whose data should be cleaned from the task queue. // // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. - ForgetVersion *v110.WorkerDeploymentVersion `protobuf:"bytes,7,opt,name=forget_version,json=forgetVersion,proto3,oneof"` + ForgetVersion *v111.WorkerDeploymentVersion `protobuf:"bytes,7,opt,name=forget_version,json=forgetVersion,proto3,oneof"` } func (*SyncDeploymentUserDataRequest_UpdateVersionData) isSyncDeploymentUserDataRequest_Operation() {} @@ -3151,7 +3174,7 @@ type ApplyTaskQueueUserDataReplicationEventRequest 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"` - UserData *v111.TaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` + UserData *v112.TaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3200,7 +3223,7 @@ func (x *ApplyTaskQueueUserDataReplicationEventRequest) GetTaskQueue() string { return "" } -func (x *ApplyTaskQueueUserDataReplicationEventRequest) GetUserData() *v111.TaskQueueUserData { +func (x *ApplyTaskQueueUserDataReplicationEventRequest) GetUserData() *v112.TaskQueueUserData { if x != nil { return x.UserData } @@ -3342,7 +3365,7 @@ func (x *GetBuildIdTaskQueueMappingResponse) GetTaskQueues() []string { type ForceLoadTaskQueuePartitionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - TaskQueuePartition *v18.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` + TaskQueuePartition *v19.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3384,7 +3407,7 @@ func (x *ForceLoadTaskQueuePartitionRequest) GetNamespaceId() string { return "" } -func (x *ForceLoadTaskQueuePartitionRequest) GetTaskQueuePartition() *v18.TaskQueuePartition { +func (x *ForceLoadTaskQueuePartitionRequest) GetTaskQueuePartition() *v19.TaskQueuePartition { if x != nil { return x.TaskQueuePartition } @@ -3440,7 +3463,7 @@ type ForceUnloadTaskQueueRequest 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"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,3,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3489,11 +3512,11 @@ func (x *ForceUnloadTaskQueueRequest) GetTaskQueue() string { return "" } -func (x *ForceUnloadTaskQueueRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *ForceUnloadTaskQueueRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } // TODO Shivam - Please remove this in 123 @@ -3544,7 +3567,7 @@ func (x *ForceUnloadTaskQueueResponse) GetWasLoaded() bool { type ForceUnloadTaskQueuePartitionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - TaskQueuePartition *v18.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` + TaskQueuePartition *v19.TaskQueuePartition `protobuf:"bytes,2,opt,name=task_queue_partition,json=taskQueuePartition,proto3" json:"task_queue_partition,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3586,7 +3609,7 @@ func (x *ForceUnloadTaskQueuePartitionRequest) GetNamespaceId() string { return "" } -func (x *ForceUnloadTaskQueuePartitionRequest) GetTaskQueuePartition() *v18.TaskQueuePartition { +func (x *ForceUnloadTaskQueuePartitionRequest) GetTaskQueuePartition() *v19.TaskQueuePartition { if x != nil { return x.TaskQueuePartition } @@ -3650,7 +3673,7 @@ type UpdateTaskQueueUserDataRequest struct { TaskQueue string `protobuf:"bytes,2,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` // Versioned user data, set if the task queue has user data and the request's last_known_user_data_version is less // than the version cached in the root partition. - UserData *v111.VersionedTaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` + UserData *v112.VersionedTaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` // List of added build ids BuildIdsAdded []string `protobuf:"bytes,4,rep,name=build_ids_added,json=buildIdsAdded,proto3" json:"build_ids_added,omitempty"` // List of removed build ids @@ -3703,7 +3726,7 @@ func (x *UpdateTaskQueueUserDataRequest) GetTaskQueue() string { return "" } -func (x *UpdateTaskQueueUserDataRequest) GetUserData() *v111.VersionedTaskQueueUserData { +func (x *UpdateTaskQueueUserDataRequest) GetUserData() *v112.VersionedTaskQueueUserData { if x != nil { return x.UserData } @@ -3764,7 +3787,7 @@ type ReplicateTaskQueueUserDataRequest 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"` - UserData *v111.TaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` + UserData *v112.TaskQueueUserData `protobuf:"bytes,3,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3813,7 +3836,7 @@ func (x *ReplicateTaskQueueUserDataRequest) GetTaskQueue() string { return "" } -func (x *ReplicateTaskQueueUserDataRequest) GetUserData() *v111.TaskQueueUserData { +func (x *ReplicateTaskQueueUserDataRequest) GetUserData() *v112.TaskQueueUserData { if x != nil { return x.UserData } @@ -3957,8 +3980,8 @@ type DispatchNexusTaskRequest struct { NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` TaskQueue *v14.TaskQueue `protobuf:"bytes,2,opt,name=task_queue,json=taskQueue,proto3" json:"task_queue,omitempty"` // Nexus request extracted by the frontend and translated into Temporal API format. - Request *v113.Request `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` - ForwardInfo *v18.TaskForwardInfo `protobuf:"bytes,4,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` + Request *v114.Request `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` + ForwardInfo *v19.TaskForwardInfo `protobuf:"bytes,4,opt,name=forward_info,json=forwardInfo,proto3" json:"forward_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4007,14 +4030,14 @@ func (x *DispatchNexusTaskRequest) GetTaskQueue() *v14.TaskQueue { return nil } -func (x *DispatchNexusTaskRequest) GetRequest() *v113.Request { +func (x *DispatchNexusTaskRequest) GetRequest() *v114.Request { if x != nil { return x.Request } return nil } -func (x *DispatchNexusTaskRequest) GetForwardInfo() *v18.TaskForwardInfo { +func (x *DispatchNexusTaskRequest) GetForwardInfo() *v19.TaskForwardInfo { if x != nil { return x.ForwardInfo } @@ -4072,7 +4095,7 @@ func (x *DispatchNexusTaskResponse) GetOutcome() isDispatchNexusTaskResponse_Out } // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. -func (x *DispatchNexusTaskResponse) GetHandlerError() *v113.HandlerError { +func (x *DispatchNexusTaskResponse) GetHandlerError() *v114.HandlerError { if x != nil { if x, ok := x.Outcome.(*DispatchNexusTaskResponse_HandlerError); ok { return x.HandlerError @@ -4081,7 +4104,7 @@ func (x *DispatchNexusTaskResponse) GetHandlerError() *v113.HandlerError { return nil } -func (x *DispatchNexusTaskResponse) GetResponse() *v113.Response { +func (x *DispatchNexusTaskResponse) GetResponse() *v114.Response { if x != nil { if x, ok := x.Outcome.(*DispatchNexusTaskResponse_Response); ok { return x.Response @@ -4099,7 +4122,7 @@ func (x *DispatchNexusTaskResponse) GetRequestTimeout() *DispatchNexusTaskRespon return nil } -func (x *DispatchNexusTaskResponse) GetFailure() *v114.Failure { +func (x *DispatchNexusTaskResponse) GetFailure() *v115.Failure { if x != nil { if x, ok := x.Outcome.(*DispatchNexusTaskResponse_Failure); ok { return x.Failure @@ -4116,12 +4139,12 @@ type DispatchNexusTaskResponse_HandlerError struct { // Deprecated. Use failure field instead. // // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. - HandlerError *v113.HandlerError `protobuf:"bytes,1,opt,name=handler_error,json=handlerError,proto3,oneof"` + HandlerError *v114.HandlerError `protobuf:"bytes,1,opt,name=handler_error,json=handlerError,proto3,oneof"` } type DispatchNexusTaskResponse_Response struct { // Set if the worker's handler responded successfully to the nexus task. - Response *v113.Response `protobuf:"bytes,2,opt,name=response,proto3,oneof"` + Response *v114.Response `protobuf:"bytes,2,opt,name=response,proto3,oneof"` } type DispatchNexusTaskResponse_RequestTimeout struct { @@ -4130,7 +4153,7 @@ type DispatchNexusTaskResponse_RequestTimeout struct { type DispatchNexusTaskResponse_Failure struct { // Set if the worker's handler failed the nexus task. Must contain a NexusHandlerFailureInfo object. - Failure *v114.Failure `protobuf:"bytes,4,opt,name=failure,proto3,oneof"` + Failure *v115.Failure `protobuf:"bytes,4,opt,name=failure,proto3,oneof"` } func (*DispatchNexusTaskResponse_HandlerError) isDispatchNexusTaskResponse_Outcome() {} @@ -4491,7 +4514,7 @@ func (*RespondNexusTaskFailedResponse) Descriptor() ([]byte, []int) { // aip.dev/not-precedent: CreateNexusEndpoint RPC doesn't follow Google API format. --) type CreateNexusEndpointRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Spec *v111.NexusEndpointSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` + Spec *v112.NexusEndpointSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4526,7 +4549,7 @@ func (*CreateNexusEndpointRequest) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{63} } -func (x *CreateNexusEndpointRequest) GetSpec() *v111.NexusEndpointSpec { +func (x *CreateNexusEndpointRequest) GetSpec() *v112.NexusEndpointSpec { if x != nil { return x.Spec } @@ -4535,7 +4558,7 @@ func (x *CreateNexusEndpointRequest) GetSpec() *v111.NexusEndpointSpec { type CreateNexusEndpointResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Entry *v111.NexusEndpointEntry `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` + Entry *v112.NexusEndpointEntry `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4570,7 +4593,7 @@ func (*CreateNexusEndpointResponse) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{64} } -func (x *CreateNexusEndpointResponse) GetEntry() *v111.NexusEndpointEntry { +func (x *CreateNexusEndpointResponse) GetEntry() *v112.NexusEndpointEntry { if x != nil { return x.Entry } @@ -4591,7 +4614,7 @@ type UpdateNexusEndpointRequest struct { // Version of the endpoint, used for optimistic concurrency. Must match current version in persistence or the // request will fail a FAILED_PRECONDITION error. Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - Spec *v111.NexusEndpointSpec `protobuf:"bytes,3,opt,name=spec,proto3" json:"spec,omitempty"` + Spec *v112.NexusEndpointSpec `protobuf:"bytes,3,opt,name=spec,proto3" json:"spec,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4640,7 +4663,7 @@ func (x *UpdateNexusEndpointRequest) GetVersion() int64 { return 0 } -func (x *UpdateNexusEndpointRequest) GetSpec() *v111.NexusEndpointSpec { +func (x *UpdateNexusEndpointRequest) GetSpec() *v112.NexusEndpointSpec { if x != nil { return x.Spec } @@ -4649,7 +4672,7 @@ func (x *UpdateNexusEndpointRequest) GetSpec() *v111.NexusEndpointSpec { type UpdateNexusEndpointResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Entry *v111.NexusEndpointEntry `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` + Entry *v112.NexusEndpointEntry `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4684,7 +4707,7 @@ func (*UpdateNexusEndpointResponse) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{66} } -func (x *UpdateNexusEndpointResponse) GetEntry() *v111.NexusEndpointEntry { +func (x *UpdateNexusEndpointResponse) GetEntry() *v112.NexusEndpointEntry { if x != nil { return x.Entry } @@ -4863,7 +4886,7 @@ type ListNexusEndpointsResponse struct { // Token for getting the next page. NextPageToken []byte `protobuf:"bytes,1,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` TableVersion int64 `protobuf:"varint,2,opt,name=table_version,json=tableVersion,proto3" json:"table_version,omitempty"` - Entries []*v111.NexusEndpointEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries,omitempty"` + Entries []*v112.NexusEndpointEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4912,7 +4935,7 @@ func (x *ListNexusEndpointsResponse) GetTableVersion() int64 { return 0 } -func (x *ListNexusEndpointsResponse) GetEntries() []*v111.NexusEndpointEntry { +func (x *ListNexusEndpointsResponse) GetEntries() []*v112.NexusEndpointEntry { if x != nil { return x.Entries } @@ -5065,9 +5088,9 @@ type ListWorkersResponse struct { // includes expensive runtime metrics. We will stop populating this field in the future. // // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. - WorkersInfo []*v115.WorkerInfo `protobuf:"bytes,1,rep,name=workers_info,json=workersInfo,proto3" json:"workers_info,omitempty"` + WorkersInfo []*v116.WorkerInfo `protobuf:"bytes,1,rep,name=workers_info,json=workersInfo,proto3" json:"workers_info,omitempty"` NextPageToken []byte `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - Workers []*v115.WorkerListInfo `protobuf:"bytes,3,rep,name=workers,proto3" json:"workers,omitempty"` + Workers []*v116.WorkerListInfo `protobuf:"bytes,3,rep,name=workers,proto3" json:"workers,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5103,7 +5126,7 @@ func (*ListWorkersResponse) Descriptor() ([]byte, []int) { } // Deprecated: Marked as deprecated in temporal/server/api/matchingservice/v1/request_response.proto. -func (x *ListWorkersResponse) GetWorkersInfo() []*v115.WorkerInfo { +func (x *ListWorkersResponse) GetWorkersInfo() []*v116.WorkerInfo { if x != nil { return x.WorkersInfo } @@ -5117,7 +5140,7 @@ func (x *ListWorkersResponse) GetNextPageToken() []byte { return nil } -func (x *ListWorkersResponse) GetWorkers() []*v115.WorkerListInfo { +func (x *ListWorkersResponse) GetWorkers() []*v116.WorkerListInfo { if x != nil { return x.Workers } @@ -5382,7 +5405,7 @@ func (x *DescribeWorkerRequest) GetRequest() *v1.DescribeWorkerRequest { type DescribeWorkerResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - WorkerInfo *v115.WorkerInfo `protobuf:"bytes,1,opt,name=worker_info,json=workerInfo,proto3" json:"worker_info,omitempty"` + WorkerInfo *v116.WorkerInfo `protobuf:"bytes,1,opt,name=worker_info,json=workerInfo,proto3" json:"worker_info,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5417,7 +5440,7 @@ func (*DescribeWorkerResponse) Descriptor() ([]byte, []int) { return file_temporal_server_api_matchingservice_v1_request_response_proto_rawDescGZIP(), []int{80} } -func (x *DescribeWorkerResponse) GetWorkerInfo() *v115.WorkerInfo { +func (x *DescribeWorkerResponse) GetWorkerInfo() *v116.WorkerInfo { if x != nil { return x.WorkerInfo } @@ -5439,8 +5462,8 @@ type UpdateFairnessStateRequest 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"` - FairnessState v116.FairnessState `protobuf:"varint,4,opt,name=fairness_state,json=fairnessState,proto3,enum=temporal.server.api.enums.v1.FairnessState" json:"fairness_state,omitempty"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,3,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + FairnessState v117.FairnessState `protobuf:"varint,4,opt,name=fairness_state,json=fairnessState,proto3,enum=temporal.server.api.enums.v1.FairnessState" json:"fairness_state,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5489,18 +5512,18 @@ func (x *UpdateFairnessStateRequest) GetTaskQueue() string { return "" } -func (x *UpdateFairnessStateRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *UpdateFairnessStateRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } -func (x *UpdateFairnessStateRequest) GetFairnessState() v116.FairnessState { +func (x *UpdateFairnessStateRequest) GetFairnessState() v117.FairnessState { if x != nil { return x.FairnessState } - return v116.FairnessState(0) + return v117.FairnessState(0) } type UpdateFairnessStateResponse struct { @@ -5543,8 +5566,8 @@ 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"` + TaskQueueType v110.TaskQueueType `protobuf:"varint,3,opt,name=task_queue_type,json=taskQueueType,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"task_queue_type,omitempty"` + Version *v111.WorkerDeploymentVersion `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5593,14 +5616,14 @@ func (x *CheckTaskQueueVersionMembershipRequest) GetTaskQueue() string { return "" } -func (x *CheckTaskQueueVersionMembershipRequest) GetTaskQueueType() v19.TaskQueueType { +func (x *CheckTaskQueueVersionMembershipRequest) GetTaskQueueType() v110.TaskQueueType { if x != nil { return x.TaskQueueType } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } -func (x *CheckTaskQueueVersionMembershipRequest) GetVersion() *v110.WorkerDeploymentVersion { +func (x *CheckTaskQueueVersionMembershipRequest) GetVersion() *v111.WorkerDeploymentVersion { if x != nil { return x.Version } @@ -5799,7 +5822,7 @@ func (x *CancelOutstandingWorkerPollsPartitionRequest_WorkerEntry) GetWorkerIden type DescribeVersionedTaskQueuesRequest_VersionTaskQueue struct { state protoimpl.MessageState `protogen:"open.v1"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Type v19.TaskQueueType `protobuf:"varint,2,opt,name=type,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"type,omitempty"` + Type v110.TaskQueueType `protobuf:"varint,2,opt,name=type,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5841,18 +5864,18 @@ func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) GetName() string { return "" } -func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) GetType() v19.TaskQueueType { +func (x *DescribeVersionedTaskQueuesRequest_VersionTaskQueue) GetType() v110.TaskQueueType { if x != nil { return x.Type } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } // (-- api-linter: core::0123::resource-annotation=disabled --) type DescribeVersionedTaskQueuesResponse_VersionTaskQueue struct { state protoimpl.MessageState `protogen:"open.v1"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Type v19.TaskQueueType `protobuf:"varint,2,opt,name=type,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"type,omitempty"` + Type v110.TaskQueueType `protobuf:"varint,2,opt,name=type,proto3,enum=temporal.api.enums.v1.TaskQueueType" json:"type,omitempty"` Stats *v14.TaskQueueStats `protobuf:"bytes,3,opt,name=stats,proto3" json:"stats,omitempty"` // (-- api-linter: core::0140::prepositions=disabled // @@ -5899,11 +5922,11 @@ func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) GetName() string return "" } -func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) GetType() v19.TaskQueueType { +func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) GetType() v110.TaskQueueType { if x != nil { return x.Type } - return v19.TaskQueueType(0) + return v110.TaskQueueType(0) } func (x *DescribeVersionedTaskQueuesResponse_VersionTaskQueue) GetStats() *v14.TaskQueueStats { @@ -6060,7 +6083,7 @@ var File_temporal_server_api_matchingservice_v1_request_response_proto protorefl const file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc = "" + "\n" + - "=temporal/server/api/matchingservice/v1/request_response.proto\x12&temporal.server.api.matchingservice.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a%temporal/api/failure/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a#temporal/api/nexus/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a6temporal/api/workflowservice/v1/request_response.proto\x1a*temporal/server/api/clock/v1/message.proto\x1a/temporal/server/api/deployment/v1/message.proto\x1a1temporal/server/api/enums/v1/fairness_state.proto\x1a,temporal/server/api/history/v1/message.proto\x1a.temporal/server/api/persistence/v1/nexus.proto\x1a4temporal/server/api/persistence/v1/task_queues.proto\x1a.temporal/server/api/taskqueue/v1/message.proto\"\xc3\x02\n" + + "=temporal/server/api/matchingservice/v1/request_response.proto\x12&temporal.server.api.matchingservice.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/deployment/v1/message.proto\x1a&temporal/api/enums/v1/task_queue.proto\x1a%temporal/api/failure/v1/message.proto\x1a%temporal/api/history/v1/message.proto\x1a#temporal/api/nexus/v1/message.proto\x1a&temporal/api/protocol/v1/message.proto\x1a#temporal/api/query/v1/message.proto\x1a$temporal/api/stream/v1/message.proto\x1a'temporal/api/taskqueue/v1/message.proto\x1a$temporal/api/worker/v1/message.proto\x1a6temporal/api/workflowservice/v1/request_response.proto\x1a*temporal/server/api/clock/v1/message.proto\x1a/temporal/server/api/deployment/v1/message.proto\x1a1temporal/server/api/enums/v1/fairness_state.proto\x1a,temporal/server/api/history/v1/message.proto\x1a.temporal/server/api/persistence/v1/nexus.proto\x1a4temporal/server/api/persistence/v1/task_queues.proto\x1a.temporal/server/api/taskqueue/v1/message.proto\"\xc3\x02\n" + "\x1cPollWorkflowTaskQueueRequest\x12!\n" + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12\x1b\n" + "\tpoller_id\x18\x02 \x01(\tR\bpollerId\x12`\n" + @@ -6068,7 +6091,7 @@ const file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc "\x10forwarded_source\x18\x04 \x01(\tR\x0fforwardedSource\x12V\n" + "\n" + "conditions\x18\x05 \x01(\v26.temporal.server.api.matchingservice.v1.PollConditionsR\n" + - "conditions\"\xd1\v\n" + + "conditions\"\x9b\f\n" + "\x1dPollWorkflowTaskQueueResponse\x12\x1d\n" + "\n" + "task_token\x18\x01 \x01(\fR\ttaskToken\x12X\n" + @@ -6093,10 +6116,11 @@ const file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc "\x0fnext_page_token\x18\x14 \x01(\fR\rnextPageToken\x12h\n" + "\x17poller_scaling_decision\x18\x15 \x01(\v20.temporal.api.taskqueue.v1.PollerScalingDecisionR\x15pollerScalingDecision\x12A\n" + "\vraw_history\x18\x16 \x01(\v2 .temporal.api.history.v1.HistoryR\n" + - "rawHistory\x1a`\n" + + "rawHistory\x12H\n" + + "\rstream_slices\x18\x17 \x03(\v2#.temporal.api.stream.v1.StreamSliceR\fstreamSlices\x1a`\n" + "\fQueriesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12:\n" + - "\x05value\x18\x02 \x01(\v2$.temporal.api.query.v1.WorkflowQueryR\x05value:\x028\x01J\x04\b\r\x10\x0e\"\xcb\v\n" + + "\x05value\x18\x02 \x01(\v2$.temporal.api.query.v1.WorkflowQueryR\x05value:\x028\x01J\x04\b\r\x10\x0e\"\x95\f\n" + "+PollWorkflowTaskQueueResponseWithRawHistory\x12\x1d\n" + "\n" + "task_token\x18\x01 \x01(\fR\ttaskToken\x12X\n" + @@ -6121,7 +6145,8 @@ const file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc "\x0fnext_page_token\x18\x14 \x01(\fR\rnextPageToken\x12h\n" + "\x17poller_scaling_decision\x18\x15 \x01(\v20.temporal.api.taskqueue.v1.PollerScalingDecisionR\x15pollerScalingDecision\x12\x1f\n" + "\vraw_history\x18\x16 \x03(\fR\n" + - "rawHistory\x1a`\n" + + "rawHistory\x12H\n" + + "\rstream_slices\x18\x17 \x03(\v2#.temporal.api.stream.v1.StreamSliceR\fstreamSlices\x1a`\n" + "\fQueriesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12:\n" + "\x05value\x18\x02 \x01(\v2$.temporal.api.query.v1.WorkflowQueryR\x05value:\x028\x01J\x04\b\r\x10\x0e\"\xc3\x02\n" + @@ -6629,61 +6654,62 @@ var file_temporal_server_api_matchingservice_v1_request_response_proto_goTypes = (*v15.Message)(nil), // 104: temporal.api.protocol.v1.Message (*v16.History)(nil), // 105: temporal.api.history.v1.History (*v14.PollerScalingDecision)(nil), // 106: temporal.api.taskqueue.v1.PollerScalingDecision - (*v1.PollActivityTaskQueueRequest)(nil), // 107: temporal.api.workflowservice.v1.PollActivityTaskQueueRequest - (*v11.ActivityType)(nil), // 108: temporal.api.common.v1.ActivityType - (*v11.Payloads)(nil), // 109: temporal.api.common.v1.Payloads - (*durationpb.Duration)(nil), // 110: google.protobuf.Duration - (*v11.Header)(nil), // 111: temporal.api.common.v1.Header - (*v11.Priority)(nil), // 112: temporal.api.common.v1.Priority - (*v11.RetryPolicy)(nil), // 113: temporal.api.common.v1.RetryPolicy - (*v17.VectorClock)(nil), // 114: temporal.server.api.clock.v1.VectorClock - (*v18.TaskVersionDirective)(nil), // 115: temporal.server.api.taskqueue.v1.TaskVersionDirective - (*v18.TaskForwardInfo)(nil), // 116: temporal.server.api.taskqueue.v1.TaskForwardInfo - (*v1.QueryWorkflowRequest)(nil), // 117: temporal.api.workflowservice.v1.QueryWorkflowRequest - (*v12.QueryRejected)(nil), // 118: temporal.api.query.v1.QueryRejected - (*v1.RespondQueryTaskCompletedRequest)(nil), // 119: temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest - (v19.TaskQueueType)(0), // 120: temporal.api.enums.v1.TaskQueueType - (*v18.TaskQueuePartition)(nil), // 121: temporal.server.api.taskqueue.v1.TaskQueuePartition - (*v1.DescribeTaskQueueRequest)(nil), // 122: temporal.api.workflowservice.v1.DescribeTaskQueueRequest - (*v110.WorkerDeploymentVersion)(nil), // 123: temporal.server.api.deployment.v1.WorkerDeploymentVersion - (*v1.DescribeTaskQueueResponse)(nil), // 124: temporal.api.workflowservice.v1.DescribeTaskQueueResponse - (*v14.TaskQueueVersionSelection)(nil), // 125: temporal.api.taskqueue.v1.TaskQueueVersionSelection - (*v18.PartitionScaleInfo)(nil), // 126: temporal.server.api.taskqueue.v1.PartitionScaleInfo - (*v14.TaskQueuePartitionMetadata)(nil), // 127: temporal.api.taskqueue.v1.TaskQueuePartitionMetadata - (*v1.GetWorkerVersioningRulesRequest)(nil), // 128: temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest - (*v1.GetWorkerVersioningRulesResponse)(nil), // 129: temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse - (*v1.UpdateWorkerVersioningRulesRequest)(nil), // 130: temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest - (*v1.UpdateWorkerVersioningRulesResponse)(nil), // 131: temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse - (*v1.GetWorkerBuildIdCompatibilityRequest)(nil), // 132: temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest - (*v1.GetWorkerBuildIdCompatibilityResponse)(nil), // 133: temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse - (*v111.VersionedTaskQueueUserData)(nil), // 134: temporal.server.api.persistence.v1.VersionedTaskQueueUserData - (*v18.VersionedEphemeralData)(nil), // 135: temporal.server.api.taskqueue.v1.VersionedEphemeralData - (*v110.DeploymentVersionData)(nil), // 136: temporal.server.api.deployment.v1.DeploymentVersionData - (*v112.RoutingConfig)(nil), // 137: temporal.api.deployment.v1.RoutingConfig - (*v111.TaskQueueUserData)(nil), // 138: temporal.server.api.persistence.v1.TaskQueueUserData - (*v113.Request)(nil), // 139: temporal.api.nexus.v1.Request - (*v113.HandlerError)(nil), // 140: temporal.api.nexus.v1.HandlerError - (*v113.Response)(nil), // 141: temporal.api.nexus.v1.Response - (*v114.Failure)(nil), // 142: temporal.api.failure.v1.Failure - (*v1.PollNexusTaskQueueRequest)(nil), // 143: temporal.api.workflowservice.v1.PollNexusTaskQueueRequest - (*v1.PollNexusTaskQueueResponse)(nil), // 144: temporal.api.workflowservice.v1.PollNexusTaskQueueResponse - (*v1.RespondNexusTaskCompletedRequest)(nil), // 145: temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest - (*v1.RespondNexusTaskFailedRequest)(nil), // 146: temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest - (*v111.NexusEndpointSpec)(nil), // 147: temporal.server.api.persistence.v1.NexusEndpointSpec - (*v111.NexusEndpointEntry)(nil), // 148: temporal.server.api.persistence.v1.NexusEndpointEntry - (*v1.RecordWorkerHeartbeatRequest)(nil), // 149: temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest - (*v1.ListWorkersRequest)(nil), // 150: temporal.api.workflowservice.v1.ListWorkersRequest - (*v115.WorkerInfo)(nil), // 151: temporal.api.worker.v1.WorkerInfo - (*v115.WorkerListInfo)(nil), // 152: temporal.api.worker.v1.WorkerListInfo - (*v1.CountWorkersRequest)(nil), // 153: temporal.api.workflowservice.v1.CountWorkersRequest - (*v1.UpdateTaskQueueConfigRequest)(nil), // 154: temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest - (*v14.TaskQueueConfig)(nil), // 155: temporal.api.taskqueue.v1.TaskQueueConfig - (*v1.DescribeWorkerRequest)(nil), // 156: temporal.api.workflowservice.v1.DescribeWorkerRequest - (v116.FairnessState)(0), // 157: temporal.server.api.enums.v1.FairnessState - (*v14.TaskQueueStats)(nil), // 158: temporal.api.taskqueue.v1.TaskQueueStats - (*v18.TaskQueueVersionInfoInternal)(nil), // 159: temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal - (*v1.UpdateWorkerBuildIdCompatibilityRequest)(nil), // 160: temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest - (*v110.WorkerDeploymentVersionData)(nil), // 161: temporal.server.api.deployment.v1.WorkerDeploymentVersionData + (*v17.StreamSlice)(nil), // 107: temporal.api.stream.v1.StreamSlice + (*v1.PollActivityTaskQueueRequest)(nil), // 108: temporal.api.workflowservice.v1.PollActivityTaskQueueRequest + (*v11.ActivityType)(nil), // 109: temporal.api.common.v1.ActivityType + (*v11.Payloads)(nil), // 110: temporal.api.common.v1.Payloads + (*durationpb.Duration)(nil), // 111: google.protobuf.Duration + (*v11.Header)(nil), // 112: temporal.api.common.v1.Header + (*v11.Priority)(nil), // 113: temporal.api.common.v1.Priority + (*v11.RetryPolicy)(nil), // 114: temporal.api.common.v1.RetryPolicy + (*v18.VectorClock)(nil), // 115: temporal.server.api.clock.v1.VectorClock + (*v19.TaskVersionDirective)(nil), // 116: temporal.server.api.taskqueue.v1.TaskVersionDirective + (*v19.TaskForwardInfo)(nil), // 117: temporal.server.api.taskqueue.v1.TaskForwardInfo + (*v1.QueryWorkflowRequest)(nil), // 118: temporal.api.workflowservice.v1.QueryWorkflowRequest + (*v12.QueryRejected)(nil), // 119: temporal.api.query.v1.QueryRejected + (*v1.RespondQueryTaskCompletedRequest)(nil), // 120: temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest + (v110.TaskQueueType)(0), // 121: temporal.api.enums.v1.TaskQueueType + (*v19.TaskQueuePartition)(nil), // 122: temporal.server.api.taskqueue.v1.TaskQueuePartition + (*v1.DescribeTaskQueueRequest)(nil), // 123: temporal.api.workflowservice.v1.DescribeTaskQueueRequest + (*v111.WorkerDeploymentVersion)(nil), // 124: temporal.server.api.deployment.v1.WorkerDeploymentVersion + (*v1.DescribeTaskQueueResponse)(nil), // 125: temporal.api.workflowservice.v1.DescribeTaskQueueResponse + (*v14.TaskQueueVersionSelection)(nil), // 126: temporal.api.taskqueue.v1.TaskQueueVersionSelection + (*v19.PartitionScaleInfo)(nil), // 127: temporal.server.api.taskqueue.v1.PartitionScaleInfo + (*v14.TaskQueuePartitionMetadata)(nil), // 128: temporal.api.taskqueue.v1.TaskQueuePartitionMetadata + (*v1.GetWorkerVersioningRulesRequest)(nil), // 129: temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest + (*v1.GetWorkerVersioningRulesResponse)(nil), // 130: temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse + (*v1.UpdateWorkerVersioningRulesRequest)(nil), // 131: temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest + (*v1.UpdateWorkerVersioningRulesResponse)(nil), // 132: temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse + (*v1.GetWorkerBuildIdCompatibilityRequest)(nil), // 133: temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest + (*v1.GetWorkerBuildIdCompatibilityResponse)(nil), // 134: temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse + (*v112.VersionedTaskQueueUserData)(nil), // 135: temporal.server.api.persistence.v1.VersionedTaskQueueUserData + (*v19.VersionedEphemeralData)(nil), // 136: temporal.server.api.taskqueue.v1.VersionedEphemeralData + (*v111.DeploymentVersionData)(nil), // 137: temporal.server.api.deployment.v1.DeploymentVersionData + (*v113.RoutingConfig)(nil), // 138: temporal.api.deployment.v1.RoutingConfig + (*v112.TaskQueueUserData)(nil), // 139: temporal.server.api.persistence.v1.TaskQueueUserData + (*v114.Request)(nil), // 140: temporal.api.nexus.v1.Request + (*v114.HandlerError)(nil), // 141: temporal.api.nexus.v1.HandlerError + (*v114.Response)(nil), // 142: temporal.api.nexus.v1.Response + (*v115.Failure)(nil), // 143: temporal.api.failure.v1.Failure + (*v1.PollNexusTaskQueueRequest)(nil), // 144: temporal.api.workflowservice.v1.PollNexusTaskQueueRequest + (*v1.PollNexusTaskQueueResponse)(nil), // 145: temporal.api.workflowservice.v1.PollNexusTaskQueueResponse + (*v1.RespondNexusTaskCompletedRequest)(nil), // 146: temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest + (*v1.RespondNexusTaskFailedRequest)(nil), // 147: temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest + (*v112.NexusEndpointSpec)(nil), // 148: temporal.server.api.persistence.v1.NexusEndpointSpec + (*v112.NexusEndpointEntry)(nil), // 149: temporal.server.api.persistence.v1.NexusEndpointEntry + (*v1.RecordWorkerHeartbeatRequest)(nil), // 150: temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest + (*v1.ListWorkersRequest)(nil), // 151: temporal.api.workflowservice.v1.ListWorkersRequest + (*v116.WorkerInfo)(nil), // 152: temporal.api.worker.v1.WorkerInfo + (*v116.WorkerListInfo)(nil), // 153: temporal.api.worker.v1.WorkerListInfo + (*v1.CountWorkersRequest)(nil), // 154: temporal.api.workflowservice.v1.CountWorkersRequest + (*v1.UpdateTaskQueueConfigRequest)(nil), // 155: temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest + (*v14.TaskQueueConfig)(nil), // 156: temporal.api.taskqueue.v1.TaskQueueConfig + (*v1.DescribeWorkerRequest)(nil), // 157: temporal.api.workflowservice.v1.DescribeWorkerRequest + (v117.FairnessState)(0), // 158: temporal.server.api.enums.v1.FairnessState + (*v14.TaskQueueStats)(nil), // 159: temporal.api.taskqueue.v1.TaskQueueStats + (*v19.TaskQueueVersionInfoInternal)(nil), // 160: temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal + (*v1.UpdateWorkerBuildIdCompatibilityRequest)(nil), // 161: temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest + (*v111.WorkerDeploymentVersionData)(nil), // 162: temporal.server.api.deployment.v1.WorkerDeploymentVersionData } var file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs = []int32{ 97, // 0: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollWorkflowTaskQueueRequest @@ -6700,148 +6726,150 @@ var file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs = 105, // 11: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.history:type_name -> temporal.api.history.v1.History 106, // 12: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision 105, // 13: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.raw_history:type_name -> temporal.api.history.v1.History - 98, // 14: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 99, // 15: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 100, // 16: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.query:type_name -> temporal.api.query.v1.WorkflowQuery - 101, // 17: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo - 102, // 18: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 103, // 19: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.scheduled_time:type_name -> google.protobuf.Timestamp - 103, // 20: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.started_time:type_name -> google.protobuf.Timestamp - 87, // 21: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.queries:type_name -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.QueriesEntry - 104, // 22: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.messages:type_name -> temporal.api.protocol.v1.Message - 105, // 23: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.history:type_name -> temporal.api.history.v1.History - 106, // 24: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision - 107, // 25: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest - 85, // 26: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.conditions:type_name -> temporal.server.api.matchingservice.v1.PollConditions - 98, // 27: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution - 108, // 28: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.activity_type:type_name -> temporal.api.common.v1.ActivityType - 109, // 29: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.input:type_name -> temporal.api.common.v1.Payloads - 103, // 30: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp - 110, // 31: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.schedule_to_close_timeout:type_name -> google.protobuf.Duration - 103, // 32: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp - 110, // 33: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.start_to_close_timeout:type_name -> google.protobuf.Duration - 110, // 34: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_timeout:type_name -> google.protobuf.Duration - 103, // 35: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp - 109, // 36: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads - 99, // 37: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType - 111, // 38: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.header:type_name -> temporal.api.common.v1.Header - 106, // 39: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision - 112, // 40: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.priority:type_name -> temporal.api.common.v1.Priority - 113, // 41: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy - 98, // 42: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 102, // 43: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 110, // 44: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration - 114, // 45: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 115, // 46: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 116, // 47: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 112, // 48: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.priority:type_name -> temporal.api.common.v1.Priority - 98, // 49: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution - 102, // 50: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 110, // 51: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration - 114, // 52: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock - 115, // 53: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 116, // 54: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 112, // 55: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.priority:type_name -> temporal.api.common.v1.Priority - 102, // 56: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 117, // 57: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.query_request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest - 115, // 58: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective - 116, // 59: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 112, // 60: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.priority:type_name -> temporal.api.common.v1.Priority - 109, // 61: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_result:type_name -> temporal.api.common.v1.Payloads - 118, // 62: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_rejected:type_name -> temporal.api.query.v1.QueryRejected - 102, // 63: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 119, // 64: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.completed_request:type_name -> temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest - 120, // 65: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 102, // 66: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 102, // 67: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 120, // 68: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 121, // 69: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 121, // 70: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.partitions:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 88, // 71: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.workers:type_name -> temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.WorkerEntry - 122, // 72: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.desc_request:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueRequest - 123, // 73: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 124, // 74: temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse.desc_response:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueResponse - 120, // 75: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 102, // 76: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 123, // 77: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 89, // 78: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue - 90, // 79: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue - 121, // 80: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 125, // 81: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.versions:type_name -> temporal.api.taskqueue.v1.TaskQueueVersionSelection - 92, // 82: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.versions_info_internal:type_name -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry - 126, // 83: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.scale_info:type_name -> temporal.server.api.taskqueue.v1.PartitionScaleInfo - 102, // 84: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 127, // 85: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.activity_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata - 127, // 86: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.workflow_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata - 93, // 87: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.apply_public_request:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest - 94, // 88: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.remove_build_ids:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.RemoveBuildIds - 128, // 89: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest - 129, // 90: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse - 130, // 91: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest - 131, // 92: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse - 132, // 93: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest - 133, // 94: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse - 120, // 95: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 134, // 96: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData - 135, // 97: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.ephemeral_data:type_name -> temporal.server.api.taskqueue.v1.VersionedEphemeralData - 120, // 98: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_types:type_name -> temporal.api.enums.v1.TaskQueueType - 136, // 99: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_version_data:type_name -> temporal.server.api.deployment.v1.DeploymentVersionData - 123, // 100: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.forget_version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 137, // 101: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_routing_config:type_name -> temporal.api.deployment.v1.RoutingConfig - 95, // 102: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.upsert_versions_data:type_name -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry - 138, // 103: temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData - 121, // 104: temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 120, // 105: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 121, // 106: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition - 134, // 107: temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData - 138, // 108: temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData - 102, // 109: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 139, // 110: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.request:type_name -> temporal.api.nexus.v1.Request - 116, // 111: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo - 140, // 112: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.handler_error:type_name -> temporal.api.nexus.v1.HandlerError - 141, // 113: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.response:type_name -> temporal.api.nexus.v1.Response - 96, // 114: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.request_timeout:type_name -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.Timeout - 142, // 115: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.failure:type_name -> temporal.api.failure.v1.Failure - 143, // 116: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.request:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueRequest - 85, // 117: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.conditions:type_name -> temporal.server.api.matchingservice.v1.PollConditions - 144, // 118: temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse.response:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueResponse - 102, // 119: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 145, // 120: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest - 102, // 121: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue - 146, // 122: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest - 147, // 123: temporal.server.api.matchingservice.v1.CreateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec - 148, // 124: temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 147, // 125: temporal.server.api.matchingservice.v1.UpdateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec - 148, // 126: temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 148, // 127: temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse.entries:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry - 149, // 128: temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatRequest.heartbeart_request:type_name -> temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest - 150, // 129: temporal.server.api.matchingservice.v1.ListWorkersRequest.list_request:type_name -> temporal.api.workflowservice.v1.ListWorkersRequest - 151, // 130: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers_info:type_name -> temporal.api.worker.v1.WorkerInfo - 152, // 131: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers:type_name -> temporal.api.worker.v1.WorkerListInfo - 153, // 132: temporal.server.api.matchingservice.v1.CountWorkersRequest.count_request:type_name -> temporal.api.workflowservice.v1.CountWorkersRequest - 154, // 133: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest.update_taskqueue_config:type_name -> temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest - 155, // 134: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse.updated_taskqueue_config:type_name -> temporal.api.taskqueue.v1.TaskQueueConfig - 156, // 135: temporal.server.api.matchingservice.v1.DescribeWorkerRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkerRequest - 151, // 136: temporal.server.api.matchingservice.v1.DescribeWorkerResponse.worker_info:type_name -> temporal.api.worker.v1.WorkerInfo - 120, // 137: temporal.server.api.matchingservice.v1.UpdateFairnessStateRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 157, // 138: temporal.server.api.matchingservice.v1.UpdateFairnessStateRequest.fairness_state:type_name -> temporal.server.api.enums.v1.FairnessState - 120, // 139: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType - 123, // 140: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion - 100, // 141: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery - 100, // 142: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery - 120, // 143: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType - 120, // 144: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType - 158, // 145: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats:type_name -> temporal.api.taskqueue.v1.TaskQueueStats - 91, // 146: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats_by_priority_key:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry - 158, // 147: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry.value:type_name -> temporal.api.taskqueue.v1.TaskQueueStats - 159, // 148: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry.value:type_name -> temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal - 160, // 149: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest - 161, // 150: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry.value:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersionData - 151, // [151:151] is the sub-list for method output_type - 151, // [151:151] is the sub-list for method input_type - 151, // [151:151] is the sub-list for extension type_name - 151, // [151:151] is the sub-list for extension extendee - 0, // [0:151] is the sub-list for field type_name + 107, // 14: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.stream_slices:type_name -> temporal.api.stream.v1.StreamSlice + 98, // 15: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 99, // 16: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 100, // 17: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.query:type_name -> temporal.api.query.v1.WorkflowQuery + 101, // 18: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.transient_workflow_task:type_name -> temporal.server.api.history.v1.TransientWorkflowTaskInfo + 102, // 19: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.workflow_execution_task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 103, // 20: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.scheduled_time:type_name -> google.protobuf.Timestamp + 103, // 21: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.started_time:type_name -> google.protobuf.Timestamp + 87, // 22: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.queries:type_name -> temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.QueriesEntry + 104, // 23: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.messages:type_name -> temporal.api.protocol.v1.Message + 105, // 24: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.history:type_name -> temporal.api.history.v1.History + 106, // 25: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision + 107, // 26: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.stream_slices:type_name -> temporal.api.stream.v1.StreamSlice + 108, // 27: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.poll_request:type_name -> temporal.api.workflowservice.v1.PollActivityTaskQueueRequest + 85, // 28: temporal.server.api.matchingservice.v1.PollActivityTaskQueueRequest.conditions:type_name -> temporal.server.api.matchingservice.v1.PollConditions + 98, // 29: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_execution:type_name -> temporal.api.common.v1.WorkflowExecution + 109, // 30: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.activity_type:type_name -> temporal.api.common.v1.ActivityType + 110, // 31: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.input:type_name -> temporal.api.common.v1.Payloads + 103, // 32: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.scheduled_time:type_name -> google.protobuf.Timestamp + 111, // 33: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.schedule_to_close_timeout:type_name -> google.protobuf.Duration + 103, // 34: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.started_time:type_name -> google.protobuf.Timestamp + 111, // 35: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.start_to_close_timeout:type_name -> google.protobuf.Duration + 111, // 36: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_timeout:type_name -> google.protobuf.Duration + 103, // 37: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.current_attempt_scheduled_time:type_name -> google.protobuf.Timestamp + 110, // 38: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.heartbeat_details:type_name -> temporal.api.common.v1.Payloads + 99, // 39: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.workflow_type:type_name -> temporal.api.common.v1.WorkflowType + 112, // 40: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.header:type_name -> temporal.api.common.v1.Header + 106, // 41: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.poller_scaling_decision:type_name -> temporal.api.taskqueue.v1.PollerScalingDecision + 113, // 42: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.priority:type_name -> temporal.api.common.v1.Priority + 114, // 43: temporal.server.api.matchingservice.v1.PollActivityTaskQueueResponse.retry_policy:type_name -> temporal.api.common.v1.RetryPolicy + 98, // 44: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 102, // 45: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 111, // 46: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration + 115, // 47: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 116, // 48: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 117, // 49: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 113, // 50: temporal.server.api.matchingservice.v1.AddWorkflowTaskRequest.priority:type_name -> temporal.api.common.v1.Priority + 98, // 51: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.execution:type_name -> temporal.api.common.v1.WorkflowExecution + 102, // 52: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 111, // 53: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.schedule_to_start_timeout:type_name -> google.protobuf.Duration + 115, // 54: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.clock:type_name -> temporal.server.api.clock.v1.VectorClock + 116, // 55: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 117, // 56: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 113, // 57: temporal.server.api.matchingservice.v1.AddActivityTaskRequest.priority:type_name -> temporal.api.common.v1.Priority + 102, // 58: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 118, // 59: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.query_request:type_name -> temporal.api.workflowservice.v1.QueryWorkflowRequest + 116, // 60: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.version_directive:type_name -> temporal.server.api.taskqueue.v1.TaskVersionDirective + 117, // 61: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 113, // 62: temporal.server.api.matchingservice.v1.QueryWorkflowRequest.priority:type_name -> temporal.api.common.v1.Priority + 110, // 63: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_result:type_name -> temporal.api.common.v1.Payloads + 119, // 64: temporal.server.api.matchingservice.v1.QueryWorkflowResponse.query_rejected:type_name -> temporal.api.query.v1.QueryRejected + 102, // 65: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 120, // 66: temporal.server.api.matchingservice.v1.RespondQueryTaskCompletedRequest.completed_request:type_name -> temporal.api.workflowservice.v1.RespondQueryTaskCompletedRequest + 121, // 67: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 102, // 68: temporal.server.api.matchingservice.v1.CancelOutstandingPollRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 102, // 69: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 121, // 70: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 122, // 71: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 122, // 72: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.partitions:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 88, // 73: temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.workers:type_name -> temporal.server.api.matchingservice.v1.CancelOutstandingWorkerPollsPartitionRequest.WorkerEntry + 123, // 74: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.desc_request:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueRequest + 124, // 75: temporal.server.api.matchingservice.v1.DescribeTaskQueueRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 125, // 76: temporal.server.api.matchingservice.v1.DescribeTaskQueueResponse.desc_response:type_name -> temporal.api.workflowservice.v1.DescribeTaskQueueResponse + 121, // 77: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 102, // 78: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 124, // 79: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 89, // 80: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue + 90, // 81: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.version_task_queues:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue + 122, // 82: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 126, // 83: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionRequest.versions:type_name -> temporal.api.taskqueue.v1.TaskQueueVersionSelection + 92, // 84: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.versions_info_internal:type_name -> temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry + 127, // 85: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.scale_info:type_name -> temporal.server.api.taskqueue.v1.PartitionScaleInfo + 102, // 86: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 128, // 87: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.activity_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata + 128, // 88: temporal.server.api.matchingservice.v1.ListTaskQueuePartitionsResponse.workflow_task_queue_partitions:type_name -> temporal.api.taskqueue.v1.TaskQueuePartitionMetadata + 93, // 89: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.apply_public_request:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest + 94, // 90: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.remove_build_ids:type_name -> temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.RemoveBuildIds + 129, // 91: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesRequest + 130, // 92: temporal.server.api.matchingservice.v1.GetWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerVersioningRulesResponse + 131, // 93: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesRequest + 132, // 94: temporal.server.api.matchingservice.v1.UpdateWorkerVersioningRulesResponse.response:type_name -> temporal.api.workflowservice.v1.UpdateWorkerVersioningRulesResponse + 133, // 95: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityRequest.request:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityRequest + 134, // 96: temporal.server.api.matchingservice.v1.GetWorkerBuildIdCompatibilityResponse.response:type_name -> temporal.api.workflowservice.v1.GetWorkerBuildIdCompatibilityResponse + 121, // 97: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 135, // 98: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData + 136, // 99: temporal.server.api.matchingservice.v1.GetTaskQueueUserDataResponse.ephemeral_data:type_name -> temporal.server.api.taskqueue.v1.VersionedEphemeralData + 121, // 100: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.task_queue_types:type_name -> temporal.api.enums.v1.TaskQueueType + 137, // 101: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_version_data:type_name -> temporal.server.api.deployment.v1.DeploymentVersionData + 124, // 102: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.forget_version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 138, // 103: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.update_routing_config:type_name -> temporal.api.deployment.v1.RoutingConfig + 95, // 104: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.upsert_versions_data:type_name -> temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry + 139, // 105: temporal.server.api.matchingservice.v1.ApplyTaskQueueUserDataReplicationEventRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData + 122, // 106: temporal.server.api.matchingservice.v1.ForceLoadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 121, // 107: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueueRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 122, // 108: temporal.server.api.matchingservice.v1.ForceUnloadTaskQueuePartitionRequest.task_queue_partition:type_name -> temporal.server.api.taskqueue.v1.TaskQueuePartition + 135, // 109: temporal.server.api.matchingservice.v1.UpdateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.VersionedTaskQueueUserData + 139, // 110: temporal.server.api.matchingservice.v1.ReplicateTaskQueueUserDataRequest.user_data:type_name -> temporal.server.api.persistence.v1.TaskQueueUserData + 102, // 111: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 140, // 112: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.request:type_name -> temporal.api.nexus.v1.Request + 117, // 113: temporal.server.api.matchingservice.v1.DispatchNexusTaskRequest.forward_info:type_name -> temporal.server.api.taskqueue.v1.TaskForwardInfo + 141, // 114: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.handler_error:type_name -> temporal.api.nexus.v1.HandlerError + 142, // 115: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.response:type_name -> temporal.api.nexus.v1.Response + 96, // 116: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.request_timeout:type_name -> temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.Timeout + 143, // 117: temporal.server.api.matchingservice.v1.DispatchNexusTaskResponse.failure:type_name -> temporal.api.failure.v1.Failure + 144, // 118: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.request:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueRequest + 85, // 119: temporal.server.api.matchingservice.v1.PollNexusTaskQueueRequest.conditions:type_name -> temporal.server.api.matchingservice.v1.PollConditions + 145, // 120: temporal.server.api.matchingservice.v1.PollNexusTaskQueueResponse.response:type_name -> temporal.api.workflowservice.v1.PollNexusTaskQueueResponse + 102, // 121: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 146, // 122: temporal.server.api.matchingservice.v1.RespondNexusTaskCompletedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskCompletedRequest + 102, // 123: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.task_queue:type_name -> temporal.api.taskqueue.v1.TaskQueue + 147, // 124: temporal.server.api.matchingservice.v1.RespondNexusTaskFailedRequest.request:type_name -> temporal.api.workflowservice.v1.RespondNexusTaskFailedRequest + 148, // 125: temporal.server.api.matchingservice.v1.CreateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec + 149, // 126: temporal.server.api.matchingservice.v1.CreateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 148, // 127: temporal.server.api.matchingservice.v1.UpdateNexusEndpointRequest.spec:type_name -> temporal.server.api.persistence.v1.NexusEndpointSpec + 149, // 128: temporal.server.api.matchingservice.v1.UpdateNexusEndpointResponse.entry:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 149, // 129: temporal.server.api.matchingservice.v1.ListNexusEndpointsResponse.entries:type_name -> temporal.server.api.persistence.v1.NexusEndpointEntry + 150, // 130: temporal.server.api.matchingservice.v1.RecordWorkerHeartbeatRequest.heartbeart_request:type_name -> temporal.api.workflowservice.v1.RecordWorkerHeartbeatRequest + 151, // 131: temporal.server.api.matchingservice.v1.ListWorkersRequest.list_request:type_name -> temporal.api.workflowservice.v1.ListWorkersRequest + 152, // 132: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers_info:type_name -> temporal.api.worker.v1.WorkerInfo + 153, // 133: temporal.server.api.matchingservice.v1.ListWorkersResponse.workers:type_name -> temporal.api.worker.v1.WorkerListInfo + 154, // 134: temporal.server.api.matchingservice.v1.CountWorkersRequest.count_request:type_name -> temporal.api.workflowservice.v1.CountWorkersRequest + 155, // 135: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigRequest.update_taskqueue_config:type_name -> temporal.api.workflowservice.v1.UpdateTaskQueueConfigRequest + 156, // 136: temporal.server.api.matchingservice.v1.UpdateTaskQueueConfigResponse.updated_taskqueue_config:type_name -> temporal.api.taskqueue.v1.TaskQueueConfig + 157, // 137: temporal.server.api.matchingservice.v1.DescribeWorkerRequest.request:type_name -> temporal.api.workflowservice.v1.DescribeWorkerRequest + 152, // 138: temporal.server.api.matchingservice.v1.DescribeWorkerResponse.worker_info:type_name -> temporal.api.worker.v1.WorkerInfo + 121, // 139: temporal.server.api.matchingservice.v1.UpdateFairnessStateRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 158, // 140: temporal.server.api.matchingservice.v1.UpdateFairnessStateRequest.fairness_state:type_name -> temporal.server.api.enums.v1.FairnessState + 121, // 141: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.task_queue_type:type_name -> temporal.api.enums.v1.TaskQueueType + 124, // 142: temporal.server.api.matchingservice.v1.CheckTaskQueueVersionMembershipRequest.version:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersion + 100, // 143: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponse.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery + 100, // 144: temporal.server.api.matchingservice.v1.PollWorkflowTaskQueueResponseWithRawHistory.QueriesEntry.value:type_name -> temporal.api.query.v1.WorkflowQuery + 121, // 145: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesRequest.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType + 121, // 146: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.type:type_name -> temporal.api.enums.v1.TaskQueueType + 159, // 147: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats:type_name -> temporal.api.taskqueue.v1.TaskQueueStats + 91, // 148: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.stats_by_priority_key:type_name -> temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry + 159, // 149: temporal.server.api.matchingservice.v1.DescribeVersionedTaskQueuesResponse.VersionTaskQueue.StatsByPriorityKeyEntry.value:type_name -> temporal.api.taskqueue.v1.TaskQueueStats + 160, // 150: temporal.server.api.matchingservice.v1.DescribeTaskQueuePartitionResponse.VersionsInfoInternalEntry.value:type_name -> temporal.server.api.taskqueue.v1.TaskQueueVersionInfoInternal + 161, // 151: temporal.server.api.matchingservice.v1.UpdateWorkerBuildIdCompatibilityRequest.ApplyPublicRequest.request:type_name -> temporal.api.workflowservice.v1.UpdateWorkerBuildIdCompatibilityRequest + 162, // 152: temporal.server.api.matchingservice.v1.SyncDeploymentUserDataRequest.UpsertVersionsDataEntry.value:type_name -> temporal.server.api.deployment.v1.WorkerDeploymentVersionData + 153, // [153:153] is the sub-list for method output_type + 153, // [153:153] is the sub-list for method input_type + 153, // [153:153] is the sub-list for extension type_name + 153, // [153:153] is the sub-list for extension extendee + 0, // [0:153] is the sub-list for field type_name } func init() { file_temporal_server_api_matchingservice_v1_request_response_proto_init() } diff --git a/chasm/lib/stream/config.go b/chasm/lib/stream/config.go new file mode 100644 index 00000000000..cb7ac2cd6d6 --- /dev/null +++ b/chasm/lib/stream/config.go @@ -0,0 +1,244 @@ +package stream + +import ( + "time" + + "go.temporal.io/server/common/dynamicconfig" +) + +// DefaultMaxMessagesPerPoll bounds a read page when the caller does not. +const DefaultMaxMessagesPerPoll = 1000 + +// MaxRecordsPerBatch bounds one append. It is not only an admission limit: a +// batch is keyed by its first offset, so to serve a read starting inside a +// batch the reader has to find the batch that contains it. Bounding the batch +// bounds how far back it has to look, which turns an unbounded scan into a +// fixed overread. +const MaxRecordsPerBatch = 1000 + +// LongPollTimeout matches the convention used by the history long polls: on +// expiry the caller gets an empty response and polls again, rather than an +// error it would have to special-case. +const LongPollTimeout = 20 * time.Second + +// LongPollBuffer leaves room to return an empty response before the caller's +// own deadline fires. +const LongPollBuffer = 3 * time.Second + +// RoutedCallTimeout bounds a call to another shard made while a workflow's lock +// is held. The request's own deadline can be far longer, and a slow stream +// shard would otherwise stretch the lock hold to match it. +const RoutedCallTimeout = 5 * time.Second + +// MaxListPageSize bounds a visibility page when the caller does not. +const MaxListPageSize = 1000 + +// MaxStreamNameLength bounds a name before it becomes a map key in mutable +// state. The name comes from the caller, and any caller in the namespace can +// pick a new one. +const MaxStreamNameLength = 255 + +// The limits below bound resource use and are namespace-scoped dynamic config, +// with these values as the defaults. They stay as constants too so component +// code driven without a config, as the unit tests do, has something to fall +// back on. +const ( + // MaxConsumeItemsPerTask bounds one Workflow Task's slice. A byte cap alone + // is not enough: a burst of tiny records stays under it while still making + // one task's drain arbitrarily long. Whichever bound binds first, the rest + // is delivered on the following task. + MaxConsumeItemsPerTask = 1000 + + // MaxConsumeBytesPerTask bounds one Workflow Task's slice by size. Paired + // with MaxConsumeItemsPerTask because neither bound alone is enough: a + // burst of tiny records slips under the byte budget, and a few large ones + // slip under the item count. + MaxConsumeBytesPerTask = 2 << 20 + + // MaxProducersPerStream bounds the per-producer dedup table. The table is + // part of the component state written on every append, so a caller that + // sends a fresh producer id per request would grow the state until the + // mutable-state size limit rejects every further append, leaving the + // stream unwritable for good. The bound turns that into a clear error on + // the offending call. + MaxProducersPerStream = 1000 + + // MaxConsumersPerStream bounds the registered consumer table for the same + // reason. Each consumer also holds a truncation floor, so an unbounded + // table would pin storage as well as grow state. + MaxConsumersPerStream = 1000 + + // MaxMessageBytes bounds one message. A message is never split, so this is + // also the smallest unit a reader can be asked to materialise. + MaxMessageBytes = 1 << 20 + + // MaxBatchBytes bounds one append. It is deliberately equal to + // MaxConsumeBytesPerTask: a batch is written as one node and read back + // whole, so a batch larger than a task's byte budget could never be + // delivered. + MaxBatchBytes = MaxConsumeBytesPerTask + + // MaxOwnedStreamsPerWorkflow bounds how many named streams one execution + // can carry. Each is a component in the workflow's mutable state, so an + // unbounded count grows that state until the size limit terminates the + // execution, and any caller in the namespace can name a new one. + MaxOwnedStreamsPerWorkflow = 100 + + // OwnedStreamMaxBytes is the byte budget of a stream a workflow owns. Its + // batches are the owning execution's mutable state, and the execution size + // limit terminates the workflow rather than refusing an append, so the + // stream refuses first. The sum over a workflow's streams is still bounded + // by that limit. + OwnedStreamMaxBytes = 2 << 20 + + // OwnedStreamMaxItems is the item budget of a stream a workflow owns, for + // the same reason: each batch is a node, and many small ones cost state + // that the byte budget alone does not see. + OwnedStreamMaxItems = 10_000 +) + +var ( + MaxConsumeItemsPerTaskSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxConsumeItemsPerTask", + MaxConsumeItemsPerTask, + `Most stream records one workflow task carries per subscription.`, + ) + MaxConsumeBytesPerTaskSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxConsumeBytesPerTask", + MaxConsumeBytesPerTask, + `Most stream record bytes one workflow task carries per subscription.`, + ) + MaxProducersPerStreamSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxProducersPerStream", + MaxProducersPerStream, + `Most producer ids a stream tracks for deduplication.`, + ) + MaxConsumersPerStreamSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxConsumersPerStream", + MaxConsumersPerStream, + `Most workflow consumers a stream registers.`, + ) + MaxMessageBytesSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxMessageBytes", + MaxMessageBytes, + `Largest single stream record accepted.`, + ) + MaxBatchBytesSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxBatchBytes", + MaxBatchBytes, + `Largest stream append accepted, summed over its records.`, + ) + MaxOwnedStreamsPerWorkflowSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.maxOwnedStreamsPerWorkflow", + MaxOwnedStreamsPerWorkflow, + `Most named streams one workflow execution can own.`, + ) + OwnedStreamMaxBytesSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.ownedStreamMaxBytes", + OwnedStreamMaxBytes, + `Byte budget of a stream a workflow owns. Appends past it are refused. Keep it well +under limit.mutableStateSize.error, which would otherwise terminate the workflow.`, + ) + OwnedStreamMaxItemsSetting = dynamicconfig.NewNamespaceIntSetting( + "stream.ownedStreamMaxItems", + OwnedStreamMaxItems, + `Message budget of a stream a workflow owns. Appends past it are refused.`, + ) + RetentionRecheckIntervalSetting = dynamicconfig.NewGlobalDurationSetting( + "stream.retentionRecheckInterval", + time.Minute, + `How long a closed stream past its retention waits before asking again whether the +consumers holding it are still running.`, + ) +) + +// Config holds the settings as live property functions. +type Config struct { + // The id length limit shared with workflow ids. A stream id becomes an + // execution's business id, and a stream name a key in mutable state. + MaxIDLength dynamicconfig.IntPropertyFn + RetentionRecheckInterval dynamicconfig.DurationPropertyFn + MaxConsumeItemsPerTask dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxConsumeBytesPerTask dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxProducersPerStream dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxConsumersPerStream dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxMessageBytes dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxBatchBytes dynamicconfig.IntPropertyFnWithNamespaceFilter + MaxOwnedStreamsPerWorkflow dynamicconfig.IntPropertyFnWithNamespaceFilter + OwnedStreamMaxBytes dynamicconfig.IntPropertyFnWithNamespaceFilter + OwnedStreamMaxItems dynamicconfig.IntPropertyFnWithNamespaceFilter +} + +func NewConfig(dc *dynamicconfig.Collection) *Config { + return &Config{ + MaxIDLength: dynamicconfig.MaxIDLengthLimit.Get(dc), + RetentionRecheckInterval: RetentionRecheckIntervalSetting.Get(dc), + MaxConsumeItemsPerTask: MaxConsumeItemsPerTaskSetting.Get(dc), + MaxConsumeBytesPerTask: MaxConsumeBytesPerTaskSetting.Get(dc), + MaxProducersPerStream: MaxProducersPerStreamSetting.Get(dc), + MaxConsumersPerStream: MaxConsumersPerStreamSetting.Get(dc), + MaxMessageBytes: MaxMessageBytesSetting.Get(dc), + MaxBatchBytes: MaxBatchBytesSetting.Get(dc), + MaxOwnedStreamsPerWorkflow: MaxOwnedStreamsPerWorkflowSetting.Get(dc), + OwnedStreamMaxBytes: OwnedStreamMaxBytesSetting.Get(dc), + OwnedStreamMaxItems: OwnedStreamMaxItemsSetting.Get(dc), + } +} + +// Limits is one namespace's resolved limits, read once per request so a +// transition sees one consistent set. +type Limits struct { + MaxConsumeItemsPerTask int + MaxConsumeBytesPerTask int + MaxProducersPerStream int + MaxConsumersPerStream int + MaxMessageBytes int + MaxBatchBytes int + MaxOwnedStreamsPerWorkflow int + OwnedStreamMaxBytes int + OwnedStreamMaxItems int +} + +// LimitsFor resolves the limits for a namespace. A nil Config, which is what +// code driven without a service gets, resolves to the defaults. +func (c *Config) LimitsFor(namespaceName string) Limits { + if c == nil { + return DefaultLimits() + } + return Limits{ + MaxConsumeItemsPerTask: c.MaxConsumeItemsPerTask(namespaceName), + MaxConsumeBytesPerTask: c.MaxConsumeBytesPerTask(namespaceName), + MaxProducersPerStream: c.MaxProducersPerStream(namespaceName), + MaxConsumersPerStream: c.MaxConsumersPerStream(namespaceName), + MaxMessageBytes: c.MaxMessageBytes(namespaceName), + MaxBatchBytes: c.MaxBatchBytes(namespaceName), + MaxOwnedStreamsPerWorkflow: c.MaxOwnedStreamsPerWorkflow(namespaceName), + OwnedStreamMaxBytes: c.OwnedStreamMaxBytes(namespaceName), + OwnedStreamMaxItems: c.OwnedStreamMaxItems(namespaceName), + }.withDefaults() +} + +// DefaultLimits is the constant set above. +func DefaultLimits() Limits { + return Limits{}.withDefaults() +} + +// withDefaults fills any limit left at zero, so a zero Limits value means the +// defaults rather than a stream that accepts nothing. +func (l Limits) withDefaults() Limits { + fill := func(v *int, def int) { + if *v <= 0 { + *v = def + } + } + fill(&l.MaxConsumeItemsPerTask, MaxConsumeItemsPerTask) + fill(&l.MaxConsumeBytesPerTask, MaxConsumeBytesPerTask) + fill(&l.MaxProducersPerStream, MaxProducersPerStream) + fill(&l.MaxConsumersPerStream, MaxConsumersPerStream) + fill(&l.MaxMessageBytes, MaxMessageBytes) + fill(&l.MaxBatchBytes, MaxBatchBytes) + fill(&l.MaxOwnedStreamsPerWorkflow, MaxOwnedStreamsPerWorkflow) + fill(&l.OwnedStreamMaxBytes, OwnedStreamMaxBytes) + fill(&l.OwnedStreamMaxItems, OwnedStreamMaxItems) + return l +} diff --git a/chasm/lib/stream/cursor.go b/chasm/lib/stream/cursor.go new file mode 100644 index 00000000000..143fc23f0b8 --- /dev/null +++ b/chasm/lib/stream/cursor.go @@ -0,0 +1,161 @@ +package stream + +import ( + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +// Cursor is a consuming workflow's position in a stream. +// +// It is a subcomponent of the consumer, not of the stream. That placement is +// the whole point: the consumer's mutable state and its History events commit +// in one transaction, so folding a delivered range into the cursor lands +// atomically with the event that records the range. Holding the cursor on the +// stream instead would make every advance a cross-execution write, and a crash +// between the two writes would either redeliver a range or skip it silently. +type Cursor struct { + chasm.UnimplementedComponent + + State *streampb.WorkflowStreamCursor +} + +type NewCursorRequest struct { + StreamID string + // External marks a stream in another execution, whose frontier this + // workflow is told about rather than reads. + External bool + + // Where to start reading. Resolving "from the tail" against the stream's + // head happens before this is called, so the value recorded here is already + // a fact rather than a reading that would differ on replay. + StartOffset int64 +} + +func NewCursor(_ chasm.MutableContext, req NewCursorRequest) (*Cursor, error) { + if req.StreamID == "" { + return nil, serviceerror.NewInvalidArgument("stream id is required") + } + if req.StartOffset < 0 { + return nil, serviceerror.NewInvalidArgument("start offset cannot be negative") + } + + return &Cursor{ + State: &streampb.WorkflowStreamCursor{ + StreamId: req.StreamID, + Offset: req.StartOffset, + StartOffset: req.StartOffset, + External: req.External, + KnownHead: req.StartOffset, + }, + }, nil +} + +// LifecycleState reports the cursor as running for as long as the workflow +// holding it exists. Deregistration is an explicit act, not a state the +// component reaches on its own. +func (c *Cursor) LifecycleState(_ chasm.Context) chasm.LifecycleState { + return chasm.LifecycleStateRunning +} + +// Offset is the next offset that has not yet been delivered and folded in. +func (c *Cursor) Offset() int64 { + return c.State.Offset +} + +func (c *Cursor) StreamID() string { + return c.State.StreamId +} + +// StagePending records the range attached to the workflow task now in flight. +// +// A redelivery overwrites whatever was staged before. That is safe because a +// range only becomes history when the task completes: if the previous task +// failed or timed out, nothing was recorded, so the replacement range is the +// first one the workflow will ever have observed at this point. +func (c *Cursor) StagePending(_ chasm.MutableContext, from int64, to int64) error { + if from < c.State.Offset { + return serviceerror.NewInvalidArgumentf( + "cannot deliver from offset %d, cursor is already at %d", from, c.State.Offset) + } + if to < from { + return serviceerror.NewInvalidArgumentf("range end %d precedes range start %d", to, from) + } + + c.State.PendingFrom = from + c.State.PendingTo = to + c.State.HasPending = true + return nil +} + +// Pending reports the staged range. The second result distinguishes "no task in +// flight" from "a task in flight that was given nothing", which are different +// facts: the latter must still be recorded. +func (c *Cursor) Pending() (from int64, to int64, ok bool) { + if !c.State.HasPending { + return 0, 0, false + } + return c.State.PendingFrom, c.State.PendingTo, true +} + +// Commit folds the staged range into the cursor and returns it for recording. +// Caller writes the returned range onto the event that closes the task, in the +// same transaction that persists this advance. +func (c *Cursor) Commit(_ chasm.MutableContext) (from int64, to int64, ok bool) { + if !c.State.HasPending { + return 0, 0, false + } + + from, to = c.State.PendingFrom, c.State.PendingTo + c.State.Offset = to + c.State.PendingFrom = 0 + c.State.PendingTo = 0 + c.State.HasPending = false + return from, to, true +} + +// IsExternal reports whether the stream lives in another execution. +func (c *Cursor) IsExternal() bool { + return c.State.External +} + +// KnownHead is the stream's frontier as last pushed to this workflow. +func (c *Cursor) KnownHead() int64 { + return c.State.KnownHead +} + +// AdvanceKnownHead moves the recorded frontier forward. It never moves back: a +// stale push arriving after a fresher one must not hide offsets already known +// to exist. +func (c *Cursor) AdvanceKnownHead(_ chasm.MutableContext, head int64) { + if head > c.State.KnownHead { + c.State.KnownHead = head + } +} + +// StartOffset is where this subscription began reading. Replay needs it to tell +// a consumer that has committed nothing apart from one whose recording events +// are simply not in the history page it was handed. +func (c *Cursor) StartOffset() int64 { + return c.State.StartOffset +} + +// Restore puts the cursor where a completed task's event says it stood, for a +// run being rebuilt from its history. It only moves forward: the events are +// applied in order, and a range folded in earlier is never taken back. +func (c *Cursor) Restore(_ chasm.MutableContext, offset int64) { + if offset > c.State.Offset { + c.State.Offset = offset + } + if offset > c.State.KnownHead { + c.State.KnownHead = offset + } +} + +// MarkExternal says the stream lives in another execution, which the subscribe +// event alone cannot tell a rebuilt run, and carries over the frontier that +// stream last pushed at the run this one was rebuilt from. +func (c *Cursor) MarkExternal(mctx chasm.MutableContext, knownHead int64) { + c.State.External = true + c.AdvanceKnownHead(mctx, knownHead) +} diff --git a/chasm/lib/stream/cursor_test.go b/chasm/lib/stream/cursor_test.go new file mode 100644 index 00000000000..deb2b95212c --- /dev/null +++ b/chasm/lib/stream/cursor_test.go @@ -0,0 +1,100 @@ +package stream + +import ( + "testing" + + "github.com/stretchr/testify/require" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +func newTestCursor(offset int64) *Cursor { + return &Cursor{ + State: &streampb.WorkflowStreamCursor{ + StreamId: "s-1", + Offset: offset, + }, + } +} + +func TestNewCursorRejectsIncompleteRequests(t *testing.T) { + cases := map[string]NewCursorRequest{ + "no stream id": {}, + "negative start": {StreamID: "s-1", StartOffset: -1}, + } + + for name, req := range cases { + t.Run(name, func(t *testing.T) { + _, err := NewCursor(nil, req) + require.Error(t, err) + }) + } +} + +func TestCursorCommitAdvancesAndClears(t *testing.T) { + c := newTestCursor(4) + + require.NoError(t, c.StagePending(nil, 4, 7)) + + from, to, ok := c.Pending() + require.True(t, ok) + require.Equal(t, int64(4), from) + require.Equal(t, int64(7), to) + + from, to, ok = c.Commit(nil) + require.True(t, ok) + require.Equal(t, int64(4), from) + require.Equal(t, int64(7), to) + require.Equal(t, int64(7), c.Offset()) + + _, _, ok = c.Pending() + require.False(t, ok, "a committed range must not be staged twice") + + _, _, ok = c.Commit(nil) + require.False(t, ok, "committing again must not re-record the range") +} + +// A task that observed nothing still has to be recorded, so an empty range is a +// pending range, not the absence of one. Replay depends on the difference. +func TestCursorTreatsAnEmptyRangeAsAFact(t *testing.T) { + c := newTestCursor(9) + + _, _, ok := c.Pending() + require.False(t, ok, "no task in flight yet") + + require.NoError(t, c.StagePending(nil, 9, 9)) + + from, to, ok := c.Pending() + require.True(t, ok, "a task given nothing is still a task that must be recorded") + require.Equal(t, from, to) + + from, to, ok = c.Commit(nil) + require.True(t, ok) + require.Equal(t, int64(9), from) + require.Equal(t, int64(9), to) + require.Equal(t, int64(9), c.Offset(), "an empty range must not move the cursor") +} + +func TestCursorRejectsARangeBehindItself(t *testing.T) { + c := newTestCursor(12) + + err := c.StagePending(nil, 11, 14) + require.ErrorContains(t, err, "cursor is already at 12") + + err = c.StagePending(nil, 12, 11) + require.ErrorContains(t, err, "precedes range start") +} + +// A task that failed recorded nothing, so the range it was given never became +// history and the replacement is free to differ. +func TestCursorRedeliveryReplacesTheStagedRange(t *testing.T) { + c := newTestCursor(2) + + require.NoError(t, c.StagePending(nil, 2, 5)) + require.NoError(t, c.StagePending(nil, 2, 9)) + + from, to, ok := c.Pending() + require.True(t, ok) + require.Equal(t, int64(2), from) + require.Equal(t, int64(9), to) + require.Equal(t, int64(2), c.Offset(), "staging alone must never advance the cursor") +} diff --git a/chasm/lib/stream/gen/streampb/v1/message.go-helpers.pb.go b/chasm/lib/stream/gen/streampb/v1/message.go-helpers.pb.go new file mode 100644 index 00000000000..ef697410810 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/message.go-helpers.pb.go @@ -0,0 +1,80 @@ +// Code generated by protoc-gen-go-helpers. DO NOT EDIT. +package streampb + +import ( + "google.golang.org/protobuf/proto" +) + +// Marshal an object of type StreamRecord to the protobuf v3 wire format +func (val *StreamRecord) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamRecord from the protobuf v3 wire format +func (val *StreamRecord) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamRecord) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamRecord 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 *StreamRecord) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamRecord + switch t := that.(type) { + case *StreamRecord: + that1 = t + case StreamRecord: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type StreamRecordBatch to the protobuf v3 wire format +func (val *StreamRecordBatch) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamRecordBatch from the protobuf v3 wire format +func (val *StreamRecordBatch) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamRecordBatch) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamRecordBatch 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 *StreamRecordBatch) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamRecordBatch + switch t := that.(type) { + case *StreamRecordBatch: + that1 = t + case StreamRecordBatch: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} diff --git a/chasm/lib/stream/gen/streampb/v1/message.pb.go b/chasm/lib/stream/gen/streampb/v1/message.pb.go new file mode 100644 index 00000000000..400dc3c16b4 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/message.pb.go @@ -0,0 +1,265 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// plugins: +// protoc-gen-go +// protoc +// source: temporal/server/chasm/lib/stream/proto/v1/message.proto + +package streampb + +import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + + v1 "go.temporal.io/api/common/v1" + v11 "go.temporal.io/api/stream/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The stored shape of temporal.api.stream.v1.StreamRecord plus the offset a +// read assigns. Field for field the public record, so one crosses the frontend +// in either direction without translation. +type StreamRecord struct { + state protoimpl.MessageState `protogen:"open.v1"` + Body *v1.Payload `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Producer-supplied provenance, stored as sent. + Metadata map[string]*v1.Payload `protobuf:"bytes,2,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Topic string `protobuf:"bytes,3,opt,name=topic,proto3" json:"topic,omitempty"` + // The producer's position within its attempt, or -1 when unnumbered. Stored + // as sent; the global offset is what orders the stream. + Sequence int64 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"` + // Settled to DATA on append when left unspecified, so a retry hashes the + // same bytes and a reader never sees the zero value. + Kind v11.StreamRecordKind `protobuf:"varint,5,opt,name=kind,proto3,enum=temporal.api.stream.v1.StreamRecordKind" json:"kind,omitempty"` + // Position in the whole stream, set on read and never stored. A consumer + // that resumes at record granularity needs it, and a topic-filtered read + // leaves gaps that make it underivable from the response alone. + Offset int64 `protobuf:"varint,6,opt,name=offset,proto3" json:"offset,omitempty"` + // Who wrote the record. Empty when the owning Workflow did: its publish + // command clears the field, whatever the worker sent. + ProducerId string `protobuf:"bytes,7,opt,name=producer_id,json=producerId,proto3" json:"producer_id,omitempty"` + // The producer's attempt, stored as sent. Readers treat a later attempt by + // the same producer as superseding what the earlier one wrote. + Attempt int64 `protobuf:"varint,8,opt,name=attempt,proto3" json:"attempt,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamRecord) Reset() { + *x = StreamRecord{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_message_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamRecord) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamRecord) ProtoMessage() {} + +func (x *StreamRecord) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_message_proto_msgTypes[0] + 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 StreamRecord.ProtoReflect.Descriptor instead. +func (*StreamRecord) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_message_proto_rawDescGZIP(), []int{0} +} + +func (x *StreamRecord) GetBody() *v1.Payload { + if x != nil { + return x.Body + } + return nil +} + +func (x *StreamRecord) GetMetadata() map[string]*v1.Payload { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *StreamRecord) GetTopic() string { + if x != nil { + return x.Topic + } + return "" +} + +func (x *StreamRecord) GetSequence() int64 { + if x != nil { + return x.Sequence + } + return 0 +} + +func (x *StreamRecord) GetKind() v11.StreamRecordKind { + if x != nil { + return x.Kind + } + return v11.StreamRecordKind(0) +} + +func (x *StreamRecord) GetOffset() int64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *StreamRecord) GetProducerId() string { + if x != nil { + return x.ProducerId + } + return "" +} + +func (x *StreamRecord) GetAttempt() int64 { + if x != nil { + return x.Attempt + } + return 0 +} + +// One append is one batch, and one batch is one data node. The server stores +// this serialized and opaque; it decodes only to trim a partial first page or +// to apply a topic filter. +type StreamRecordBatch struct { + state protoimpl.MessageState `protogen:"open.v1"` + Records []*StreamRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamRecordBatch) Reset() { + *x = StreamRecordBatch{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_message_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamRecordBatch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamRecordBatch) ProtoMessage() {} + +func (x *StreamRecordBatch) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_message_proto_msgTypes[1] + 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 StreamRecordBatch.ProtoReflect.Descriptor instead. +func (*StreamRecordBatch) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_message_proto_rawDescGZIP(), []int{1} +} + +func (x *StreamRecordBatch) GetRecords() []*StreamRecord { + if x != nil { + return x.Records + } + return nil +} + +var File_temporal_server_chasm_lib_stream_proto_v1_message_proto protoreflect.FileDescriptor + +const file_temporal_server_chasm_lib_stream_proto_v1_message_proto_rawDesc = "" + + "\n" + + "7temporal/server/chasm/lib/stream/proto/v1/message.proto\x12)temporal.server.chasm.lib.stream.proto.v1\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/stream/v1/message.proto\"\xc7\x03\n" + + "\fStreamRecord\x123\n" + + "\x04body\x18\x01 \x01(\v2\x1f.temporal.api.common.v1.PayloadR\x04body\x12a\n" + + "\bmetadata\x18\x02 \x03(\v2E.temporal.server.chasm.lib.stream.proto.v1.StreamRecord.MetadataEntryR\bmetadata\x12\x14\n" + + "\x05topic\x18\x03 \x01(\tR\x05topic\x12\x1a\n" + + "\bsequence\x18\x04 \x01(\x03R\bsequence\x12<\n" + + "\x04kind\x18\x05 \x01(\x0e2(.temporal.api.stream.v1.StreamRecordKindR\x04kind\x12\x16\n" + + "\x06offset\x18\x06 \x01(\x03R\x06offset\x12\x1f\n" + + "\vproducer_id\x18\a \x01(\tR\n" + + "producerId\x12\x18\n" + + "\aattempt\x18\b \x01(\x03R\aattempt\x1a\\\n" + + "\rMetadataEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x125\n" + + "\x05value\x18\x02 \x01(\v2\x1f.temporal.api.common.v1.PayloadR\x05value:\x028\x01\"f\n" + + "\x11StreamRecordBatch\x12Q\n" + + "\arecords\x18\x01 \x03(\v27.temporal.server.chasm.lib.stream.proto.v1.StreamRecordR\arecordsB>Z temporal.api.common.v1.Payload + 2, // 1: temporal.server.chasm.lib.stream.proto.v1.StreamRecord.metadata:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamRecord.MetadataEntry + 4, // 2: temporal.server.chasm.lib.stream.proto.v1.StreamRecord.kind:type_name -> temporal.api.stream.v1.StreamRecordKind + 0, // 3: temporal.server.chasm.lib.stream.proto.v1.StreamRecordBatch.records:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamRecord + 3, // 4: temporal.server.chasm.lib.stream.proto.v1.StreamRecord.MetadataEntry.value:type_name -> temporal.api.common.v1.Payload + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_temporal_server_chasm_lib_stream_proto_v1_message_proto_init() } +func file_temporal_server_chasm_lib_stream_proto_v1_message_proto_init() { + if File_temporal_server_chasm_lib_stream_proto_v1_message_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_stream_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_stream_proto_v1_message_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_temporal_server_chasm_lib_stream_proto_v1_message_proto_goTypes, + DependencyIndexes: file_temporal_server_chasm_lib_stream_proto_v1_message_proto_depIdxs, + MessageInfos: file_temporal_server_chasm_lib_stream_proto_v1_message_proto_msgTypes, + }.Build() + File_temporal_server_chasm_lib_stream_proto_v1_message_proto = out.File + file_temporal_server_chasm_lib_stream_proto_v1_message_proto_goTypes = nil + file_temporal_server_chasm_lib_stream_proto_v1_message_proto_depIdxs = nil +} diff --git a/chasm/lib/stream/gen/streampb/v1/namespace.go b/chasm/lib/stream/gen/streampb/v1/namespace.go new file mode 100644 index 00000000000..dd465ef065e --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/namespace.go @@ -0,0 +1,75 @@ +package streampb + +// Every RPC here carries its namespace inside `frontend_request` rather than at +// the top level, because the top-level field is the resolved namespace id the +// frontend fills in before routing. +// +// The server's interceptors find a request's namespace by asserting it to +// `interceptor.NamespaceNameGetter`, which wants `GetNamespace() string` on the +// request itself. Without these the assertion falls through to the id getter, +// which at the frontend is still empty, so namespace rate limits, request +// validation, the authorization target, redirection and the long-poll deadline +// all resolve to the empty namespace and silently do nothing. +// +// The generator has no way to express "read it from this nested field", so the +// methods are written here, next to the generated types they belong to. + +func (x *CreateStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *AddMessagesRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *FinishWritingRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *SubscribeWorkflowRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *PollMessagesRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *DescribeStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *PollWorkflowMessagesRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *DescribeWorkflowStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *AddWorkflowMessagesRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *RegisterStreamConsumerRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *AdvanceConsumerHeadRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *CloseStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *TruncateStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *ListStreamsRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} + +func (x *DeleteStreamRequest) GetNamespace() string { + return x.GetFrontendRequest().GetNamespace() +} diff --git a/chasm/lib/stream/gen/streampb/v1/namespace_test.go b/chasm/lib/stream/gen/streampb/v1/namespace_test.go new file mode 100644 index 00000000000..b88bcaf856c --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/namespace_test.go @@ -0,0 +1,38 @@ +package streampb + +import ( + "testing" + + "go.temporal.io/server/common/rpc/interceptor" + "google.golang.org/protobuf/reflect/protoregistry" +) + +// Every request carrying a frontend_request must expose its namespace to the +// interceptors. Driven off the descriptor rather than a hand-written list so a +// new RPC fails here instead of silently opting out of namespace rate limits, +// validation, authorization and redirection. +func TestEveryRoutedRequestExposesNamespace(t *testing.T) { + fd := File_temporal_server_chasm_lib_stream_proto_v1_request_response_proto + messages := fd.Messages() + + checked := 0 + for i := 0; i < messages.Len(); i++ { + md := messages.Get(i) + if md.Fields().ByName("frontend_request") == nil { + continue + } + mt, err := protoregistry.GlobalTypes.FindMessageByName(md.FullName()) + if err != nil { + t.Fatalf("%s is not registered: %v", md.FullName(), err) + } + msg := mt.New().Interface() + if _, ok := msg.(interceptor.NamespaceNameGetter); !ok { + t.Errorf("%s has a frontend_request but no GetNamespace; add it in namespace.go", md.FullName()) + } + checked++ + } + + if checked == 0 { + t.Fatal("found no routed requests, so this test is not checking anything") + } +} diff --git a/chasm/lib/stream/gen/streampb/v1/request_response.go-helpers.pb.go b/chasm/lib/stream/gen/streampb/v1/request_response.go-helpers.pb.go new file mode 100644 index 00000000000..7c11d9434cd --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/request_response.go-helpers.pb.go @@ -0,0 +1,2152 @@ +// Code generated by protoc-gen-go-helpers. DO NOT EDIT. +package streampb + +import ( + "google.golang.org/protobuf/proto" +) + +// Marshal an object of type CreateStreamInput to the protobuf v3 wire format +func (val *CreateStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CreateStreamInput from the protobuf v3 wire format +func (val *CreateStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CreateStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CreateStreamInput 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 *CreateStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CreateStreamInput + switch t := that.(type) { + case *CreateStreamInput: + that1 = t + case CreateStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CreateStreamOutput to the protobuf v3 wire format +func (val *CreateStreamOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CreateStreamOutput from the protobuf v3 wire format +func (val *CreateStreamOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CreateStreamOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CreateStreamOutput 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 *CreateStreamOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CreateStreamOutput + switch t := that.(type) { + case *CreateStreamOutput: + that1 = t + case CreateStreamOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddMessagesInput to the protobuf v3 wire format +func (val *AddMessagesInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddMessagesInput from the protobuf v3 wire format +func (val *AddMessagesInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddMessagesInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddMessagesInput 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 *AddMessagesInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddMessagesInput + switch t := that.(type) { + case *AddMessagesInput: + that1 = t + case AddMessagesInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddMessagesOutput to the protobuf v3 wire format +func (val *AddMessagesOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddMessagesOutput from the protobuf v3 wire format +func (val *AddMessagesOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddMessagesOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddMessagesOutput 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 *AddMessagesOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddMessagesOutput + switch t := that.(type) { + case *AddMessagesOutput: + that1 = t + case AddMessagesOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type FinishWritingInput to the protobuf v3 wire format +func (val *FinishWritingInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type FinishWritingInput from the protobuf v3 wire format +func (val *FinishWritingInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *FinishWritingInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two FinishWritingInput 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 *FinishWritingInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *FinishWritingInput + switch t := that.(type) { + case *FinishWritingInput: + that1 = t + case FinishWritingInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type FinishWritingOutput to the protobuf v3 wire format +func (val *FinishWritingOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type FinishWritingOutput from the protobuf v3 wire format +func (val *FinishWritingOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *FinishWritingOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two FinishWritingOutput 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 *FinishWritingOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *FinishWritingOutput + switch t := that.(type) { + case *FinishWritingOutput: + that1 = t + case FinishWritingOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type SubscribeWorkflowInput to the protobuf v3 wire format +func (val *SubscribeWorkflowInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type SubscribeWorkflowInput from the protobuf v3 wire format +func (val *SubscribeWorkflowInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *SubscribeWorkflowInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two SubscribeWorkflowInput 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 *SubscribeWorkflowInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *SubscribeWorkflowInput + switch t := that.(type) { + case *SubscribeWorkflowInput: + that1 = t + case SubscribeWorkflowInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type SubscribeWorkflowOutput to the protobuf v3 wire format +func (val *SubscribeWorkflowOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type SubscribeWorkflowOutput from the protobuf v3 wire format +func (val *SubscribeWorkflowOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *SubscribeWorkflowOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two SubscribeWorkflowOutput 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 *SubscribeWorkflowOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *SubscribeWorkflowOutput + switch t := that.(type) { + case *SubscribeWorkflowOutput: + that1 = t + case SubscribeWorkflowOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollMessagesInput to the protobuf v3 wire format +func (val *PollMessagesInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollMessagesInput from the protobuf v3 wire format +func (val *PollMessagesInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollMessagesInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollMessagesInput 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 *PollMessagesInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollMessagesInput + switch t := that.(type) { + case *PollMessagesInput: + that1 = t + case PollMessagesInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollMessagesOutput to the protobuf v3 wire format +func (val *PollMessagesOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollMessagesOutput from the protobuf v3 wire format +func (val *PollMessagesOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollMessagesOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollMessagesOutput 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 *PollMessagesOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollMessagesOutput + switch t := that.(type) { + case *PollMessagesOutput: + that1 = t + case PollMessagesOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeStreamInput to the protobuf v3 wire format +func (val *DescribeStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeStreamInput from the protobuf v3 wire format +func (val *DescribeStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeStreamInput 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 *DescribeStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeStreamInput + switch t := that.(type) { + case *DescribeStreamInput: + that1 = t + case DescribeStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollWorkflowMessagesInput to the protobuf v3 wire format +func (val *PollWorkflowMessagesInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollWorkflowMessagesInput from the protobuf v3 wire format +func (val *PollWorkflowMessagesInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollWorkflowMessagesInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollWorkflowMessagesInput 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 *PollWorkflowMessagesInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollWorkflowMessagesInput + switch t := that.(type) { + case *PollWorkflowMessagesInput: + that1 = t + case PollWorkflowMessagesInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeWorkflowStreamInput to the protobuf v3 wire format +func (val *DescribeWorkflowStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeWorkflowStreamInput from the protobuf v3 wire format +func (val *DescribeWorkflowStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeWorkflowStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeWorkflowStreamInput 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 *DescribeWorkflowStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeWorkflowStreamInput + switch t := that.(type) { + case *DescribeWorkflowStreamInput: + that1 = t + case DescribeWorkflowStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddWorkflowMessagesInput to the protobuf v3 wire format +func (val *AddWorkflowMessagesInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddWorkflowMessagesInput from the protobuf v3 wire format +func (val *AddWorkflowMessagesInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddWorkflowMessagesInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddWorkflowMessagesInput 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 *AddWorkflowMessagesInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddWorkflowMessagesInput + switch t := that.(type) { + case *AddWorkflowMessagesInput: + that1 = t + case AddWorkflowMessagesInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeStreamOutput to the protobuf v3 wire format +func (val *DescribeStreamOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeStreamOutput from the protobuf v3 wire format +func (val *DescribeStreamOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeStreamOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeStreamOutput 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 *DescribeStreamOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeStreamOutput + switch t := that.(type) { + case *DescribeStreamOutput: + that1 = t + case DescribeStreamOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CloseStreamInput to the protobuf v3 wire format +func (val *CloseStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CloseStreamInput from the protobuf v3 wire format +func (val *CloseStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CloseStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CloseStreamInput 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 *CloseStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CloseStreamInput + switch t := that.(type) { + case *CloseStreamInput: + that1 = t + case CloseStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CloseStreamOutput to the protobuf v3 wire format +func (val *CloseStreamOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CloseStreamOutput from the protobuf v3 wire format +func (val *CloseStreamOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CloseStreamOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CloseStreamOutput 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 *CloseStreamOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CloseStreamOutput + switch t := that.(type) { + case *CloseStreamOutput: + that1 = t + case CloseStreamOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type TruncateStreamInput to the protobuf v3 wire format +func (val *TruncateStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type TruncateStreamInput from the protobuf v3 wire format +func (val *TruncateStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *TruncateStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two TruncateStreamInput 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 *TruncateStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *TruncateStreamInput + switch t := that.(type) { + case *TruncateStreamInput: + that1 = t + case TruncateStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type TruncateStreamOutput to the protobuf v3 wire format +func (val *TruncateStreamOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type TruncateStreamOutput from the protobuf v3 wire format +func (val *TruncateStreamOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *TruncateStreamOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two TruncateStreamOutput 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 *TruncateStreamOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *TruncateStreamOutput + switch t := that.(type) { + case *TruncateStreamOutput: + that1 = t + case TruncateStreamOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DeleteStreamInput to the protobuf v3 wire format +func (val *DeleteStreamInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DeleteStreamInput from the protobuf v3 wire format +func (val *DeleteStreamInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DeleteStreamInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DeleteStreamInput 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 *DeleteStreamInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DeleteStreamInput + switch t := that.(type) { + case *DeleteStreamInput: + that1 = t + case DeleteStreamInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DeleteStreamOutput to the protobuf v3 wire format +func (val *DeleteStreamOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DeleteStreamOutput from the protobuf v3 wire format +func (val *DeleteStreamOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DeleteStreamOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DeleteStreamOutput 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 *DeleteStreamOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DeleteStreamOutput + switch t := that.(type) { + case *DeleteStreamOutput: + that1 = t + case DeleteStreamOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CreateStreamRequest to the protobuf v3 wire format +func (val *CreateStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CreateStreamRequest from the protobuf v3 wire format +func (val *CreateStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CreateStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CreateStreamRequest 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 *CreateStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CreateStreamRequest + switch t := that.(type) { + case *CreateStreamRequest: + that1 = t + case CreateStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CreateStreamResponse to the protobuf v3 wire format +func (val *CreateStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CreateStreamResponse from the protobuf v3 wire format +func (val *CreateStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CreateStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CreateStreamResponse 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 *CreateStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CreateStreamResponse + switch t := that.(type) { + case *CreateStreamResponse: + that1 = t + case CreateStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddMessagesRequest to the protobuf v3 wire format +func (val *AddMessagesRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddMessagesRequest from the protobuf v3 wire format +func (val *AddMessagesRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddMessagesRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddMessagesRequest 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 *AddMessagesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddMessagesRequest + switch t := that.(type) { + case *AddMessagesRequest: + that1 = t + case AddMessagesRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddMessagesResponse to the protobuf v3 wire format +func (val *AddMessagesResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddMessagesResponse from the protobuf v3 wire format +func (val *AddMessagesResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddMessagesResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddMessagesResponse 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 *AddMessagesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddMessagesResponse + switch t := that.(type) { + case *AddMessagesResponse: + that1 = t + case AddMessagesResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type FinishWritingRequest to the protobuf v3 wire format +func (val *FinishWritingRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type FinishWritingRequest from the protobuf v3 wire format +func (val *FinishWritingRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *FinishWritingRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two FinishWritingRequest 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 *FinishWritingRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *FinishWritingRequest + switch t := that.(type) { + case *FinishWritingRequest: + that1 = t + case FinishWritingRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type FinishWritingResponse to the protobuf v3 wire format +func (val *FinishWritingResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type FinishWritingResponse from the protobuf v3 wire format +func (val *FinishWritingResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *FinishWritingResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two FinishWritingResponse 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 *FinishWritingResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *FinishWritingResponse + switch t := that.(type) { + case *FinishWritingResponse: + that1 = t + case FinishWritingResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type SubscribeWorkflowRequest to the protobuf v3 wire format +func (val *SubscribeWorkflowRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type SubscribeWorkflowRequest from the protobuf v3 wire format +func (val *SubscribeWorkflowRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *SubscribeWorkflowRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two SubscribeWorkflowRequest 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 *SubscribeWorkflowRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *SubscribeWorkflowRequest + switch t := that.(type) { + case *SubscribeWorkflowRequest: + that1 = t + case SubscribeWorkflowRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type SubscribeWorkflowResponse to the protobuf v3 wire format +func (val *SubscribeWorkflowResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type SubscribeWorkflowResponse from the protobuf v3 wire format +func (val *SubscribeWorkflowResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *SubscribeWorkflowResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two SubscribeWorkflowResponse 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 *SubscribeWorkflowResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *SubscribeWorkflowResponse + switch t := that.(type) { + case *SubscribeWorkflowResponse: + that1 = t + case SubscribeWorkflowResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollMessagesRequest to the protobuf v3 wire format +func (val *PollMessagesRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollMessagesRequest from the protobuf v3 wire format +func (val *PollMessagesRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollMessagesRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollMessagesRequest 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 *PollMessagesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollMessagesRequest + switch t := that.(type) { + case *PollMessagesRequest: + that1 = t + case PollMessagesRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollMessagesResponse to the protobuf v3 wire format +func (val *PollMessagesResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollMessagesResponse from the protobuf v3 wire format +func (val *PollMessagesResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollMessagesResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollMessagesResponse 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 *PollMessagesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollMessagesResponse + switch t := that.(type) { + case *PollMessagesResponse: + that1 = t + case PollMessagesResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeStreamRequest to the protobuf v3 wire format +func (val *DescribeStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeStreamRequest from the protobuf v3 wire format +func (val *DescribeStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeStreamRequest 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 *DescribeStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeStreamRequest + switch t := that.(type) { + case *DescribeStreamRequest: + that1 = t + case DescribeStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeStreamResponse to the protobuf v3 wire format +func (val *DescribeStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeStreamResponse from the protobuf v3 wire format +func (val *DescribeStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeStreamResponse 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 *DescribeStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeStreamResponse + switch t := that.(type) { + case *DescribeStreamResponse: + that1 = t + case DescribeStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollWorkflowMessagesRequest to the protobuf v3 wire format +func (val *PollWorkflowMessagesRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollWorkflowMessagesRequest from the protobuf v3 wire format +func (val *PollWorkflowMessagesRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollWorkflowMessagesRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollWorkflowMessagesRequest 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 *PollWorkflowMessagesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollWorkflowMessagesRequest + switch t := that.(type) { + case *PollWorkflowMessagesRequest: + that1 = t + case PollWorkflowMessagesRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type PollWorkflowMessagesResponse to the protobuf v3 wire format +func (val *PollWorkflowMessagesResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type PollWorkflowMessagesResponse from the protobuf v3 wire format +func (val *PollWorkflowMessagesResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *PollWorkflowMessagesResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two PollWorkflowMessagesResponse 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 *PollWorkflowMessagesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *PollWorkflowMessagesResponse + switch t := that.(type) { + case *PollWorkflowMessagesResponse: + that1 = t + case PollWorkflowMessagesResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeWorkflowStreamRequest to the protobuf v3 wire format +func (val *DescribeWorkflowStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeWorkflowStreamRequest from the protobuf v3 wire format +func (val *DescribeWorkflowStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeWorkflowStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeWorkflowStreamRequest 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 *DescribeWorkflowStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeWorkflowStreamRequest + switch t := that.(type) { + case *DescribeWorkflowStreamRequest: + that1 = t + case DescribeWorkflowStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DescribeWorkflowStreamResponse to the protobuf v3 wire format +func (val *DescribeWorkflowStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DescribeWorkflowStreamResponse from the protobuf v3 wire format +func (val *DescribeWorkflowStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DescribeWorkflowStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DescribeWorkflowStreamResponse 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 *DescribeWorkflowStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DescribeWorkflowStreamResponse + switch t := that.(type) { + case *DescribeWorkflowStreamResponse: + that1 = t + case DescribeWorkflowStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type RegisterStreamConsumerInput to the protobuf v3 wire format +func (val *RegisterStreamConsumerInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type RegisterStreamConsumerInput from the protobuf v3 wire format +func (val *RegisterStreamConsumerInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *RegisterStreamConsumerInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two RegisterStreamConsumerInput 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 *RegisterStreamConsumerInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *RegisterStreamConsumerInput + switch t := that.(type) { + case *RegisterStreamConsumerInput: + that1 = t + case RegisterStreamConsumerInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type RegisterStreamConsumerOutput to the protobuf v3 wire format +func (val *RegisterStreamConsumerOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type RegisterStreamConsumerOutput from the protobuf v3 wire format +func (val *RegisterStreamConsumerOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *RegisterStreamConsumerOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two RegisterStreamConsumerOutput 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 *RegisterStreamConsumerOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *RegisterStreamConsumerOutput + switch t := that.(type) { + case *RegisterStreamConsumerOutput: + that1 = t + case RegisterStreamConsumerOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AdvanceConsumerHeadInput to the protobuf v3 wire format +func (val *AdvanceConsumerHeadInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AdvanceConsumerHeadInput from the protobuf v3 wire format +func (val *AdvanceConsumerHeadInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AdvanceConsumerHeadInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AdvanceConsumerHeadInput 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 *AdvanceConsumerHeadInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AdvanceConsumerHeadInput + switch t := that.(type) { + case *AdvanceConsumerHeadInput: + that1 = t + case AdvanceConsumerHeadInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AdvanceConsumerHeadOutput to the protobuf v3 wire format +func (val *AdvanceConsumerHeadOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AdvanceConsumerHeadOutput from the protobuf v3 wire format +func (val *AdvanceConsumerHeadOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AdvanceConsumerHeadOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AdvanceConsumerHeadOutput 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 *AdvanceConsumerHeadOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AdvanceConsumerHeadOutput + switch t := that.(type) { + case *AdvanceConsumerHeadOutput: + that1 = t + case AdvanceConsumerHeadOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddWorkflowMessagesRequest to the protobuf v3 wire format +func (val *AddWorkflowMessagesRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddWorkflowMessagesRequest from the protobuf v3 wire format +func (val *AddWorkflowMessagesRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddWorkflowMessagesRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddWorkflowMessagesRequest 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 *AddWorkflowMessagesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddWorkflowMessagesRequest + switch t := that.(type) { + case *AddWorkflowMessagesRequest: + that1 = t + case AddWorkflowMessagesRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AddWorkflowMessagesResponse to the protobuf v3 wire format +func (val *AddWorkflowMessagesResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AddWorkflowMessagesResponse from the protobuf v3 wire format +func (val *AddWorkflowMessagesResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AddWorkflowMessagesResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AddWorkflowMessagesResponse 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 *AddWorkflowMessagesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AddWorkflowMessagesResponse + switch t := that.(type) { + case *AddWorkflowMessagesResponse: + that1 = t + case AddWorkflowMessagesResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type RegisterStreamConsumerRequest to the protobuf v3 wire format +func (val *RegisterStreamConsumerRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type RegisterStreamConsumerRequest from the protobuf v3 wire format +func (val *RegisterStreamConsumerRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *RegisterStreamConsumerRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two RegisterStreamConsumerRequest 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 *RegisterStreamConsumerRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *RegisterStreamConsumerRequest + switch t := that.(type) { + case *RegisterStreamConsumerRequest: + that1 = t + case RegisterStreamConsumerRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type RegisterStreamConsumerResponse to the protobuf v3 wire format +func (val *RegisterStreamConsumerResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type RegisterStreamConsumerResponse from the protobuf v3 wire format +func (val *RegisterStreamConsumerResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *RegisterStreamConsumerResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two RegisterStreamConsumerResponse 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 *RegisterStreamConsumerResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *RegisterStreamConsumerResponse + switch t := that.(type) { + case *RegisterStreamConsumerResponse: + that1 = t + case RegisterStreamConsumerResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AdvanceConsumerHeadRequest to the protobuf v3 wire format +func (val *AdvanceConsumerHeadRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AdvanceConsumerHeadRequest from the protobuf v3 wire format +func (val *AdvanceConsumerHeadRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AdvanceConsumerHeadRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AdvanceConsumerHeadRequest 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 *AdvanceConsumerHeadRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AdvanceConsumerHeadRequest + switch t := that.(type) { + case *AdvanceConsumerHeadRequest: + that1 = t + case AdvanceConsumerHeadRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type AdvanceConsumerHeadResponse to the protobuf v3 wire format +func (val *AdvanceConsumerHeadResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type AdvanceConsumerHeadResponse from the protobuf v3 wire format +func (val *AdvanceConsumerHeadResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *AdvanceConsumerHeadResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two AdvanceConsumerHeadResponse 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 *AdvanceConsumerHeadResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *AdvanceConsumerHeadResponse + switch t := that.(type) { + case *AdvanceConsumerHeadResponse: + that1 = t + case AdvanceConsumerHeadResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CloseStreamRequest to the protobuf v3 wire format +func (val *CloseStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CloseStreamRequest from the protobuf v3 wire format +func (val *CloseStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CloseStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CloseStreamRequest 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 *CloseStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CloseStreamRequest + switch t := that.(type) { + case *CloseStreamRequest: + that1 = t + case CloseStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type CloseStreamResponse to the protobuf v3 wire format +func (val *CloseStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type CloseStreamResponse from the protobuf v3 wire format +func (val *CloseStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *CloseStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two CloseStreamResponse 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 *CloseStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *CloseStreamResponse + switch t := that.(type) { + case *CloseStreamResponse: + that1 = t + case CloseStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type TruncateStreamRequest to the protobuf v3 wire format +func (val *TruncateStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type TruncateStreamRequest from the protobuf v3 wire format +func (val *TruncateStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *TruncateStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two TruncateStreamRequest 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 *TruncateStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *TruncateStreamRequest + switch t := that.(type) { + case *TruncateStreamRequest: + that1 = t + case TruncateStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type TruncateStreamResponse to the protobuf v3 wire format +func (val *TruncateStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type TruncateStreamResponse from the protobuf v3 wire format +func (val *TruncateStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *TruncateStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two TruncateStreamResponse 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 *TruncateStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *TruncateStreamResponse + switch t := that.(type) { + case *TruncateStreamResponse: + that1 = t + case TruncateStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ListStreamsInput to the protobuf v3 wire format +func (val *ListStreamsInput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ListStreamsInput from the protobuf v3 wire format +func (val *ListStreamsInput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ListStreamsInput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ListStreamsInput 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 *ListStreamsInput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ListStreamsInput + switch t := that.(type) { + case *ListStreamsInput: + that1 = t + case ListStreamsInput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type StreamListEntry to the protobuf v3 wire format +func (val *StreamListEntry) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamListEntry from the protobuf v3 wire format +func (val *StreamListEntry) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamListEntry) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamListEntry 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 *StreamListEntry) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamListEntry + switch t := that.(type) { + case *StreamListEntry: + that1 = t + case StreamListEntry: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ListStreamsOutput to the protobuf v3 wire format +func (val *ListStreamsOutput) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ListStreamsOutput from the protobuf v3 wire format +func (val *ListStreamsOutput) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ListStreamsOutput) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ListStreamsOutput 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 *ListStreamsOutput) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ListStreamsOutput + switch t := that.(type) { + case *ListStreamsOutput: + that1 = t + case ListStreamsOutput: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ListStreamsRequest to the protobuf v3 wire format +func (val *ListStreamsRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ListStreamsRequest from the protobuf v3 wire format +func (val *ListStreamsRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ListStreamsRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ListStreamsRequest 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 *ListStreamsRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ListStreamsRequest + switch t := that.(type) { + case *ListStreamsRequest: + that1 = t + case ListStreamsRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ListStreamsResponse to the protobuf v3 wire format +func (val *ListStreamsResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ListStreamsResponse from the protobuf v3 wire format +func (val *ListStreamsResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ListStreamsResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ListStreamsResponse 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 *ListStreamsResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ListStreamsResponse + switch t := that.(type) { + case *ListStreamsResponse: + that1 = t + case ListStreamsResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DeleteStreamRequest to the protobuf v3 wire format +func (val *DeleteStreamRequest) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DeleteStreamRequest from the protobuf v3 wire format +func (val *DeleteStreamRequest) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DeleteStreamRequest) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DeleteStreamRequest 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 *DeleteStreamRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DeleteStreamRequest + switch t := that.(type) { + case *DeleteStreamRequest: + that1 = t + case DeleteStreamRequest: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type DeleteStreamResponse to the protobuf v3 wire format +func (val *DeleteStreamResponse) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type DeleteStreamResponse from the protobuf v3 wire format +func (val *DeleteStreamResponse) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *DeleteStreamResponse) Size() int { + return proto.Size(val) +} + +// Equal returns whether two DeleteStreamResponse 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 *DeleteStreamResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *DeleteStreamResponse + switch t := that.(type) { + case *DeleteStreamResponse: + that1 = t + case DeleteStreamResponse: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} diff --git a/chasm/lib/stream/gen/streampb/v1/request_response.pb.go b/chasm/lib/stream/gen/streampb/v1/request_response.pb.go new file mode 100644 index 00000000000..ab1d3863ef8 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/request_response.pb.go @@ -0,0 +1,3658 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// plugins: +// protoc-gen-go +// protoc +// source: temporal/server/chasm/lib/stream/proto/v1/request_response.proto + +package streampb + +import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + + v1 "go.temporal.io/api/common/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CreateStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + Lifecycle *StreamLifecycle `protobuf:"bytes,3,opt,name=lifecycle,proto3" json:"lifecycle,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateStreamInput) Reset() { + *x = CreateStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateStreamInput) ProtoMessage() {} + +func (x *CreateStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[0] + 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 CreateStreamInput.ProtoReflect.Descriptor instead. +func (*CreateStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *CreateStreamInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *CreateStreamInput) GetLifecycle() *StreamLifecycle { + if x != nil { + return x.Lifecycle + } + return nil +} + +type CreateStreamOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + RunId string `protobuf:"bytes,1,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateStreamOutput) Reset() { + *x = CreateStreamOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateStreamOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateStreamOutput) ProtoMessage() {} + +func (x *CreateStreamOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[1] + 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 CreateStreamOutput.ProtoReflect.Descriptor instead. +func (*CreateStreamOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateStreamOutput) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +type AddMessagesInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // Optional. Supplying it skips resolving the stream's current run, which is + // a persistence lookup on every call. CreateStream returns it. + RunId string `protobuf:"bytes,9,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + Records []*StreamRecord `protobuf:"bytes,3,rep,name=records,proto3" json:"records,omitempty"` + // Idempotency, all optional. Supply a producer identity and sequence, or an + // expected offset, or neither and accept at-least-once. + ProducerId string `protobuf:"bytes,4,opt,name=producer_id,json=producerId,proto3" json:"producer_id,omitempty"` + Sequence int64 `protobuf:"varint,5,opt,name=sequence,proto3" json:"sequence,omitempty"` + // Guarded by use_expected_offset because proto3 optional is not supported + // by this repo's helper generator. + ExpectedOffset int64 `protobuf:"varint,6,opt,name=expected_offset,json=expectedOffset,proto3" json:"expected_offset,omitempty"` + UseExpectedOffset bool `protobuf:"varint,8,opt,name=use_expected_offset,json=useExpectedOffset,proto3" json:"use_expected_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddMessagesInput) Reset() { + *x = AddMessagesInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddMessagesInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMessagesInput) ProtoMessage() {} + +func (x *AddMessagesInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[2] + 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 AddMessagesInput.ProtoReflect.Descriptor instead. +func (*AddMessagesInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{2} +} + +func (x *AddMessagesInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *AddMessagesInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *AddMessagesInput) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +func (x *AddMessagesInput) GetRecords() []*StreamRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *AddMessagesInput) GetProducerId() string { + if x != nil { + return x.ProducerId + } + return "" +} + +func (x *AddMessagesInput) GetSequence() int64 { + if x != nil { + return x.Sequence + } + return 0 +} + +func (x *AddMessagesInput) GetExpectedOffset() int64 { + if x != nil { + return x.ExpectedOffset + } + return 0 +} + +func (x *AddMessagesInput) GetUseExpectedOffset() bool { + if x != nil { + return x.UseExpectedOffset + } + return false +} + +type AddMessagesOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + FirstOffset int64 `protobuf:"varint,1,opt,name=first_offset,json=firstOffset,proto3" json:"first_offset,omitempty"` + NextOffset int64 `protobuf:"varint,2,opt,name=next_offset,json=nextOffset,proto3" json:"next_offset,omitempty"` + Count int64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + // True when a retry matched a recorded sequence and nothing was appended. + Deduplicated bool `protobuf:"varint,4,opt,name=deduplicated,proto3" json:"deduplicated,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddMessagesOutput) Reset() { + *x = AddMessagesOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddMessagesOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMessagesOutput) ProtoMessage() {} + +func (x *AddMessagesOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[3] + 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 AddMessagesOutput.ProtoReflect.Descriptor instead. +func (*AddMessagesOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{3} +} + +func (x *AddMessagesOutput) GetFirstOffset() int64 { + if x != nil { + return x.FirstOffset + } + return 0 +} + +func (x *AddMessagesOutput) GetNextOffset() int64 { + if x != nil { + return x.NextOffset + } + return 0 +} + +func (x *AddMessagesOutput) GetCount() int64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *AddMessagesOutput) GetDeduplicated() bool { + if x != nil { + return x.Deduplicated + } + return false +} + +type FinishWritingInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + ProducerId string `protobuf:"bytes,3,opt,name=producer_id,json=producerId,proto3" json:"producer_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FinishWritingInput) Reset() { + *x = FinishWritingInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FinishWritingInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinishWritingInput) ProtoMessage() {} + +func (x *FinishWritingInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[4] + 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 FinishWritingInput.ProtoReflect.Descriptor instead. +func (*FinishWritingInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{4} +} + +func (x *FinishWritingInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *FinishWritingInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *FinishWritingInput) GetProducerId() string { + if x != nil { + return x.ProducerId + } + return "" +} + +type FinishWritingOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FinishWritingOutput) Reset() { + *x = FinishWritingOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FinishWritingOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinishWritingOutput) ProtoMessage() {} + +func (x *FinishWritingOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[5] + 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 FinishWritingOutput.ProtoReflect.Descriptor instead. +func (*FinishWritingOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{5} +} + +// Registers a Workflow as a consumer of a stream it owns. The cursor lands in +// the Workflow's own state, so from then on each of its Workflow Tasks carries +// the next range and records what it consumed. +type SubscribeWorkflowInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + OwnerRunId string `protobuf:"bytes,6,opt,name=owner_run_id,json=ownerRunId,proto3" json:"owner_run_id,omitempty"` + // Name of the stream within the Workflow, for a stream it owns. + StreamName string `protobuf:"bytes,3,opt,name=stream_name,json=streamName,proto3" json:"stream_name,omitempty"` + // Id of a standalone stream in another execution. Exactly one of this and + // stream_name is set. + StreamId string `protobuf:"bytes,5,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // Where to start. Resolved here rather than at delivery, so the first + // recorded range starts from a fact instead of a reading. + StartOffset int64 `protobuf:"varint,4,opt,name=start_offset,json=startOffset,proto3" json:"start_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeWorkflowInput) Reset() { + *x = SubscribeWorkflowInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeWorkflowInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeWorkflowInput) ProtoMessage() {} + +func (x *SubscribeWorkflowInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[6] + 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 SubscribeWorkflowInput.ProtoReflect.Descriptor instead. +func (*SubscribeWorkflowInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{6} +} + +func (x *SubscribeWorkflowInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *SubscribeWorkflowInput) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *SubscribeWorkflowInput) GetOwnerRunId() string { + if x != nil { + return x.OwnerRunId + } + return "" +} + +func (x *SubscribeWorkflowInput) GetStreamName() string { + if x != nil { + return x.StreamName + } + return "" +} + +func (x *SubscribeWorkflowInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *SubscribeWorkflowInput) GetStartOffset() int64 { + if x != nil { + return x.StartOffset + } + return 0 +} + +type SubscribeWorkflowOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + StartOffset int64 `protobuf:"varint,1,opt,name=start_offset,json=startOffset,proto3" json:"start_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeWorkflowOutput) Reset() { + *x = SubscribeWorkflowOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeWorkflowOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeWorkflowOutput) ProtoMessage() {} + +func (x *SubscribeWorkflowOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[7] + 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 SubscribeWorkflowOutput.ProtoReflect.Descriptor instead. +func (*SubscribeWorkflowOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{7} +} + +func (x *SubscribeWorkflowOutput) GetStartOffset() int64 { + if x != nil { + return x.StartOffset + } + return 0 +} + +type PollMessagesInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // Optional, as on AddMessagesInput. + RunId string `protobuf:"bytes,7,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + FromOffset int64 `protobuf:"varint,3,opt,name=from_offset,json=fromOffset,proto3" json:"from_offset,omitempty"` + MaxMessages int32 `protobuf:"varint,4,opt,name=max_messages,json=maxMessages,proto3" json:"max_messages,omitempty"` + // Filters by exact topic. Offsets are assigned over the unfiltered stream, so + // next_offset advances past filtered-out records too. + Topics []string `protobuf:"bytes,5,rep,name=topics,proto3" json:"topics,omitempty"` + // When set and the reader is caught up, block until something arrives, the + // stream closes, or the server's long-poll timeout elapses. A timeout returns + // an empty response rather than an error, so the caller simply polls again. + WaitNewMessages bool `protobuf:"varint,6,opt,name=wait_new_messages,json=waitNewMessages,proto3" json:"wait_new_messages,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollMessagesInput) Reset() { + *x = PollMessagesInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollMessagesInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollMessagesInput) ProtoMessage() {} + +func (x *PollMessagesInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[8] + 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 PollMessagesInput.ProtoReflect.Descriptor instead. +func (*PollMessagesInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{8} +} + +func (x *PollMessagesInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *PollMessagesInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *PollMessagesInput) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +func (x *PollMessagesInput) GetFromOffset() int64 { + if x != nil { + return x.FromOffset + } + return 0 +} + +func (x *PollMessagesInput) GetMaxMessages() int32 { + if x != nil { + return x.MaxMessages + } + return 0 +} + +func (x *PollMessagesInput) GetTopics() []string { + if x != nil { + return x.Topics + } + return nil +} + +func (x *PollMessagesInput) GetWaitNewMessages() bool { + if x != nil { + return x.WaitNewMessages + } + return false +} + +type PollMessagesOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Records []*StreamRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + NextOffset int64 `protobuf:"varint,2,opt,name=next_offset,json=nextOffset,proto3" json:"next_offset,omitempty"` + HeadOffset int64 `protobuf:"varint,3,opt,name=head_offset,json=headOffset,proto3" json:"head_offset,omitempty"` + Closed bool `protobuf:"varint,4,opt,name=closed,proto3" json:"closed,omitempty"` + CloseReason *v1.Payload `protobuf:"bytes,5,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` + // The execution holding the stream. A workflow task slice built from this + // read names the run it came from. + RunId string `protobuf:"bytes,6,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollMessagesOutput) Reset() { + *x = PollMessagesOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollMessagesOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollMessagesOutput) ProtoMessage() {} + +func (x *PollMessagesOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[9] + 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 PollMessagesOutput.ProtoReflect.Descriptor instead. +func (*PollMessagesOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{9} +} + +func (x *PollMessagesOutput) GetRecords() []*StreamRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *PollMessagesOutput) GetNextOffset() int64 { + if x != nil { + return x.NextOffset + } + return 0 +} + +func (x *PollMessagesOutput) GetHeadOffset() int64 { + if x != nil { + return x.HeadOffset + } + return 0 +} + +func (x *PollMessagesOutput) GetClosed() bool { + if x != nil { + return x.Closed + } + return false +} + +func (x *PollMessagesOutput) GetCloseReason() *v1.Payload { + if x != nil { + return x.CloseReason + } + return nil +} + +func (x *PollMessagesOutput) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +type DescribeStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeStreamInput) Reset() { + *x = DescribeStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeStreamInput) ProtoMessage() {} + +func (x *DescribeStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[10] + 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 DescribeStreamInput.ProtoReflect.Descriptor instead. +func (*DescribeStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{10} +} + +func (x *DescribeStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *DescribeStreamInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +// A stream a workflow owns lives inside that workflow's execution, so it has +// no standalone id to address it by. It is named by its owner and its name +// instead, and routed on the owner. +type PollWorkflowMessagesInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + OwnerRunId string `protobuf:"bytes,8,opt,name=owner_run_id,json=ownerRunId,proto3" json:"owner_run_id,omitempty"` + // Empty means the workflow's default output stream. + StreamName string `protobuf:"bytes,3,opt,name=stream_name,json=streamName,proto3" json:"stream_name,omitempty"` + FromOffset int64 `protobuf:"varint,4,opt,name=from_offset,json=fromOffset,proto3" json:"from_offset,omitempty"` + MaxMessages int32 `protobuf:"varint,5,opt,name=max_messages,json=maxMessages,proto3" json:"max_messages,omitempty"` + // Filters as on PollMessagesInput. + Topics []string `protobuf:"bytes,6,rep,name=topics,proto3" json:"topics,omitempty"` + WaitNewMessages bool `protobuf:"varint,7,opt,name=wait_new_messages,json=waitNewMessages,proto3" json:"wait_new_messages,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollWorkflowMessagesInput) Reset() { + *x = PollWorkflowMessagesInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollWorkflowMessagesInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollWorkflowMessagesInput) ProtoMessage() {} + +func (x *PollWorkflowMessagesInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[11] + 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 PollWorkflowMessagesInput.ProtoReflect.Descriptor instead. +func (*PollWorkflowMessagesInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{11} +} + +func (x *PollWorkflowMessagesInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *PollWorkflowMessagesInput) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *PollWorkflowMessagesInput) GetOwnerRunId() string { + if x != nil { + return x.OwnerRunId + } + return "" +} + +func (x *PollWorkflowMessagesInput) GetStreamName() string { + if x != nil { + return x.StreamName + } + return "" +} + +func (x *PollWorkflowMessagesInput) GetFromOffset() int64 { + if x != nil { + return x.FromOffset + } + return 0 +} + +func (x *PollWorkflowMessagesInput) GetMaxMessages() int32 { + if x != nil { + return x.MaxMessages + } + return 0 +} + +func (x *PollWorkflowMessagesInput) GetTopics() []string { + if x != nil { + return x.Topics + } + return nil +} + +func (x *PollWorkflowMessagesInput) GetWaitNewMessages() bool { + if x != nil { + return x.WaitNewMessages + } + return false +} + +type DescribeWorkflowStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + OwnerRunId string `protobuf:"bytes,4,opt,name=owner_run_id,json=ownerRunId,proto3" json:"owner_run_id,omitempty"` + StreamName string `protobuf:"bytes,3,opt,name=stream_name,json=streamName,proto3" json:"stream_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeWorkflowStreamInput) Reset() { + *x = DescribeWorkflowStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeWorkflowStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeWorkflowStreamInput) ProtoMessage() {} + +func (x *DescribeWorkflowStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[12] + 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 DescribeWorkflowStreamInput.ProtoReflect.Descriptor instead. +func (*DescribeWorkflowStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{12} +} + +func (x *DescribeWorkflowStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *DescribeWorkflowStreamInput) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *DescribeWorkflowStreamInput) GetOwnerRunId() string { + if x != nil { + return x.OwnerRunId + } + return "" +} + +func (x *DescribeWorkflowStreamInput) GetStreamName() string { + if x != nil { + return x.StreamName + } + return "" +} + +// Appending to a stream a workflow owns, from outside that workflow. The +// workflow's own publishes ride its Workflow Task instead. +type AddWorkflowMessagesInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + OwnerRunId string `protobuf:"bytes,7,opt,name=owner_run_id,json=ownerRunId,proto3" json:"owner_run_id,omitempty"` + // Empty means the workflow's default output stream. + StreamName string `protobuf:"bytes,3,opt,name=stream_name,json=streamName,proto3" json:"stream_name,omitempty"` + Records []*StreamRecord `protobuf:"bytes,4,rep,name=records,proto3" json:"records,omitempty"` + // Optional idempotency, as on AddMessagesInput. + ProducerId string `protobuf:"bytes,5,opt,name=producer_id,json=producerId,proto3" json:"producer_id,omitempty"` + Sequence int64 `protobuf:"varint,6,opt,name=sequence,proto3" json:"sequence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddWorkflowMessagesInput) Reset() { + *x = AddWorkflowMessagesInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddWorkflowMessagesInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddWorkflowMessagesInput) ProtoMessage() {} + +func (x *AddWorkflowMessagesInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[13] + 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 AddWorkflowMessagesInput.ProtoReflect.Descriptor instead. +func (*AddWorkflowMessagesInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{13} +} + +func (x *AddWorkflowMessagesInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *AddWorkflowMessagesInput) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *AddWorkflowMessagesInput) GetOwnerRunId() string { + if x != nil { + return x.OwnerRunId + } + return "" +} + +func (x *AddWorkflowMessagesInput) GetStreamName() string { + if x != nil { + return x.StreamName + } + return "" +} + +func (x *AddWorkflowMessagesInput) GetRecords() []*StreamRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *AddWorkflowMessagesInput) GetProducerId() string { + if x != nil { + return x.ProducerId + } + return "" +} + +func (x *AddWorkflowMessagesInput) GetSequence() int64 { + if x != nil { + return x.Sequence + } + return 0 +} + +type DescribeStreamOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + State *StreamState `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeStreamOutput) Reset() { + *x = DescribeStreamOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeStreamOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeStreamOutput) ProtoMessage() {} + +func (x *DescribeStreamOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[14] + 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 DescribeStreamOutput.ProtoReflect.Descriptor instead. +func (*DescribeStreamOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{14} +} + +func (x *DescribeStreamOutput) GetState() *StreamState { + if x != nil { + return x.State + } + return nil +} + +type CloseStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + Reason *v1.Payload `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStreamInput) Reset() { + *x = CloseStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStreamInput) ProtoMessage() {} + +func (x *CloseStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[15] + 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 CloseStreamInput.ProtoReflect.Descriptor instead. +func (*CloseStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{15} +} + +func (x *CloseStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *CloseStreamInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *CloseStreamInput) GetReason() *v1.Payload { + if x != nil { + return x.Reason + } + return nil +} + +type CloseStreamOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStreamOutput) Reset() { + *x = CloseStreamOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStreamOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStreamOutput) ProtoMessage() {} + +func (x *CloseStreamOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[16] + 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 CloseStreamOutput.ProtoReflect.Descriptor instead. +func (*CloseStreamOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{16} +} + +type TruncateStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + NewBaseOffset int64 `protobuf:"varint,3,opt,name=new_base_offset,json=newBaseOffset,proto3" json:"new_base_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TruncateStreamInput) Reset() { + *x = TruncateStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TruncateStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateStreamInput) ProtoMessage() {} + +func (x *TruncateStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[17] + 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 TruncateStreamInput.ProtoReflect.Descriptor instead. +func (*TruncateStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{17} +} + +func (x *TruncateStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *TruncateStreamInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *TruncateStreamInput) GetNewBaseOffset() int64 { + if x != nil { + return x.NewBaseOffset + } + return 0 +} + +type TruncateStreamOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TruncateStreamOutput) Reset() { + *x = TruncateStreamOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TruncateStreamOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateStreamOutput) ProtoMessage() {} + +func (x *TruncateStreamOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[18] + 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 TruncateStreamOutput.ProtoReflect.Descriptor instead. +func (*TruncateStreamOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{18} +} + +type DeleteStreamInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // Delete even while a workflow consumer is active. Without it the call is + // refused, because the consumer's History depends on ranges the deletion + // takes with it. + Force bool `protobuf:"varint,3,opt,name=force,proto3" json:"force,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteStreamInput) Reset() { + *x = DeleteStreamInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteStreamInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteStreamInput) ProtoMessage() {} + +func (x *DeleteStreamInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[19] + 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 DeleteStreamInput.ProtoReflect.Descriptor instead. +func (*DeleteStreamInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{19} +} + +func (x *DeleteStreamInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *DeleteStreamInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *DeleteStreamInput) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + +type DeleteStreamOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteStreamOutput) Reset() { + *x = DeleteStreamOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteStreamOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteStreamOutput) ProtoMessage() {} + +func (x *DeleteStreamOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[20] + 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 DeleteStreamOutput.ProtoReflect.Descriptor instead. +func (*DeleteStreamOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{20} +} + +type CreateStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *CreateStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateStreamRequest) Reset() { + *x = CreateStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateStreamRequest) ProtoMessage() {} + +func (x *CreateStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[21] + 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 CreateStreamRequest.ProtoReflect.Descriptor instead. +func (*CreateStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{21} +} + +func (x *CreateStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *CreateStreamRequest) GetFrontendRequest() *CreateStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type CreateStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *CreateStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateStreamResponse) Reset() { + *x = CreateStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateStreamResponse) ProtoMessage() {} + +func (x *CreateStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[22] + 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 CreateStreamResponse.ProtoReflect.Descriptor instead. +func (*CreateStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{22} +} + +func (x *CreateStreamResponse) GetFrontendResponse() *CreateStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type AddMessagesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *AddMessagesInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddMessagesRequest) Reset() { + *x = AddMessagesRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddMessagesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMessagesRequest) ProtoMessage() {} + +func (x *AddMessagesRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[23] + 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 AddMessagesRequest.ProtoReflect.Descriptor instead. +func (*AddMessagesRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{23} +} + +func (x *AddMessagesRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *AddMessagesRequest) GetFrontendRequest() *AddMessagesInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type AddMessagesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *AddMessagesOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddMessagesResponse) Reset() { + *x = AddMessagesResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddMessagesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMessagesResponse) ProtoMessage() {} + +func (x *AddMessagesResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[24] + 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 AddMessagesResponse.ProtoReflect.Descriptor instead. +func (*AddMessagesResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{24} +} + +func (x *AddMessagesResponse) GetFrontendResponse() *AddMessagesOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type FinishWritingRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *FinishWritingInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FinishWritingRequest) Reset() { + *x = FinishWritingRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FinishWritingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinishWritingRequest) ProtoMessage() {} + +func (x *FinishWritingRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[25] + 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 FinishWritingRequest.ProtoReflect.Descriptor instead. +func (*FinishWritingRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{25} +} + +func (x *FinishWritingRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *FinishWritingRequest) GetFrontendRequest() *FinishWritingInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type FinishWritingResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *FinishWritingOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FinishWritingResponse) Reset() { + *x = FinishWritingResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FinishWritingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinishWritingResponse) ProtoMessage() {} + +func (x *FinishWritingResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[26] + 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 FinishWritingResponse.ProtoReflect.Descriptor instead. +func (*FinishWritingResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{26} +} + +func (x *FinishWritingResponse) GetFrontendResponse() *FinishWritingOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type SubscribeWorkflowRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *SubscribeWorkflowInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeWorkflowRequest) Reset() { + *x = SubscribeWorkflowRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeWorkflowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeWorkflowRequest) ProtoMessage() {} + +func (x *SubscribeWorkflowRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[27] + 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 SubscribeWorkflowRequest.ProtoReflect.Descriptor instead. +func (*SubscribeWorkflowRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{27} +} + +func (x *SubscribeWorkflowRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *SubscribeWorkflowRequest) GetFrontendRequest() *SubscribeWorkflowInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type SubscribeWorkflowResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *SubscribeWorkflowOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeWorkflowResponse) Reset() { + *x = SubscribeWorkflowResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeWorkflowResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeWorkflowResponse) ProtoMessage() {} + +func (x *SubscribeWorkflowResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[28] + 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 SubscribeWorkflowResponse.ProtoReflect.Descriptor instead. +func (*SubscribeWorkflowResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{28} +} + +func (x *SubscribeWorkflowResponse) GetFrontendResponse() *SubscribeWorkflowOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type PollMessagesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *PollMessagesInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollMessagesRequest) Reset() { + *x = PollMessagesRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollMessagesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollMessagesRequest) ProtoMessage() {} + +func (x *PollMessagesRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[29] + 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 PollMessagesRequest.ProtoReflect.Descriptor instead. +func (*PollMessagesRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{29} +} + +func (x *PollMessagesRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *PollMessagesRequest) GetFrontendRequest() *PollMessagesInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type PollMessagesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *PollMessagesOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollMessagesResponse) Reset() { + *x = PollMessagesResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollMessagesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollMessagesResponse) ProtoMessage() {} + +func (x *PollMessagesResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[30] + 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 PollMessagesResponse.ProtoReflect.Descriptor instead. +func (*PollMessagesResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{30} +} + +func (x *PollMessagesResponse) GetFrontendResponse() *PollMessagesOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type DescribeStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *DescribeStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeStreamRequest) Reset() { + *x = DescribeStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeStreamRequest) ProtoMessage() {} + +func (x *DescribeStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[31] + 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 DescribeStreamRequest.ProtoReflect.Descriptor instead. +func (*DescribeStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{31} +} + +func (x *DescribeStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *DescribeStreamRequest) GetFrontendRequest() *DescribeStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type DescribeStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *DescribeStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeStreamResponse) Reset() { + *x = DescribeStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeStreamResponse) ProtoMessage() {} + +func (x *DescribeStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[32] + 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 DescribeStreamResponse.ProtoReflect.Descriptor instead. +func (*DescribeStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{32} +} + +func (x *DescribeStreamResponse) GetFrontendResponse() *DescribeStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type PollWorkflowMessagesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *PollWorkflowMessagesInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollWorkflowMessagesRequest) Reset() { + *x = PollWorkflowMessagesRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollWorkflowMessagesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollWorkflowMessagesRequest) ProtoMessage() {} + +func (x *PollWorkflowMessagesRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[33] + 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 PollWorkflowMessagesRequest.ProtoReflect.Descriptor instead. +func (*PollWorkflowMessagesRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{33} +} + +func (x *PollWorkflowMessagesRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *PollWorkflowMessagesRequest) GetFrontendRequest() *PollWorkflowMessagesInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type PollWorkflowMessagesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *PollMessagesOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PollWorkflowMessagesResponse) Reset() { + *x = PollWorkflowMessagesResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PollWorkflowMessagesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PollWorkflowMessagesResponse) ProtoMessage() {} + +func (x *PollWorkflowMessagesResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[34] + 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 PollWorkflowMessagesResponse.ProtoReflect.Descriptor instead. +func (*PollWorkflowMessagesResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{34} +} + +func (x *PollWorkflowMessagesResponse) GetFrontendResponse() *PollMessagesOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type DescribeWorkflowStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *DescribeWorkflowStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeWorkflowStreamRequest) Reset() { + *x = DescribeWorkflowStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeWorkflowStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeWorkflowStreamRequest) ProtoMessage() {} + +func (x *DescribeWorkflowStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[35] + 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 DescribeWorkflowStreamRequest.ProtoReflect.Descriptor instead. +func (*DescribeWorkflowStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{35} +} + +func (x *DescribeWorkflowStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *DescribeWorkflowStreamRequest) GetFrontendRequest() *DescribeWorkflowStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type DescribeWorkflowStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *DescribeStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DescribeWorkflowStreamResponse) Reset() { + *x = DescribeWorkflowStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DescribeWorkflowStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DescribeWorkflowStreamResponse) ProtoMessage() {} + +func (x *DescribeWorkflowStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[36] + 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 DescribeWorkflowStreamResponse.ProtoReflect.Descriptor instead. +func (*DescribeWorkflowStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{36} +} + +func (x *DescribeWorkflowStreamResponse) GetFrontendResponse() *DescribeStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +// Registering a consumer on a stream in another execution. Split out from +// SubscribeWorkflow because the two halves live on different shards: the pin +// goes on the stream, the cursor goes on the consuming workflow, and a handler +// can only reach the shard it was routed to. +type RegisterStreamConsumerInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + StreamId string `protobuf:"bytes,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // The workflow that will consume. Together with the run it names the pin, + // so a later run of the same workflow id registers fresh rather than + // inheriting a closed run's floor. + ConsumerWorkflowId string `protobuf:"bytes,3,opt,name=consumer_workflow_id,json=consumerWorkflowId,proto3" json:"consumer_workflow_id,omitempty"` + ConsumerRunId string `protobuf:"bytes,5,opt,name=consumer_run_id,json=consumerRunId,proto3" json:"consumer_run_id,omitempty"` + // Negative means from wherever the stream is when the pin is taken. Resolved + // here, where the frontier is, and returned so the cursor records a fact. + StartOffset int64 `protobuf:"varint,4,opt,name=start_offset,json=startOffset,proto3" json:"start_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterStreamConsumerInput) Reset() { + *x = RegisterStreamConsumerInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterStreamConsumerInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterStreamConsumerInput) ProtoMessage() {} + +func (x *RegisterStreamConsumerInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[37] + 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 RegisterStreamConsumerInput.ProtoReflect.Descriptor instead. +func (*RegisterStreamConsumerInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{37} +} + +func (x *RegisterStreamConsumerInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *RegisterStreamConsumerInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *RegisterStreamConsumerInput) GetConsumerWorkflowId() string { + if x != nil { + return x.ConsumerWorkflowId + } + return "" +} + +func (x *RegisterStreamConsumerInput) GetConsumerRunId() string { + if x != nil { + return x.ConsumerRunId + } + return "" +} + +func (x *RegisterStreamConsumerInput) GetStartOffset() int64 { + if x != nil { + return x.StartOffset + } + return 0 +} + +type RegisterStreamConsumerOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + StartOffset int64 `protobuf:"varint,1,opt,name=start_offset,json=startOffset,proto3" json:"start_offset,omitempty"` + // The frontier at registration, so the cursor starts with a known head + // instead of waiting for the first push. + KnownHead int64 `protobuf:"varint,4,opt,name=known_head,json=knownHead,proto3" json:"known_head,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterStreamConsumerOutput) Reset() { + *x = RegisterStreamConsumerOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterStreamConsumerOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterStreamConsumerOutput) ProtoMessage() {} + +func (x *RegisterStreamConsumerOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[38] + 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 RegisterStreamConsumerOutput.ProtoReflect.Descriptor instead. +func (*RegisterStreamConsumerOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{38} +} + +func (x *RegisterStreamConsumerOutput) GetStartOffset() int64 { + if x != nil { + return x.StartOffset + } + return 0 +} + +func (x *RegisterStreamConsumerOutput) GetKnownHead() int64 { + if x != nil { + return x.KnownHead + } + return 0 +} + +// Telling one consumer that the frontier moved. Routed to the consumer, which +// is not where the stream lives. +type AdvanceConsumerHeadInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + // The run that subscribed. A successor from continue-as-new holds no cursor + // for this stream, so pushing the frontier at it would land nowhere. + OwnerRunId string `protobuf:"bytes,5,opt,name=owner_run_id,json=ownerRunId,proto3" json:"owner_run_id,omitempty"` + StreamId string `protobuf:"bytes,3,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + HeadOffset int64 `protobuf:"varint,4,opt,name=head_offset,json=headOffset,proto3" json:"head_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdvanceConsumerHeadInput) Reset() { + *x = AdvanceConsumerHeadInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdvanceConsumerHeadInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdvanceConsumerHeadInput) ProtoMessage() {} + +func (x *AdvanceConsumerHeadInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[39] + 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 AdvanceConsumerHeadInput.ProtoReflect.Descriptor instead. +func (*AdvanceConsumerHeadInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{39} +} + +func (x *AdvanceConsumerHeadInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *AdvanceConsumerHeadInput) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *AdvanceConsumerHeadInput) GetOwnerRunId() string { + if x != nil { + return x.OwnerRunId + } + return "" +} + +func (x *AdvanceConsumerHeadInput) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *AdvanceConsumerHeadInput) GetHeadOffset() int64 { + if x != nil { + return x.HeadOffset + } + return 0 +} + +type AdvanceConsumerHeadOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The run that held the pin is closed and no current run of the workflow + // consumes the stream, so the stream can release the pin. + ConsumerClosed bool `protobuf:"varint,1,opt,name=consumer_closed,json=consumerClosed,proto3" json:"consumer_closed,omitempty"` + // The run that held the pin is closed but a successor carries the + // subscription, so the stream re-keys the pin to it, with the floor the + // successor's cursor started from. + SuccessorRunId string `protobuf:"bytes,2,opt,name=successor_run_id,json=successorRunId,proto3" json:"successor_run_id,omitempty"` + SuccessorStartOffset int64 `protobuf:"varint,3,opt,name=successor_start_offset,json=successorStartOffset,proto3" json:"successor_start_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdvanceConsumerHeadOutput) Reset() { + *x = AdvanceConsumerHeadOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdvanceConsumerHeadOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdvanceConsumerHeadOutput) ProtoMessage() {} + +func (x *AdvanceConsumerHeadOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[40] + 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 AdvanceConsumerHeadOutput.ProtoReflect.Descriptor instead. +func (*AdvanceConsumerHeadOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{40} +} + +func (x *AdvanceConsumerHeadOutput) GetConsumerClosed() bool { + if x != nil { + return x.ConsumerClosed + } + return false +} + +func (x *AdvanceConsumerHeadOutput) GetSuccessorRunId() string { + if x != nil { + return x.SuccessorRunId + } + return "" +} + +func (x *AdvanceConsumerHeadOutput) GetSuccessorStartOffset() int64 { + if x != nil { + return x.SuccessorStartOffset + } + return 0 +} + +type AddWorkflowMessagesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *AddWorkflowMessagesInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddWorkflowMessagesRequest) Reset() { + *x = AddWorkflowMessagesRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddWorkflowMessagesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddWorkflowMessagesRequest) ProtoMessage() {} + +func (x *AddWorkflowMessagesRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[41] + 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 AddWorkflowMessagesRequest.ProtoReflect.Descriptor instead. +func (*AddWorkflowMessagesRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{41} +} + +func (x *AddWorkflowMessagesRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *AddWorkflowMessagesRequest) GetFrontendRequest() *AddWorkflowMessagesInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type AddWorkflowMessagesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *AddMessagesOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddWorkflowMessagesResponse) Reset() { + *x = AddWorkflowMessagesResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddWorkflowMessagesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddWorkflowMessagesResponse) ProtoMessage() {} + +func (x *AddWorkflowMessagesResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[42] + 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 AddWorkflowMessagesResponse.ProtoReflect.Descriptor instead. +func (*AddWorkflowMessagesResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{42} +} + +func (x *AddWorkflowMessagesResponse) GetFrontendResponse() *AddMessagesOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type RegisterStreamConsumerRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *RegisterStreamConsumerInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterStreamConsumerRequest) Reset() { + *x = RegisterStreamConsumerRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterStreamConsumerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterStreamConsumerRequest) ProtoMessage() {} + +func (x *RegisterStreamConsumerRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[43] + 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 RegisterStreamConsumerRequest.ProtoReflect.Descriptor instead. +func (*RegisterStreamConsumerRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{43} +} + +func (x *RegisterStreamConsumerRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *RegisterStreamConsumerRequest) GetFrontendRequest() *RegisterStreamConsumerInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type RegisterStreamConsumerResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *RegisterStreamConsumerOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterStreamConsumerResponse) Reset() { + *x = RegisterStreamConsumerResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterStreamConsumerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterStreamConsumerResponse) ProtoMessage() {} + +func (x *RegisterStreamConsumerResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[44] + 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 RegisterStreamConsumerResponse.ProtoReflect.Descriptor instead. +func (*RegisterStreamConsumerResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{44} +} + +func (x *RegisterStreamConsumerResponse) GetFrontendResponse() *RegisterStreamConsumerOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type AdvanceConsumerHeadRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *AdvanceConsumerHeadInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdvanceConsumerHeadRequest) Reset() { + *x = AdvanceConsumerHeadRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdvanceConsumerHeadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdvanceConsumerHeadRequest) ProtoMessage() {} + +func (x *AdvanceConsumerHeadRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[45] + 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 AdvanceConsumerHeadRequest.ProtoReflect.Descriptor instead. +func (*AdvanceConsumerHeadRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{45} +} + +func (x *AdvanceConsumerHeadRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *AdvanceConsumerHeadRequest) GetFrontendRequest() *AdvanceConsumerHeadInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type AdvanceConsumerHeadResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *AdvanceConsumerHeadOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdvanceConsumerHeadResponse) Reset() { + *x = AdvanceConsumerHeadResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdvanceConsumerHeadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdvanceConsumerHeadResponse) ProtoMessage() {} + +func (x *AdvanceConsumerHeadResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[46] + 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 AdvanceConsumerHeadResponse.ProtoReflect.Descriptor instead. +func (*AdvanceConsumerHeadResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{46} +} + +func (x *AdvanceConsumerHeadResponse) GetFrontendResponse() *AdvanceConsumerHeadOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type CloseStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *CloseStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStreamRequest) Reset() { + *x = CloseStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStreamRequest) ProtoMessage() {} + +func (x *CloseStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[47] + 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 CloseStreamRequest.ProtoReflect.Descriptor instead. +func (*CloseStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{47} +} + +func (x *CloseStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *CloseStreamRequest) GetFrontendRequest() *CloseStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type CloseStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *CloseStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStreamResponse) Reset() { + *x = CloseStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStreamResponse) ProtoMessage() {} + +func (x *CloseStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[48] + 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 CloseStreamResponse.ProtoReflect.Descriptor instead. +func (*CloseStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{48} +} + +func (x *CloseStreamResponse) GetFrontendResponse() *CloseStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type TruncateStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *TruncateStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TruncateStreamRequest) Reset() { + *x = TruncateStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TruncateStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateStreamRequest) ProtoMessage() {} + +func (x *TruncateStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[49] + 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 TruncateStreamRequest.ProtoReflect.Descriptor instead. +func (*TruncateStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{49} +} + +func (x *TruncateStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *TruncateStreamRequest) GetFrontendRequest() *TruncateStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type TruncateStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *TruncateStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TruncateStreamResponse) Reset() { + *x = TruncateStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TruncateStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateStreamResponse) ProtoMessage() {} + +func (x *TruncateStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[50] + 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 TruncateStreamResponse.ProtoReflect.Descriptor instead. +func (*TruncateStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{50} +} + +func (x *TruncateStreamResponse) GetFrontendResponse() *TruncateStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type ListStreamsInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + NextPageToken []byte `protobuf:"bytes,3,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + Query string `protobuf:"bytes,4,opt,name=query,proto3" json:"query,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListStreamsInput) Reset() { + *x = ListStreamsInput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListStreamsInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStreamsInput) ProtoMessage() {} + +func (x *ListStreamsInput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[51] + 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 ListStreamsInput.ProtoReflect.Descriptor instead. +func (*ListStreamsInput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{51} +} + +func (x *ListStreamsInput) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ListStreamsInput) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListStreamsInput) GetNextPageToken() []byte { + if x != nil { + return x.NextPageToken + } + return nil +} + +func (x *ListStreamsInput) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +type StreamListEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + RunId string `protobuf:"bytes,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamListEntry) Reset() { + *x = StreamListEntry{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamListEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamListEntry) ProtoMessage() {} + +func (x *StreamListEntry) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[52] + 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 StreamListEntry.ProtoReflect.Descriptor instead. +func (*StreamListEntry) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{52} +} + +func (x *StreamListEntry) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *StreamListEntry) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +type ListStreamsOutput struct { + state protoimpl.MessageState `protogen:"open.v1"` + Streams []*StreamListEntry `protobuf:"bytes,1,rep,name=streams,proto3" json:"streams,omitempty"` + NextPageToken []byte `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListStreamsOutput) Reset() { + *x = ListStreamsOutput{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListStreamsOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStreamsOutput) ProtoMessage() {} + +func (x *ListStreamsOutput) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[53] + 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 ListStreamsOutput.ProtoReflect.Descriptor instead. +func (*ListStreamsOutput) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{53} +} + +func (x *ListStreamsOutput) GetStreams() []*StreamListEntry { + if x != nil { + return x.Streams + } + return nil +} + +func (x *ListStreamsOutput) GetNextPageToken() []byte { + if x != nil { + return x.NextPageToken + } + return nil +} + +type ListStreamsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *ListStreamsInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListStreamsRequest) Reset() { + *x = ListStreamsRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListStreamsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStreamsRequest) ProtoMessage() {} + +func (x *ListStreamsRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[54] + 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 ListStreamsRequest.ProtoReflect.Descriptor instead. +func (*ListStreamsRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{54} +} + +func (x *ListStreamsRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *ListStreamsRequest) GetFrontendRequest() *ListStreamsInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type ListStreamsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *ListStreamsOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListStreamsResponse) Reset() { + *x = ListStreamsResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListStreamsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStreamsResponse) ProtoMessage() {} + +func (x *ListStreamsResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[55] + 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 ListStreamsResponse.ProtoReflect.Descriptor instead. +func (*ListStreamsResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{55} +} + +func (x *ListStreamsResponse) GetFrontendResponse() *ListStreamsOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +type DeleteStreamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + FrontendRequest *DeleteStreamInput `protobuf:"bytes,2,opt,name=frontend_request,json=frontendRequest,proto3" json:"frontend_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteStreamRequest) Reset() { + *x = DeleteStreamRequest{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteStreamRequest) ProtoMessage() {} + +func (x *DeleteStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[56] + 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 DeleteStreamRequest.ProtoReflect.Descriptor instead. +func (*DeleteStreamRequest) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{56} +} + +func (x *DeleteStreamRequest) GetNamespaceId() string { + if x != nil { + return x.NamespaceId + } + return "" +} + +func (x *DeleteStreamRequest) GetFrontendRequest() *DeleteStreamInput { + if x != nil { + return x.FrontendRequest + } + return nil +} + +type DeleteStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontendResponse *DeleteStreamOutput `protobuf:"bytes,1,opt,name=frontend_response,json=frontendResponse,proto3" json:"frontend_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteStreamResponse) Reset() { + *x = DeleteStreamResponse{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteStreamResponse) ProtoMessage() {} + +func (x *DeleteStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes[57] + 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 DeleteStreamResponse.ProtoReflect.Descriptor instead. +func (*DeleteStreamResponse) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDescGZIP(), []int{57} +} + +func (x *DeleteStreamResponse) GetFrontendResponse() *DeleteStreamOutput { + if x != nil { + return x.FrontendResponse + } + return nil +} + +var File_temporal_server_chasm_lib_stream_proto_v1_request_response_proto protoreflect.FileDescriptor + +const file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDesc = "" + + "\n" + + "@temporal/server/chasm/lib/stream/proto/v1/request_response.proto\x12)temporal.server.chasm.lib.stream.proto.v1\x1a7temporal/server/chasm/lib/stream/proto/v1/message.proto\x1a.temporal.server.chasm.lib.stream.proto.v1.FinishWritingOutputR\x10frontendResponse\"\xab\x01\n" + + "\x18SubscribeWorkflowRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12l\n" + + "\x10frontend_request\x18\x02 \x01(\v2A.temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowInputR\x0ffrontendRequest\"\x8c\x01\n" + + "\x19SubscribeWorkflowResponse\x12o\n" + + "\x11frontend_response\x18\x01 \x01(\v2B.temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowOutputR\x10frontendResponse\"\xa1\x01\n" + + "\x13PollMessagesRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12g\n" + + "\x10frontend_request\x18\x02 \x01(\v2<.temporal.server.chasm.lib.stream.proto.v1.PollMessagesInputR\x0ffrontendRequest\"\x82\x01\n" + + "\x14PollMessagesResponse\x12j\n" + + "\x11frontend_response\x18\x01 \x01(\v2=.temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutputR\x10frontendResponse\"\xa5\x01\n" + + "\x15DescribeStreamRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12i\n" + + "\x10frontend_request\x18\x02 \x01(\v2>.temporal.server.chasm.lib.stream.proto.v1.DescribeStreamInputR\x0ffrontendRequest\"\x86\x01\n" + + "\x16DescribeStreamResponse\x12l\n" + + "\x11frontend_response\x18\x01 \x01(\v2?.temporal.server.chasm.lib.stream.proto.v1.DescribeStreamOutputR\x10frontendResponse\"\xb1\x01\n" + + "\x1bPollWorkflowMessagesRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12o\n" + + "\x10frontend_request\x18\x02 \x01(\v2D.temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesInputR\x0ffrontendRequest\"\x8a\x01\n" + + "\x1cPollWorkflowMessagesResponse\x12j\n" + + "\x11frontend_response\x18\x01 \x01(\v2=.temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutputR\x10frontendResponse\"\xb5\x01\n" + + "\x1dDescribeWorkflowStreamRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12q\n" + + "\x10frontend_request\x18\x02 \x01(\v2F.temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamInputR\x0ffrontendRequest\"\x8e\x01\n" + + "\x1eDescribeWorkflowStreamResponse\x12l\n" + + "\x11frontend_response\x18\x01 \x01(\v2?.temporal.server.chasm.lib.stream.proto.v1.DescribeStreamOutputR\x10frontendResponse\"\xd5\x01\n" + + "\x1bRegisterStreamConsumerInput\x12\x1c\n" + + "\tnamespace\x18\x01 \x01(\tR\tnamespace\x12\x1b\n" + + "\tstream_id\x18\x02 \x01(\tR\bstreamId\x120\n" + + "\x14consumer_workflow_id\x18\x03 \x01(\tR\x12consumerWorkflowId\x12&\n" + + "\x0fconsumer_run_id\x18\x05 \x01(\tR\rconsumerRunId\x12!\n" + + "\fstart_offset\x18\x04 \x01(\x03R\vstartOffset\"l\n" + + "\x1cRegisterStreamConsumerOutput\x12!\n" + + "\fstart_offset\x18\x01 \x01(\x03R\vstartOffset\x12\x1d\n" + + "\n" + + "known_head\x18\x04 \x01(\x03R\tknownHeadJ\x04\b\x02\x10\x03J\x04\b\x03\x10\x04\"\xb9\x01\n" + + "\x18AdvanceConsumerHeadInput\x12\x1c\n" + + "\tnamespace\x18\x01 \x01(\tR\tnamespace\x12\x1f\n" + + "\vworkflow_id\x18\x02 \x01(\tR\n" + + "workflowId\x12 \n" + + "\fowner_run_id\x18\x05 \x01(\tR\n" + + "ownerRunId\x12\x1b\n" + + "\tstream_id\x18\x03 \x01(\tR\bstreamId\x12\x1f\n" + + "\vhead_offset\x18\x04 \x01(\x03R\n" + + "headOffset\"\xa4\x01\n" + + "\x19AdvanceConsumerHeadOutput\x12'\n" + + "\x0fconsumer_closed\x18\x01 \x01(\bR\x0econsumerClosed\x12(\n" + + "\x10successor_run_id\x18\x02 \x01(\tR\x0esuccessorRunId\x124\n" + + "\x16successor_start_offset\x18\x03 \x01(\x03R\x14successorStartOffset\"\xaf\x01\n" + + "\x1aAddWorkflowMessagesRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12n\n" + + "\x10frontend_request\x18\x02 \x01(\v2C.temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesInputR\x0ffrontendRequest\"\x88\x01\n" + + "\x1bAddWorkflowMessagesResponse\x12i\n" + + "\x11frontend_response\x18\x01 \x01(\v2<.temporal.server.chasm.lib.stream.proto.v1.AddMessagesOutputR\x10frontendResponse\"\xb5\x01\n" + + "\x1dRegisterStreamConsumerRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12q\n" + + "\x10frontend_request\x18\x02 \x01(\v2F.temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerInputR\x0ffrontendRequest\"\x96\x01\n" + + "\x1eRegisterStreamConsumerResponse\x12t\n" + + "\x11frontend_response\x18\x01 \x01(\v2G.temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerOutputR\x10frontendResponse\"\xaf\x01\n" + + "\x1aAdvanceConsumerHeadRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12n\n" + + "\x10frontend_request\x18\x02 \x01(\v2C.temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadInputR\x0ffrontendRequest\"\x90\x01\n" + + "\x1bAdvanceConsumerHeadResponse\x12q\n" + + "\x11frontend_response\x18\x01 \x01(\v2D.temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadOutputR\x10frontendResponse\"\x9f\x01\n" + + "\x12CloseStreamRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12f\n" + + "\x10frontend_request\x18\x02 \x01(\v2;.temporal.server.chasm.lib.stream.proto.v1.CloseStreamInputR\x0ffrontendRequest\"\x80\x01\n" + + "\x13CloseStreamResponse\x12i\n" + + "\x11frontend_response\x18\x01 \x01(\v2<.temporal.server.chasm.lib.stream.proto.v1.CloseStreamOutputR\x10frontendResponse\"\xa5\x01\n" + + "\x15TruncateStreamRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12i\n" + + "\x10frontend_request\x18\x02 \x01(\v2>.temporal.server.chasm.lib.stream.proto.v1.TruncateStreamInputR\x0ffrontendRequest\"\x86\x01\n" + + "\x16TruncateStreamResponse\x12l\n" + + "\x11frontend_response\x18\x01 \x01(\v2?.temporal.server.chasm.lib.stream.proto.v1.TruncateStreamOutputR\x10frontendResponse\"\x8b\x01\n" + + "\x10ListStreamsInput\x12\x1c\n" + + "\tnamespace\x18\x01 \x01(\tR\tnamespace\x12\x1b\n" + + "\tpage_size\x18\x02 \x01(\x05R\bpageSize\x12&\n" + + "\x0fnext_page_token\x18\x03 \x01(\fR\rnextPageToken\x12\x14\n" + + "\x05query\x18\x04 \x01(\tR\x05query\"E\n" + + "\x0fStreamListEntry\x12\x1b\n" + + "\tstream_id\x18\x01 \x01(\tR\bstreamId\x12\x15\n" + + "\x06run_id\x18\x02 \x01(\tR\x05runId\"\x91\x01\n" + + "\x11ListStreamsOutput\x12T\n" + + "\astreams\x18\x01 \x03(\v2:.temporal.server.chasm.lib.stream.proto.v1.StreamListEntryR\astreams\x12&\n" + + "\x0fnext_page_token\x18\x02 \x01(\fR\rnextPageToken\"\x9f\x01\n" + + "\x12ListStreamsRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12f\n" + + "\x10frontend_request\x18\x02 \x01(\v2;.temporal.server.chasm.lib.stream.proto.v1.ListStreamsInputR\x0ffrontendRequest\"\x80\x01\n" + + "\x13ListStreamsResponse\x12i\n" + + "\x11frontend_response\x18\x01 \x01(\v2<.temporal.server.chasm.lib.stream.proto.v1.ListStreamsOutputR\x10frontendResponse\"\xa1\x01\n" + + "\x13DeleteStreamRequest\x12!\n" + + "\fnamespace_id\x18\x01 \x01(\tR\vnamespaceId\x12g\n" + + "\x10frontend_request\x18\x02 \x01(\v2<.temporal.server.chasm.lib.stream.proto.v1.DeleteStreamInputR\x0ffrontendRequest\"\x82\x01\n" + + "\x14DeleteStreamResponse\x12j\n" + + "\x11frontend_response\x18\x01 \x01(\v2=.temporal.server.chasm.lib.stream.proto.v1.DeleteStreamOutputR\x10frontendResponseB>Z temporal.server.chasm.lib.stream.proto.v1.StreamLifecycle + 59, // 1: temporal.server.chasm.lib.stream.proto.v1.AddMessagesInput.records:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamRecord + 59, // 2: temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutput.records:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamRecord + 60, // 3: temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutput.close_reason:type_name -> temporal.api.common.v1.Payload + 59, // 4: temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesInput.records:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamRecord + 61, // 5: temporal.server.chasm.lib.stream.proto.v1.DescribeStreamOutput.state:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamState + 60, // 6: temporal.server.chasm.lib.stream.proto.v1.CloseStreamInput.reason:type_name -> temporal.api.common.v1.Payload + 0, // 7: temporal.server.chasm.lib.stream.proto.v1.CreateStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.CreateStreamInput + 1, // 8: temporal.server.chasm.lib.stream.proto.v1.CreateStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.CreateStreamOutput + 2, // 9: temporal.server.chasm.lib.stream.proto.v1.AddMessagesRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.AddMessagesInput + 3, // 10: temporal.server.chasm.lib.stream.proto.v1.AddMessagesResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.AddMessagesOutput + 4, // 11: temporal.server.chasm.lib.stream.proto.v1.FinishWritingRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.FinishWritingInput + 5, // 12: temporal.server.chasm.lib.stream.proto.v1.FinishWritingResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.FinishWritingOutput + 6, // 13: temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowInput + 7, // 14: temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowOutput + 8, // 15: temporal.server.chasm.lib.stream.proto.v1.PollMessagesRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.PollMessagesInput + 9, // 16: temporal.server.chasm.lib.stream.proto.v1.PollMessagesResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutput + 10, // 17: temporal.server.chasm.lib.stream.proto.v1.DescribeStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.DescribeStreamInput + 14, // 18: temporal.server.chasm.lib.stream.proto.v1.DescribeStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.DescribeStreamOutput + 11, // 19: temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesInput + 9, // 20: temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.PollMessagesOutput + 12, // 21: temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamInput + 14, // 22: temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.DescribeStreamOutput + 13, // 23: temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesInput + 3, // 24: temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.AddMessagesOutput + 37, // 25: temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerInput + 38, // 26: temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerOutput + 39, // 27: temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadInput + 40, // 28: temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadOutput + 15, // 29: temporal.server.chasm.lib.stream.proto.v1.CloseStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.CloseStreamInput + 16, // 30: temporal.server.chasm.lib.stream.proto.v1.CloseStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.CloseStreamOutput + 17, // 31: temporal.server.chasm.lib.stream.proto.v1.TruncateStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.TruncateStreamInput + 18, // 32: temporal.server.chasm.lib.stream.proto.v1.TruncateStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.TruncateStreamOutput + 52, // 33: temporal.server.chasm.lib.stream.proto.v1.ListStreamsOutput.streams:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamListEntry + 51, // 34: temporal.server.chasm.lib.stream.proto.v1.ListStreamsRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.ListStreamsInput + 53, // 35: temporal.server.chasm.lib.stream.proto.v1.ListStreamsResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.ListStreamsOutput + 19, // 36: temporal.server.chasm.lib.stream.proto.v1.DeleteStreamRequest.frontend_request:type_name -> temporal.server.chasm.lib.stream.proto.v1.DeleteStreamInput + 20, // 37: temporal.server.chasm.lib.stream.proto.v1.DeleteStreamResponse.frontend_response:type_name -> temporal.server.chasm.lib.stream.proto.v1.DeleteStreamOutput + 38, // [38:38] is the sub-list for method output_type + 38, // [38:38] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name +} + +func init() { file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_init() } +func file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_init() { + if File_temporal_server_chasm_lib_stream_proto_v1_request_response_proto != nil { + return + } + file_temporal_server_chasm_lib_stream_proto_v1_message_proto_init() + file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_rawDesc)), + NumEnums: 0, + NumMessages: 58, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_goTypes, + DependencyIndexes: file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_depIdxs, + MessageInfos: file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_msgTypes, + }.Build() + File_temporal_server_chasm_lib_stream_proto_v1_request_response_proto = out.File + file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_goTypes = nil + file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_depIdxs = nil +} diff --git a/chasm/lib/stream/gen/streampb/v1/service.pb.go b/chasm/lib/stream/gen/streampb/v1/service.pb.go new file mode 100644 index 00000000000..e0bb7981366 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/service.pb.go @@ -0,0 +1,140 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// plugins: +// protoc-gen-go +// protoc +// source: temporal/server/chasm/lib/stream/proto/v1/service.proto + +package streampb + +import ( + reflect "reflect" + unsafe "unsafe" + + _ "go.temporal.io/server/api/common/v1" + _ "go.temporal.io/server/api/routing/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var File_temporal_server_chasm_lib_stream_proto_v1_service_proto protoreflect.FileDescriptor + +const file_temporal_server_chasm_lib_stream_proto_v1_service_proto_rawDesc = "" + + "\n" + + "7temporal/server/chasm/lib/stream/proto/v1/service.proto\x12)temporal.server.chasm.lib.stream.proto.v1\x1a@temporal/server/chasm/lib/stream/proto/v1/request_response.proto\x1a0temporal/server/api/common/v1/api_category.proto\x1a.temporal/server/api/routing/v1/extension.proto2\xf8\x16\n" + + "\rStreamService\x12\xb7\x01\n" + + "\fCreateStream\x12>.temporal.server.chasm.lib.stream.proto.v1.CreateStreamRequest\x1a?.temporal.server.chasm.lib.stream.proto.v1.CreateStreamResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xb4\x01\n" + + "\vAddMessages\x12=.temporal.server.chasm.lib.stream.proto.v1.AddMessagesRequest\x1a>.temporal.server.chasm.lib.stream.proto.v1.AddMessagesResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xba\x01\n" + + "\rFinishWriting\x12?.temporal.server.chasm.lib.stream.proto.v1.FinishWritingRequest\x1a@.temporal.server.chasm.lib.stream.proto.v1.FinishWritingResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xc8\x01\n" + + "\x11SubscribeWorkflow\x12C.temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowRequest\x1aD.temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowResponse\"(\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1e\x1a\x1cfrontend_request.workflow_id\x12\xb7\x01\n" + + "\fPollMessages\x12>.temporal.server.chasm.lib.stream.proto.v1.PollMessagesRequest\x1a?.temporal.server.chasm.lib.stream.proto.v1.PollMessagesResponse\"&\x8a\xb5\x18\x02\b\x02\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xbd\x01\n" + + "\x0eDescribeStream\x12@.temporal.server.chasm.lib.stream.proto.v1.DescribeStreamRequest\x1aA.temporal.server.chasm.lib.stream.proto.v1.DescribeStreamResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xd1\x01\n" + + "\x14PollWorkflowMessages\x12F.temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesRequest\x1aG.temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesResponse\"(\x8a\xb5\x18\x02\b\x02\xd2\xc3\x18\x1e\x1a\x1cfrontend_request.workflow_id\x12\xd7\x01\n" + + "\x16DescribeWorkflowStream\x12H.temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamRequest\x1aI.temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamResponse\"(\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1e\x1a\x1cfrontend_request.workflow_id\x12\xce\x01\n" + + "\x13AddWorkflowMessages\x12E.temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesRequest\x1aF.temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesResponse\"(\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1e\x1a\x1cfrontend_request.workflow_id\x12\xd5\x01\n" + + "\x16RegisterStreamConsumer\x12H.temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerRequest\x1aI.temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xce\x01\n" + + "\x13AdvanceConsumerHead\x12E.temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadRequest\x1aF.temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadResponse\"(\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1e\x1a\x1cfrontend_request.workflow_id\x12\xb4\x01\n" + + "\vCloseStream\x12=.temporal.server.chasm.lib.stream.proto.v1.CloseStreamRequest\x1a>.temporal.server.chasm.lib.stream.proto.v1.CloseStreamResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\xbd\x01\n" + + "\x0eTruncateStream\x12@.temporal.server.chasm.lib.stream.proto.v1.TruncateStreamRequest\x1aA.temporal.server.chasm.lib.stream.proto.v1.TruncateStreamResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_id\x12\x9a\x01\n" + + "\vListStreams\x12=.temporal.server.chasm.lib.stream.proto.v1.ListStreamsRequest\x1a>.temporal.server.chasm.lib.stream.proto.v1.ListStreamsResponse\"\f\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x02\b\x01\x12\xb7\x01\n" + + "\fDeleteStream\x12>.temporal.server.chasm.lib.stream.proto.v1.DeleteStreamRequest\x1a?.temporal.server.chasm.lib.stream.proto.v1.DeleteStreamResponse\"&\x8a\xb5\x18\x02\b\x01\xd2\xc3\x18\x1c\x1a\x1afrontend_request.stream_idB>Z temporal.server.chasm.lib.stream.proto.v1.CreateStreamRequest + 1, // 1: temporal.server.chasm.lib.stream.proto.v1.StreamService.AddMessages:input_type -> temporal.server.chasm.lib.stream.proto.v1.AddMessagesRequest + 2, // 2: temporal.server.chasm.lib.stream.proto.v1.StreamService.FinishWriting:input_type -> temporal.server.chasm.lib.stream.proto.v1.FinishWritingRequest + 3, // 3: temporal.server.chasm.lib.stream.proto.v1.StreamService.SubscribeWorkflow:input_type -> temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowRequest + 4, // 4: temporal.server.chasm.lib.stream.proto.v1.StreamService.PollMessages:input_type -> temporal.server.chasm.lib.stream.proto.v1.PollMessagesRequest + 5, // 5: temporal.server.chasm.lib.stream.proto.v1.StreamService.DescribeStream:input_type -> temporal.server.chasm.lib.stream.proto.v1.DescribeStreamRequest + 6, // 6: temporal.server.chasm.lib.stream.proto.v1.StreamService.PollWorkflowMessages:input_type -> temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesRequest + 7, // 7: temporal.server.chasm.lib.stream.proto.v1.StreamService.DescribeWorkflowStream:input_type -> temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamRequest + 8, // 8: temporal.server.chasm.lib.stream.proto.v1.StreamService.AddWorkflowMessages:input_type -> temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesRequest + 9, // 9: temporal.server.chasm.lib.stream.proto.v1.StreamService.RegisterStreamConsumer:input_type -> temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerRequest + 10, // 10: temporal.server.chasm.lib.stream.proto.v1.StreamService.AdvanceConsumerHead:input_type -> temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadRequest + 11, // 11: temporal.server.chasm.lib.stream.proto.v1.StreamService.CloseStream:input_type -> temporal.server.chasm.lib.stream.proto.v1.CloseStreamRequest + 12, // 12: temporal.server.chasm.lib.stream.proto.v1.StreamService.TruncateStream:input_type -> temporal.server.chasm.lib.stream.proto.v1.TruncateStreamRequest + 13, // 13: temporal.server.chasm.lib.stream.proto.v1.StreamService.ListStreams:input_type -> temporal.server.chasm.lib.stream.proto.v1.ListStreamsRequest + 14, // 14: temporal.server.chasm.lib.stream.proto.v1.StreamService.DeleteStream:input_type -> temporal.server.chasm.lib.stream.proto.v1.DeleteStreamRequest + 15, // 15: temporal.server.chasm.lib.stream.proto.v1.StreamService.CreateStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.CreateStreamResponse + 16, // 16: temporal.server.chasm.lib.stream.proto.v1.StreamService.AddMessages:output_type -> temporal.server.chasm.lib.stream.proto.v1.AddMessagesResponse + 17, // 17: temporal.server.chasm.lib.stream.proto.v1.StreamService.FinishWriting:output_type -> temporal.server.chasm.lib.stream.proto.v1.FinishWritingResponse + 18, // 18: temporal.server.chasm.lib.stream.proto.v1.StreamService.SubscribeWorkflow:output_type -> temporal.server.chasm.lib.stream.proto.v1.SubscribeWorkflowResponse + 19, // 19: temporal.server.chasm.lib.stream.proto.v1.StreamService.PollMessages:output_type -> temporal.server.chasm.lib.stream.proto.v1.PollMessagesResponse + 20, // 20: temporal.server.chasm.lib.stream.proto.v1.StreamService.DescribeStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.DescribeStreamResponse + 21, // 21: temporal.server.chasm.lib.stream.proto.v1.StreamService.PollWorkflowMessages:output_type -> temporal.server.chasm.lib.stream.proto.v1.PollWorkflowMessagesResponse + 22, // 22: temporal.server.chasm.lib.stream.proto.v1.StreamService.DescribeWorkflowStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.DescribeWorkflowStreamResponse + 23, // 23: temporal.server.chasm.lib.stream.proto.v1.StreamService.AddWorkflowMessages:output_type -> temporal.server.chasm.lib.stream.proto.v1.AddWorkflowMessagesResponse + 24, // 24: temporal.server.chasm.lib.stream.proto.v1.StreamService.RegisterStreamConsumer:output_type -> temporal.server.chasm.lib.stream.proto.v1.RegisterStreamConsumerResponse + 25, // 25: temporal.server.chasm.lib.stream.proto.v1.StreamService.AdvanceConsumerHead:output_type -> temporal.server.chasm.lib.stream.proto.v1.AdvanceConsumerHeadResponse + 26, // 26: temporal.server.chasm.lib.stream.proto.v1.StreamService.CloseStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.CloseStreamResponse + 27, // 27: temporal.server.chasm.lib.stream.proto.v1.StreamService.TruncateStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.TruncateStreamResponse + 28, // 28: temporal.server.chasm.lib.stream.proto.v1.StreamService.ListStreams:output_type -> temporal.server.chasm.lib.stream.proto.v1.ListStreamsResponse + 29, // 29: temporal.server.chasm.lib.stream.proto.v1.StreamService.DeleteStream:output_type -> temporal.server.chasm.lib.stream.proto.v1.DeleteStreamResponse + 15, // [15:30] is the sub-list for method output_type + 0, // [0:15] 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 +} + +func init() { file_temporal_server_chasm_lib_stream_proto_v1_service_proto_init() } +func file_temporal_server_chasm_lib_stream_proto_v1_service_proto_init() { + if File_temporal_server_chasm_lib_stream_proto_v1_service_proto != nil { + return + } + file_temporal_server_chasm_lib_stream_proto_v1_request_response_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_stream_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_stream_proto_v1_service_proto_rawDesc)), + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_temporal_server_chasm_lib_stream_proto_v1_service_proto_goTypes, + DependencyIndexes: file_temporal_server_chasm_lib_stream_proto_v1_service_proto_depIdxs, + }.Build() + File_temporal_server_chasm_lib_stream_proto_v1_service_proto = out.File + file_temporal_server_chasm_lib_stream_proto_v1_service_proto_goTypes = nil + file_temporal_server_chasm_lib_stream_proto_v1_service_proto_depIdxs = nil +} diff --git a/chasm/lib/stream/gen/streampb/v1/service_client.pb.go b/chasm/lib/stream/gen/streampb/v1/service_client.pb.go new file mode 100644 index 00000000000..946c94e2831 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/service_client.pb.go @@ -0,0 +1,713 @@ +// Code generated by protoc-gen-go-chasm. DO NOT EDIT. +package streampb + +import ( + "context" + "math/rand" + "time" + + "go.temporal.io/server/client/history" + "go.temporal.io/server/common" + "go.temporal.io/server/common/backoff" + "go.temporal.io/server/common/config" + "go.temporal.io/server/common/dynamicconfig" + "go.temporal.io/server/common/headers" + "go.temporal.io/server/common/log" + "go.temporal.io/server/common/membership" + "go.temporal.io/server/common/metrics" + "go.temporal.io/server/common/primitives" + "go.uber.org/fx" + "google.golang.org/grpc" +) + +// StreamServiceLayeredClient is a client for StreamService. +type StreamServiceLayeredClient struct { + metricsHandler metrics.Handler + numShards int32 + redirector history.Redirector[StreamServiceClient] + retryPolicy backoff.RetryPolicy +} + +// NewStreamServiceLayeredClient initializes a new StreamServiceLayeredClient. +func NewStreamServiceLayeredClient( + lc fx.Lifecycle, + dc *dynamicconfig.Collection, + rpcFactory common.RPCFactory, + monitor membership.Monitor, + config *config.Persistence, + logger log.Logger, + metricsHandler metrics.Handler, +) (StreamServiceClient, error) { + resolver, err := monitor.GetResolver(primitives.HistoryService) + if err != nil { + return nil, err + } + connections := history.NewConnectionPool(resolver, rpcFactory, NewStreamServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) + var redirector history.Redirector[StreamServiceClient] + if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() { + redirector = history.NewCachingRedirector( + connections, + resolver, + logger, + dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc), + ) + } else { + redirector = history.NewBasicRedirector(connections, resolver) + } + client := &StreamServiceLayeredClient{ + metricsHandler: metricsHandler, + redirector: redirector, + numShards: config.NumHistoryShards, + retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)), + } + lc.Append(fx.StopHook(client.Stop)) + return client, nil +} +func (c *StreamServiceLayeredClient) Stop() { + c.redirector.Close() +} +func (c *StreamServiceLayeredClient) callCreateStreamNoRetry( + ctx context.Context, + request *CreateStreamRequest, + opts ...grpc.CallOption, +) (*CreateStreamResponse, error) { + var response *CreateStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.CreateStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.CreateStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) CreateStream( + ctx context.Context, + request *CreateStreamRequest, + opts ...grpc.CallOption, +) (*CreateStreamResponse, error) { + call := func(ctx context.Context) (*CreateStreamResponse, error) { + return c.callCreateStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callAddMessagesNoRetry( + ctx context.Context, + request *AddMessagesRequest, + opts ...grpc.CallOption, +) (*AddMessagesResponse, error) { + var response *AddMessagesResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.AddMessages"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.AddMessages(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) AddMessages( + ctx context.Context, + request *AddMessagesRequest, + opts ...grpc.CallOption, +) (*AddMessagesResponse, error) { + call := func(ctx context.Context) (*AddMessagesResponse, error) { + return c.callAddMessagesNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callFinishWritingNoRetry( + ctx context.Context, + request *FinishWritingRequest, + opts ...grpc.CallOption, +) (*FinishWritingResponse, error) { + var response *FinishWritingResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.FinishWriting"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.FinishWriting(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) FinishWriting( + ctx context.Context, + request *FinishWritingRequest, + opts ...grpc.CallOption, +) (*FinishWritingResponse, error) { + call := func(ctx context.Context) (*FinishWritingResponse, error) { + return c.callFinishWritingNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callSubscribeWorkflowNoRetry( + ctx context.Context, + request *SubscribeWorkflowRequest, + opts ...grpc.CallOption, +) (*SubscribeWorkflowResponse, error) { + var response *SubscribeWorkflowResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.SubscribeWorkflow"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetWorkflowId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.SubscribeWorkflow(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) SubscribeWorkflow( + ctx context.Context, + request *SubscribeWorkflowRequest, + opts ...grpc.CallOption, +) (*SubscribeWorkflowResponse, error) { + call := func(ctx context.Context) (*SubscribeWorkflowResponse, error) { + return c.callSubscribeWorkflowNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callPollMessagesNoRetry( + ctx context.Context, + request *PollMessagesRequest, + opts ...grpc.CallOption, +) (*PollMessagesResponse, error) { + var response *PollMessagesResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.PollMessages"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.PollMessages(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) PollMessages( + ctx context.Context, + request *PollMessagesRequest, + opts ...grpc.CallOption, +) (*PollMessagesResponse, error) { + call := func(ctx context.Context) (*PollMessagesResponse, error) { + return c.callPollMessagesNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callDescribeStreamNoRetry( + ctx context.Context, + request *DescribeStreamRequest, + opts ...grpc.CallOption, +) (*DescribeStreamResponse, error) { + var response *DescribeStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.DescribeStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.DescribeStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) DescribeStream( + ctx context.Context, + request *DescribeStreamRequest, + opts ...grpc.CallOption, +) (*DescribeStreamResponse, error) { + call := func(ctx context.Context) (*DescribeStreamResponse, error) { + return c.callDescribeStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callPollWorkflowMessagesNoRetry( + ctx context.Context, + request *PollWorkflowMessagesRequest, + opts ...grpc.CallOption, +) (*PollWorkflowMessagesResponse, error) { + var response *PollWorkflowMessagesResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.PollWorkflowMessages"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetWorkflowId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.PollWorkflowMessages(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) PollWorkflowMessages( + ctx context.Context, + request *PollWorkflowMessagesRequest, + opts ...grpc.CallOption, +) (*PollWorkflowMessagesResponse, error) { + call := func(ctx context.Context) (*PollWorkflowMessagesResponse, error) { + return c.callPollWorkflowMessagesNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callDescribeWorkflowStreamNoRetry( + ctx context.Context, + request *DescribeWorkflowStreamRequest, + opts ...grpc.CallOption, +) (*DescribeWorkflowStreamResponse, error) { + var response *DescribeWorkflowStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.DescribeWorkflowStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetWorkflowId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.DescribeWorkflowStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) DescribeWorkflowStream( + ctx context.Context, + request *DescribeWorkflowStreamRequest, + opts ...grpc.CallOption, +) (*DescribeWorkflowStreamResponse, error) { + call := func(ctx context.Context) (*DescribeWorkflowStreamResponse, error) { + return c.callDescribeWorkflowStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callAddWorkflowMessagesNoRetry( + ctx context.Context, + request *AddWorkflowMessagesRequest, + opts ...grpc.CallOption, +) (*AddWorkflowMessagesResponse, error) { + var response *AddWorkflowMessagesResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.AddWorkflowMessages"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetWorkflowId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.AddWorkflowMessages(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) AddWorkflowMessages( + ctx context.Context, + request *AddWorkflowMessagesRequest, + opts ...grpc.CallOption, +) (*AddWorkflowMessagesResponse, error) { + call := func(ctx context.Context) (*AddWorkflowMessagesResponse, error) { + return c.callAddWorkflowMessagesNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callRegisterStreamConsumerNoRetry( + ctx context.Context, + request *RegisterStreamConsumerRequest, + opts ...grpc.CallOption, +) (*RegisterStreamConsumerResponse, error) { + var response *RegisterStreamConsumerResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.RegisterStreamConsumer"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.RegisterStreamConsumer(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) RegisterStreamConsumer( + ctx context.Context, + request *RegisterStreamConsumerRequest, + opts ...grpc.CallOption, +) (*RegisterStreamConsumerResponse, error) { + call := func(ctx context.Context) (*RegisterStreamConsumerResponse, error) { + return c.callRegisterStreamConsumerNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callAdvanceConsumerHeadNoRetry( + ctx context.Context, + request *AdvanceConsumerHeadRequest, + opts ...grpc.CallOption, +) (*AdvanceConsumerHeadResponse, error) { + var response *AdvanceConsumerHeadResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.AdvanceConsumerHead"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetWorkflowId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.AdvanceConsumerHead(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) AdvanceConsumerHead( + ctx context.Context, + request *AdvanceConsumerHeadRequest, + opts ...grpc.CallOption, +) (*AdvanceConsumerHeadResponse, error) { + call := func(ctx context.Context) (*AdvanceConsumerHeadResponse, error) { + return c.callAdvanceConsumerHeadNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callCloseStreamNoRetry( + ctx context.Context, + request *CloseStreamRequest, + opts ...grpc.CallOption, +) (*CloseStreamResponse, error) { + var response *CloseStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.CloseStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.CloseStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) CloseStream( + ctx context.Context, + request *CloseStreamRequest, + opts ...grpc.CallOption, +) (*CloseStreamResponse, error) { + call := func(ctx context.Context) (*CloseStreamResponse, error) { + return c.callCloseStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callTruncateStreamNoRetry( + ctx context.Context, + request *TruncateStreamRequest, + opts ...grpc.CallOption, +) (*TruncateStreamResponse, error) { + var response *TruncateStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.TruncateStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.TruncateStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) TruncateStream( + ctx context.Context, + request *TruncateStreamRequest, + opts ...grpc.CallOption, +) (*TruncateStreamResponse, error) { + call := func(ctx context.Context) (*TruncateStreamResponse, error) { + return c.callTruncateStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callListStreamsNoRetry( + ctx context.Context, + request *ListStreamsRequest, + opts ...grpc.CallOption, +) (*ListStreamsResponse, error) { + var response *ListStreamsResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.ListStreams"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := int32(rand.Intn(int(c.numShards)) + 1) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.ListStreams(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) ListStreams( + ctx context.Context, + request *ListStreamsRequest, + opts ...grpc.CallOption, +) (*ListStreamsResponse, error) { + call := func(ctx context.Context) (*ListStreamsResponse, error) { + return c.callListStreamsNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} +func (c *StreamServiceLayeredClient) callDeleteStreamNoRetry( + ctx context.Context, + request *DeleteStreamRequest, + opts ...grpc.CallOption, +) (*DeleteStreamResponse, error) { + var response *DeleteStreamResponse + var err error + startTime := time.Now().UTC() + // the caller is a namespace, hence the tag below. + caller := headers.GetCallerInfo(ctx).CallerName + metricsHandler := c.metricsHandler.WithTags( + metrics.OperationTag("StreamService.DeleteStream"), + metrics.NamespaceTag(caller), + metrics.ServiceRoleTag(metrics.HistoryRoleTagValue), + ) + metrics.ClientRequests.With(metricsHandler).Record(1) + defer func() { + if err != nil { + metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) + } + metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) + }() + shardID := common.WorkflowIDToHistoryShard(request.GetNamespaceId(), request.GetFrontendRequest().GetStreamId(), c.numShards) + op := func(ctx context.Context, client StreamServiceClient) error { + var err error + ctx, cancel := context.WithTimeout(ctx, history.DefaultTimeout) + defer cancel() + response, err = client.DeleteStream(ctx, request, opts...) + return err + } + err = c.redirector.Execute(ctx, shardID, op) + return response, err +} +func (c *StreamServiceLayeredClient) DeleteStream( + ctx context.Context, + request *DeleteStreamRequest, + opts ...grpc.CallOption, +) (*DeleteStreamResponse, error) { + call := func(ctx context.Context) (*DeleteStreamResponse, error) { + return c.callDeleteStreamNoRetry(ctx, request, opts...) + } + return backoff.ThrottleRetryContextWithReturn(ctx, call, c.retryPolicy, common.IsServiceClientTransientError) +} diff --git a/chasm/lib/stream/gen/streampb/v1/service_grpc.pb.go b/chasm/lib/stream/gen/streampb/v1/service_grpc.pb.go new file mode 100644 index 00000000000..0a9d2f93a28 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/service_grpc.pb.go @@ -0,0 +1,640 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// plugins: +// - protoc-gen-go-grpc +// - protoc +// source: temporal/server/chasm/lib/stream/proto/v1/service.proto + +package streampb + +import ( + context "context" + + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + StreamService_CreateStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/CreateStream" + StreamService_AddMessages_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/AddMessages" + StreamService_FinishWriting_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/FinishWriting" + StreamService_SubscribeWorkflow_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/SubscribeWorkflow" + StreamService_PollMessages_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/PollMessages" + StreamService_DescribeStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/DescribeStream" + StreamService_PollWorkflowMessages_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/PollWorkflowMessages" + StreamService_DescribeWorkflowStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/DescribeWorkflowStream" + StreamService_AddWorkflowMessages_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/AddWorkflowMessages" + StreamService_RegisterStreamConsumer_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/RegisterStreamConsumer" + StreamService_AdvanceConsumerHead_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/AdvanceConsumerHead" + StreamService_CloseStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/CloseStream" + StreamService_TruncateStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/TruncateStream" + StreamService_ListStreams_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/ListStreams" + StreamService_DeleteStream_FullMethodName = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/DeleteStream" +) + +// StreamServiceClient is the client API for StreamService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type StreamServiceClient interface { + CreateStream(ctx context.Context, in *CreateStreamRequest, opts ...grpc.CallOption) (*CreateStreamResponse, error) + AddMessages(ctx context.Context, in *AddMessagesRequest, opts ...grpc.CallOption) (*AddMessagesResponse, error) + FinishWriting(ctx context.Context, in *FinishWritingRequest, opts ...grpc.CallOption) (*FinishWritingResponse, error) + SubscribeWorkflow(ctx context.Context, in *SubscribeWorkflowRequest, opts ...grpc.CallOption) (*SubscribeWorkflowResponse, error) + PollMessages(ctx context.Context, in *PollMessagesRequest, opts ...grpc.CallOption) (*PollMessagesResponse, error) + DescribeStream(ctx context.Context, in *DescribeStreamRequest, opts ...grpc.CallOption) (*DescribeStreamResponse, error) + // Routed on the owner, because the stream it reads has no id of its own. + PollWorkflowMessages(ctx context.Context, in *PollWorkflowMessagesRequest, opts ...grpc.CallOption) (*PollWorkflowMessagesResponse, error) + DescribeWorkflowStream(ctx context.Context, in *DescribeWorkflowStreamRequest, opts ...grpc.CallOption) (*DescribeWorkflowStreamResponse, error) + AddWorkflowMessages(ctx context.Context, in *AddWorkflowMessagesRequest, opts ...grpc.CallOption) (*AddWorkflowMessagesResponse, error) + // Internal. History calls these on itself to reach a shard it does not own, + // which is the only way a step that spans two executions can work on a + // cluster with more than one history host. + RegisterStreamConsumer(ctx context.Context, in *RegisterStreamConsumerRequest, opts ...grpc.CallOption) (*RegisterStreamConsumerResponse, error) + AdvanceConsumerHead(ctx context.Context, in *AdvanceConsumerHeadRequest, opts ...grpc.CallOption) (*AdvanceConsumerHeadResponse, error) + CloseStream(ctx context.Context, in *CloseStreamRequest, opts ...grpc.CallOption) (*CloseStreamResponse, error) + TruncateStream(ctx context.Context, in *TruncateStreamRequest, opts ...grpc.CallOption) (*TruncateStreamResponse, error) + // Served on the frontend only: it queries visibility rather than a stream, + // so there is no business ID to route on and nothing for a shard to answer. + ListStreams(ctx context.Context, in *ListStreamsRequest, opts ...grpc.CallOption) (*ListStreamsResponse, error) + DeleteStream(ctx context.Context, in *DeleteStreamRequest, opts ...grpc.CallOption) (*DeleteStreamResponse, error) +} + +type streamServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewStreamServiceClient(cc grpc.ClientConnInterface) StreamServiceClient { + return &streamServiceClient{cc} +} + +func (c *streamServiceClient) CreateStream(ctx context.Context, in *CreateStreamRequest, opts ...grpc.CallOption) (*CreateStreamResponse, error) { + out := new(CreateStreamResponse) + err := c.cc.Invoke(ctx, StreamService_CreateStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) AddMessages(ctx context.Context, in *AddMessagesRequest, opts ...grpc.CallOption) (*AddMessagesResponse, error) { + out := new(AddMessagesResponse) + err := c.cc.Invoke(ctx, StreamService_AddMessages_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) FinishWriting(ctx context.Context, in *FinishWritingRequest, opts ...grpc.CallOption) (*FinishWritingResponse, error) { + out := new(FinishWritingResponse) + err := c.cc.Invoke(ctx, StreamService_FinishWriting_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) SubscribeWorkflow(ctx context.Context, in *SubscribeWorkflowRequest, opts ...grpc.CallOption) (*SubscribeWorkflowResponse, error) { + out := new(SubscribeWorkflowResponse) + err := c.cc.Invoke(ctx, StreamService_SubscribeWorkflow_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) PollMessages(ctx context.Context, in *PollMessagesRequest, opts ...grpc.CallOption) (*PollMessagesResponse, error) { + out := new(PollMessagesResponse) + err := c.cc.Invoke(ctx, StreamService_PollMessages_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) DescribeStream(ctx context.Context, in *DescribeStreamRequest, opts ...grpc.CallOption) (*DescribeStreamResponse, error) { + out := new(DescribeStreamResponse) + err := c.cc.Invoke(ctx, StreamService_DescribeStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) PollWorkflowMessages(ctx context.Context, in *PollWorkflowMessagesRequest, opts ...grpc.CallOption) (*PollWorkflowMessagesResponse, error) { + out := new(PollWorkflowMessagesResponse) + err := c.cc.Invoke(ctx, StreamService_PollWorkflowMessages_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) DescribeWorkflowStream(ctx context.Context, in *DescribeWorkflowStreamRequest, opts ...grpc.CallOption) (*DescribeWorkflowStreamResponse, error) { + out := new(DescribeWorkflowStreamResponse) + err := c.cc.Invoke(ctx, StreamService_DescribeWorkflowStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) AddWorkflowMessages(ctx context.Context, in *AddWorkflowMessagesRequest, opts ...grpc.CallOption) (*AddWorkflowMessagesResponse, error) { + out := new(AddWorkflowMessagesResponse) + err := c.cc.Invoke(ctx, StreamService_AddWorkflowMessages_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) RegisterStreamConsumer(ctx context.Context, in *RegisterStreamConsumerRequest, opts ...grpc.CallOption) (*RegisterStreamConsumerResponse, error) { + out := new(RegisterStreamConsumerResponse) + err := c.cc.Invoke(ctx, StreamService_RegisterStreamConsumer_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) AdvanceConsumerHead(ctx context.Context, in *AdvanceConsumerHeadRequest, opts ...grpc.CallOption) (*AdvanceConsumerHeadResponse, error) { + out := new(AdvanceConsumerHeadResponse) + err := c.cc.Invoke(ctx, StreamService_AdvanceConsumerHead_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) CloseStream(ctx context.Context, in *CloseStreamRequest, opts ...grpc.CallOption) (*CloseStreamResponse, error) { + out := new(CloseStreamResponse) + err := c.cc.Invoke(ctx, StreamService_CloseStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) TruncateStream(ctx context.Context, in *TruncateStreamRequest, opts ...grpc.CallOption) (*TruncateStreamResponse, error) { + out := new(TruncateStreamResponse) + err := c.cc.Invoke(ctx, StreamService_TruncateStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) ListStreams(ctx context.Context, in *ListStreamsRequest, opts ...grpc.CallOption) (*ListStreamsResponse, error) { + out := new(ListStreamsResponse) + err := c.cc.Invoke(ctx, StreamService_ListStreams_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *streamServiceClient) DeleteStream(ctx context.Context, in *DeleteStreamRequest, opts ...grpc.CallOption) (*DeleteStreamResponse, error) { + out := new(DeleteStreamResponse) + err := c.cc.Invoke(ctx, StreamService_DeleteStream_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// StreamServiceServer is the server API for StreamService service. +// All implementations must embed UnimplementedStreamServiceServer +// for forward compatibility +type StreamServiceServer interface { + CreateStream(context.Context, *CreateStreamRequest) (*CreateStreamResponse, error) + AddMessages(context.Context, *AddMessagesRequest) (*AddMessagesResponse, error) + FinishWriting(context.Context, *FinishWritingRequest) (*FinishWritingResponse, error) + SubscribeWorkflow(context.Context, *SubscribeWorkflowRequest) (*SubscribeWorkflowResponse, error) + PollMessages(context.Context, *PollMessagesRequest) (*PollMessagesResponse, error) + DescribeStream(context.Context, *DescribeStreamRequest) (*DescribeStreamResponse, error) + // Routed on the owner, because the stream it reads has no id of its own. + PollWorkflowMessages(context.Context, *PollWorkflowMessagesRequest) (*PollWorkflowMessagesResponse, error) + DescribeWorkflowStream(context.Context, *DescribeWorkflowStreamRequest) (*DescribeWorkflowStreamResponse, error) + AddWorkflowMessages(context.Context, *AddWorkflowMessagesRequest) (*AddWorkflowMessagesResponse, error) + // Internal. History calls these on itself to reach a shard it does not own, + // which is the only way a step that spans two executions can work on a + // cluster with more than one history host. + RegisterStreamConsumer(context.Context, *RegisterStreamConsumerRequest) (*RegisterStreamConsumerResponse, error) + AdvanceConsumerHead(context.Context, *AdvanceConsumerHeadRequest) (*AdvanceConsumerHeadResponse, error) + CloseStream(context.Context, *CloseStreamRequest) (*CloseStreamResponse, error) + TruncateStream(context.Context, *TruncateStreamRequest) (*TruncateStreamResponse, error) + // Served on the frontend only: it queries visibility rather than a stream, + // so there is no business ID to route on and nothing for a shard to answer. + ListStreams(context.Context, *ListStreamsRequest) (*ListStreamsResponse, error) + DeleteStream(context.Context, *DeleteStreamRequest) (*DeleteStreamResponse, error) + mustEmbedUnimplementedStreamServiceServer() +} + +// UnimplementedStreamServiceServer must be embedded to have forward compatible implementations. +type UnimplementedStreamServiceServer struct { +} + +func (UnimplementedStreamServiceServer) CreateStream(context.Context, *CreateStreamRequest) (*CreateStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateStream not implemented") +} +func (UnimplementedStreamServiceServer) AddMessages(context.Context, *AddMessagesRequest) (*AddMessagesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddMessages not implemented") +} +func (UnimplementedStreamServiceServer) FinishWriting(context.Context, *FinishWritingRequest) (*FinishWritingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FinishWriting not implemented") +} +func (UnimplementedStreamServiceServer) SubscribeWorkflow(context.Context, *SubscribeWorkflowRequest) (*SubscribeWorkflowResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubscribeWorkflow not implemented") +} +func (UnimplementedStreamServiceServer) PollMessages(context.Context, *PollMessagesRequest) (*PollMessagesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PollMessages not implemented") +} +func (UnimplementedStreamServiceServer) DescribeStream(context.Context, *DescribeStreamRequest) (*DescribeStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DescribeStream not implemented") +} +func (UnimplementedStreamServiceServer) PollWorkflowMessages(context.Context, *PollWorkflowMessagesRequest) (*PollWorkflowMessagesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PollWorkflowMessages not implemented") +} +func (UnimplementedStreamServiceServer) DescribeWorkflowStream(context.Context, *DescribeWorkflowStreamRequest) (*DescribeWorkflowStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DescribeWorkflowStream not implemented") +} +func (UnimplementedStreamServiceServer) AddWorkflowMessages(context.Context, *AddWorkflowMessagesRequest) (*AddWorkflowMessagesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddWorkflowMessages not implemented") +} +func (UnimplementedStreamServiceServer) RegisterStreamConsumer(context.Context, *RegisterStreamConsumerRequest) (*RegisterStreamConsumerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterStreamConsumer not implemented") +} +func (UnimplementedStreamServiceServer) AdvanceConsumerHead(context.Context, *AdvanceConsumerHeadRequest) (*AdvanceConsumerHeadResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AdvanceConsumerHead not implemented") +} +func (UnimplementedStreamServiceServer) CloseStream(context.Context, *CloseStreamRequest) (*CloseStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CloseStream not implemented") +} +func (UnimplementedStreamServiceServer) TruncateStream(context.Context, *TruncateStreamRequest) (*TruncateStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TruncateStream not implemented") +} +func (UnimplementedStreamServiceServer) ListStreams(context.Context, *ListStreamsRequest) (*ListStreamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListStreams not implemented") +} +func (UnimplementedStreamServiceServer) DeleteStream(context.Context, *DeleteStreamRequest) (*DeleteStreamResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteStream not implemented") +} +func (UnimplementedStreamServiceServer) mustEmbedUnimplementedStreamServiceServer() {} + +// UnsafeStreamServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to StreamServiceServer will +// result in compilation errors. +type UnsafeStreamServiceServer interface { + mustEmbedUnimplementedStreamServiceServer() +} + +func RegisterStreamServiceServer(s grpc.ServiceRegistrar, srv StreamServiceServer) { + s.RegisterService(&StreamService_ServiceDesc, srv) +} + +func _StreamService_CreateStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).CreateStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_CreateStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).CreateStream(ctx, req.(*CreateStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_AddMessages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddMessagesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).AddMessages(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_AddMessages_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).AddMessages(ctx, req.(*AddMessagesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_FinishWriting_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FinishWritingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).FinishWriting(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_FinishWriting_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).FinishWriting(ctx, req.(*FinishWritingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_SubscribeWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SubscribeWorkflowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).SubscribeWorkflow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_SubscribeWorkflow_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).SubscribeWorkflow(ctx, req.(*SubscribeWorkflowRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_PollMessages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PollMessagesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).PollMessages(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_PollMessages_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).PollMessages(ctx, req.(*PollMessagesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_DescribeStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DescribeStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).DescribeStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_DescribeStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).DescribeStream(ctx, req.(*DescribeStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_PollWorkflowMessages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PollWorkflowMessagesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).PollWorkflowMessages(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_PollWorkflowMessages_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).PollWorkflowMessages(ctx, req.(*PollWorkflowMessagesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_DescribeWorkflowStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DescribeWorkflowStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).DescribeWorkflowStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_DescribeWorkflowStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).DescribeWorkflowStream(ctx, req.(*DescribeWorkflowStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_AddWorkflowMessages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddWorkflowMessagesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).AddWorkflowMessages(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_AddWorkflowMessages_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).AddWorkflowMessages(ctx, req.(*AddWorkflowMessagesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_RegisterStreamConsumer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterStreamConsumerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).RegisterStreamConsumer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_RegisterStreamConsumer_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).RegisterStreamConsumer(ctx, req.(*RegisterStreamConsumerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_AdvanceConsumerHead_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdvanceConsumerHeadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).AdvanceConsumerHead(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_AdvanceConsumerHead_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).AdvanceConsumerHead(ctx, req.(*AdvanceConsumerHeadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_CloseStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CloseStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).CloseStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_CloseStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).CloseStream(ctx, req.(*CloseStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_TruncateStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TruncateStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).TruncateStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_TruncateStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).TruncateStream(ctx, req.(*TruncateStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_ListStreams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListStreamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).ListStreams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_ListStreams_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).ListStreams(ctx, req.(*ListStreamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StreamService_DeleteStream_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteStreamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StreamServiceServer).DeleteStream(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StreamService_DeleteStream_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StreamServiceServer).DeleteStream(ctx, req.(*DeleteStreamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// StreamService_ServiceDesc is the grpc.ServiceDesc for StreamService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var StreamService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "temporal.server.chasm.lib.stream.proto.v1.StreamService", + HandlerType: (*StreamServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateStream", + Handler: _StreamService_CreateStream_Handler, + }, + { + MethodName: "AddMessages", + Handler: _StreamService_AddMessages_Handler, + }, + { + MethodName: "FinishWriting", + Handler: _StreamService_FinishWriting_Handler, + }, + { + MethodName: "SubscribeWorkflow", + Handler: _StreamService_SubscribeWorkflow_Handler, + }, + { + MethodName: "PollMessages", + Handler: _StreamService_PollMessages_Handler, + }, + { + MethodName: "DescribeStream", + Handler: _StreamService_DescribeStream_Handler, + }, + { + MethodName: "PollWorkflowMessages", + Handler: _StreamService_PollWorkflowMessages_Handler, + }, + { + MethodName: "DescribeWorkflowStream", + Handler: _StreamService_DescribeWorkflowStream_Handler, + }, + { + MethodName: "AddWorkflowMessages", + Handler: _StreamService_AddWorkflowMessages_Handler, + }, + { + MethodName: "RegisterStreamConsumer", + Handler: _StreamService_RegisterStreamConsumer_Handler, + }, + { + MethodName: "AdvanceConsumerHead", + Handler: _StreamService_AdvanceConsumerHead_Handler, + }, + { + MethodName: "CloseStream", + Handler: _StreamService_CloseStream_Handler, + }, + { + MethodName: "TruncateStream", + Handler: _StreamService_TruncateStream_Handler, + }, + { + MethodName: "ListStreams", + Handler: _StreamService_ListStreams_Handler, + }, + { + MethodName: "DeleteStream", + Handler: _StreamService_DeleteStream_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "temporal/server/chasm/lib/stream/proto/v1/service.proto", +} diff --git a/chasm/lib/stream/gen/streampb/v1/stream_state.go-helpers.pb.go b/chasm/lib/stream/gen/streampb/v1/stream_state.go-helpers.pb.go new file mode 100644 index 00000000000..c97d64015d9 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/stream_state.go-helpers.pb.go @@ -0,0 +1,228 @@ +// Code generated by protoc-gen-go-helpers. DO NOT EDIT. +package streampb + +import ( + "google.golang.org/protobuf/proto" +) + +// Marshal an object of type StreamState to the protobuf v3 wire format +func (val *StreamState) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamState from the protobuf v3 wire format +func (val *StreamState) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamState) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamState 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 *StreamState) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamState + switch t := that.(type) { + case *StreamState: + that1 = t + case StreamState: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type StreamBudget to the protobuf v3 wire format +func (val *StreamBudget) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamBudget from the protobuf v3 wire format +func (val *StreamBudget) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamBudget) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamBudget 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 *StreamBudget) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamBudget + switch t := that.(type) { + case *StreamBudget: + that1 = t + case StreamBudget: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ProducerCursor to the protobuf v3 wire format +func (val *ProducerCursor) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ProducerCursor from the protobuf v3 wire format +func (val *ProducerCursor) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ProducerCursor) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ProducerCursor 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 *ProducerCursor) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ProducerCursor + switch t := that.(type) { + case *ProducerCursor: + that1 = t + case ProducerCursor: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type ConsumerCursor to the protobuf v3 wire format +func (val *ConsumerCursor) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type ConsumerCursor from the protobuf v3 wire format +func (val *ConsumerCursor) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *ConsumerCursor) Size() int { + return proto.Size(val) +} + +// Equal returns whether two ConsumerCursor 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 *ConsumerCursor) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *ConsumerCursor + switch t := that.(type) { + case *ConsumerCursor: + that1 = t + case ConsumerCursor: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type WorkflowStreamCursor to the protobuf v3 wire format +func (val *WorkflowStreamCursor) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type WorkflowStreamCursor from the protobuf v3 wire format +func (val *WorkflowStreamCursor) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *WorkflowStreamCursor) Size() int { + return proto.Size(val) +} + +// Equal returns whether two WorkflowStreamCursor 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 *WorkflowStreamCursor) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *WorkflowStreamCursor + switch t := that.(type) { + case *WorkflowStreamCursor: + that1 = t + case WorkflowStreamCursor: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type StreamLifecycle to the protobuf v3 wire format +func (val *StreamLifecycle) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamLifecycle from the protobuf v3 wire format +func (val *StreamLifecycle) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamLifecycle) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamLifecycle 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 *StreamLifecycle) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamLifecycle + switch t := that.(type) { + case *StreamLifecycle: + that1 = t + case StreamLifecycle: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} diff --git a/chasm/lib/stream/gen/streampb/v1/stream_state.pb.go b/chasm/lib/stream/gen/streampb/v1/stream_state.pb.go new file mode 100644 index 00000000000..ac663fb790d --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/stream_state.pb.go @@ -0,0 +1,706 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// plugins: +// protoc-gen-go +// protoc +// source: temporal/server/chasm/lib/stream/proto/v1/stream_state.proto + +package streampb + +import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + + v1 "go.temporal.io/api/common/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Size is O(producers + consumers), never O(messages). Payload bytes live in +// the component's data nodes, not here, which keeps this off the CHASM +// partial-read path. +type StreamState struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Visibility frontier. Readers never observe an offset at or past this. + HeadOffset int64 `protobuf:"varint,1,opt,name=head_offset,json=headOffset,proto3" json:"head_offset,omitempty"` + // Truncation floor. Offsets below this are gone. + BaseOffset int64 `protobuf:"varint,2,opt,name=base_offset,json=baseOffset,proto3" json:"base_offset,omitempty"` + Closed bool `protobuf:"varint,4,opt,name=closed,proto3" json:"closed,omitempty"` + CloseReason *v1.Payload `protobuf:"bytes,5,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` + Producers map[string]*ProducerCursor `protobuf:"bytes,9,rep,name=producers,proto3" json:"producers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Consumers map[string]*ConsumerCursor `protobuf:"bytes,10,rep,name=consumers,proto3" json:"consumers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Lifecycle *StreamLifecycle `protobuf:"bytes,11,opt,name=lifecycle,proto3" json:"lifecycle,omitempty"` + // Set when a successor run takes ownership, so an in-flight poll can follow + // the chain instead of stalling on a superseded run. + RedirectRunId string `protobuf:"bytes,12,opt,name=redirect_run_id,json=redirectRunId,proto3" json:"redirect_run_id,omitempty"` + // Wall-clock close time, used to schedule retention deletion. + CloseTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=close_time,json=closeTime,proto3" json:"close_time,omitempty"` + // Set on a stream a workflow owns. Its batches are the owning execution's + // mutable state, so appends past the budget are refused rather than left to + // the execution size limit, which terminates the workflow. + Budget *StreamBudget `protobuf:"bytes,14,opt,name=budget,proto3" json:"budget,omitempty"` + // Bytes appended over the stream's life, kept for the budget check. A stream + // with a budget never reclaims, so this is also what it holds. + AppendedBytes int64 `protobuf:"varint,15,opt,name=appended_bytes,json=appendedBytes,proto3" json:"appended_bytes,omitempty"` + // A notify task is scheduled and has not run yet. Appends while it is set + // schedule none of their own; the task reads the head when it runs, so it + // carries every append that landed before it. + NotifyPending bool `protobuf:"varint,16,opt,name=notify_pending,json=notifyPending,proto3" json:"notify_pending,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamState) Reset() { + *x = StreamState{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamState) ProtoMessage() {} + +func (x *StreamState) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[0] + 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 StreamState.ProtoReflect.Descriptor instead. +func (*StreamState) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{0} +} + +func (x *StreamState) GetHeadOffset() int64 { + if x != nil { + return x.HeadOffset + } + return 0 +} + +func (x *StreamState) GetBaseOffset() int64 { + if x != nil { + return x.BaseOffset + } + return 0 +} + +func (x *StreamState) GetClosed() bool { + if x != nil { + return x.Closed + } + return false +} + +func (x *StreamState) GetCloseReason() *v1.Payload { + if x != nil { + return x.CloseReason + } + return nil +} + +func (x *StreamState) GetProducers() map[string]*ProducerCursor { + if x != nil { + return x.Producers + } + return nil +} + +func (x *StreamState) GetConsumers() map[string]*ConsumerCursor { + if x != nil { + return x.Consumers + } + return nil +} + +func (x *StreamState) GetLifecycle() *StreamLifecycle { + if x != nil { + return x.Lifecycle + } + return nil +} + +func (x *StreamState) GetRedirectRunId() string { + if x != nil { + return x.RedirectRunId + } + return "" +} + +func (x *StreamState) GetCloseTime() *timestamppb.Timestamp { + if x != nil { + return x.CloseTime + } + return nil +} + +func (x *StreamState) GetBudget() *StreamBudget { + if x != nil { + return x.Budget + } + return nil +} + +func (x *StreamState) GetAppendedBytes() int64 { + if x != nil { + return x.AppendedBytes + } + return 0 +} + +func (x *StreamState) GetNotifyPending() bool { + if x != nil { + return x.NotifyPending + } + return false +} + +// Hard bounds on what a stream may hold. Distinct from StreamLifecycle.max_items, +// which reclaims the oldest messages: a budget refuses the newest. +type StreamBudget struct { + state protoimpl.MessageState `protogen:"open.v1"` + MaxItems int64 `protobuf:"varint,1,opt,name=max_items,json=maxItems,proto3" json:"max_items,omitempty"` + MaxBytes int64 `protobuf:"varint,2,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamBudget) Reset() { + *x = StreamBudget{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamBudget) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamBudget) ProtoMessage() {} + +func (x *StreamBudget) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[1] + 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 StreamBudget.ProtoReflect.Descriptor instead. +func (*StreamBudget) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{1} +} + +func (x *StreamBudget) GetMaxItems() int64 { + if x != nil { + return x.MaxItems + } + return 0 +} + +func (x *StreamBudget) GetMaxBytes() int64 { + if x != nil { + return x.MaxBytes + } + return 0 +} + +type ProducerCursor struct { + state protoimpl.MessageState `protogen:"open.v1"` + Seq int64 `protobuf:"varint,1,opt,name=seq,proto3" json:"seq,omitempty"` + FirstOffset int64 `protobuf:"varint,2,opt,name=first_offset,json=firstOffset,proto3" json:"first_offset,omitempty"` + Count int64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + // Distinguishes a genuine retry from a client reusing a sequence with + // different content, which must be rejected rather than deduplicated. + ContentHash []byte `protobuf:"bytes,4,opt,name=content_hash,json=contentHash,proto3" json:"content_hash,omitempty"` + // Set by FinishWriting. Ends this producer's writes without closing the + // stream for anyone else. + Fenced bool `protobuf:"varint,5,opt,name=fenced,proto3" json:"fenced,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProducerCursor) Reset() { + *x = ProducerCursor{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProducerCursor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProducerCursor) ProtoMessage() {} + +func (x *ProducerCursor) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[2] + 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 ProducerCursor.ProtoReflect.Descriptor instead. +func (*ProducerCursor) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{2} +} + +func (x *ProducerCursor) GetSeq() int64 { + if x != nil { + return x.Seq + } + return 0 +} + +func (x *ProducerCursor) GetFirstOffset() int64 { + if x != nil { + return x.FirstOffset + } + return 0 +} + +func (x *ProducerCursor) GetCount() int64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *ProducerCursor) GetContentHash() []byte { + if x != nil { + return x.ContentHash + } + return nil +} + +func (x *ProducerCursor) GetFenced() bool { + if x != nil { + return x.Fenced + } + return false +} + +type ConsumerCursor struct { + state protoimpl.MessageState `protogen:"open.v1"` + WorkflowId string `protobuf:"bytes,1,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + RunId string `protobuf:"bytes,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + // How far this consumer has read. Used to decide whether it needs waking, + // not to decide what the stream may drop. + Offset int64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` + Active bool `protobuf:"varint,4,opt,name=active,proto3" json:"active,omitempty"` + // Set when the consumer is a workflow in another execution, which is the + // only case that has to be told the frontier moved. A workflow consuming a + // stream it owns sees that while closing its own transaction. + External bool `protobuf:"varint,5,opt,name=external,proto3" json:"external,omitempty"` + // The oldest offset this consumer's History still depends on. + // + // It is where the subscription started, not where it has read to. A range + // this consumer already consumed is recorded in its History and has to be + // re-readable for the workflow to replay, so bytes below the read position + // are exactly the ones a replay needs most. It stays put while the consumer + // is active and is released when it deregisters. + ReplayFloor int64 `protobuf:"varint,6,opt,name=replay_floor,json=replayFloor,proto3" json:"replay_floor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConsumerCursor) Reset() { + *x = ConsumerCursor{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsumerCursor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsumerCursor) ProtoMessage() {} + +func (x *ConsumerCursor) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[3] + 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 ConsumerCursor.ProtoReflect.Descriptor instead. +func (*ConsumerCursor) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{3} +} + +func (x *ConsumerCursor) GetWorkflowId() string { + if x != nil { + return x.WorkflowId + } + return "" +} + +func (x *ConsumerCursor) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +func (x *ConsumerCursor) GetOffset() int64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *ConsumerCursor) GetActive() bool { + if x != nil { + return x.Active + } + return false +} + +func (x *ConsumerCursor) GetExternal() bool { + if x != nil { + return x.External + } + return false +} + +func (x *ConsumerCursor) GetReplayFloor() int64 { + if x != nil { + return x.ReplayFloor + } + return 0 +} + +// A consuming Workflow's position in a stream. This lives in the consuming +// Workflow's own state rather than on the stream, so advancing it commits in +// the same transaction as the WorkflowTaskCompleted event that records the +// range. Keeping it on the stream would make the advance a cross-execution +// write, and a crash between the two would either redeliver or skip. +type WorkflowStreamCursor struct { + state protoimpl.MessageState `protogen:"open.v1"` + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + // Next offset to deliver. + Offset int64 `protobuf:"varint,4,opt,name=offset,proto3" json:"offset,omitempty"` + // The stream's frontier as of the last delivery. A workflow consuming a + // stream in another execution cannot read the real frontier while closing its + // own transaction, so this is what tells it a capped slice left more behind. + KnownHead int64 `protobuf:"varint,8,opt,name=known_head,json=knownHead,proto3" json:"known_head,omitempty"` + // Set when the stream lives in another execution, which decides whether the + // frontier is read locally or taken from known_head. + External bool `protobuf:"varint,9,opt,name=external,proto3" json:"external,omitempty"` + // The range attached to the Workflow Task currently in flight. Recorded on + // the event that closes that task, then folded into offset. An empty range + // is still recorded: a task where the subscription saw nothing is a fact + // replay has to reproduce. + PendingFrom int64 `protobuf:"varint,5,opt,name=pending_from,json=pendingFrom,proto3" json:"pending_from,omitempty"` + PendingTo int64 `protobuf:"varint,6,opt,name=pending_to,json=pendingTo,proto3" json:"pending_to,omitempty"` + HasPending bool `protobuf:"varint,7,opt,name=has_pending,json=hasPending,proto3" json:"has_pending,omitempty"` + // Where this subscription began reading. Retained separately from offset, + // which advances, because replay has to tell "committed nothing yet" apart + // from "the events recording what was committed are not in this page". + StartOffset int64 `protobuf:"varint,10,opt,name=start_offset,json=startOffset,proto3" json:"start_offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkflowStreamCursor) Reset() { + *x = WorkflowStreamCursor{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkflowStreamCursor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkflowStreamCursor) ProtoMessage() {} + +func (x *WorkflowStreamCursor) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[4] + 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 WorkflowStreamCursor.ProtoReflect.Descriptor instead. +func (*WorkflowStreamCursor) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{4} +} + +func (x *WorkflowStreamCursor) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *WorkflowStreamCursor) GetOffset() int64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *WorkflowStreamCursor) GetKnownHead() int64 { + if x != nil { + return x.KnownHead + } + return 0 +} + +func (x *WorkflowStreamCursor) GetExternal() bool { + if x != nil { + return x.External + } + return false +} + +func (x *WorkflowStreamCursor) GetPendingFrom() int64 { + if x != nil { + return x.PendingFrom + } + return 0 +} + +func (x *WorkflowStreamCursor) GetPendingTo() int64 { + if x != nil { + return x.PendingTo + } + return 0 +} + +func (x *WorkflowStreamCursor) GetHasPending() bool { + if x != nil { + return x.HasPending + } + return false +} + +func (x *WorkflowStreamCursor) GetStartOffset() int64 { + if x != nil { + return x.StartOffset + } + return 0 +} + +type StreamLifecycle struct { + state protoimpl.MessageState `protogen:"open.v1"` + // How long a closed stream stays readable before it is deleted. + Retention *durationpb.Duration `protobuf:"bytes,1,opt,name=retention,proto3" json:"retention,omitempty"` + // Cap on readable messages. Whole batches are reclaimed once the floor + // passes them, so a capped stream has bounded storage. + MaxItems int64 `protobuf:"varint,2,opt,name=max_items,json=maxItems,proto3" json:"max_items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamLifecycle) Reset() { + *x = StreamLifecycle{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamLifecycle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamLifecycle) ProtoMessage() {} + +func (x *StreamLifecycle) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes[5] + 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 StreamLifecycle.ProtoReflect.Descriptor instead. +func (*StreamLifecycle) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDescGZIP(), []int{5} +} + +func (x *StreamLifecycle) GetRetention() *durationpb.Duration { + if x != nil { + return x.Retention + } + return nil +} + +func (x *StreamLifecycle) GetMaxItems() int64 { + if x != nil { + return x.MaxItems + } + return 0 +} + +var File_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto protoreflect.FileDescriptor + +const file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDesc = "" + + "\n" + + "Z temporal.api.common.v1.Payload + 6, // 1: temporal.server.chasm.lib.stream.proto.v1.StreamState.producers:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamState.ProducersEntry + 7, // 2: temporal.server.chasm.lib.stream.proto.v1.StreamState.consumers:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamState.ConsumersEntry + 5, // 3: temporal.server.chasm.lib.stream.proto.v1.StreamState.lifecycle:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamLifecycle + 9, // 4: temporal.server.chasm.lib.stream.proto.v1.StreamState.close_time:type_name -> google.protobuf.Timestamp + 1, // 5: temporal.server.chasm.lib.stream.proto.v1.StreamState.budget:type_name -> temporal.server.chasm.lib.stream.proto.v1.StreamBudget + 10, // 6: temporal.server.chasm.lib.stream.proto.v1.StreamLifecycle.retention:type_name -> google.protobuf.Duration + 2, // 7: temporal.server.chasm.lib.stream.proto.v1.StreamState.ProducersEntry.value:type_name -> temporal.server.chasm.lib.stream.proto.v1.ProducerCursor + 3, // 8: temporal.server.chasm.lib.stream.proto.v1.StreamState.ConsumersEntry.value:type_name -> temporal.server.chasm.lib.stream.proto.v1.ConsumerCursor + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_init() } +func file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_init() { + if File_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDesc), len(file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_goTypes, + DependencyIndexes: file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_depIdxs, + MessageInfos: file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_msgTypes, + }.Build() + File_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto = out.File + file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_goTypes = nil + file_temporal_server_chasm_lib_stream_proto_v1_stream_state_proto_depIdxs = nil +} diff --git a/chasm/lib/stream/gen/streampb/v1/tasks.go-helpers.pb.go b/chasm/lib/stream/gen/streampb/v1/tasks.go-helpers.pb.go new file mode 100644 index 00000000000..9644b7bbe02 --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/tasks.go-helpers.pb.go @@ -0,0 +1,80 @@ +// Code generated by protoc-gen-go-helpers. DO NOT EDIT. +package streampb + +import ( + "google.golang.org/protobuf/proto" +) + +// Marshal an object of type StreamRetentionTask to the protobuf v3 wire format +func (val *StreamRetentionTask) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamRetentionTask from the protobuf v3 wire format +func (val *StreamRetentionTask) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamRetentionTask) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamRetentionTask 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 *StreamRetentionTask) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamRetentionTask + switch t := that.(type) { + case *StreamRetentionTask: + that1 = t + case StreamRetentionTask: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} + +// Marshal an object of type StreamNotifyConsumersTask to the protobuf v3 wire format +func (val *StreamNotifyConsumersTask) Marshal() ([]byte, error) { + return proto.Marshal(val) +} + +// Unmarshal an object of type StreamNotifyConsumersTask from the protobuf v3 wire format +func (val *StreamNotifyConsumersTask) Unmarshal(buf []byte) error { + return proto.Unmarshal(buf, val) +} + +// Size returns the size of the object, in bytes, once serialized +func (val *StreamNotifyConsumersTask) Size() int { + return proto.Size(val) +} + +// Equal returns whether two StreamNotifyConsumersTask 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 *StreamNotifyConsumersTask) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + var that1 *StreamNotifyConsumersTask + switch t := that.(type) { + case *StreamNotifyConsumersTask: + that1 = t + case StreamNotifyConsumersTask: + that1 = &t + default: + return false + } + + return proto.Equal(this, that1) +} diff --git a/chasm/lib/stream/gen/streampb/v1/tasks.pb.go b/chasm/lib/stream/gen/streampb/v1/tasks.pb.go new file mode 100644 index 00000000000..2b944c7d24d --- /dev/null +++ b/chasm/lib/stream/gen/streampb/v1/tasks.pb.go @@ -0,0 +1,160 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// plugins: +// protoc-gen-go +// protoc +// source: temporal/server/chasm/lib/stream/proto/v1/tasks.proto + +package streampb + +import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Fires at close_time plus retention. A closed stream stays readable until +// then, which is what removes the shutdown handshake the signal-based +// implementation forces on producers and consumers. +type StreamRetentionTask struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamRetentionTask) Reset() { + *x = StreamRetentionTask{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamRetentionTask) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamRetentionTask) ProtoMessage() {} + +func (x *StreamRetentionTask) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_msgTypes[0] + 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 StreamRetentionTask.ProtoReflect.Descriptor instead. +func (*StreamRetentionTask) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_rawDescGZIP(), []int{0} +} + +// Fires after an append that leaves a registered consumer behind. Appending +// never schedules a workflow task on its own, because a stream item is data an +// execution produced rather than a decision input to it. A workflow that +// subscribed is the exception: it asked to be told, and it cannot find out any +// other way, since nothing else it does would notice the stream moved. +type StreamNotifyConsumersTask struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamNotifyConsumersTask) Reset() { + *x = StreamNotifyConsumersTask{} + mi := &file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamNotifyConsumersTask) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamNotifyConsumersTask) ProtoMessage() {} + +func (x *StreamNotifyConsumersTask) ProtoReflect() protoreflect.Message { + mi := &file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_msgTypes[1] + 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 StreamNotifyConsumersTask.ProtoReflect.Descriptor instead. +func (*StreamNotifyConsumersTask) Descriptor() ([]byte, []int) { + return file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_rawDescGZIP(), []int{1} +} + +var File_temporal_server_chasm_lib_stream_proto_v1_tasks_proto protoreflect.FileDescriptor + +const file_temporal_server_chasm_lib_stream_proto_v1_tasks_proto_rawDesc = "" + + "\n" + + "5temporal/server/chasm/lib/stream/proto/v1/tasks.proto\x12)temporal.server.chasm.lib.stream.proto.v1\"\x15\n" + + "\x13StreamRetentionTask\"\x1b\n" + + "\x19StreamNotifyConsumersTaskB>Z= head { + continue + } + if len(out) >= maxMessages { + return out, next, nil + } + next = offset + 1 + if len(wanted) > 0 { + if _, ok := wanted[msg.GetTopic()]; !ok { + continue + } + } + // Set here rather than stored: it is decided by where the + // message sits in the log, not by what the producer wrote. + msg.Offset = offset + out = append(out, msg) + } + } + return out, next, nil +} + +// ToAPIRecords converts stored records to the shape carried on a Workflow +// Task. Every stored field crosses over except the offset, which the slice +// carries as a range, so a reader in any language sees the record the producer +// wrote, kind and identity included. +func ToAPIRecords(in []*streamlib.StreamRecord) []*streampb.StreamRecord { + out := make([]*streampb.StreamRecord, 0, len(in)) + for _, m := range in { + out = append(out, &streampb.StreamRecord{ + Body: m.GetBody(), + Metadata: m.GetMetadata(), + Topic: m.GetTopic(), + Kind: m.GetKind(), + ProducerId: m.GetProducerId(), + Attempt: m.GetAttempt(), + Sequence: m.GetSequence(), + }) + } + return out +} + +// CapByBytes trims a contiguous run of records to a byte budget and returns +// the offset just past the last one kept. +// +// It always keeps the first record, however large. Dropping it would leave the +// cursor unable to advance, and since an unconsumed range schedules a workflow +// task, a stream holding one oversized record would wake the workflow forever +// without ever delivering anything. +func CapByBytes( + records []*streamlib.StreamRecord, + from int64, + maxBytes int, +) ([]*streamlib.StreamRecord, int64) { + if len(records) == 0 { + return records, from + } + + total := 0 + for i, m := range records { + total += proto.Size(m) + if total > maxBytes && i > 0 { + return records[:i], from + int64(i) + } + } + return records, from + int64(len(records)) +} + +// checkBatchBytes rejects an append that is too large to store or too large to +// ever hand back. +// +// The per-record bound matters on its own: a record is never split, so one +// that exceeds a consumer's byte budget can never be delivered, and CapByBytes +// would hand it over alone forever rather than reject it. The batch bound is +// the storage side, since a batch is written as a single node. +func checkBatchBytes(records []*streamlib.StreamRecord, limits Limits) error { + total := 0 + for i, m := range records { + size := proto.Size(m) + if size > limits.MaxMessageBytes { + return serviceerror.NewInvalidArgumentf( + "record %d is %d bytes, over the %d byte limit", i, size, limits.MaxMessageBytes) + } + total += size + } + if total > limits.MaxBatchBytes { + return serviceerror.NewInvalidArgumentf( + "batch is %d bytes, over the %d byte limit", total, limits.MaxBatchBytes) + } + return nil +} diff --git a/chasm/lib/stream/messages_test.go b/chasm/lib/stream/messages_test.go new file mode 100644 index 00000000000..ee7fd463a8c --- /dev/null +++ b/chasm/lib/stream/messages_test.go @@ -0,0 +1,91 @@ +package stream + +import ( + "testing" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + streampb "go.temporal.io/api/stream/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +func sized(n int, bytes int) []*streamlib.StreamRecord { + out := make([]*streamlib.StreamRecord, n) + for i := range out { + out[i] = &streamlib.StreamRecord{ + Body: &commonpb.Payload{Data: make([]byte, bytes)}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + } + } + return out +} + +func TestCapByBytesTrimsToAPrefix(t *testing.T) { + messages, next := CapByBytes(sized(10, 100), 4, 250) + require.Len(t, messages, 2) + require.Equal(t, int64(6), next, "the recorded range must cover exactly what was kept") +} + +func TestCapByBytesKeepsEverythingUnderBudget(t *testing.T) { + messages, next := CapByBytes(sized(3, 10), 0, 1<<20) + require.Len(t, messages, 3) + require.Equal(t, int64(3), next) +} + +// A single oversized message must still go out. Held back it would stall the +// cursor, and an unconsumed range schedules a workflow task, so the workflow +// would wake forever and never receive anything. +func TestCapByBytesAlwaysDeliversTheFirstMessage(t *testing.T) { + messages, next := CapByBytes(sized(3, 5000), 7, 10) + require.Len(t, messages, 1) + require.Equal(t, int64(8), next) +} + +func TestCapByBytesOnAnEmptyRun(t *testing.T) { + messages, next := CapByBytes(nil, 9, 100) + require.Empty(t, messages) + require.Equal(t, int64(9), next) +} + +// A reader in any language decodes the record the producer wrote, so every +// field the store holds has to come back on the Workflow Task, the kind and the +// producer identity included. A FINISH record is a record like any other to the +// consumer that reads it. +func TestToAPIRecordsCarriesTheRecordAsWritten(t *testing.T) { + stored := []*streamlib.StreamRecord{ + { + Body: &commonpb.Payload{Data: []byte("token")}, + Metadata: map[string]*commonpb.Payload{"model": {Data: []byte("m1")}}, + Topic: "tokens", + Kind: streampb.STREAM_RECORD_KIND_DATA, + ProducerId: "model-call", + Attempt: 2, + Sequence: 7, + Offset: 41, + }, + { + Topic: "tokens", + Kind: streampb.STREAM_RECORD_KIND_FINISH, + ProducerId: "model-call", + Attempt: 2, + Sequence: -1, + Offset: 42, + }, + } + + got := ToAPIRecords(stored) + require.Len(t, got, 2) + + require.Equal(t, "token", string(got[0].GetBody().GetData())) + require.Equal(t, "m1", string(got[0].GetMetadata()["model"].GetData())) + require.Equal(t, "tokens", got[0].GetTopic()) + require.Equal(t, streampb.STREAM_RECORD_KIND_DATA, got[0].GetKind()) + require.Equal(t, "model-call", got[0].GetProducerId()) + require.Equal(t, int64(2), got[0].GetAttempt()) + require.Equal(t, int64(7), got[0].GetSequence()) + + require.Equal(t, streampb.STREAM_RECORD_KIND_FINISH, got[1].GetKind()) + require.Nil(t, got[1].GetBody()) + require.Equal(t, "model-call", got[1].GetProducerId()) + require.Equal(t, int64(-1), got[1].GetSequence()) +} diff --git a/chasm/lib/stream/proto/v1/message.proto b/chasm/lib/stream/proto/v1/message.proto new file mode 100644 index 00000000000..d940f769789 --- /dev/null +++ b/chasm/lib/stream/proto/v1/message.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; + +package temporal.server.chasm.lib.stream.proto.v1; + +import "temporal/api/common/v1/message.proto"; +import "temporal/api/stream/v1/message.proto"; + +option go_package = "go.temporal.io/server/chasm/lib/stream/gen/streampb;streampb"; + +// The stored shape of temporal.api.stream.v1.StreamRecord plus the offset a +// read assigns. Field for field the public record, so one crosses the frontend +// in either direction without translation. +message StreamRecord { + temporal.api.common.v1.Payload body = 1; + // Producer-supplied provenance, stored as sent. + map metadata = 2; + string topic = 3; + // The producer's position within its attempt, or -1 when unnumbered. Stored + // as sent; the global offset is what orders the stream. + int64 sequence = 4; + // Settled to DATA on append when left unspecified, so a retry hashes the + // same bytes and a reader never sees the zero value. + temporal.api.stream.v1.StreamRecordKind kind = 5; + + // Position in the whole stream, set on read and never stored. A consumer + // that resumes at record granularity needs it, and a topic-filtered read + // leaves gaps that make it underivable from the response alone. + int64 offset = 6; + // Who wrote the record. Empty when the owning Workflow did: its publish + // command clears the field, whatever the worker sent. + string producer_id = 7; + // The producer's attempt, stored as sent. Readers treat a later attempt by + // the same producer as superseding what the earlier one wrote. + int64 attempt = 8; +} + +// One append is one batch, and one batch is one data node. The server stores +// this serialized and opaque; it decodes only to trim a partial first page or +// to apply a topic filter. +message StreamRecordBatch { + repeated StreamRecord records = 1; +} diff --git a/chasm/lib/stream/proto/v1/request_response.proto b/chasm/lib/stream/proto/v1/request_response.proto new file mode 100644 index 00000000000..66e5dadb63f --- /dev/null +++ b/chasm/lib/stream/proto/v1/request_response.proto @@ -0,0 +1,384 @@ +syntax = "proto3"; + +package temporal.server.chasm.lib.stream.proto.v1; + +import "chasm/lib/stream/proto/v1/message.proto"; +import "chasm/lib/stream/proto/v1/stream_state.proto"; +import "temporal/api/common/v1/message.proto"; + +option go_package = "go.temporal.io/server/chasm/lib/stream/gen/streampb;streampb"; + +// The frontend-facing shapes are defined here rather than in the public API +// because streams have no public API yet. Keeping them in a nested +// frontend_request mirrors the other CHASM libraries, so promoting them later +// is a package move rather than a redesign. + +message CreateStreamInput { + string namespace = 1; + string stream_id = 2; + StreamLifecycle lifecycle = 3; +} + +message CreateStreamOutput { + string run_id = 1; +} + +message AddMessagesInput { + string namespace = 1; + string stream_id = 2; + // Optional. Supplying it skips resolving the stream's current run, which is + // a persistence lookup on every call. CreateStream returns it. + string run_id = 9; + repeated StreamRecord records = 3; + + // Idempotency, all optional. Supply a producer identity and sequence, or an + // expected offset, or neither and accept at-least-once. + string producer_id = 4; + int64 sequence = 5; + // Guarded by use_expected_offset because proto3 optional is not supported + // by this repo's helper generator. + int64 expected_offset = 6; + bool use_expected_offset = 8; + + reserved 7; +} + +message AddMessagesOutput { + int64 first_offset = 1; + int64 next_offset = 2; + int64 count = 3; + // True when a retry matched a recorded sequence and nothing was appended. + bool deduplicated = 4; +} + +message FinishWritingInput { + string namespace = 1; + string stream_id = 2; + string producer_id = 3; +} + +message FinishWritingOutput {} + +// Registers a Workflow as a consumer of a stream it owns. The cursor lands in +// the Workflow's own state, so from then on each of its Workflow Tasks carries +// the next range and records what it consumed. +message SubscribeWorkflowInput { + string namespace = 1; + string workflow_id = 2; + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + string owner_run_id = 6; + + // Name of the stream within the Workflow, for a stream it owns. + string stream_name = 3; + // Id of a standalone stream in another execution. Exactly one of this and + // stream_name is set. + string stream_id = 5; + // Where to start. Resolved here rather than at delivery, so the first + // recorded range starts from a fact instead of a reading. + int64 start_offset = 4; +} + +message SubscribeWorkflowOutput { + int64 start_offset = 1; +} + +message PollMessagesInput { + string namespace = 1; + string stream_id = 2; + // Optional, as on AddMessagesInput. + string run_id = 7; + int64 from_offset = 3; + int32 max_messages = 4; + // Filters by exact topic. Offsets are assigned over the unfiltered stream, so + // next_offset advances past filtered-out records too. + repeated string topics = 5; + + // When set and the reader is caught up, block until something arrives, the + // stream closes, or the server's long-poll timeout elapses. A timeout returns + // an empty response rather than an error, so the caller simply polls again. + bool wait_new_messages = 6; +} + +message PollMessagesOutput { + repeated StreamRecord records = 1; + int64 next_offset = 2; + int64 head_offset = 3; + bool closed = 4; + temporal.api.common.v1.Payload close_reason = 5; + // The execution holding the stream. A workflow task slice built from this + // read names the run it came from. + string run_id = 6; +} + +message DescribeStreamInput { + string namespace = 1; + string stream_id = 2; +} + +// A stream a workflow owns lives inside that workflow's execution, so it has +// no standalone id to address it by. It is named by its owner and its name +// instead, and routed on the owner. +message PollWorkflowMessagesInput { + string namespace = 1; + string workflow_id = 2; + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + string owner_run_id = 8; + + // Empty means the workflow's default output stream. + string stream_name = 3; + int64 from_offset = 4; + int32 max_messages = 5; + // Filters as on PollMessagesInput. + repeated string topics = 6; + bool wait_new_messages = 7; +} + +message DescribeWorkflowStreamInput { + string namespace = 1; + string workflow_id = 2; + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + string owner_run_id = 4; + + string stream_name = 3; +} + +// Appending to a stream a workflow owns, from outside that workflow. The +// workflow's own publishes ride its Workflow Task instead. +message AddWorkflowMessagesInput { + string namespace = 1; + string workflow_id = 2; + // Optional. Pins to one run, so a caller that has continued as new is not + // silently redirected to the successor's stream, which starts empty and at + // offset zero. Empty means whichever run is current. + string owner_run_id = 7; + + // Empty means the workflow's default output stream. + string stream_name = 3; + repeated StreamRecord records = 4; + // Optional idempotency, as on AddMessagesInput. + string producer_id = 5; + int64 sequence = 6; +} + +message DescribeStreamOutput { + StreamState state = 1; +} + +message CloseStreamInput { + string namespace = 1; + string stream_id = 2; + temporal.api.common.v1.Payload reason = 3; +} + +message CloseStreamOutput {} + +message TruncateStreamInput { + string namespace = 1; + string stream_id = 2; + int64 new_base_offset = 3; +} + +message TruncateStreamOutput {} + +message DeleteStreamInput { + string namespace = 1; + string stream_id = 2; + // Delete even while a workflow consumer is active. Without it the call is + // refused, because the consumer's History depends on ranges the deletion + // takes with it. + bool force = 3; +} + +message DeleteStreamOutput {} + +message CreateStreamRequest { + string namespace_id = 1; + CreateStreamInput frontend_request = 2; +} +message CreateStreamResponse { + CreateStreamOutput frontend_response = 1; +} + +message AddMessagesRequest { + string namespace_id = 1; + AddMessagesInput frontend_request = 2; +} +message AddMessagesResponse { + AddMessagesOutput frontend_response = 1; +} + +message FinishWritingRequest { + string namespace_id = 1; + FinishWritingInput frontend_request = 2; +} +message FinishWritingResponse { + FinishWritingOutput frontend_response = 1; +} + +message SubscribeWorkflowRequest { + string namespace_id = 1; + SubscribeWorkflowInput frontend_request = 2; +} +message SubscribeWorkflowResponse { + SubscribeWorkflowOutput frontend_response = 1; +} + +message PollMessagesRequest { + string namespace_id = 1; + PollMessagesInput frontend_request = 2; +} +message PollMessagesResponse { + PollMessagesOutput frontend_response = 1; +} + +message DescribeStreamRequest { + string namespace_id = 1; + DescribeStreamInput frontend_request = 2; +} +message DescribeStreamResponse { + DescribeStreamOutput frontend_response = 1; +} + +message PollWorkflowMessagesRequest { + string namespace_id = 1; + PollWorkflowMessagesInput frontend_request = 2; +} +message PollWorkflowMessagesResponse { + PollMessagesOutput frontend_response = 1; +} + +message DescribeWorkflowStreamRequest { + string namespace_id = 1; + DescribeWorkflowStreamInput frontend_request = 2; +} +message DescribeWorkflowStreamResponse { + DescribeStreamOutput frontend_response = 1; +} + +// Registering a consumer on a stream in another execution. Split out from +// SubscribeWorkflow because the two halves live on different shards: the pin +// goes on the stream, the cursor goes on the consuming workflow, and a handler +// can only reach the shard it was routed to. +message RegisterStreamConsumerInput { + string namespace = 1; + string stream_id = 2; + // The workflow that will consume. Together with the run it names the pin, + // so a later run of the same workflow id registers fresh rather than + // inheriting a closed run's floor. + string consumer_workflow_id = 3; + string consumer_run_id = 5; + // Negative means from wherever the stream is when the pin is taken. Resolved + // here, where the frontier is, and returned so the cursor records a fact. + int64 start_offset = 4; +} + +message RegisterStreamConsumerOutput { + reserved 2, 3; + + int64 start_offset = 1; + // The frontier at registration, so the cursor starts with a known head + // instead of waiting for the first push. + int64 known_head = 4; +} + +// Telling one consumer that the frontier moved. Routed to the consumer, which +// is not where the stream lives. +message AdvanceConsumerHeadInput { + string namespace = 1; + string workflow_id = 2; + // The run that subscribed. A successor from continue-as-new holds no cursor + // for this stream, so pushing the frontier at it would land nowhere. + string owner_run_id = 5; + string stream_id = 3; + int64 head_offset = 4; +} + +message AdvanceConsumerHeadOutput { + // The run that held the pin is closed and no current run of the workflow + // consumes the stream, so the stream can release the pin. + bool consumer_closed = 1; + // The run that held the pin is closed but a successor carries the + // subscription, so the stream re-keys the pin to it, with the floor the + // successor's cursor started from. + string successor_run_id = 2; + int64 successor_start_offset = 3; +} + +message AddWorkflowMessagesRequest { + string namespace_id = 1; + AddWorkflowMessagesInput frontend_request = 2; +} +message AddWorkflowMessagesResponse { + AddMessagesOutput frontend_response = 1; +} + +message RegisterStreamConsumerRequest { + string namespace_id = 1; + RegisterStreamConsumerInput frontend_request = 2; +} +message RegisterStreamConsumerResponse { + RegisterStreamConsumerOutput frontend_response = 1; +} + +message AdvanceConsumerHeadRequest { + string namespace_id = 1; + AdvanceConsumerHeadInput frontend_request = 2; +} +message AdvanceConsumerHeadResponse { + AdvanceConsumerHeadOutput frontend_response = 1; +} + +message CloseStreamRequest { + string namespace_id = 1; + CloseStreamInput frontend_request = 2; +} +message CloseStreamResponse { + CloseStreamOutput frontend_response = 1; +} + +message TruncateStreamRequest { + string namespace_id = 1; + TruncateStreamInput frontend_request = 2; +} +message TruncateStreamResponse { + TruncateStreamOutput frontend_response = 1; +} + +message ListStreamsInput { + string namespace = 1; + int32 page_size = 2; + bytes next_page_token = 3; + string query = 4; +} + +message StreamListEntry { + string stream_id = 1; + string run_id = 2; +} + +message ListStreamsOutput { + repeated StreamListEntry streams = 1; + bytes next_page_token = 2; +} + +message ListStreamsRequest { + string namespace_id = 1; + ListStreamsInput frontend_request = 2; +} +message ListStreamsResponse { + ListStreamsOutput frontend_response = 1; +} + +message DeleteStreamRequest { + string namespace_id = 1; + DeleteStreamInput frontend_request = 2; +} +message DeleteStreamResponse { + DeleteStreamOutput frontend_response = 1; +} diff --git a/chasm/lib/stream/proto/v1/service.proto b/chasm/lib/stream/proto/v1/service.proto new file mode 100644 index 00000000000..bdd0a918551 --- /dev/null +++ b/chasm/lib/stream/proto/v1/service.proto @@ -0,0 +1,92 @@ +syntax = "proto3"; + +package temporal.server.chasm.lib.stream.proto.v1; + +import "chasm/lib/stream/proto/v1/request_response.proto"; +import "temporal/server/api/common/v1/api_category.proto"; +import "temporal/server/api/routing/v1/extension.proto"; + +option go_package = "go.temporal.io/server/chasm/lib/stream/gen/streampb;streampb"; + +service StreamService { + rpc CreateStream(CreateStreamRequest) returns (CreateStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc AddMessages(AddMessagesRequest) returns (AddMessagesResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc FinishWriting(FinishWritingRequest) returns (FinishWritingResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc SubscribeWorkflow(SubscribeWorkflowRequest) returns (SubscribeWorkflowResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.workflow_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc PollMessages(PollMessagesRequest) returns (PollMessagesResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_LONG_POLL; + } + + rpc DescribeStream(DescribeStreamRequest) returns (DescribeStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + // Routed on the owner, because the stream it reads has no id of its own. + rpc PollWorkflowMessages(PollWorkflowMessagesRequest) returns (PollWorkflowMessagesResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.workflow_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_LONG_POLL; + } + + rpc DescribeWorkflowStream(DescribeWorkflowStreamRequest) returns (DescribeWorkflowStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.workflow_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc AddWorkflowMessages(AddWorkflowMessagesRequest) returns (AddWorkflowMessagesResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.workflow_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + // Internal. History calls these on itself to reach a shard it does not own, + // which is the only way a step that spans two executions can work on a + // cluster with more than one history host. + rpc RegisterStreamConsumer(RegisterStreamConsumerRequest) returns (RegisterStreamConsumerResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc AdvanceConsumerHead(AdvanceConsumerHeadRequest) returns (AdvanceConsumerHeadResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.workflow_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc CloseStream(CloseStreamRequest) returns (CloseStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc TruncateStream(TruncateStreamRequest) returns (TruncateStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + // Served on the frontend only: it queries visibility rather than a stream, + // so there is no business ID to route on and nothing for a shard to answer. + rpc ListStreams(ListStreamsRequest) returns (ListStreamsResponse) { + option (temporal.server.api.routing.v1.routing).random = true; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + + rpc DeleteStream(DeleteStreamRequest) returns (DeleteStreamResponse) { + option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.stream_id"; + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } +} diff --git a/chasm/lib/stream/proto/v1/stream_state.proto b/chasm/lib/stream/proto/v1/stream_state.proto new file mode 100644 index 00000000000..2ea9beaec59 --- /dev/null +++ b/chasm/lib/stream/proto/v1/stream_state.proto @@ -0,0 +1,136 @@ +syntax = "proto3"; + +package temporal.server.chasm.lib.stream.proto.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "temporal/api/common/v1/message.proto"; + +option go_package = "go.temporal.io/server/chasm/lib/stream/gen/streampb;streampb"; + +// Size is O(producers + consumers), never O(messages). Payload bytes live in +// the component's data nodes, not here, which keeps this off the CHASM +// partial-read path. +message StreamState { + // Field numbers of removed fields, kept out of reuse so an old blob never + // decodes into a field with a different meaning. + reserved 3, 6, 7, 8; + + // Visibility frontier. Readers never observe an offset at or past this. + int64 head_offset = 1; + // Truncation floor. Offsets below this are gone. + int64 base_offset = 2; + + bool closed = 4; + temporal.api.common.v1.Payload close_reason = 5; + + map producers = 9; + map consumers = 10; + + StreamLifecycle lifecycle = 11; + + // Set when a successor run takes ownership, so an in-flight poll can follow + // the chain instead of stalling on a superseded run. + string redirect_run_id = 12; + + // Wall-clock close time, used to schedule retention deletion. + google.protobuf.Timestamp close_time = 13; + + // Set on a stream a workflow owns. Its batches are the owning execution's + // mutable state, so appends past the budget are refused rather than left to + // the execution size limit, which terminates the workflow. + StreamBudget budget = 14; + + // Bytes appended over the stream's life, kept for the budget check. A stream + // with a budget never reclaims, so this is also what it holds. + int64 appended_bytes = 15; + + // A notify task is scheduled and has not run yet. Appends while it is set + // schedule none of their own; the task reads the head when it runs, so it + // carries every append that landed before it. + bool notify_pending = 16; +} + +// Hard bounds on what a stream may hold. Distinct from StreamLifecycle.max_items, +// which reclaims the oldest messages: a budget refuses the newest. +message StreamBudget { + int64 max_items = 1; + int64 max_bytes = 2; +} + +message ProducerCursor { + int64 seq = 1; + int64 first_offset = 2; + int64 count = 3; + // Distinguishes a genuine retry from a client reusing a sequence with + // different content, which must be rejected rather than deduplicated. + bytes content_hash = 4; + // Set by FinishWriting. Ends this producer's writes without closing the + // stream for anyone else. + bool fenced = 5; +} + +message ConsumerCursor { + string workflow_id = 1; + string run_id = 2; + // How far this consumer has read. Used to decide whether it needs waking, + // not to decide what the stream may drop. + int64 offset = 3; + bool active = 4; + // Set when the consumer is a workflow in another execution, which is the + // only case that has to be told the frontier moved. A workflow consuming a + // stream it owns sees that while closing its own transaction. + bool external = 5; + // The oldest offset this consumer's History still depends on. + // + // It is where the subscription started, not where it has read to. A range + // this consumer already consumed is recorded in its History and has to be + // re-readable for the workflow to replay, so bytes below the read position + // are exactly the ones a replay needs most. It stays put while the consumer + // is active and is released when it deregisters. + int64 replay_floor = 6; +} + +// A consuming Workflow's position in a stream. This lives in the consuming +// Workflow's own state rather than on the stream, so advancing it commits in +// the same transaction as the WorkflowTaskCompleted event that records the +// range. Keeping it on the stream would make the advance a cross-execution +// write, and a crash between the two would either redeliver or skip. +message WorkflowStreamCursor { + reserved 2, 3; + + string stream_id = 1; + + // Next offset to deliver. + int64 offset = 4; + + // The stream's frontier as of the last delivery. A workflow consuming a + // stream in another execution cannot read the real frontier while closing its + // own transaction, so this is what tells it a capped slice left more behind. + int64 known_head = 8; + + // Set when the stream lives in another execution, which decides whether the + // frontier is read locally or taken from known_head. + bool external = 9; + + // The range attached to the Workflow Task currently in flight. Recorded on + // the event that closes that task, then folded into offset. An empty range + // is still recorded: a task where the subscription saw nothing is a fact + // replay has to reproduce. + int64 pending_from = 5; + int64 pending_to = 6; + bool has_pending = 7; + + // Where this subscription began reading. Retained separately from offset, + // which advances, because replay has to tell "committed nothing yet" apart + // from "the events recording what was committed are not in this page". + int64 start_offset = 10; +} + +message StreamLifecycle { + // How long a closed stream stays readable before it is deleted. + google.protobuf.Duration retention = 1; + // Cap on readable messages. Whole batches are reclaimed once the floor + // passes them, so a capped stream has bounded storage. + int64 max_items = 2; +} diff --git a/chasm/lib/stream/proto/v1/tasks.proto b/chasm/lib/stream/proto/v1/tasks.proto new file mode 100644 index 00000000000..c4b8e5e6c6a --- /dev/null +++ b/chasm/lib/stream/proto/v1/tasks.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package temporal.server.chasm.lib.stream.proto.v1; + +option go_package = "go.temporal.io/server/chasm/lib/stream/gen/streampb;streampb"; + +// Fires at close_time plus retention. A closed stream stays readable until +// then, which is what removes the shutdown handshake the signal-based +// implementation forces on producers and consumers. +message StreamRetentionTask {} + +// Fires after an append that leaves a registered consumer behind. Appending +// never schedules a workflow task on its own, because a stream item is data an +// execution produced rather than a decision input to it. A workflow that +// subscribed is the exception: it asked to be told, and it cannot find out any +// other way, since nothing else it does would notice the stream moved. +message StreamNotifyConsumersTask {} diff --git a/chasm/lib/stream/service/events.go b/chasm/lib/stream/service/events.go new file mode 100644 index 00000000000..d496181ee3a --- /dev/null +++ b/chasm/lib/stream/service/events.go @@ -0,0 +1,78 @@ +package service + +import ( + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + "go.temporal.io/server/service/history/hsm" +) + +// streamSubscribedEventDefinition tells the history service how to treat the +// event a subscribe command writes. +// +// It applies nothing. The cursor lives in CHASM state, which is persisted and +// rebuilt with the execution, so replication and reset have nothing to +// reconstruct from the event. It exists so the command has an event at all: +// every SDK matches issued commands against command-generated events in order, +// and a command producing none puts that matching out of step. +type streamSubscribedEventDefinition struct{} + +func (streamSubscribedEventDefinition) Type() enumspb.EventType { + return enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED +} + +// Subscribing does not itself give the workflow anything to decide on. The +// range that follows does, and that wakes the workflow through its cursor. +func (streamSubscribedEventDefinition) IsWorkflowTaskTrigger() bool { return false } + +func (streamSubscribedEventDefinition) Apply(*hsm.Node, *historypb.HistoryEvent) error { + return nil +} + +// A command event, so never reapplied onto another branch: a workflow that +// still wants the subscription issues the command again on the new one. +func (streamSubscribedEventDefinition) CherryPick( + *hsm.Node, + *historypb.HistoryEvent, + map[enumspb.ResetReapplyExcludeType]struct{}, +) error { + return hsm.ErrNotCherryPickable +} + +// streamRecordsAppendedEventDefinition tells the history service how to treat +// the event a publish command writes. +// +// Like the subscription event it applies nothing: the stream's frontier is +// CHASM state committed with the workflow task, and the bodies are in the +// stream component. What the event carries is the offset range, which is what +// lets anyone reading History find the batch without History having held it. +type streamRecordsAppendedEventDefinition struct{} + +func (streamRecordsAppendedEventDefinition) Type() enumspb.EventType { + return enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED +} + +// A workflow publishing to its own stream has nothing to be woken about. +func (streamRecordsAppendedEventDefinition) IsWorkflowTaskTrigger() bool { return false } + +func (streamRecordsAppendedEventDefinition) Apply(*hsm.Node, *historypb.HistoryEvent) error { + return nil +} + +// A command event, so never reapplied onto another branch. Reapplying would +// claim offsets in a log the new branch never wrote to. +func (streamRecordsAppendedEventDefinition) CherryPick( + *hsm.Node, + *historypb.HistoryEvent, + map[enumspb.ResetReapplyExcludeType]struct{}, +) error { + return hsm.ErrNotCherryPickable +} + +// RegisterEventDefinitions makes the stream events known to the history +// service. +func RegisterEventDefinitions(reg *hsm.Registry) error { + if err := reg.RegisterEventDefinition(streamSubscribedEventDefinition{}); err != nil { + return err + } + return reg.RegisterEventDefinition(streamRecordsAppendedEventDefinition{}) +} diff --git a/chasm/lib/stream/service/frontend.go b/chasm/lib/stream/service/frontend.go new file mode 100644 index 00000000000..431ae37ec06 --- /dev/null +++ b/chasm/lib/stream/service/frontend.go @@ -0,0 +1,389 @@ +package service + +import ( + "context" + + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/log" + "go.temporal.io/server/common/namespace" + "google.golang.org/protobuf/types/known/emptypb" +) + +// FrontendHandler serves StreamService on the frontend. It resolves the +// namespace name to an ID, checks what can be checked without the stream, and +// forwards to the history shard that owns the stream; the layered client does +// the routing from the business ID. +// +// The checks are the ones the workflow handler makes for its own ids. A stream +// id becomes an execution's business id and a stream name a key in mutable +// state, so neither may be longer than an id is allowed to be, and an offset +// or page size that history would only clamp or refuse later is refused here +// before the request is routed. +type FrontendHandler struct { + streampb.UnimplementedStreamServiceServer + + client streampb.StreamServiceClient + namespaceRegistry namespace.Registry + logger log.Logger + config *stream.Config +} + +func NewFrontendHandler( + client streampb.StreamServiceClient, + namespaceRegistry namespace.Registry, + logger log.Logger, + config *stream.Config, +) *FrontendHandler { + return &FrontendHandler{ + client: client, + namespaceRegistry: namespaceRegistry, + logger: logger, + config: config, + } +} + +// RedirectableMethods lists the stream RPCs a cell forwards to the namespace's +// active cell when it is not that cell itself, each with the response it +// answers with, for the redirection interceptor. +// +// The stream lives in the active cell's mutable state, so a call served where +// it happens to land would write to a copy nothing reads or read one that +// stops at the last replication. The two calls History makes on itself are not +// listed: they never reach a frontend legitimately, and this handler answers +// them with Unimplemented wherever they land. +func RedirectableMethods() map[string]func() any { + return map[string]func() any{ + streampb.StreamService_CreateStream_FullMethodName: func() any { + return &streampb.CreateStreamResponse{} + }, + streampb.StreamService_AddMessages_FullMethodName: func() any { + return &streampb.AddMessagesResponse{} + }, + streampb.StreamService_FinishWriting_FullMethodName: func() any { + return &streampb.FinishWritingResponse{} + }, + streampb.StreamService_SubscribeWorkflow_FullMethodName: func() any { + return &streampb.SubscribeWorkflowResponse{} + }, + streampb.StreamService_PollMessages_FullMethodName: func() any { + return &streampb.PollMessagesResponse{} + }, + streampb.StreamService_DescribeStream_FullMethodName: func() any { + return &streampb.DescribeStreamResponse{} + }, + streampb.StreamService_PollWorkflowMessages_FullMethodName: func() any { + return &streampb.PollWorkflowMessagesResponse{} + }, + streampb.StreamService_DescribeWorkflowStream_FullMethodName: func() any { + return &streampb.DescribeWorkflowStreamResponse{} + }, + streampb.StreamService_AddWorkflowMessages_FullMethodName: func() any { + return &streampb.AddWorkflowMessagesResponse{} + }, + streampb.StreamService_CloseStream_FullMethodName: func() any { + return &streampb.CloseStreamResponse{} + }, + streampb.StreamService_TruncateStream_FullMethodName: func() any { + return &streampb.TruncateStreamResponse{} + }, + streampb.StreamService_ListStreams_FullMethodName: func() any { + return &streampb.ListStreamsResponse{} + }, + streampb.StreamService_DeleteStream_FullMethodName: func() any { + return &streampb.DeleteStreamResponse{} + }, + } +} + +func (h *FrontendHandler) namespaceID(name string) (string, error) { + if name == "" { + return "", serviceerror.NewInvalidArgument("namespace is required") + } + id, err := h.namespaceRegistry.GetNamespaceID(namespace.Name(name)) + if err != nil { + return "", err + } + return id.String(), nil +} + +// checkID refuses an id or name longer than the namespace's id limit. Empty is +// allowed here: some fields mean the default when empty and the ones that do +// not are checked by their handler. +func (h *FrontendHandler) checkID(field, value string) error { + if len(value) > h.config.MaxIDLength() { + return serviceerror.NewInvalidArgumentf( + "%s is %d characters, over the %d limit", field, len(value), h.config.MaxIDLength()) + } + return nil +} + +func checkOffset(field string, value int64) error { + if value < 0 { + return serviceerror.NewInvalidArgumentf("%s cannot be negative, got %d", field, value) + } + return nil +} + +// clampMaxMessages bounds a page the way the history side does, so a caller +// asking for more sees the same page size it would have been given anyway. +func clampMaxMessages(requested int32) int32 { + if requested <= 0 || requested > stream.DefaultMaxMessagesPerPoll { + return stream.DefaultMaxMessagesPerPoll + } + return requested +} + +func (h *FrontendHandler) CreateStream( + ctx context.Context, req *streampb.CreateStreamRequest, +) (*streampb.CreateStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if in.GetStreamId() == "" { + return nil, serviceerror.NewInvalidArgument("stream id is required") + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.CreateStream(ctx, &streampb.CreateStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) AddMessages( + ctx context.Context, req *streampb.AddMessagesRequest, +) (*streampb.AddMessagesResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.AddMessages(ctx, &streampb.AddMessagesRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) FinishWriting( + ctx context.Context, req *streampb.FinishWritingRequest, +) (*streampb.FinishWritingResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.FinishWriting(ctx, &streampb.FinishWritingRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) SubscribeWorkflow( + ctx context.Context, req *streampb.SubscribeWorkflowRequest, +) (*streampb.SubscribeWorkflowResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + if err := h.checkID("stream name", in.GetStreamName()); err != nil { + return nil, err + } + return h.client.SubscribeWorkflow(ctx, &streampb.SubscribeWorkflowRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) PollMessages( + ctx context.Context, req *streampb.PollMessagesRequest, +) (*streampb.PollMessagesResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + if err := checkOffset("from offset", in.GetFromOffset()); err != nil { + return nil, err + } + in.MaxMessages = clampMaxMessages(in.GetMaxMessages()) + return h.client.PollMessages(ctx, &streampb.PollMessagesRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) PollWorkflowMessages( + ctx context.Context, req *streampb.PollWorkflowMessagesRequest, +) (*streampb.PollWorkflowMessagesResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream name", in.GetStreamName()); err != nil { + return nil, err + } + if err := checkOffset("from offset", in.GetFromOffset()); err != nil { + return nil, err + } + in.MaxMessages = clampMaxMessages(in.GetMaxMessages()) + return h.client.PollWorkflowMessages(ctx, &streampb.PollWorkflowMessagesRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) DescribeWorkflowStream( + ctx context.Context, req *streampb.DescribeWorkflowStreamRequest, +) (*streampb.DescribeWorkflowStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream name", in.GetStreamName()); err != nil { + return nil, err + } + return h.client.DescribeWorkflowStream(ctx, &streampb.DescribeWorkflowStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) AddWorkflowMessages( + ctx context.Context, req *streampb.AddWorkflowMessagesRequest, +) (*streampb.AddWorkflowMessagesResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream name", in.GetStreamName()); err != nil { + return nil, err + } + return h.client.AddWorkflowMessages(ctx, &streampb.AddWorkflowMessagesRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) DescribeStream( + ctx context.Context, req *streampb.DescribeStreamRequest, +) (*streampb.DescribeStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.DescribeStream(ctx, &streampb.DescribeStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) CloseStream( + ctx context.Context, req *streampb.CloseStreamRequest, +) (*streampb.CloseStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.CloseStream(ctx, &streampb.CloseStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) TruncateStream( + ctx context.Context, req *streampb.TruncateStreamRequest, +) (*streampb.TruncateStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + if err := checkOffset("new base offset", in.GetNewBaseOffset()); err != nil { + return nil, err + } + return h.client.TruncateStream(ctx, &streampb.TruncateStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +func (h *FrontendHandler) DeleteStream( + ctx context.Context, req *streampb.DeleteStreamRequest, +) (*streampb.DeleteStreamResponse, error) { + in := req.GetFrontendRequest() + id, err := h.namespaceID(in.GetNamespace()) + if err != nil { + return nil, err + } + if err := h.checkID("stream id", in.GetStreamId()); err != nil { + return nil, err + } + return h.client.DeleteStream(ctx, &streampb.DeleteStreamRequest{ + NamespaceId: id, FrontendRequest: in, + }) +} + +// ListStreams answers from visibility rather than from any one stream, so it +// does not route to a shard and is served here rather than on the history side. +func (h *FrontendHandler) ListStreams( + ctx context.Context, req *streampb.ListStreamsRequest, +) (*streampb.ListStreamsResponse, error) { + in := req.GetFrontendRequest() + if in.GetNamespace() == "" { + return nil, serviceerror.NewInvalidArgument("namespace is required") + } + + pageSize := int(in.GetPageSize()) + if pageSize <= 0 || pageSize > stream.MaxListPageSize { + pageSize = stream.MaxListPageSize + } + + resp, err := chasm.ListExecutions[*stream.Stream, *emptypb.Empty]( + ctx, + &chasm.ListExecutionsRequest{ + NamespaceName: in.GetNamespace(), + PageSize: pageSize, + NextPageToken: in.GetNextPageToken(), + Query: in.GetQuery(), + }, + ) + if err != nil { + return nil, err + } + + entries := make([]*streampb.StreamListEntry, 0, len(resp.Executions)) + for _, e := range resp.Executions { + entries = append(entries, &streampb.StreamListEntry{ + StreamId: e.BusinessID, + RunId: e.RunID, + }) + } + return &streampb.ListStreamsResponse{ + FrontendResponse: &streampb.ListStreamsOutput{ + Streams: entries, + NextPageToken: resp.NextPageToken, + }, + }, nil +} diff --git a/chasm/lib/stream/service/frontend_test.go b/chasm/lib/stream/service/frontend_test.go new file mode 100644 index 00000000000..b861176fc80 --- /dev/null +++ b/chasm/lib/stream/service/frontend_test.go @@ -0,0 +1,95 @@ +package service + +import ( + "context" + "strings" + "testing" + + "github.com/stretchr/testify/require" + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm/lib/stream" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/dynamicconfig" + "go.temporal.io/server/common/log" + "go.temporal.io/server/common/namespace" + "go.uber.org/mock/gomock" + "google.golang.org/grpc" +) + +// recordingClient captures what the frontend forwards, so a test can check +// what history would have been asked without a history service. +type recordingClient struct { + streampb.StreamServiceClient + polls []*streampb.PollMessagesRequest + truncates []*streampb.TruncateStreamRequest +} + +func (c *recordingClient) PollMessages( + _ context.Context, req *streampb.PollMessagesRequest, _ ...grpc.CallOption, +) (*streampb.PollMessagesResponse, error) { + c.polls = append(c.polls, req) + return &streampb.PollMessagesResponse{}, nil +} + +func (c *recordingClient) TruncateStream( + _ context.Context, req *streampb.TruncateStreamRequest, _ ...grpc.CallOption, +) (*streampb.TruncateStreamResponse, error) { + c.truncates = append(c.truncates, req) + return &streampb.TruncateStreamResponse{}, nil +} + +func newTestFrontend(t *testing.T, maxIDLength int) (*FrontendHandler, *recordingClient) { + t.Helper() + registry := namespace.NewMockRegistry(gomock.NewController(t)) + registry.EXPECT().GetNamespaceID(namespace.Name("ns")).Return(namespace.ID("ns-id"), nil).AnyTimes() + client := &recordingClient{} + config := &stream.Config{MaxIDLength: dynamicconfig.GetIntPropertyFn(maxIDLength)} + return NewFrontendHandler(client, registry, log.NewNoopLogger(), config), client +} + +// The checks the workflow handler makes for its own ids, made here for stream +// ids and names before a request is routed. +func TestFrontendRefusesWhatHistoryWouldOnlyDiscoverLater(t *testing.T) { + h, client := newTestFrontend(t, 16) + ctx := context.Background() + var invalid *serviceerror.InvalidArgument + + _, err := h.CreateStream(ctx, &streampb.CreateStreamRequest{ + FrontendRequest: &streampb.CreateStreamInput{Namespace: "ns", StreamId: strings.Repeat("x", 17)}, + }) + require.ErrorAs(t, err, &invalid, "a stream id becomes a business id and is bounded like one") + + _, err = h.PollWorkflowMessages(ctx, &streampb.PollWorkflowMessagesRequest{ + FrontendRequest: &streampb.PollWorkflowMessagesInput{ + Namespace: "ns", WorkflowId: "wf", StreamName: strings.Repeat("n", 17), + }, + }) + require.ErrorAs(t, err, &invalid, "a stream name becomes a state key and is bounded the same way") + + _, err = h.PollMessages(ctx, &streampb.PollMessagesRequest{ + FrontendRequest: &streampb.PollMessagesInput{Namespace: "ns", StreamId: "s", FromOffset: -1}, + }) + require.ErrorAs(t, err, &invalid) + + _, err = h.TruncateStream(ctx, &streampb.TruncateStreamRequest{ + FrontendRequest: &streampb.TruncateStreamInput{Namespace: "ns", StreamId: "s", NewBaseOffset: -5}, + }) + require.ErrorAs(t, err, &invalid) + require.Empty(t, client.polls) + require.Empty(t, client.truncates, "a refused request is never routed") +} + +// A page larger than the server serves is clamped before routing, so the +// caller sees the same page it would have been given anyway. +func TestFrontendClampsThePageSize(t *testing.T) { + h, client := newTestFrontend(t, 1000) + _, err := h.PollMessages(context.Background(), &streampb.PollMessagesRequest{ + FrontendRequest: &streampb.PollMessagesInput{ + Namespace: "ns", StreamId: "s", MaxMessages: stream.DefaultMaxMessagesPerPoll * 4, + }, + }) + require.NoError(t, err) + require.Len(t, client.polls, 1) + require.Equal(t, "ns-id", client.polls[0].GetNamespaceId()) + require.EqualValues(t, stream.DefaultMaxMessagesPerPoll, client.polls[0].GetFrontendRequest().GetMaxMessages()) +} diff --git a/chasm/lib/stream/service/fx.go b/chasm/lib/stream/service/fx.go new file mode 100644 index 00000000000..b8592129f53 --- /dev/null +++ b/chasm/lib/stream/service/fx.go @@ -0,0 +1,36 @@ +package service + +import ( + "go.temporal.io/server/chasm" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.uber.org/fx" +) + +var HistoryModule = fx.Module( + "stream-history", + fx.Provide( + // Routes a call to the host owning a shard. History needs it too, not + // just the frontend: a step that spans two executions has to reach a + // shard this host may not own. The stream config comes from the + // workflow library module, which every service running this one has. + streampb.NewStreamServiceLayeredClient, + newHandler, + newRetentionTaskHandler, + newNotifyConsumersTaskHandler, + newLibrary, + ), + fx.Invoke(func(l *library, registry *chasm.Registry) error { + return registry.Register(l) + }), + fx.Invoke(RegisterEventDefinitions), +) + +var FrontendModule = fx.Module( + "stream-frontend", + fx.Provide(streampb.NewStreamServiceLayeredClient), + fx.Provide(NewFrontendHandler), + fx.Provide(newComponentOnlyLibrary), + fx.Invoke(func(l *componentOnlyLibrary, registry *chasm.Registry) error { + return registry.Register(l) + }), +) diff --git a/chasm/lib/stream/service/handler.go b/chasm/lib/stream/service/handler.go new file mode 100644 index 00000000000..2d716ce671c --- /dev/null +++ b/chasm/lib/stream/service/handler.go @@ -0,0 +1,900 @@ +package service + +import ( + "context" + "errors" + + commonpb "go.temporal.io/api/common/v1" + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common" + "go.temporal.io/server/common/contextutil" + "go.temporal.io/server/common/headers" + "go.temporal.io/server/common/log" + "go.temporal.io/server/common/namespace" + "go.temporal.io/server/service/history/shard" +) + +type handler struct { + streampb.UnimplementedStreamServiceServer + + shardController shard.Controller + namespaceRegistry namespace.Registry + logger log.Logger + config *stream.Config + + // Routes a call to the host that owns a shard. A step spanning two + // executions cannot resolve both through the local controller, which + // refuses a shard this host does not own, so the far half goes back out + // through the service and lands wherever it belongs. + routed streampb.StreamServiceClient +} + +func newHandler( + shardController shard.Controller, + namespaceRegistry namespace.Registry, + logger log.Logger, + config *stream.Config, + routed streampb.StreamServiceClient, +) *handler { + return &handler{ + shardController: shardController, + namespaceRegistry: namespaceRegistry, + logger: logger, + config: config, + routed: routed, + } +} + +// limitsFor resolves the namespace's limits. An id the registry cannot name +// falls back to the defaults; the interceptors have already refused requests +// for namespaces that do not exist. +func (h *handler) limitsFor(namespaceID string) stream.Limits { + name, err := h.namespaceRegistry.GetNamespaceName(namespace.ID(namespaceID)) + if err != nil { + return stream.DefaultLimits() + } + return h.config.LimitsFor(name.String()) +} + +// withCallerInfo tags the context so the stream's direct persistence calls are +// attributed to the namespace that caused them. Without it they carry no caller +// name, which means they escape namespace rate limiting and priority as well as +// going uncounted in per-namespace metrics. The RPC path sets this via +// interceptors; calls made outside a request handler have to set it themselves. +func (h *handler) withCallerInfo(ctx context.Context, namespaceID string) context.Context { + name, err := h.namespaceRegistry.GetNamespaceName(namespace.ID(namespaceID)) + if err != nil { + return ctx + } + return headers.SetCallerInfo(ctx, headers.NewCallerInfo( + name.String(), headers.CallerTypeAPI, "")) +} + +// refFor builds a reference to a stream. A supplied run ID lets the engine skip +// resolving the current run, which is otherwise a persistence lookup on every +// call and dominates the cost of an otherwise cheap read. +func refFor(namespaceID, streamID string) chasm.ComponentRef { + return refForRun(namespaceID, streamID, "") +} + +func refForRun(namespaceID, streamID, runID string) chasm.ComponentRef { + return chasm.NewComponentRef[*stream.Stream](chasm.ExecutionKey{ + NamespaceID: namespaceID, + BusinessID: streamID, + RunID: runID, + }) +} + +// workflowRef builds a reference to the execution that owns an attached +// stream. An attached stream is a subcomponent, so it has no id of its own and +// everything about it is reached through its owner. +// +// An empty runID means the current run. A caller that supplies one is pinning: +// an owned stream does not carry across continue-as-new, so the successor's +// stream of the same name is a different, empty one, and a caller that meant +// the predecessor would otherwise be redirected to it without being told. +func workflowRef(namespaceID, workflowID, runID string) chasm.ComponentRef { + return chasm.NewComponentRef[*chasmworkflow.Workflow](chasm.ExecutionKey{ + NamespaceID: namespaceID, + BusinessID: workflowID, + RunID: runID, + }) +} + +// ownedStreamName resolves a name the caller left empty the same way a publish +// command does, so a reader addresses the default stream by omission just as a +// writer creates it by omission. +func ownedStreamName(name string) string { + if name == "" { + return chasmworkflow.DefaultStreamName + } + return name +} + +func (h *handler) CreateStream( + ctx context.Context, + req *streampb.CreateStreamRequest, +) (*streampb.CreateStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + if in.GetStreamId() == "" { + return nil, serviceerror.NewInvalidArgument("stream id is required") + } + + result, err := chasm.StartExecution( + ctx, + chasm.ExecutionKey{NamespaceID: req.GetNamespaceId(), BusinessID: in.GetStreamId()}, + func(mctx chasm.MutableContext, input *streampb.CreateStreamInput) (*stream.Stream, error) { + return stream.NewStream(mctx, stream.NewStreamRequest{Lifecycle: input.GetLifecycle()}) + }, + in, + ) + if err != nil { + return nil, err + } + return &streampb.CreateStreamResponse{ + FrontendResponse: &streampb.CreateStreamOutput{RunId: result.ExecutionKey.RunID}, + }, nil +} + +func (h *handler) AddMessages( + ctx context.Context, + req *streampb.AddMessagesRequest, +) (*streampb.AddMessagesResponse, error) { + in := req.GetFrontendRequest() + if len(in.GetRecords()) == 0 { + return nil, serviceerror.NewInvalidArgument("no records to append") + } + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + // The batch and the frontier commit in one transition, and the execution + // serializes transitions, so a producer that names no expected offset takes + // whatever offset it lands at. A retried sequence is answered by the + // producer table, not by a pin on the head. + addReq := stream.AddMessagesRequest{ + Records: in.GetRecords(), + ProducerID: in.GetProducerId(), + Sequence: in.GetSequence(), + Limits: h.limitsFor(req.GetNamespaceId()), + } + if in.GetUseExpectedOffset() { + expected := in.GetExpectedOffset() + addReq.ExpectedOffset = &expected + } + + result, _, err := chasm.UpdateComponent(ctx, + refForRun(req.GetNamespaceId(), in.GetStreamId(), in.GetRunId()), + (*stream.Stream).AddMessages, addReq) + if err != nil { + return nil, err + } + + return &streampb.AddMessagesResponse{ + FrontendResponse: &streampb.AddMessagesOutput{ + FirstOffset: result.FirstOffset, + NextOffset: result.NextOffset, + Count: result.Count, + Deduplicated: result.Deduplicated, + }, + }, nil +} + +// AddWorkflowMessages appends to a stream a workflow owns, from outside that +// workflow. +// +// The workflow's own publishes ride its Workflow Task and cost no transition of +// their own. This producer is off-shard, so it pays one transition on the +// owning execution per batch, and batching is what keeps that cheap. It is the +// path a model activity streaming tokens takes, where the workflow is only +// bracketing what the activity produces. +// +// One transition does everything: the stream is created on first write, and +// the workflow's own publishes are serialized against this append by the +// execution, so neither producer needs to pin the head against the other. +func (h *handler) AddWorkflowMessages( + ctx context.Context, + req *streampb.AddWorkflowMessagesRequest, +) (*streampb.AddWorkflowMessagesResponse, error) { + in := req.GetFrontendRequest() + if len(in.GetRecords()) == 0 { + return nil, serviceerror.NewInvalidArgument("no records to append") + } + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + // The records go in as sent, producer identity included. Who is writing is + // the caller's claim to make; the store only answers whether it fits. + name := ownedStreamName(in.GetStreamName()) + addReq := stream.AddMessagesRequest{ + Records: in.GetRecords(), + ProducerID: in.GetProducerId(), + Sequence: in.GetSequence(), + Limits: h.limitsFor(req.GetNamespaceId()), + } + result, _, err := chasm.UpdateComponent(ctx, + workflowRef(req.GetNamespaceId(), in.GetWorkflowId(), in.GetOwnerRunId()), + func( + wf *chasmworkflow.Workflow, mctx chasm.MutableContext, r stream.AddMessagesRequest, + ) (stream.AddMessagesResult, error) { + return wf.AppendToOwnedStream(mctx, name, r) + }, addReq) + if err != nil { + return nil, err + } + + return &streampb.AddWorkflowMessagesResponse{ + FrontendResponse: &streampb.AddMessagesOutput{ + FirstOffset: result.FirstOffset, + NextOffset: result.NextOffset, + Count: result.Count, + Deduplicated: result.Deduplicated, + }, + }, nil +} + +func (h *handler) FinishWriting( + ctx context.Context, + req *streampb.FinishWritingRequest, +) (*streampb.FinishWritingResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + _, _, err := chasm.UpdateComponent( + ctx, + refFor(req.GetNamespaceId(), in.GetStreamId()), + func(s *stream.Stream, mctx chasm.MutableContext, producerID string) (struct{}, error) { + return struct{}{}, s.FinishWriting(mctx, producerID) + }, + in.GetProducerId(), + ) + if err != nil { + return nil, err + } + return &streampb.FinishWritingResponse{FrontendResponse: &streampb.FinishWritingOutput{}}, nil +} + +// SubscribeWorkflow registers a workflow as a consumer of a stream it owns. +// +// The cursor is written into the workflow's own state, not the stream's, which +// is what lets every later advance commit with the event that records it. Only +// a stream the workflow owns can be subscribed here: reaching one in another +// execution needs that stream's frontier, and reading it from inside the +// consuming workflow's transaction is a separate problem. +func (h *handler) SubscribeWorkflow( + ctx context.Context, + req *streampb.SubscribeWorkflowRequest, +) (*streampb.SubscribeWorkflowResponse, error) { + in := req.GetFrontendRequest() + + if in.GetStreamId() != "" { + return h.subscribeToExternalStream(ctx, req.GetNamespaceId(), in) + } + + limits := h.limitsFor(req.GetNamespaceId()) + startOffset, _, err := chasm.UpdateComponent( + ctx, + workflowRef(req.GetNamespaceId(), in.GetWorkflowId(), in.GetOwnerRunId()), + func( + wf *chasmworkflow.Workflow, mctx chasm.MutableContext, input *streampb.SubscribeWorkflowInput, + ) (int64, error) { + return wf.SubscribeToOwnedStream( + mctx, ownedStreamName(input.GetStreamName()), input.GetStartOffset(), limits) + }, + in, + ) + if err != nil { + return nil, err + } + + return &streampb.SubscribeWorkflowResponse{ + FrontendResponse: &streampb.SubscribeWorkflowOutput{StartOffset: startOffset}, + }, nil +} + +// subscribeToExternalStream registers a cursor against a stream in another +// execution. +// +// The pin goes on the stream before the cursor goes on the workflow, and the +// order is the guarantee: interrupted after the first write there is a pin +// holding storage nothing reads, which costs space. Interrupted after the +// other order there would be a cursor with no pin, and truncation would be free +// to take a range that cursor still points at. +func (h *handler) subscribeToExternalStream( + ctx context.Context, + namespaceID string, + in *streampb.SubscribeWorkflowInput, +) (*streampb.SubscribeWorkflowResponse, error) { + // The pin is keyed by the consuming run, so the run is resolved first. It + // also pins the cursor write below to that run, so a run that ends between + // the two steps cannot leave the pin on one run and the cursor on another. + consumerRunID, err := chasm.ReadComponent(ctx, + workflowRef(namespaceID, in.GetWorkflowId(), in.GetOwnerRunId()), + func(_ *chasmworkflow.Workflow, cctx chasm.Context, _ struct{}) (string, error) { + return cctx.ExecutionKey().RunID, nil + }, struct{}{}) + if err != nil { + return nil, err + } + + // The stream half goes out and comes back on the shard that owns it. This + // handler was routed to the consuming workflow, so the stream may well be + // somewhere else, and resolving it here would fail on any cluster with more + // than one history host. + // + // The pin still lands before the cursor, which is the guarantee: interrupted + // between them there is a pin holding storage nothing reads, which costs + // space, where the other order would leave a cursor with no pin and let + // truncation take a range it still points at. + registered, err := h.routed.RegisterStreamConsumer(ctx, &streampb.RegisterStreamConsumerRequest{ + NamespaceId: namespaceID, + FrontendRequest: &streampb.RegisterStreamConsumerInput{ + Namespace: in.GetNamespace(), + StreamId: in.GetStreamId(), + ConsumerWorkflowId: in.GetWorkflowId(), + ConsumerRunId: consumerRunID, + StartOffset: in.GetStartOffset(), + }, + }) + if err != nil { + return nil, err + } + pin := registered.GetFrontendResponse() + + startOffset, _, err := chasm.UpdateComponent( + ctx, + workflowRef(namespaceID, in.GetWorkflowId(), consumerRunID), + func(wf *chasmworkflow.Workflow, mctx chasm.MutableContext, offset int64) (int64, error) { + return wf.SubscribeToExternalStream(mctx, chasmworkflow.ExternalStreamSubscription{ + StreamID: in.GetStreamId(), + StartOffset: offset, + KnownHead: pin.GetKnownHead(), + }) + }, + pin.GetStartOffset(), + ) + if err != nil { + return nil, err + } + + return &streampb.SubscribeWorkflowResponse{ + FrontendResponse: &streampb.SubscribeWorkflowOutput{StartOffset: startOffset}, + }, nil +} + +// RegisterStreamConsumer takes the pin, on the shard that owns the stream. +// +// Internal. Called by SubscribeWorkflow and by the workflow task completion +// path, both of which run on the consumer's shard and so cannot reach the +// stream themselves. The start offset is resolved inside the transition that +// records it, against the same frontier it hands back, so the consumer records +// facts rather than readings. +func (h *handler) RegisterStreamConsumer( + ctx context.Context, + req *streampb.RegisterStreamConsumerRequest, +) (*streampb.RegisterStreamConsumerResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + limits := h.limitsFor(req.GetNamespaceId()) + pin, _, err := chasm.UpdateComponent( + ctx, + refFor(req.GetNamespaceId(), in.GetStreamId()), + func( + s *stream.Stream, mctx chasm.MutableContext, offset int64, + ) (*streampb.RegisterStreamConsumerOutput, error) { + startOffset, err := s.RegisterConsumer(mctx, stream.ConsumerRegistration{ + ConsumerID: externalConsumerID(in.GetConsumerWorkflowId(), in.GetConsumerRunId()), + WorkflowID: in.GetConsumerWorkflowId(), + RunID: in.GetConsumerRunId(), + Offset: offset, + External: true, + MaxConsumers: limits.MaxConsumersPerStream, + }) + if err != nil { + return nil, err + } + return &streampb.RegisterStreamConsumerOutput{ + StartOffset: startOffset, + KnownHead: s.State.GetHeadOffset(), + }, nil + }, + in.GetStartOffset(), + ) + if err != nil { + return nil, err + } + return &streampb.RegisterStreamConsumerResponse{FrontendResponse: pin}, nil +} + +// externalConsumerID names a workflow run's pin on a stream in another +// execution. Keyed by run, so a later run of the same workflow id registers +// fresh instead of inheriting a closed run's floor. +func externalConsumerID(workflowID, runID string) string { + return "workflow:" + workflowID + "/" + runID +} + +// consumerProbe is what one run says about a subscription: whether the run is +// still open, whether it holds a cursor for the stream, and where that cursor +// began, which is the floor a re-keyed pin has to hold. +type consumerProbe struct { + runID string + closed bool + consumes bool + startOffset int64 +} + +// probeConsumer reads a run without touching it. A run that is gone reads as +// closed, since the notify task only needs to know whether pushing at it can +// achieve anything. +func (h *handler) probeConsumer( + ctx context.Context, + namespaceID, workflowID, runID, streamID string, +) (consumerProbe, error) { + probe, err := chasm.ReadComponent(ctx, workflowRef(namespaceID, workflowID, runID), + func(wf *chasmworkflow.Workflow, cctx chasm.Context, _ struct{}) (consumerProbe, error) { + p := consumerProbe{ + runID: cctx.ExecutionKey().RunID, + closed: !cctx.ExecutionInfo().CloseTime.IsZero(), + } + if field, ok := wf.StreamCursors[streamID]; ok { + p.consumes = true + p.startOffset = field.Get(cctx).StartOffset() + } + return p, nil + }, struct{}{}) + var notFound *serviceerror.NotFound + if errors.As(err, ¬Found) { + return consumerProbe{runID: runID, closed: true}, nil + } + return probe, err +} + +func (h *handler) pushHead( + ctx context.Context, + namespaceID, workflowID, runID, streamID string, + head int64, +) error { + _, _, err := chasm.UpdateComponent( + ctx, + workflowRef(namespaceID, workflowID, runID), + func(wf *chasmworkflow.Workflow, mctx chasm.MutableContext, at int64) (struct{}, error) { + return struct{}{}, wf.AdvanceKnownHead(mctx, streamID, at) + }, + head, + ) + return err +} + +// AdvanceConsumerHead tells one consumer that the frontier moved, on the shard +// that owns that consumer. +// +// Internal. Called by the notify task, which runs on the stream's shard and so +// cannot reach a consumer living anywhere else. The task pins a run, and a run +// ends: the answer then says whether a successor carries the subscription, so +// the stream re-keys its pin, or nothing does, so the stream releases it. +func (h *handler) AdvanceConsumerHead( + ctx context.Context, + req *streampb.AdvanceConsumerHeadRequest, +) (*streampb.AdvanceConsumerHeadResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + namespaceID, workflowID, streamID := req.GetNamespaceId(), in.GetWorkflowId(), in.GetStreamId() + + pinned, err := h.probeConsumer(ctx, namespaceID, workflowID, in.GetOwnerRunId(), streamID) + if err != nil { + return nil, err + } + out := &streampb.AdvanceConsumerHeadOutput{} + if !pinned.closed { + if !pinned.consumes { + out.ConsumerClosed = true + return &streampb.AdvanceConsumerHeadResponse{FrontendResponse: out}, nil + } + err := h.pushHead(ctx, namespaceID, workflowID, pinned.runID, streamID, in.GetHeadOffset()) + if err != nil { + return nil, err + } + return &streampb.AdvanceConsumerHeadResponse{FrontendResponse: out}, nil + } + + // The pinned run is over. A continue-as-new carries the subscription to the + // current run, and that is the only run worth pushing at. + current, err := h.probeConsumer(ctx, namespaceID, workflowID, "", streamID) + if err != nil { + return nil, err + } + if current.closed || current.runID == pinned.runID || !current.consumes { + out.ConsumerClosed = true + return &streampb.AdvanceConsumerHeadResponse{FrontendResponse: out}, nil + } + err = h.pushHead(ctx, namespaceID, workflowID, current.runID, streamID, in.GetHeadOffset()) + if err != nil { + return nil, err + } + out.SuccessorRunId = current.runID + out.SuccessorStartOffset = current.startOffset + return &streampb.AdvanceConsumerHeadResponse{FrontendResponse: out}, nil +} + +func (h *handler) PollMessages( + ctx context.Context, + req *streampb.PollMessagesRequest, +) (*streampb.PollMessagesResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + ref := refForRun(req.GetNamespaceId(), in.GetStreamId(), in.GetRunId()) + from := in.GetFromOffset() + + state, err := chasm.ReadComponent(ctx, ref, (*stream.Stream).Snapshot, struct{}{}) + if err != nil { + return nil, err + } + + // Blocking is only worth it once the reader is genuinely caught up. + if in.GetWaitNewMessages() && from == state.GetHeadOffset() && !state.GetClosed() { + // The window is re-read below, so only the blocking matters here. + if _, err := h.waitForMessages(ctx, ref, from, state); err != nil { + return nil, err + } + } + + wreq := stream.WindowRequest{From: from, MaxMessages: in.GetMaxMessages(), Topics: in.GetTopics()} + w, err := chasm.ReadComponent(ctx, ref, (*stream.Stream).ReadWindow, wreq) + if err != nil { + return nil, err + } + out, err := formatWindow(w, wreq) + if err != nil { + return nil, err + } + return &streampb.PollMessagesResponse{FrontendResponse: out}, nil +} + +// PollWorkflowMessages reads a stream a workflow owns. +// +// An attached stream is reached through its owner, so this call routes on the +// workflow id and both the frontier and the batches come out of the owner's +// component. +func (h *handler) PollWorkflowMessages( + ctx context.Context, + req *streampb.PollWorkflowMessagesRequest, +) (*streampb.PollWorkflowMessagesResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + ref := workflowRef(req.GetNamespaceId(), in.GetWorkflowId(), in.GetOwnerRunId()) + name := ownedStreamName(in.GetStreamName()) + from := in.GetFromOffset() + + state, err := h.ownedStreamState(ctx, ref, name) + if err != nil { + return nil, err + } + + if in.GetWaitNewMessages() && from == state.GetHeadOffset() && !state.GetClosed() { + if _, err := h.waitForOwnedMessages(ctx, ref, name, from, state); err != nil { + return nil, err + } + } + + wreq := stream.WindowRequest{From: from, MaxMessages: in.GetMaxMessages(), Topics: in.GetTopics()} + w, err := chasm.ReadComponent(ctx, ref, readOwnedWindow, + ownedWindowRequest{Name: name, Window: wreq}) + if err != nil { + return nil, err + } + out, err := formatWindow(w, wreq) + if err != nil { + return nil, err + } + return &streampb.PollWorkflowMessagesResponse{FrontendResponse: out}, nil +} + +// formatWindow turns a component read into the wire response. The read happens +// in the component, so the frontier and the bytes it was served with cannot +// disagree. +// +// The reader is advanced only over offsets that were examined. CollectRecords +// steps past every message it filtered out, so a filtered page that matched +// nothing still moves the reader; a window whose batches stop short of its end +// must not be reported as read to the end. +func formatWindow(w stream.Window, req stream.WindowRequest) (*streampb.PollMessagesOutput, error) { + out := &streampb.PollMessagesOutput{ + NextOffset: req.From, + HeadOffset: w.State.GetHeadOffset(), + Closed: w.State.GetClosed(), + CloseReason: w.State.GetCloseReason(), + RunId: w.RunID, + } + if req.From == w.State.GetHeadOffset() { + return out, nil + } + + records, next, err := stream.CollectRecords( + w.Blobs, w.Starts, req.From, w.To, w.Limit, req.Topics) + if err != nil { + return nil, err + } + out.Records = records + out.NextOffset = next + return out, nil +} + +// ownedWindowRequest names which attached stream to read and what to read. +type ownedWindowRequest struct { + Name string + Window stream.WindowRequest +} + +// readOwnedWindow reads a stream attached to a workflow. +// +// A closed execution can take no more publishes, from its own Workflow Task or +// from anywhere else, so its stream is finished whether or not a producer said +// so. Without that a reader tailing a workflow that ended stays parked forever. +func readOwnedWindow( + wf *chasmworkflow.Workflow, + cctx chasm.Context, + req ownedWindowRequest, +) (stream.Window, error) { + s := wf.OwnedStream(cctx, req.Name) + if s == nil { + // Nothing published yet, which reads as an empty stream so a reader can + // attach before the first append. + return stream.Window{ + State: &streampb.StreamState{Closed: !cctx.ExecutionInfo().CloseTime.IsZero()}, + To: req.Window.From, + }, nil + } + w, err := s.ReadWindow(cctx, req.Window) + if err != nil { + return stream.Window{}, err + } + if !cctx.ExecutionInfo().CloseTime.IsZero() { + w.State.Closed = true + } + return w, nil +} + +// ownedStreamState snapshots an attached stream through the component that +// owns it. A stream the workflow has not published to yet reads as an empty +// one, so a reader may attach before the first event. +func (h *handler) ownedStreamState( + ctx context.Context, + ref chasm.ComponentRef, + name string, +) (*streampb.StreamState, error) { + state, err := chasm.ReadComponent(ctx, ref, readOwnedStream, name) + if err != nil { + return nil, err + } + return state, nil +} + +// readOwnedStream snapshots an attached stream and reports whether anything +// can still be added to it. +// +// A closed execution can take no more publishes, from its own Workflow Task or +// from anywhere else, so its stream is finished whether or not a producer said +// so. Without this a reader tailing a workflow that ended stays parked forever. +func readOwnedStream( + wf *chasmworkflow.Workflow, + cctx chasm.Context, + name string, +) (*streampb.StreamState, error) { + state, err := wf.OwnedStreamState(cctx, name) + if err != nil { + return nil, err + } + if state == nil { + state = &streampb.StreamState{} + } + if !cctx.ExecutionInfo().CloseTime.IsZero() { + state.Closed = true + } + return state, nil +} + +// waitForMessages blocks until the head passes the reader's offset or the +// stream closes. On the server's long-poll timeout it returns the state it last +// saw, so the caller gets an empty response and polls again rather than an +// error it would have to distinguish from a real failure. +func (h *handler) waitForMessages( + ctx context.Context, + ref chasm.ComponentRef, + from int64, + current *streampb.StreamState, +) (*streampb.StreamState, error) { + pollCtx, cancel := contextutil.WithDeadlineBuffer( + ctx, stream.LongPollTimeout, stream.LongPollBuffer) + defer cancel() + + state, _, err := chasm.PollComponent(pollCtx, ref, + func(s *stream.Stream, _ chasm.Context, offset int64) (*streampb.StreamState, bool, error) { + // Monotonic, as PollComponent requires: the head only advances and + // closed never clears. + if !pollSatisfied(s.State, offset) { + return nil, false, nil + } + return common.CloneProto(s.State), true, nil + }, from) + return pollOutcome(pollCtx, ctx, state, err, current) +} + +// waitForOwnedMessages is waitForMessages against a stream reached through its +// owner. The predicate has to re-resolve the stream on every evaluation, +// because what the poll observes is the owning execution. +func (h *handler) waitForOwnedMessages( + ctx context.Context, + ref chasm.ComponentRef, + name string, + from int64, + current *streampb.StreamState, +) (*streampb.StreamState, error) { + pollCtx, cancel := contextutil.WithDeadlineBuffer( + ctx, stream.LongPollTimeout, stream.LongPollBuffer) + defer cancel() + + state, _, err := chasm.PollComponent(pollCtx, ref, + func( + wf *chasmworkflow.Workflow, cctx chasm.Context, offset int64, + ) (*streampb.StreamState, bool, error) { + owned, err := readOwnedStream(wf, cctx, name) + if err != nil { + return nil, false, err + } + if !pollSatisfied(owned, offset) { + return nil, false, nil + } + return owned, true, nil + }, from) + return pollOutcome(pollCtx, ctx, state, err, current) +} + +// pollSatisfied is the monotonic condition PollComponent requires: the head +// only advances and closed never clears. +func pollSatisfied(state *streampb.StreamState, from int64) bool { + return state.GetHeadOffset() > from || state.GetClosed() +} + +// pollOutcome turns a long-poll result into the state the reader should be +// served. +func pollOutcome( + pollCtx, callerCtx context.Context, + state *streampb.StreamState, + err error, + current *streampb.StreamState, +) (*streampb.StreamState, error) { + if err != nil { + if pollCtx.Err() != nil && callerCtx.Err() == nil { + // Our long-poll budget expired, not the caller's. Hand back the + // state we already had so the reader gets an empty response and + // polls again, rather than an error it has to tell apart from a + // real failure. + return current, nil + } + return nil, err + } + if state == nil { + return current, nil + } + return state, nil +} + +func (h *handler) DescribeStream( + ctx context.Context, + req *streampb.DescribeStreamRequest, +) (*streampb.DescribeStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + state, err := chasm.ReadComponent(ctx, + refFor(req.GetNamespaceId(), in.GetStreamId()), (*stream.Stream).Snapshot, struct{}{}) + if err != nil { + return nil, err + } + return &streampb.DescribeStreamResponse{ + FrontendResponse: &streampb.DescribeStreamOutput{State: state}, + }, nil +} + +// DescribeWorkflowStream reports the frontier of a stream a workflow owns. A +// reader needs it to start at the tail rather than at the beginning, which an +// attached stream offers no other way to find. +func (h *handler) DescribeWorkflowStream( + ctx context.Context, + req *streampb.DescribeWorkflowStreamRequest, +) (*streampb.DescribeWorkflowStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + state, err := h.ownedStreamState(ctx, + workflowRef(req.GetNamespaceId(), in.GetWorkflowId(), in.GetOwnerRunId()), + ownedStreamName(in.GetStreamName())) + if err != nil { + return nil, err + } + return &streampb.DescribeWorkflowStreamResponse{ + FrontendResponse: &streampb.DescribeStreamOutput{State: state}, + }, nil +} + +func (h *handler) CloseStream( + ctx context.Context, + req *streampb.CloseStreamRequest, +) (*streampb.CloseStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + _, _, err := chasm.UpdateComponent( + ctx, + refFor(req.GetNamespaceId(), in.GetStreamId()), + func(s *stream.Stream, mctx chasm.MutableContext, reason *commonpb.Payload) (struct{}, error) { + return struct{}{}, s.CloseAndSchedule(mctx, reason) + }, + in.GetReason(), + ) + if err != nil { + return nil, err + } + return &streampb.CloseStreamResponse{FrontendResponse: &streampb.CloseStreamOutput{}}, nil +} + +func (h *handler) TruncateStream( + ctx context.Context, + req *streampb.TruncateStreamRequest, +) (*streampb.TruncateStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + + if _, _, err := chasm.UpdateComponent( + ctx, + refFor(req.GetNamespaceId(), in.GetStreamId()), + func(s *stream.Stream, mctx chasm.MutableContext, newBase int64) (struct{}, error) { + return struct{}{}, s.Truncate(mctx, newBase) + }, + in.GetNewBaseOffset(), + ); err != nil { + return nil, err + } + return &streampb.TruncateStreamResponse{FrontendResponse: &streampb.TruncateStreamOutput{}}, nil +} + +// ListStreams is intentionally not implemented here. It queries visibility, so +// it has no business ID to route on and the frontend answers it directly. + +func (h *handler) DeleteStream( + ctx context.Context, + req *streampb.DeleteStreamRequest, +) (*streampb.DeleteStreamResponse, error) { + in := req.GetFrontendRequest() + ctx = h.withCallerInfo(ctx, req.GetNamespaceId()) + key := chasm.ExecutionKey{NamespaceID: req.GetNamespaceId(), BusinessID: in.GetStreamId()} + + // A workflow consuming the stream recorded ranges its replay will ask for. + // Deleting under it succeeds now and fails that workflow later, so the + // caller has to say it means it. Checked and then deleted rather than in + // one transition, which leaves a window for a subscription that lands in + // between; that consumer finds out at its next task, with a cause. + if !in.GetForce() { + state, err := chasm.ReadComponent(ctx, refFor(key.NamespaceID, key.BusinessID), + (*stream.Stream).Snapshot, struct{}{}) + if err != nil { + return nil, err + } + for id, consumer := range state.GetConsumers() { + if consumer.GetActive() { + return nil, serviceerror.NewFailedPreconditionf( + "stream %q is consumed by workflow %q (%s); set force to delete it anyway", + key.BusinessID, consumer.GetWorkflowId(), id) + } + } + } + + // The payload is component state, so deleting the execution takes it too. + err := chasm.DeleteExecution[*stream.Stream](ctx, key, chasm.DeleteExecutionRequest{}) + if err != nil { + return nil, err + } + return &streampb.DeleteStreamResponse{FrontendResponse: &streampb.DeleteStreamOutput{}}, nil +} diff --git a/chasm/lib/stream/service/handler_test.go b/chasm/lib/stream/service/handler_test.go new file mode 100644 index 00000000000..68d4259859c --- /dev/null +++ b/chasm/lib/stream/service/handler_test.go @@ -0,0 +1,55 @@ +package service + +import ( + "testing" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "google.golang.org/protobuf/proto" +) + +func batchBlob(t *testing.T, topic string, bodies ...string) *commonpb.DataBlob { + t.Helper() + messages := make([]*streamlib.StreamRecord, len(bodies)) + for i, b := range bodies { + messages[i] = &streamlib.StreamRecord{ + Body: &commonpb.Payload{Data: []byte(b)}, + Topic: topic, + Kind: streampb.STREAM_RECORD_KIND_DATA, + } + } + data, err := proto.Marshal(&streamlib.StreamRecordBatch{Records: messages}) + require.NoError(t, err) + return &commonpb.DataBlob{EncodingType: enumspb.ENCODING_TYPE_PROTO3, Data: data} +} + +// A filtered page that matched nothing still advances the reader, but only +// over the offsets that were actually examined. A window whose batches stop +// short of its end must not report the end as the next offset, or the reader +// steps over messages it was never shown. +func TestFormatWindowAdvancesOnlyOverExaminedOffsets(t *testing.T) { + w := stream.Window{ + State: &streamlib.StreamState{HeadOffset: 10}, + Blobs: []*commonpb.DataBlob{batchBlob(t, "a", "m0", "m1", "m2")}, + Starts: []int64{0}, + To: 5, + Limit: 5, + } + out, err := formatWindow(w, stream.WindowRequest{From: 0, Topics: []string{"nothing"}}) + require.NoError(t, err) + require.Empty(t, out.GetRecords()) + require.Equal(t, int64(3), out.GetNextOffset(), + "offsets 3 and 4 were never read, so the reader must not be moved past them") + + // A page that filtered everything out but covered its whole window does + // advance to the end, so the reader does not loop on the same offsets. + w.Blobs = []*commonpb.DataBlob{batchBlob(t, "a", "m0", "m1", "m2", "m3", "m4")} + out, err = formatWindow(w, stream.WindowRequest{From: 0, Topics: []string{"nothing"}}) + require.NoError(t, err) + require.Empty(t, out.GetRecords()) + require.Equal(t, int64(5), out.GetNextOffset()) +} diff --git a/chasm/lib/stream/service/library.go b/chasm/lib/stream/service/library.go new file mode 100644 index 00000000000..8abf549cbbe --- /dev/null +++ b/chasm/lib/stream/service/library.go @@ -0,0 +1,89 @@ +package service + +import ( + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "google.golang.org/grpc" +) + +const ( + libraryName = "stream" + componentName = "stream" +) + +var ( + Archetype = chasm.FullyQualifiedName(libraryName, componentName) + ArchetypeID = chasm.GenerateTypeID(Archetype) +) + +type library struct { + chasm.UnimplementedLibrary + handler *handler + retention *retentionTaskHandler + notifyConsumers *notifyConsumersTaskHandler +} + +func newLibrary( + h *handler, + retention *retentionTaskHandler, + notifyConsumers *notifyConsumersTaskHandler, +) *library { + return &library{handler: h, retention: retention, notifyConsumers: notifyConsumers} +} + +// componentOnlyLibrary registers the component without the service, which is +// what the frontend needs in order to serialize component references. +type componentOnlyLibrary struct { + chasm.UnimplementedLibrary +} + +func newComponentOnlyLibrary() *componentOnlyLibrary { + return &componentOnlyLibrary{} +} + +func (l *componentOnlyLibrary) Name() string { + return libraryName +} + +func (l *componentOnlyLibrary) Components() []*chasm.RegistrableComponent { + return components() +} + +func components() []*chasm.RegistrableComponent { + return []*chasm.RegistrableComponent{ + chasm.NewRegistrableComponent[*stream.Stream]( + componentName, + chasm.WithBusinessIDAlias("StreamId"), + ), + // Registered here rather than with the workflow library because it is + // this package's type, even though it only ever hangs off a consuming + // workflow. + chasm.NewRegistrableComponent[*stream.Cursor]("streamCursor"), + } +} + +func (l *library) Name() string { + return libraryName +} + +func (l *library) Components() []*chasm.RegistrableComponent { + return components() +} + +func (l *library) Tasks() []*chasm.RegistrableTask { + return []*chasm.RegistrableTask{ + chasm.NewRegistrableSideEffectTask( + "streamRetention", + l.retention, + ), + chasm.NewRegistrableSideEffectTask( + "streamNotifyConsumers", + l.notifyConsumers, + ), + } +} + +func (l *library) RegisterServices(server *grpc.Server) { + streampb.RegisterStreamServiceServer(server, l.handler) +} diff --git a/chasm/lib/stream/service/tasks.go b/chasm/lib/stream/service/tasks.go new file mode 100644 index 00000000000..3471da034b2 --- /dev/null +++ b/chasm/lib/stream/service/tasks.go @@ -0,0 +1,292 @@ +package service + +import ( + "context" + "errors" + + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/headers" + "go.temporal.io/server/common/log" + "go.temporal.io/server/common/log/tag" + "go.temporal.io/server/common/namespace" + "go.temporal.io/server/service/history/shard" +) + +// consumerNotifier pushes a stream's frontier at its workflow consumers and +// keeps the consumer table honest about which of them still exist. +// +// A consumer lives wherever its own execution does, so telling it goes back +// out through the service to be routed rather than resolved on this shard. The +// answer also says when the run that subscribed is over: the pin is then +// dropped, or moved to the run that continued it. +type consumerNotifier struct { + logger log.Logger + routed streampb.StreamServiceClient +} + +// notify tells every active external consumer behind head that it moved. With +// probeAll it also tells the caught-up ones, which is how a closed stream +// learns whether anyone still holds it. Errors are collected rather than +// returned at the first, so one unreachable consumer does not stop the others +// being told, and returned at the end so the task retries. +func (n *consumerNotifier) notify( + ctx context.Context, + ref chasm.ComponentRef, + state *streampb.StreamState, + probeAll bool, +) error { + head := state.GetHeadOffset() + var notifyErrs []error + for consumerID, consumer := range state.GetConsumers() { + if !consumer.GetExternal() || !consumer.GetActive() { + continue + } + if !probeAll && consumer.GetOffset() >= head { + continue + } + + response, err := n.routed.AdvanceConsumerHead(ctx, &streampb.AdvanceConsumerHeadRequest{ + NamespaceId: ref.NamespaceID, + FrontendRequest: &streampb.AdvanceConsumerHeadInput{ + WorkflowId: consumer.GetWorkflowId(), + OwnerRunId: consumer.GetRunId(), + StreamId: ref.BusinessID, + HeadOffset: head, + }, + }) + var gone *serviceerror.NotFound + out := response.GetFrontendResponse() + switch { + case errors.As(err, &gone), err == nil && out.GetConsumerClosed(): + // The run that subscribed is over and nothing carries the + // subscription on. Its replay floor is holding storage for a + // recovery that can no longer be asked for, and this probe is the + // one place that finds out. + notifyErrs = append(notifyErrs, forgetConsumer(ctx, ref, consumerID)) + case err != nil: + n.logger.Error("failed to tell a stream consumer that the frontier moved", + tag.NewStringTag("stream-id", ref.BusinessID), + tag.NewStringTag("consumer-workflow-id", consumer.GetWorkflowId()), + tag.Error(err)) + notifyErrs = append(notifyErrs, err) + case out.GetSuccessorRunId() != "": + // A continue-as-new moved the subscription to a new run. The pin + // follows it, with the floor the successor's cursor began at; the + // predecessor's ranges are in a closed history that never replays. + notifyErrs = append(notifyErrs, rekeyConsumer(ctx, ref, consumer, out)) + default: + // Told, and still there. Nothing to clean up. + } + } + return errors.Join(notifyErrs...) +} + +func forgetConsumer(ctx context.Context, ref chasm.ComponentRef, consumerID string) error { + _, _, err := chasm.UpdateComponent(ctx, ref, + func(s *stream.Stream, mctx chasm.MutableContext, id string) (struct{}, error) { + s.ForgetConsumer(mctx, id) + return struct{}{}, nil + }, consumerID) + return err +} + +func rekeyConsumer( + ctx context.Context, + ref chasm.ComponentRef, + consumer *streampb.ConsumerCursor, + out *streampb.AdvanceConsumerHeadOutput, +) error { + registration := stream.ConsumerRegistration{ + ConsumerID: externalConsumerID(consumer.GetWorkflowId(), out.GetSuccessorRunId()), + WorkflowID: consumer.GetWorkflowId(), + RunID: out.GetSuccessorRunId(), + Offset: out.GetSuccessorStartOffset(), + External: true, + } + _, _, err := chasm.UpdateComponent(ctx, ref, + func( + s *stream.Stream, mctx chasm.MutableContext, reg stream.ConsumerRegistration, + ) (struct{}, error) { + // Registering the successor drops the predecessor's entry, since + // they share a workflow id and differ in run. + _, err := s.RegisterConsumer(mctx, reg) + return struct{}{}, err + }, registration) + return err +} + +// backgroundCallerContext tags a task's context with the namespace, since the +// task runs outside any request and nothing else has done it. +func backgroundCallerContext( + ctx context.Context, + registry namespace.Registry, + namespaceID string, +) context.Context { + if name, err := registry.GetNamespaceName(namespace.ID(namespaceID)); err == nil { + return headers.SetCallerInfo(ctx, headers.NewBackgroundLowCallerInfo(name.String())) + } + return ctx +} + +// retentionTaskHandler deletes a stream once its retention has elapsed. Close +// only seals; deletion is deliberately later, so a consumer can still drain a +// finished stream without coordinating a shutdown with the producer. +type retentionTaskHandler struct { + chasm.SideEffectTaskHandlerBase[*streampb.StreamRetentionTask] + + shardController shard.Controller + namespaceRegistry namespace.Registry + logger log.Logger + config *stream.Config + notifier consumerNotifier +} + +func newRetentionTaskHandler( + shardController shard.Controller, + namespaceRegistry namespace.Registry, + logger log.Logger, + config *stream.Config, + routed streampb.StreamServiceClient, +) *retentionTaskHandler { + return &retentionTaskHandler{ + shardController: shardController, + namespaceRegistry: namespaceRegistry, + logger: logger, + config: config, + notifier: consumerNotifier{logger: logger, routed: routed}, + } +} + +func (h *retentionTaskHandler) Validate( + _ chasm.Context, + s *stream.Stream, + _ chasm.TaskInvocation, + _ *streampb.StreamRetentionTask, +) (bool, error) { + // A stream that was reopened, or never closed, has nothing to expire. The + // task is scheduled at close and only meaningful while that still holds. + return s.State.GetClosed(), nil +} + +// Execute deletes the stream unless a workflow still consumes it. +// +// A consumer's History depends on the ranges it consumed, and deleting them +// turns its next replay into a failure. So while any consumer is active the +// deletion waits and asks again later. A closed stream gets no appends, and +// appends are what otherwise make the stream discover that a consumer is +// gone, so the probe here is what lets a held stream ever be released. +func (h *retentionTaskHandler) Execute( + ctx context.Context, + ref chasm.ComponentRef, + _ chasm.TaskAttributes, + _ *streampb.StreamRetentionTask, +) error { + ctx = backgroundCallerContext(ctx, h.namespaceRegistry, ref.NamespaceID) + + state, err := chasm.ReadComponent(ctx, ref, (*stream.Stream).Snapshot, struct{}{}) + if err != nil { + return err + } + if err := h.notifier.notify(ctx, ref, state, true); err != nil { + return err + } + + held, _, err := chasm.UpdateComponent(ctx, ref, + func(s *stream.Stream, mctx chasm.MutableContext, _ struct{}) (bool, error) { + for _, consumer := range s.State.GetConsumers() { + if consumer.GetActive() { + mctx.AddTask(s, chasm.TaskAttributes{ + ScheduledTime: mctx.Now(s).Add(h.config.RetentionRecheckInterval()), + }, &streampb.StreamRetentionTask{}) + return true, nil + } + } + return false, nil + }, struct{}{}) + if err != nil || held { + return err + } + + // The payload is component state, so deleting the execution takes it too. + return chasm.DeleteExecution[*stream.Stream](ctx, ref.ExecutionKey, chasm.DeleteExecutionRequest{}) +} + +func (h *retentionTaskHandler) Discard( + _ context.Context, + _ chasm.ComponentRef, + _ chasm.TaskAttributes, + _ *streampb.StreamRetentionTask, +) error { + // Nothing to undo: the task carries no side effect until it executes. + return nil +} + +// notifyConsumersTaskHandler tells workflows in other executions that the +// stream moved. +// +// Appending never schedules a workflow task by itself, because a stream item is +// data an execution produced rather than a decision input to it. A workflow +// that subscribed is the exception, and it has no other way to find out: it +// cannot read another execution's frontier while closing its own transaction. +// So the frontier is pushed into its cursor, which dirties that execution and +// lets its own transaction close decide it owes a workflow task. +type notifyConsumersTaskHandler struct { + chasm.SideEffectTaskHandlerBase[*streampb.StreamNotifyConsumersTask] + + namespaceRegistry namespace.Registry + notifier consumerNotifier +} + +func newNotifyConsumersTaskHandler( + namespaceRegistry namespace.Registry, + logger log.Logger, + routed streampb.StreamServiceClient, +) *notifyConsumersTaskHandler { + return ¬ifyConsumersTaskHandler{ + namespaceRegistry: namespaceRegistry, + notifier: consumerNotifier{logger: logger, routed: routed}, + } +} + +func (h *notifyConsumersTaskHandler) Validate( + _ chasm.Context, + s *stream.Stream, + _ chasm.TaskInvocation, + _ *streampb.StreamNotifyConsumersTask, +) (bool, error) { + for _, consumer := range s.State.GetConsumers() { + if consumer.GetExternal() && consumer.GetActive() { + return true, nil + } + } + return false, nil +} + +func (h *notifyConsumersTaskHandler) Execute( + ctx context.Context, + ref chasm.ComponentRef, + _ chasm.TaskAttributes, + _ *streampb.StreamNotifyConsumersTask, +) error { + ctx = backgroundCallerContext(ctx, h.namespaceRegistry, ref.NamespaceID) + + // A write rather than a read, because it also lowers the coalescing flag. + // Appends that commit after this transition schedule their own task. + state, _, err := chasm.UpdateComponent(ctx, ref, (*stream.Stream).TakeNotifySnapshot, struct{}{}) + if err != nil { + return err + } + return h.notifier.notify(ctx, ref, state, false) +} + +func (h *notifyConsumersTaskHandler) Discard( + _ context.Context, + _ chasm.ComponentRef, + _ chasm.TaskAttributes, + _ *streampb.StreamNotifyConsumersTask, +) error { + return nil +} diff --git a/chasm/lib/stream/stream.go b/chasm/lib/stream/stream.go new file mode 100644 index 00000000000..12243b09b8d --- /dev/null +++ b/chasm/lib/stream/stream.go @@ -0,0 +1,779 @@ +package stream + +import ( + "bytes" + "crypto/sha256" + "maps" + "slices" + "time" + + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// Stream is a durable, offset-addressed append-only sequence. State holds the +// frontier and the producer and consumer tables, so it is O(producers + +// consumers) no matter how long the stream gets; the payload lives in Batches. +// +// Appending never schedules a workflow task. A stream item is data produced by +// an execution, not a decision input to it, so nothing in a workflow's state +// machine advances because one arrived. +type Stream struct { + chasm.UnimplementedComponent + + State *streamlib.StreamState + + // Batches holds the payload, each keyed by the offset it starts at. They are + // data nodes, so they replicate with the component and are reclaimed with + // it, and a retry addresses the same key rather than racing it. + // + // They also live in mutable state, so the payload counts against the + // execution size limit of whatever execution holds the stream. + Batches chasm.Map[int64, *commonpb.DataBlob] + + // Present so streams are listable. Operators need to find them the same way + // they find workflows, and without this the only way to reach a stream is + // to already know its ID. + Visibility chasm.Field[*chasm.Visibility] +} + +type NewStreamRequest struct { + Lifecycle *streamlib.StreamLifecycle + + // Budget bounds what the stream may hold. Set for a stream a workflow + // owns, whose batches are the owning execution's mutable state. + Budget *streamlib.StreamBudget + + // Attached means the stream is a subcomponent of another execution rather + // than a root. CHASM requires a visibility component to be an immediate + // child of the root, so an attached stream carries none and is found + // through its owner instead of through ListStreams. + Attached bool + + // StartOffset is where the stream's offsets begin. Zero for a new stream. + // A run created by a reset inherits a cursor whose position is written in + // its History, so the stream it goes on reading has to continue that + // offset space rather than start over at zero. + StartOffset int64 +} + +type AddMessagesRequest struct { + Records []*streamlib.StreamRecord + + // Optional idempotency. A producer supplies either an identity and + // sequence, or an expected offset, or neither and accepts at-least-once. + ProducerID string + Sequence int64 + ExpectedOffset *int64 + + // The namespace's limits, resolved by the caller. A zero value means the + // defaults. + Limits Limits +} + +type AddMessagesResult struct { + FirstOffset int64 + NextOffset int64 + Count int64 + + // True when a retry matched a recorded producer sequence, so nothing was + // appended and the original offsets are returned. + Deduplicated bool + + // The bytes this append wrote, so a caller can prime a cache without + // reading them back. Nil when deduplicated. + Blob *commonpb.DataBlob +} + +func NewStream(ctx chasm.MutableContext, req NewStreamRequest) (*Stream, error) { + if req.StartOffset < 0 { + return nil, serviceerror.NewInvalidArgument("start offset cannot be negative") + } + visibility := chasm.NewEmptyField[*chasm.Visibility]() + if !req.Attached { + visibility = chasm.NewComponentField(ctx, chasm.NewVisibility(ctx)) + } + return &Stream{ + Visibility: visibility, + Batches: make(chasm.Map[int64, *commonpb.DataBlob]), + State: &streamlib.StreamState{ + HeadOffset: req.StartOffset, + BaseOffset: req.StartOffset, + Lifecycle: req.Lifecycle, + Budget: req.Budget, + Producers: make(map[string]*streamlib.ProducerCursor), + Consumers: make(map[string]*streamlib.ConsumerCursor), + }, + }, nil +} + +// ContextMetadata satisfies chasm.RootComponent. A stream carries no metadata +// worth propagating to the request context. +func (s *Stream) ContextMetadata(_ chasm.Context) map[string]string { + return nil +} + +// Terminate seals the stream so a forced shutdown does not leave it accepting +// writes. Data already appended stays readable, because consumers may have read +// it and the stream is append-only. +func (s *Stream) Terminate( + mctx chasm.MutableContext, + req chasm.TerminateComponentRequest, +) (chasm.TerminateComponentResponse, error) { + reason := &commonpb.Payload{Data: []byte(req.Reason)} + return chasm.TerminateComponentResponse{}, s.CloseAndSchedule(mctx, reason) +} + +// Snapshot returns a copy of the frontier for read paths. It is a copy because +// the caller reads it outside the transition that produced it. +func (s *Stream) Snapshot(_ chasm.Context, _ struct{}) (*streamlib.StreamState, error) { + return common.CloneProto(s.State), nil +} + +func (s *Stream) LifecycleState(_ chasm.Context) chasm.LifecycleState { + if s.State.Closed { + return chasm.LifecycleStateCompleted + } + return chasm.LifecycleStateRunning +} + +// AddMessages assigns a contiguous offset range and writes the bytes into the +// component, so the payload and the frontier commit in one transaction. A torn +// append is therefore not a state anyone can observe. +func (s *Stream) AddMessages( + mctx chasm.MutableContext, + req AddMessagesRequest, +) (AddMessagesResult, error) { + if s.State.Closed { + return AddMessagesResult{}, serviceerror.NewFailedPrecondition("stream is closed") + } + if len(req.Records) == 0 { + return AddMessagesResult{}, serviceerror.NewInvalidArgument("no records to append") + } + if len(req.Records) > MaxRecordsPerBatch { + return AddMessagesResult{}, serviceerror.NewInvalidArgumentf( + "batch of %d exceeds the limit of %d records", len(req.Records), MaxRecordsPerBatch) + } + limits := req.Limits.withDefaults() + if err := checkBatchBytes(req.Records, limits); err != nil { + return AddMessagesResult{}, err + } + // A record with no kind is data. A producer that never heard of kinds + // leaves the field at its zero value, and every reader would otherwise have + // to agree on what that means. Settled before the batch is marshalled, so a + // retry hashes the same bytes. + for _, m := range req.Records { + if m.GetKind() == streampb.STREAM_RECORD_KIND_UNSPECIFIED { + m.Kind = streampb.STREAM_RECORD_KIND_DATA + } + } + + blob, err := marshalBatch(req.Records) + if err != nil { + return AddMessagesResult{}, err + } + hash := contentHash(blob.Data) + + if replay, err := s.checkProducer(req, hash); err != nil || replay != nil { + if err != nil { + return AddMessagesResult{}, err + } + return *replay, nil + } + + // After the retry check, so a known producer is never rejected for room. + if err := s.checkProducerRoom(req.ProducerID, limits.MaxProducersPerStream); err != nil { + return AddMessagesResult{}, err + } + if err := s.checkBudget(int64(len(req.Records)), int64(len(blob.Data))); err != nil { + return AddMessagesResult{}, err + } + + // Before anything is written, because the alternative is to write and then + // discover the cap can only be met by deleting bytes a consumer's committed + // History still refers to. Refusing the write is the honest half of that + // choice: capacity may constrain what is admitted, and may not quietly take + // back a workflow's ability to replay a decision it already made. + if err := s.checkCapRoom(int64(len(req.Records))); err != nil { + return AddMessagesResult{}, err + } + + if req.ExpectedOffset != nil && *req.ExpectedOffset != s.State.HeadOffset { + return AddMessagesResult{}, serviceerror.NewAlreadyExistsf( + "expected offset %d but stream head is %d", *req.ExpectedOffset, s.State.HeadOffset) + } + + first := s.State.HeadOffset + count := int64(len(req.Records)) + + if s.Batches == nil { + s.Batches = make(chasm.Map[int64, *commonpb.DataBlob]) + } + s.Batches[first] = chasm.NewDataField(mctx, blob) + + s.State.HeadOffset = first + count + s.State.AppendedBytes += int64(len(blob.Data)) + if req.ProducerID != "" { + if s.State.Producers == nil { + s.State.Producers = make(map[string]*streamlib.ProducerCursor) + } + s.State.Producers[req.ProducerID] = &streamlib.ProducerCursor{ + Seq: req.Sequence, + FirstOffset: first, + Count: count, + ContentHash: hash, + } + } + + s.applyCap() + result := AddMessagesResult{ + FirstOffset: first, + NextOffset: s.State.HeadOffset, + Count: count, + Blob: blob, + } + s.notifyConsumers(mctx) + return result, nil +} + +// notifyConsumers schedules the wake for consumers this append left behind. +// +// Only a workflow in another execution needs it. One consuming a stream it owns +// sees the new frontier while closing its own transaction, so waking it through +// a task would only duplicate a decision already made locally. +func (s *Stream) notifyConsumers(mctx chasm.MutableContext) { + // Without a context there is no transition to attach the task to. The + // component's own unit tests drive the transitions that way. + if mctx == nil { + return + } + // One task outstanding at a time. The task reads the head when it runs and + // clears the flag before it reads, so an append that lands after the clear + // schedules the next one and nothing is missed. + if s.State.NotifyPending { + return + } + for _, consumer := range s.State.Consumers { + if consumer.GetExternal() && consumer.GetActive() && consumer.GetOffset() < s.State.HeadOffset { + s.State.NotifyPending = true + mctx.AddTask(s, chasm.TaskAttributes{ScheduledTime: mctx.Now(s)}, + &streamlib.StreamNotifyConsumersTask{}) + return + } + } +} + +// TakeNotifySnapshot is the notify task's read of the stream. Clearing the +// pending flag in the same transition that reads the head is what makes the +// coalescing safe: any append that commits after this one sees the flag down +// and schedules its own task. +func (s *Stream) TakeNotifySnapshot( + _ chasm.MutableContext, _ struct{}, +) (*streamlib.StreamState, error) { + s.State.NotifyPending = false + return common.CloneProto(s.State), nil +} + +// checkProducerRoom keeps the dedup table bounded. +// +// Entries whose whole batch sits below the floor go first: a retry of a batch +// that truncation already removed cannot be served its recorded offsets +// anyway, so the entry has no use left. +func (s *Stream) checkProducerRoom(producerID string, maxProducers int) error { + if producerID == "" { + return nil + } + if _, known := s.State.Producers[producerID]; known { + return nil + } + if len(s.State.Producers) < maxProducers { + return nil + } + for id, cursor := range s.State.Producers { + if cursor.GetFirstOffset()+cursor.GetCount() <= s.State.GetBaseOffset() { + delete(s.State.Producers, id) + } + } + if len(s.State.Producers) >= maxProducers { + return serviceerror.NewInvalidArgumentf( + "stream already tracks %d producers, which is the limit", maxProducers) + } + return nil +} + +// checkBudget refuses an append a budgeted stream cannot hold. +// +// Refused rather than reclaimed: the budget exists because the batches are +// mutable state of the execution that owns the stream, and the alternative to +// refusing here is the execution size limit terminating that workflow later, +// with nothing naming the stream as the cause. +func (s *Stream) checkBudget(count int64, size int64) error { + budget := s.State.GetBudget() + if budget == nil { + return nil + } + if limit := budget.GetMaxItems(); limit > 0 && s.State.HeadOffset+count > limit { + return serviceerror.NewResourceExhaustedf( + enumspb.RESOURCE_EXHAUSTED_CAUSE_PERSISTENCE_STORAGE_LIMIT, + "stream holds %d of its budget of %d records; the append of %d does not fit", + s.State.HeadOffset, limit, count) + } + if limit := budget.GetMaxBytes(); limit > 0 && s.State.AppendedBytes+size > limit { + return serviceerror.NewResourceExhaustedf( + enumspb.RESOURCE_EXHAUSTED_CAUSE_PERSISTENCE_STORAGE_LIMIT, + "stream holds %d of its budget of %d bytes; the append of %d does not fit", + s.State.AppendedBytes, limit, size) + } + return nil +} + +// checkProducer applies per-producer idempotency. It returns a replay result +// when the request is a genuine retry, and an error when it is not a retry but +// cannot be accepted either. +func (s *Stream) checkProducer(req AddMessagesRequest, hash []byte) (*AddMessagesResult, error) { + if req.ProducerID == "" { + return nil, nil + } + cursor := s.State.Producers[req.ProducerID] + if cursor == nil { + return nil, nil + } + if cursor.Fenced { + return nil, serviceerror.NewFailedPrecondition("producer has finished writing to this stream") + } + if req.Sequence > cursor.Seq { + return nil, nil + } + if req.Sequence < cursor.Seq { + return nil, serviceerror.NewInvalidArgumentf( + "stale producer sequence %d, last accepted is %d", req.Sequence, cursor.Seq) + } + // Same sequence. Identical content is a retry; different content is a + // client bug, and returning the recorded offsets would report success while + // silently dropping the caller's data. + if !bytes.Equal(cursor.ContentHash, hash) { + return nil, serviceerror.NewInvalidArgumentf( + "producer sequence %d already used with different content", req.Sequence) + } + return &AddMessagesResult{ + FirstOffset: cursor.FirstOffset, + NextOffset: cursor.FirstOffset + cursor.Count, + Count: cursor.Count, + Deduplicated: true, + }, nil +} + +// FinishWriting ends one producer's writes without closing the stream, so other +// producers carry on. Weaker than Close on purpose. +func (s *Stream) FinishWriting(_ chasm.MutableContext, producerID string) error { + if producerID == "" { + return serviceerror.NewInvalidArgument("producer id is required") + } + if s.State.Producers == nil { + s.State.Producers = make(map[string]*streamlib.ProducerCursor) + } + cursor := s.State.Producers[producerID] + if cursor == nil { + cursor = &streamlib.ProducerCursor{Seq: -1} + s.State.Producers[producerID] = cursor + } + cursor.Fenced = true + return nil +} + +// Close seals the stream. It does not delete it: a closed stream stays readable +// through retention, which is what removes the shutdown handshake the current +// signal-based implementation forces on users. +// Close returns when retention deletion should be scheduled, or the zero time +// if the stream was already closed or has no retention configured. Scheduling +// is the caller's job, which keeps the component a pure state transition and +// testable without a live context. +func (s *Stream) Close(now time.Time, reason *commonpb.Payload) time.Time { + if s.State.Closed { + return time.Time{} + } + s.State.Closed = true + s.State.CloseReason = reason + s.State.CloseTime = timestamppb.New(now) + + retention := s.State.GetLifecycle().GetRetention().AsDuration() + if retention <= 0 { + return time.Time{} + } + return now.Add(retention) +} + +// CloseAndSchedule closes the stream and arms retention if it asked for it. +func (s *Stream) CloseAndSchedule(mctx chasm.MutableContext, reason *commonpb.Payload) error { + if at := s.Close(mctx.Now(s), reason); !at.IsZero() { + mctx.AddTask(s, chasm.TaskAttributes{ScheduledTime: at}, &streamlib.StreamRetentionTask{}) + } + return nil +} + +// Truncate advances the readable floor. +// +// It stops at an active consumer's replay floor. A workflow that consumed a +// range recorded that range in its History and can be asked to replay from it, +// so those bytes are part of its recovery rather than spare capacity. Dropping +// them succeeds here and fails much later, during a replay nobody is watching, +// which is the worst place to find out. +// +// The floor is released by deregistering the consumer, which is an act someone +// takes deliberately. An operator who means to drop the bytes anyway does that +// first, and then this call goes through. +// +// A consumer that is behind but not active is not protected. Reading from +// below the base is an error naming where the stream now starts, the same +// answer a log with a retention window gives anywhere else. +func (s *Stream) Truncate(_ chasm.MutableContext, newBase int64) error { + if newBase < s.State.BaseOffset { + return serviceerror.NewInvalidArgumentf( + "cannot truncate backwards from %d to %d", s.State.BaseOffset, newBase) + } + if newBase > s.State.HeadOffset { + return serviceerror.NewInvalidArgumentf( + "cannot truncate past head offset %d", s.State.HeadOffset) + } + if floor, holder, pinned := s.replayFloor(); pinned && newBase > floor { + return serviceerror.NewFailedPreconditionf( + "cannot truncate to %d: consumer %q still depends on offset %d and above "+ + "to replay; deregister it first if those records are no longer needed", + newBase, holder, floor) + } + s.State.BaseOffset = newBase + s.reclaim(newBase) + return nil +} + +// replayFloor is the oldest offset any active consumer's History still depends +// on, and who is holding it. Named, because a refusal that does not say which +// consumer to look at leaves the operator with nothing to act on. +func (s *Stream) replayFloor() (int64, string, bool) { + var floor int64 + var holder string + found := false + for id, c := range s.State.Consumers { + if !c.GetActive() { + continue + } + if !found || c.GetReplayFloor() < floor { + floor = c.GetReplayFloor() + holder = id + found = true + } + } + return floor, holder, found +} + +// reclaim drops batches lying entirely below the readable floor. A batch +// straddling the floor stays, because the offsets above it are still readable. +func (s *Stream) reclaim(newBase int64) { + starts := s.batchStarts() + for i, start := range starts { + end := s.State.HeadOffset + if i+1 < len(starts) { + end = starts[i+1] + } + if end > newBase { + return + } + delete(s.Batches, start) + } +} + +// batchStarts returns the batch keys in offset order. Reading and reclaiming +// both need where a batch ends, which is where the next one begins. +func (s *Stream) batchStarts() []int64 { + return slices.Sorted(maps.Keys(s.Batches)) +} + +// WindowRequest asks for whatever a reader can be given from an offset. +type WindowRequest struct { + From int64 + MaxMessages int32 + Topics []string +} + +// Window is one read's worth: the frontier it was served against, the batches +// covering the range, and the range itself. +type Window struct { + State *streamlib.StreamState + Blobs []*commonpb.DataBlob + Starts []int64 + To int64 + Limit int + // The execution holding the stream, so a slice built from this window can + // say which run it came from. + RunID string +} + +// ReadWindow serves a read from the component, so the frontier and the bytes +// come from one view. Read separately they can disagree, because the frontier +// moves while the bytes are being fetched. +func (s *Stream) ReadWindow(ctx chasm.Context, req WindowRequest) (Window, error) { + if req.From < s.State.BaseOffset { + return Window{}, serviceerror.NewFailedPreconditionf( + "offset %d has been truncated, the stream starts at %d", req.From, s.State.BaseOffset) + } + if req.From > s.State.HeadOffset { + return Window{}, serviceerror.NewInvalidArgumentf( + "offset %d is past the stream head %d", req.From, s.State.HeadOffset) + } + + // Clamped at both ends. The caller picks the page size, and an unclamped + // one lets a single poll ask the store to materialise the whole stream. + limit := int(req.MaxMessages) + if limit <= 0 || limit > DefaultMaxMessagesPerPoll { + limit = DefaultMaxMessagesPerPoll + } + w := Window{ + State: common.CloneProto(s.State), + To: req.From, + Limit: limit, + RunID: ctx.ExecutionKey().RunID, + } + if req.From == s.State.HeadOffset { + return w, nil + } + + // Clip to what the caller can actually be given. One offset is one record, + // so the bound is exact. Without it a poll for a single record off a long + // stream materialises every batch to the head before trimming. + w.To = min(s.State.HeadOffset, req.From+int64(limit)) + blobs, starts, err := s.ReadBatches(ctx, req.From, w.To, 0) + if err != nil { + return Window{}, err + } + w.Blobs, w.Starts = blobs, starts + return w, nil +} + +// ReadBatches returns the batches covering [from, to), oldest first, alongside +// the offset each one starts at. A read landing mid-batch gets the batch +// holding it, because a consumer asks for an offset rather than for a batch. +// Blobs come back unparsed: decoding user payloads is the SDK's job. +func (s *Stream) ReadBatches( + ctx chasm.Context, + from int64, + to int64, + maxBatches int, +) ([]*commonpb.DataBlob, []int64, error) { + if from >= to { + return nil, nil, nil + } + var blobs []*commonpb.DataBlob + var starts []int64 + all := s.batchStarts() + for i, start := range all { + end := s.State.HeadOffset + if i+1 < len(all) { + end = all[i+1] + } + if end <= from { + continue + } + if start >= to { + break + } + blobs = append(blobs, s.Batches[start].Get(ctx)) + starts = append(starts, start) + if maxBatches > 0 && len(blobs) >= maxBatches { + break + } + } + return blobs, starts, nil +} + +// applyCap advances the readable floor when the stream is over its record cap. +// Evaluated at the end of a successful append rather than by a sweeper: the +// append transition is already writing, so folding the check into it costs +// nothing and keeps the cap tight instead of eventually true. +func (s *Stream) applyCap() { + maxItems := s.State.GetLifecycle().GetMaxItems() + if maxItems <= 0 { + return + } + readable := s.State.HeadOffset - s.State.BaseOffset + if readable <= maxItems { + return + } + newBase := s.State.HeadOffset - maxItems + // Clamped rather than refused, because refusing belongs to admission and + // has already happened: checkCapRoom turned away the append that would have + // needed this. Reaching the clamp means a consumer registered after the + // records were written, and keeping its bytes is still the right answer. + if floor, _, pinned := s.replayFloor(); pinned && newBase > floor { + newBase = floor + } + if newBase <= s.State.BaseOffset { + return + } + s.State.BaseOffset = newBase + s.reclaim(newBase) +} + +// checkCapRoom refuses an append the cap could only absorb by dropping bytes an +// active consumer still needs. +// +// A capped stream with no consumer behaves as before: the oldest records go. +// The refusal only arrives when honouring the cap and honouring a recorded +// consumption are the same records, and it names the consumer so the operator +// knows what to do about it. +func (s *Stream) checkCapRoom(count int64) error { + maxItems := s.State.GetLifecycle().GetMaxItems() + if maxItems <= 0 { + return nil + } + wantBase := s.State.HeadOffset + count - maxItems + if wantBase <= s.State.BaseOffset { + return nil + } + floor, holder, pinned := s.replayFloor() + if !pinned || wantBase <= floor { + return nil + } + return serviceerror.NewResourceExhaustedf( + enumspb.RESOURCE_EXHAUSTED_CAUSE_UNSPECIFIED, + "stream is at its cap of %d records and consumer %q still depends on "+ + "offset %d and above to replay; the append would have to delete those "+ + "records to make room", + maxItems, holder, floor) +} + +// ConsumerRegistration describes a consumer being registered on a stream. +type ConsumerRegistration struct { + ConsumerID string + WorkflowID string + RunID string + // Negative means the head as of the registering transition. + Offset int64 + External bool + // Zero means the default. + MaxConsumers int +} + +// RegisterConsumer records an in-workflow consumer, so appends know who to wake +// and retention knows what it may not delete. It returns the offset the +// consumer reads from: the resolved start for a new consumer, and the current +// read position for one that is already registered. +// +// A negative offset means the head as of this transition. Resolving it here, +// against the frontier the same transaction sees, is what makes the recorded +// start a fact rather than a reading taken a moment earlier. +// +// The floor it records is where the subscription started, not where it has read +// to. The ranges this consumer already took are written into its History, and a +// replay is asked to reproduce them, so the bytes behind the read position are +// the ones a recovery needs. Deregistering releases the floor. +func (s *Stream) RegisterConsumer(_ chasm.MutableContext, reg ConsumerRegistration) (int64, error) { + if reg.ConsumerID == "" { + return 0, serviceerror.NewInvalidArgument("consumer id is required") + } + maxConsumers := reg.MaxConsumers + if maxConsumers <= 0 { + maxConsumers = MaxConsumersPerStream + } + offset := reg.Offset + if offset < 0 { + offset = s.State.HeadOffset + } + if offset < s.State.BaseOffset { + return 0, serviceerror.NewFailedPreconditionf( + "offset %d is below the stream's floor of %d", offset, s.State.BaseOffset) + } + if _, known := s.State.Consumers[reg.ConsumerID]; !known && + len(s.State.Consumers) >= maxConsumers { + return 0, serviceerror.NewInvalidArgumentf( + "stream already has %d consumers, which is the limit", maxConsumers) + } + if s.State.Consumers == nil { + s.State.Consumers = make(map[string]*streamlib.ConsumerCursor) + } + // One workflow id has one open run, so an entry for another run of this + // workflow belongs to a closed run. Its floor would otherwise hold storage + // for a replay nobody can ask for, and the new run would inherit it. + for id, c := range s.State.Consumers { + if id != reg.ConsumerID && c.GetExternal() && + c.GetWorkflowId() == reg.WorkflowID && c.GetRunId() != reg.RunID { + delete(s.State.Consumers, id) + } + } + if existing, ok := s.State.Consumers[reg.ConsumerID]; ok { + // A consumer coming back after its floor was released can find the + // stream has moved past what its History refers to. Saying so here is + // the only chance to say it before the workflow depends on it again. + if existing.GetReplayFloor() < s.State.BaseOffset { + return 0, serviceerror.NewFailedPreconditionf( + "consumer %q recorded offset %d, and the stream now starts at %d", + reg.ConsumerID, existing.GetReplayFloor(), s.State.BaseOffset) + } + existing.Active = true + return existing.GetOffset(), nil + } + s.State.Consumers[reg.ConsumerID] = &streamlib.ConsumerCursor{ + WorkflowId: reg.WorkflowID, + RunId: reg.RunID, + Offset: offset, + Active: true, + External: reg.External, + ReplayFloor: offset, + } + return offset, nil +} + +// AdvanceConsumer moves a consumer's pin forward as it reads. It never moves +// backwards: the floor is what lets a recorded range still be re-read, so +// lowering it would give back a guarantee already written to History. +func (s *Stream) AdvanceConsumer(_ chasm.MutableContext, consumerID string, offset int64) { + consumer, ok := s.State.Consumers[consumerID] + if !ok || offset <= consumer.Offset { + return + } + consumer.Offset = offset +} + +// DeregisterConsumer releases the floor a consumer was holding, so retention +// and the record cap can reach its records again. The entry stays, inactive, +// so the same consumer coming back is refused if the stream has moved past +// what its History refers to. +func (s *Stream) DeregisterConsumer(_ chasm.MutableContext, consumerID string) { + if consumer, ok := s.State.Consumers[consumerID]; ok { + consumer.Active = false + } +} + +// ForgetConsumer drops a consumer whose run is closed. A closed run never +// replays and never comes back, so unlike a deregistration there is nothing +// left to refuse later. +func (s *Stream) ForgetConsumer(_ chasm.MutableContext, consumerID string) { + delete(s.State.Consumers, consumerID) +} + +func marshalBatch(records []*streamlib.StreamRecord) (*commonpb.DataBlob, error) { + // The serialized batch is also the producer's deduplication fingerprint, and + // protobuf map iteration order is not stable. A record carrying payload or + // record metadata would otherwise hash differently on a retry and be + // refused as a conflicting duplicate of itself. + data, err := (proto.MarshalOptions{Deterministic: true}).Marshal( + &streamlib.StreamRecordBatch{Records: records}) + if err != nil { + return nil, err + } + return &commonpb.DataBlob{ + EncodingType: enumspb.ENCODING_TYPE_PROTO3, + Data: data, + }, nil +} + +func contentHash(data []byte) []byte { + sum := sha256.Sum256(data) + return sum[:] +} diff --git a/chasm/lib/stream/stream_test.go b/chasm/lib/stream/stream_test.go new file mode 100644 index 00000000000..9438b8bc435 --- /dev/null +++ b/chasm/lib/stream/stream_test.go @@ -0,0 +1,655 @@ +package stream + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "google.golang.org/protobuf/types/known/durationpb" +) + +// Built directly rather than through NewStream: these exercise state +// transitions, and NewStream also wires a visibility field that needs a live +// context. Construction through the real path is covered end to end in +// tests/stream_test.go. +func newTestStream(t *testing.T) *Stream { + t.Helper() + return &Stream{ + State: &streamlib.StreamState{ + Producers: make(map[string]*streamlib.ProducerCursor), + Consumers: make(map[string]*streamlib.ConsumerCursor), + }, + } +} + +func msgs(bodies ...string) []*streamlib.StreamRecord { + out := make([]*streamlib.StreamRecord, len(bodies)) + for i, b := range bodies { + out[i] = &streamlib.StreamRecord{ + Body: &commonpb.Payload{Data: []byte(b)}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + } + } + return out +} + +func TestAddMessagesAssignsContiguousOffsets(t *testing.T) { + s := newTestStream(t) + + first, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c")}) + require.NoError(t, err) + require.Equal(t, int64(0), first.FirstOffset) + require.Equal(t, int64(3), first.Count) + require.Equal(t, int64(3), first.NextOffset) + + second, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("d", "e")}) + require.NoError(t, err) + require.Equal(t, int64(3), second.FirstOffset) + require.Equal(t, int64(5), second.NextOffset) + require.Equal(t, int64(5), s.State.HeadOffset) +} + +func TestAddMessagesWritesTheBatchIntoTheComponent(t *testing.T) { + s := newTestStream(t) + + res, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + require.NotEmpty(t, res.Blob.Data) + + // Keyed by the offset it starts at, which is the key a retry of this + // append writes under, so the retry replaces rather than races. + require.Len(t, s.Batches, 1) + _, ok := s.Batches[0] + require.True(t, ok, "the batch must be keyed by its first offset") + require.Equal(t, int64(2), s.State.HeadOffset) +} + +func TestDedupReturnsOriginalOffsets(t *testing.T) { + s := newTestStream(t) + req := AddMessagesRequest{Records: msgs("a", "b"), ProducerID: "p1", Sequence: 1} + + first, err := s.AddMessages(nil, req) + require.NoError(t, err) + require.False(t, first.Deduplicated) + + retry := req + again, err := s.AddMessages(nil, retry) + require.NoError(t, err) + require.True(t, again.Deduplicated) + require.Equal(t, first.FirstOffset, again.FirstOffset) + require.Nil(t, again.Blob, "a deduplicated retry writes nothing") + require.Equal(t, int64(2), s.State.HeadOffset, "a retry must not advance the head") +} + +func TestDedupIgnoresPayloadMetadataMapOrder(t *testing.T) { + s := newTestStream(t) + for attempt := range 32 { + body := &commonpb.Payload{ + Data: []byte("encoded"), + Metadata: map[string][]byte{ + "encoding": []byte("test/envelope"), + "key-id": []byte("key-1"), + "nonce": []byte("fixed-for-this-record"), + }, + } + result, err := s.AddMessages(nil, AddMessagesRequest{ + Records: []*streamlib.StreamRecord{{ + Kind: streampb.STREAM_RECORD_KIND_DATA, + Body: body, + Metadata: map[string]*commonpb.Payload{"attempt": body, "checkpoint": body}, + }}, + ProducerID: "encoded-producer", Sequence: 1, + }) + require.NoError(t, err, "identical retry %d must ignore protobuf map iteration order", attempt) + require.Equal(t, attempt > 0, result.Deduplicated) + require.Equal(t, int64(0), result.FirstOffset) + require.Equal(t, int64(1), s.State.HeadOffset) + } +} + +func TestDedupRejectsDifferentContent(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("a"), ProducerID: "p1", Sequence: 1, + }) + require.NoError(t, err) + + // Returning the recorded offsets here would report success while dropping + // the caller's data, which is worse than failing. + _, err = s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("different"), ProducerID: "p1", Sequence: 1, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "different content") +} + +func TestExpectedOffsetMismatchReportsHead(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a")}) + require.NoError(t, err) + + stale := int64(0) + _, err = s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("b"), ExpectedOffset: &stale, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "stream head is 1") +} + +func TestFinishWritingFencesOneProducerOnly(t *testing.T) { + s := newTestStream(t) + require.NoError(t, s.FinishWriting(nil, "p1")) + + _, err := s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("a"), ProducerID: "p1", Sequence: 1, + }) + require.Error(t, err) + + // Another producer is unaffected: finishing is per-producer, not a close. + _, err = s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("a"), ProducerID: "p2", Sequence: 1, + }) + require.NoError(t, err) + require.False(t, s.State.Closed) +} + +func TestCloseRejectsFurtherAppends(t *testing.T) { + s := newTestStream(t) + s.Close(time.Now(), nil) + + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a")}) + require.Error(t, err) + var precondition *serviceerror.FailedPrecondition + require.ErrorAs(t, err, &precondition) +} + +func TestReadSpansBatchesAndStartsAtTheBatchHoldingTheOffset(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c")}) + require.NoError(t, err) + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("d", "e")}) + require.NoError(t, err) + require.Len(t, s.Batches, 2) + + // A read from offset 1 lands inside the first batch. It gets that batch + // whole, because a consumer asks for an offset and not for a batch, and + // the batch is the smallest thing stored. + blobs, starts, err := s.ReadBatches(nil, 1, 5, 0) + require.NoError(t, err) + require.Len(t, blobs, 2) + require.Equal(t, []int64{0, 3}, starts) + + // A read wholly inside the second batch does not drag the first along. + blobs, starts, err = s.ReadBatches(nil, 3, 5, 0) + require.NoError(t, err) + require.Len(t, blobs, 1) + require.Equal(t, []int64{3}, starts) +} + +func TestReclaimDropsOnlyBatchesFullyBelowTheFloor(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c")}) + require.NoError(t, err) + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("d", "e")}) + require.NoError(t, err) + + // The floor lands mid-batch, so that batch stays: offsets above the floor + // are still readable and they live in it. + require.NoError(t, s.Truncate(nil, 1)) + require.Len(t, s.Batches, 2) + + // Now the whole first batch is below the floor and can go. + require.NoError(t, s.Truncate(nil, 3)) + require.Len(t, s.Batches, 1) + _, ok := s.Batches[3] + require.True(t, ok, "the batch holding readable offsets must survive") +} + +func TestTruncateStopsAtAnActiveConsumersReplayFloor(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "wf-1", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + s.AdvanceConsumer(nil, "wf-1", 2) + + // Reading to 2 is exactly what makes offsets 0 and 1 matter: they are in + // this consumer's History and a replay is asked to reproduce them. + err = s.Truncate(nil, 3) + require.ErrorContains(t, err, "still depends on offset 0") + require.Equal(t, int64(0), s.State.BaseOffset) + + // Whatever is above the floor is still spare capacity. + require.NoError(t, s.Truncate(nil, 0)) +} + +func TestTruncateBounds(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + + err = s.Truncate(nil, 1) + require.NoError(t, err) + err = s.Truncate(nil, 0) + require.Error(t, err, "truncation must not go backwards") + err = s.Truncate(nil, 3) + require.Error(t, err, "truncation must not pass the head") +} + +func TestCapTruncatesInline(t *testing.T) { + s := newTestStream(t) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 4} + + for range 4 { + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + } + + // Eight appended, four retained, so the floor sits at 4 and the first two + // batches are entirely below it. + require.Equal(t, int64(8), s.State.HeadOffset) + require.Equal(t, int64(4), s.State.BaseOffset) +} + +func TestCapRefusesAnAppendItCouldOnlyAbsorbByDroppingReadRecords(t *testing.T) { + s := newTestStream(t) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 2} + _, err := s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "wf-1", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.ErrorContains(t, err, "still depends on offset 0") + require.Equal(t, int64(0), s.State.HeadOffset, "a refused append writes nothing") + + // Nothing is stuck. The consumer going away is what makes room, and it is + // something someone does rather than something that happens quietly. + s.DeregisterConsumer(nil, "wf-1") + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + require.Equal(t, int64(2), s.State.BaseOffset, "the cap applies once nobody needs the bytes") +} + +func TestCloseSchedulesRetentionOnlyWhenConfigured(t *testing.T) { + now := time.Now() + + plain := newTestStream(t) + require.True(t, plain.Close(now, nil).IsZero(), "no retention configured, nothing to schedule") + + withRetention := newTestStream(t) + withRetention.State.Lifecycle = &streamlib.StreamLifecycle{ + Retention: durationpb.New(time.Hour), + } + at := withRetention.Close(now, nil) + require.Equal(t, now.Add(time.Hour), at) + require.NotNil(t, withRetention.State.CloseTime) + + // Closing twice must not re-arm deletion. + require.True(t, withRetention.Close(now, nil).IsZero()) +} + +func TestRegisterConsumerPinsFromWhereItSubscribed(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + + // Subscribing at 2 says nothing about offsets 0 and 1, so those stay + // droppable and everything from 2 up does not. + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 2, + }) + require.NoError(t, err) + + require.NoError(t, s.Truncate(nil, 2)) + require.Equal(t, int64(2), s.State.BaseOffset) + require.ErrorContains(t, s.Truncate(nil, 3), "still depends on offset 2") +} + +func TestAdvanceConsumerTracksWhereAConsumerHasReached(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + + // The read position decides whether this consumer is worth waking. The + // replay floor, not this, is what retention respects. + s.AdvanceConsumer(nil, "workflow:output", 3) + require.Equal(t, int64(3), s.State.Consumers["workflow:output"].Offset) +} + +// Lowering the pin would hand back a guarantee already written to History: a +// recorded range has to stay re-readable. +func TestAdvanceConsumerNeverRewinds(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + + s.AdvanceConsumer(nil, "workflow:output", 3) + s.AdvanceConsumer(nil, "workflow:output", 1) + + require.Equal(t, int64(3), s.State.Consumers["workflow:output"].GetOffset()) +} + +func TestRegisterConsumerRejectsAnOffsetBelowTheFloor(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + err = s.Truncate(nil, 2) + require.NoError(t, err) + + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 1, + }) + require.ErrorContains(t, err, "below the stream's floor") +} + +// Resubscribing reactivates the existing pin rather than resetting it, so a +// consumer cannot rewind its own floor by subscribing again. +func TestRegisterConsumerTwiceKeepsThePin(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + s.AdvanceConsumer(nil, "workflow:output", 3) + + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + + require.Equal(t, int64(3), s.State.Consumers["workflow:output"].GetOffset()) +} + +func TestDeregisterConsumerReleasesThePin(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 1, + }) + require.NoError(t, err) + + s.DeregisterConsumer(nil, "workflow:output") + + err = s.Truncate(nil, 4) + require.NoError(t, err) +} + +func TestMessageCapStillAppliesWithNoConsumerToProtect(t *testing.T) { + s := newTestStream(t) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 2} + + for range 3 { + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + } + + // The refusal is about a consumer's recovery, so a stream with none behaves + // exactly as a capped log should. + require.Equal(t, int64(6), s.State.HeadOffset) + require.Equal(t, int64(4), s.State.BaseOffset) +} + +// A consumer that arrives after the messages were written cannot make the cap +// retroactively wrong, so the clamp keeps its bytes and the stream sits over +// its cap until it goes away. +func TestCapClampsToAConsumerThatRegisteredLate(t *testing.T) { + s := newTestStream(t) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 2} + + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 1} + s.applyCap() + + require.Equal(t, int64(0), s.State.BaseOffset, "the clamp keeps what the consumer needs") +} + +// The reason the pin was taken out in the first place. It must not come back: +// a consumer that finished has to stop holding storage. +func TestAConsumerThatDeregisteredHoldsNothing(t *testing.T) { + s := newTestStream(t) + s.State.Lifecycle = &streamlib.StreamLifecycle{MaxItems: 2} + _, err := s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + s.DeregisterConsumer(nil, "workflow:output") + + for range 3 { + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + } + require.Equal(t, int64(4), s.State.BaseOffset) +} + +// Coming back to a stream that moved past what its History refers to has to be +// refused at registration, which is the last moment before the workflow +// depends on those offsets again. +func TestReregisteringBelowTheFloorIsRefused(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 0, + }) + require.NoError(t, err) + s.DeregisterConsumer(nil, "workflow:output") + require.NoError(t, s.Truncate(nil, 2)) + + // Resubscribing further along does not repair the gap. What this consumer + // already recorded starts at 0, and offsets 0 and 1 are gone. + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:output", WorkflowID: "wf-1", RunID: "run-1", Offset: 3, + }) + require.ErrorContains(t, err, "the stream now starts at 2") +} + +// A caller sending a fresh producer id per request would otherwise grow the +// component state until no append fits, which leaves the stream unwritable for +// good rather than failing the call that caused it. +func TestStreamProducerTableIsBounded(t *testing.T) { + s := newTestStream(t) + + for i := range MaxProducersPerStream { + _, err := s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("m"), + ProducerID: fmt.Sprintf("p%d", i), + Sequence: 1, + }) + require.NoError(t, err) + } + + _, err := s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("one too many"), + ProducerID: "p-over", + Sequence: 1, + }) + var invalid *serviceerror.InvalidArgument + require.ErrorAs(t, err, &invalid) + + // A producer already tracked keeps working, so the cap cannot wedge the + // producers that filled it. + _, err = s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("still fine"), + ProducerID: "p0", + Sequence: 2, + }) + require.NoError(t, err) + + // An anonymous append is never blocked by the table. + _, err = s.AddMessages(nil, AddMessagesRequest{ + Records: msgs("anon"), + }) + require.NoError(t, err) +} + +// Each consumer holds a truncation floor, so an unbounded table pins storage as +// well as growing state. +func TestStreamConsumerTableIsBounded(t *testing.T) { + s := newTestStream(t) + + for i := range MaxConsumersPerStream { + _, err := s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: fmt.Sprintf("c%d", i), WorkflowID: "wf", RunID: "run", External: true, + }) + require.NoError(t, err) + } + + _, err := s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "c-over", WorkflowID: "wf", RunID: "run", Offset: 0, External: true, + }) + var invalid *serviceerror.InvalidArgument + require.ErrorAs(t, err, &invalid) + + // Re-registering an existing consumer is an update, not a new entry. + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "c0", WorkflowID: "wf", RunID: "run", Offset: 0, External: true, + }) + require.NoError(t, err) +} + +// A producer that leaves the kind unset means data. Delivery to a workflow +// drops anything that is not data, so without this the message would take an +// offset and never be seen by a subscriber. +func TestAddMessagesTreatsAnUnsetKindAsData(t *testing.T) { + s := newTestStream(t) + unset := []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("a")}}, + {Body: &commonpb.Payload{Data: []byte("b")}}, + } + _, err := s.AddMessages(nil, AddMessagesRequest{ + Records: unset, ProducerID: "p", Sequence: 1, + }) + require.NoError(t, err) + + blobs, starts, err := s.ReadBatches(nil, 0, 2, 0) + require.NoError(t, err) + collected, _, err := CollectRecords(blobs, starts, 0, 2, 10, nil) + require.NoError(t, err) + require.Len(t, ToAPIRecords(collected), 2, "both messages must reach a subscriber") + + // The retry carries the same unset kind and has to hash the same. + retry, err := s.AddMessages(nil, AddMessagesRequest{ + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("a")}}, + {Body: &commonpb.Payload{Data: []byte("b")}}, + }, + ProducerID: "p", Sequence: 1, + }) + require.NoError(t, err) + require.True(t, retry.Deduplicated) +} + +// A budgeted stream refuses the append that would not fit rather than dropping +// older messages: its batches are someone's mutable state, and the alternative +// to refusing is the execution size limit terminating that workflow later. +func TestBudgetRefusesAnAppendThatDoesNotFit(t *testing.T) { + s := newTestStream(t) + s.State.Budget = &streamlib.StreamBudget{MaxItems: 3} + + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b")}) + require.NoError(t, err) + + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("c", "d")}) + var exhausted *serviceerror.ResourceExhausted + require.ErrorAs(t, err, &exhausted) + require.Equal(t, int64(2), s.State.HeadOffset, "a refused append writes nothing") + + // The last slot is still there for an append that fits. + _, err = s.AddMessages(nil, AddMessagesRequest{Records: msgs("c")}) + require.NoError(t, err) + + bytesOnly := newTestStream(t) + bytesOnly.State.Budget = &streamlib.StreamBudget{MaxBytes: 16} + _, err = bytesOnly.AddMessages(nil, AddMessagesRequest{Records: msgs("small")}) + require.NoError(t, err) + _, err = bytesOnly.AddMessages(nil, AddMessagesRequest{Records: msgs("another one")}) + require.ErrorAs(t, err, &exhausted) + require.Equal(t, int64(1), bytesOnly.State.HeadOffset) +} + +// One workflow id has one open run, so a pin from another run of the same +// workflow belongs to a run that finished. Registering the new run drops it, +// which is what lets the new run start at its own offset instead of inheriting +// a floor that may already be below the stream's base. +func TestRegisterConsumerReplacesAnEntryFromAnotherRun(t *testing.T) { + s := newTestStream(t) + _, err := s.AddMessages(nil, AddMessagesRequest{Records: msgs("a", "b", "c", "d")}) + require.NoError(t, err) + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:wf/run-1", WorkflowID: "wf", RunID: "run-1", Offset: 0, External: true, + }) + require.NoError(t, err) + + start, err := s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:wf/run-2", WorkflowID: "wf", RunID: "run-2", Offset: 3, External: true, + }) + require.NoError(t, err) + require.Equal(t, int64(3), start) + require.Len(t, s.State.Consumers, 1) + require.Equal(t, "run-2", s.State.Consumers["workflow:wf/run-2"].GetRunId()) + require.NoError(t, s.Truncate(nil, 3), "only the new run's floor holds") + + // A different workflow id is not the same consumer and keeps its pin. + _, err = s.RegisterConsumer(nil, ConsumerRegistration{ + ConsumerID: "workflow:other/run-9", WorkflowID: "other", RunID: "run-9", + Offset: 3, External: true, + }) + require.NoError(t, err) + require.Len(t, s.State.Consumers, 2) +} + +// Every append that leaves an external consumer behind would otherwise queue a +// task of its own. One outstanding task carries every append that lands before +// it runs, and the task's own read lowers the flag before the next one is owed. +func TestNotifyCoalescesIntoOneOutstandingTask(t *testing.T) { + mctx := &chasm.MockMutableContext{MockContext: chasm.MockContext{ + HandleNow: func(chasm.Component) time.Time { return time.Unix(0, 0) }, + }} + s := newTestStream(t) + s.Batches = make(chasm.Map[int64, *commonpb.DataBlob]) + _, err := s.RegisterConsumer(mctx, ConsumerRegistration{ + ConsumerID: "workflow:wf/run-1", WorkflowID: "wf", RunID: "run-1", Offset: 0, External: true, + }) + require.NoError(t, err) + + _, err = s.AddMessages(mctx, AddMessagesRequest{Records: msgs("a")}) + require.NoError(t, err) + _, err = s.AddMessages(mctx, AddMessagesRequest{Records: msgs("b")}) + require.NoError(t, err) + require.Len(t, mctx.Tasks, 1, "the second append rides the task the first scheduled") + + // The task's read lowers the flag, so the next append owes a new task. + state, err := s.TakeNotifySnapshot(mctx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(2), state.GetHeadOffset(), + "the task sees every append that landed before it") + _, err = s.AddMessages(mctx, AddMessagesRequest{Records: msgs("c")}) + require.NoError(t, err) + require.Len(t, mctx.Tasks, 2) +} diff --git a/chasm/lib/tests/nexus_service.go b/chasm/lib/tests/nexus_service.go index 0ae0d42905f..386073e1ec6 100644 --- a/chasm/lib/tests/nexus_service.go +++ b/chasm/lib/tests/nexus_service.go @@ -9,9 +9,14 @@ import ( "go.temporal.io/server/common/payload" ) -var TestOperation = nexus.NewSyncOperation("TestOperation", func(ctx context.Context, input string, options nexus.StartOperationOptions) (string, error) { - return "Hello, " + input, nil -}) +// TestOperation returns a failurepb.Failure so that it is a proper protobuf type. Its used for +// testing the System Nexus Endpoint, which only accepts protobuf-encoded payloads. +var TestOperation = nexus.NewSyncOperation( + "TestOperation", + func(ctx context.Context, input string, options nexus.StartOperationOptions) (*commonpb.DataBlob, error) { + d := []byte("Hello, " + input) + return &commonpb.DataBlob{Data: d}, nil + }) // TestOperationWithPayload is identical to TestOperation, except its response embeds a // nested *commonpb.Payload. It exists to exercise the commonnexus.SystemPayloadMetadataKey @@ -20,10 +25,18 @@ var TestOperationWithPayload = nexus.NewSyncOperation("TestOperationWithPayload" return &commonpb.Payloads{Payloads: []*commonpb.Payload{payload.EncodeString("Hello, " + input)}}, nil }) +// TestOperationStringOutput returns a string, which the data converter encodes as JSON rather +// than protobuf. It exists to exercise the System Nexus Endpoint's rejection of non-protobuf +// responses in service/history/handler.go's StartNexusOperation. +var TestOperationStringOutput = nexus.NewSyncOperation("TestOperationStringOutput", func(ctx context.Context, input string, options nexus.StartOperationOptions) (string, error) { + return "Hello, " + input, nil +}) + func NewTestServiceNexusService() *nexus.Service { service := nexus.NewService("TestService") service.MustRegister(TestOperation) service.MustRegister(TestOperationWithPayload) + service.MustRegister(TestOperationStringOutput) return service } @@ -43,5 +56,6 @@ func NewTestServiceNexusServiceProcessor() *chasm.NexusServiceProcessor { sp := chasm.NewNexusServiceProcessor("TestService") sp.MustRegisterOperation("TestOperation", chasm.NewRegisterableNexusOperationProcessor(testOperationProcessor{})) sp.MustRegisterOperation("TestOperationWithPayload", chasm.NewRegisterableNexusOperationProcessor(testOperationProcessor{})) + sp.MustRegisterOperation("TestOperationStringOutput", chasm.NewRegisterableNexusOperationProcessor(testOperationProcessor{})) return sp } diff --git a/chasm/lib/workflow/fx.go b/chasm/lib/workflow/fx.go index 52730794faa..8e69ef2f8b8 100644 --- a/chasm/lib/workflow/fx.go +++ b/chasm/lib/workflow/fx.go @@ -4,6 +4,7 @@ import ( "go.temporal.io/server/api/historyservice/v1" "go.temporal.io/server/chasm" "go.temporal.io/server/chasm/lib/nexusoperation" + "go.temporal.io/server/chasm/lib/stream" "go.uber.org/fx" ) @@ -12,16 +13,23 @@ var Module = fx.Module( fx.Provide(NewConfig), fx.Provide(NewRegistry), fx.Provide(newLibrary), + // Provided here rather than by the stream service module, because the + // command handlers need it in every service that runs this library. + fx.Provide(stream.NewConfig), fx.Invoke(func( chasmRegistry *chasm.Registry, library *library, config *nexusoperation.Config, + streamConfig *stream.Config, ) error { if err := library.registry.Register( newNexusLibrary(config, chasmRegistry.NexusEndpointProcessor), ); err != nil { return err } + if err := library.registry.Register(newStreamLibrary(streamConfig)); err != nil { + return err + } return chasmRegistry.Register(library) }), ) diff --git a/chasm/lib/workflow/stream_commands.go b/chasm/lib/workflow/stream_commands.go new file mode 100644 index 00000000000..0c6ea260709 --- /dev/null +++ b/chasm/lib/workflow/stream_commands.go @@ -0,0 +1,406 @@ +package workflow + +import ( + "errors" + + commandpb "go.temporal.io/api/command/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +// DefaultStreamName is the stream a command addresses when it names none. +const DefaultStreamName = "output" + +// StreamAdmissionFailure turns a refusal of a stream command into a workflow +// task failure with the given cause. +// +// A refusal returned as a plain error fails the RespondWorkflowTaskCompleted +// call instead, and the worker then retries the same commands against the same +// limits until the task times out, with nothing in History saying why. Only +// refusals are converted: an internal or storage error is still the request's +// to report, because a retry can succeed. +func StreamAdmissionFailure(cause enumspb.WorkflowTaskFailedCause, err error) error { + var invalid *serviceerror.InvalidArgument + var precondition *serviceerror.FailedPrecondition + var exhausted *serviceerror.ResourceExhausted + var notFound *serviceerror.NotFound + if errors.As(err, &invalid) || errors.As(err, &precondition) || + errors.As(err, &exhausted) || errors.As(err, ¬Found) { + return FailWorkflowTaskError{Cause: cause, Message: err.Error()} + } + return err +} + +// handleAppendStreamRecordsCommand appends to a stream the workflow owns. +// +// The stream is a co-located subcomponent, so the batch and the frontier land +// in the workflow task's own commit: no extra transition, no cross-execution +// write, and a task that fails takes the publish with it. +// +// The offsets are known here, unlike a subscription's, so the event is written +// here too rather than reserved and filled in later. +func handleAppendStreamRecordsCommand( + chasmCtx chasm.MutableContext, + wf *Workflow, + validator Validator, + command *commandpb.Command, + opts CommandHandlerOptions, + limits stream.Limits, +) error { + badAttributes := enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_APPEND_STREAM_RECORDS_ATTRIBUTES + attrs := command.GetAppendStreamRecordsCommandAttributes() + if attrs == nil { + return FailWorkflowTaskError{ + Cause: badAttributes, Message: "AppendStreamRecordsCommandAttributes is not set", + } + } + if len(attrs.GetRecords()) == 0 { + return FailWorkflowTaskError{ + Cause: badAttributes, Message: "AppendStreamRecords command carries no records", + } + } + + // The batch becomes one data node, so the whole batch is what has to fit. + // Left unchecked it fails later in the flush, which surfaces as a + // persistence error out of a task the worker will replay and re-issue + // forever, with nothing naming the batch as the cause. + size := 0 + for _, m := range attrs.GetRecords() { + size += m.Size() + } + if !validator.IsValidPayloadSize(size) { + return FailWorkflowTaskError{ + Cause: enumspb.WORKFLOW_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE, + Message: "AppendStreamRecordsCommandAttributes.Records exceeds size limit", + TerminateWorkflow: true, + } + } + + name := attrs.GetStreamId() + if name == "" { + name = DefaultStreamName + } + + s, err := wf.streamNamed(chasmCtx, name, limits) + if err != nil { + return StreamAdmissionFailure(badAttributes, err) + } + + result, err := s.AddMessages(chasmCtx, stream.AddMessagesRequest{ + Records: toLibraryRecords(attrs.GetRecords()), + Limits: limits, + }) + if err != nil { + return StreamAdmissionFailure(badAttributes, err) + } + // Written even when a producer sequence deduplicated the append, because + // the command was still issued and the event is what the replaying worker + // matches it against. It names the original offsets, which is what a + // deduplicated append resolves to. + wf.RecordStreamRecordsAppended( + name, result.FirstOffset, result.Count, opts.WorkflowTaskCompletedEventID) + return nil +} + +// handleSubscribeStreamCommand registers this workflow as a consumer. +// +// Nothing is registered here. A stream in another execution has to be pinned +// on its own shard, which a command handler cannot reach while holding the +// state lock, so the subscription is staged and resolved after the commands and +// before the commit. +func handleSubscribeStreamCommand( + chasmCtx chasm.MutableContext, + wf *Workflow, + _ Validator, + command *commandpb.Command, + opts CommandHandlerOptions, +) error { + badAttributes := enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SUBSCRIBE_STREAM_ATTRIBUTES + attrs := command.GetSubscribeStreamCommandAttributes() + if attrs == nil { + return FailWorkflowTaskError{ + Cause: badAttributes, Message: "SubscribeStreamCommandAttributes is not set", + } + } + streamID := attrs.GetStreamId() + if streamID == "" { + return FailWorkflowTaskError{ + Cause: badAttributes, Message: "SubscribeStream command names no stream", + } + } + + // A second subscribe to the same stream registers nothing, but it still + // gets an event. Every SDK matches issued commands against + // command-generated events in order, so a command that produces none puts + // that matching out of step, which is the whole reason this event exists. + _, already := wf.StreamCursors[streamID] + + // Everything is staged, including a stream this workflow owns, so that the + // resolved start offset and the event recording it are produced in one + // place rather than two. + wf.StagePendingSubscription(PendingStreamSubscription{ + StreamID: streamID, + StartOffset: attrs.GetStartOffset(), + AlreadySubscribed: already, + Event: wf.ReserveStreamSubscribedEvent( + streamID, opts.WorkflowTaskCompletedEventID), + }) + return nil +} + +// streamSubscribedEvent is the event a subscription writes. +// +// It is recorded once per subscription, not per record: the offsets a task +// consumed ride WorkflowTaskCompleted, and payloads never enter History. The +// event exists because a command that produces none desynchronises the +// command-to-event matching every SDK's replay depends on, and because without +// it nothing in History explains why a workflow started receiving stream data. +type streamSubscribedEvent struct{} + +func (streamSubscribedEvent) Type() enumspb.EventType { + return enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED +} + +func (streamSubscribedEvent) IsWorkflowTaskTrigger() bool { return false } + +// Apply recreates the cursor for a run rebuilt from its history, which is how a +// reset run comes to exist. The event records the stream and where reading +// began; the ranges consumed since are folded in as the completed events that +// carry them are applied. Whether the stream lives in this execution or in +// another is not in the event, so the rebuilt cursor is owned until the reset +// copies that from the run it was rebuilt from. +func (streamSubscribedEvent) Apply( + mctx chasm.MutableContext, + wf *Workflow, + event *historypb.HistoryEvent, +) error { + attrs := event.GetWorkflowStreamSubscribedEventAttributes() + if _, ok := wf.StreamCursors[attrs.GetStreamId()]; ok { + return nil + } + cursor, err := stream.NewCursor(mctx, stream.NewCursorRequest{ + StreamID: attrs.GetStreamId(), + StartOffset: attrs.GetStartOffset(), + }) + if err != nil { + return err + } + if wf.StreamCursors == nil { + wf.StreamCursors = make(chasm.Map[string, *stream.Cursor]) + } + wf.StreamCursors[attrs.GetStreamId()] = chasm.NewComponentField(mctx, cursor) + return nil +} + +// A command event, so it is never cherry-picked: the workflow reissues the +// subscribe command on the new branch if it still wants one. +func (streamSubscribedEvent) CherryPick( + chasm.MutableContext, + *Workflow, + *historypb.HistoryEvent, + map[enumspb.ResetReapplyExcludeType]struct{}, +) error { + return ErrEventNotCherryPickable +} + +// ReserveStreamSubscribedEvent writes the event a subscribe command owes, +// leaving the start offset for the flush to fill in. +// +// Written here rather than where the offset becomes known, because an SDK +// matches the commands a workflow issued against the events they produced by +// position. The flush runs after every command, so an event written there +// would sit behind the events of commands that were issued later, and the +// first replay of a workflow that subscribed before doing anything else would +// fail on the mismatch. +func (w *Workflow) ReserveStreamSubscribedEvent( + streamID string, + workflowTaskCompletedEventID int64, +) *historypb.HistoryEvent { + eventType := enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED + return w.AddHistoryEvent(eventType, func(e *historypb.HistoryEvent) { + attrs := &historypb.WorkflowStreamSubscribedEventAttributes{ + WorkflowTaskCompletedEventId: workflowTaskCompletedEventID, + StreamId: streamID, + } + e.Attributes = &historypb.HistoryEvent_WorkflowStreamSubscribedEventAttributes{ + WorkflowStreamSubscribedEventAttributes: attrs, + } + }) +} + +// RecordStreamSubscribedOffset completes a reserved event. Safe to do after the +// fact because the builder serializes the batch at commit, which is after the +// flush that resolves the offset. +func RecordStreamSubscribedOffset(event *historypb.HistoryEvent, startOffset int64) { + event.GetWorkflowStreamSubscribedEventAttributes().StartOffset = startOffset +} + +// streamRecordsAppendedEvent is the event a publish writes. +// +// One per batch, holding the offset range and nothing else. That is what makes +// it a fixed cost: a batch of one 20-byte record and a batch of a thousand +// 2KB records write the same event, because the bodies stay in the stream +// component. It exists for the same reason the subscription event does, that a +// command producing no event desynchronises the command-to-event matching +// every SDK's replay depends on, and it doubles as the only record in History +// that the workflow published at all. +type streamRecordsAppendedEvent struct{} + +func (streamRecordsAppendedEvent) Type() enumspb.EventType { + return enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED +} + +func (streamRecordsAppendedEvent) IsWorkflowTaskTrigger() bool { return false } + +// The frontier it describes is CHASM state, persisted and rebuilt with the +// execution, so there is nothing here to reconstruct. +func (streamRecordsAppendedEvent) Apply( + chasm.MutableContext, *Workflow, *historypb.HistoryEvent, +) error { + return nil +} + +// A command event, so it is never cherry-picked: the offsets belong to a log +// the new branch did not write. +func (streamRecordsAppendedEvent) CherryPick( + chasm.MutableContext, + *Workflow, + *historypb.HistoryEvent, + map[enumspb.ResetReapplyExcludeType]struct{}, +) error { + return ErrEventNotCherryPickable +} + +// RecordStreamRecordsAppended writes the event for one published batch. +func (w *Workflow) RecordStreamRecordsAppended( + streamID string, + firstOffset int64, + count int64, + workflowTaskCompletedEventID int64, +) { + eventType := enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED + w.AddHistoryEvent(eventType, func(e *historypb.HistoryEvent) { + attrs := &historypb.WorkflowStreamRecordsAppendedEventAttributes{ + WorkflowTaskCompletedEventId: workflowTaskCompletedEventID, + StreamId: streamID, + FirstOffset: firstOffset, + RecordCount: count, + } + e.Attributes = &historypb.HistoryEvent_WorkflowStreamRecordsAppendedEventAttributes{ + WorkflowStreamRecordsAppendedEventAttributes: attrs, + } + }) +} + +// streamNamed returns the workflow's stream of that name, creating it on first +// use. Implicit creation is deliberate: a workflow publishing to its own output +// should not have to coordinate with anyone about who creates it. +// +// The stream belongs to this run. After a reset the new run publishes to and +// subscribes on streams of its own, created here on first use, and the run it +// was reset from keeps the records its own history refers to. A stream the +// reset run inherited a subscription to is created by the reset itself, at the +// offset that subscription stood at, so it is already here by the time a +// command names it. +func (w *Workflow) streamNamed( + ctx chasm.MutableContext, + name string, + limits stream.Limits, +) (*stream.Stream, error) { + if w.Streams == nil { + w.Streams = make(chasm.Map[string, *stream.Stream]) + } + if field, ok := w.Streams[name]; ok { + return field.Get(ctx), nil + } + + // Checked only on the create path, so an existing stream is never refused + // for room. The name arrives from the caller and every distinct one adds a + // component to this execution's mutable state, so without a bound an + // outside writer can grow that state until the size limit terminates the + // workflow. + if len(name) > stream.MaxStreamNameLength { + return nil, serviceerror.NewInvalidArgumentf( + "stream name is %d characters, over the %d limit", len(name), stream.MaxStreamNameLength) + } + if len(w.Streams) >= limits.MaxOwnedStreamsPerWorkflow { + return nil, serviceerror.NewFailedPreconditionf( + "workflow already owns %d streams, the limit", limits.MaxOwnedStreamsPerWorkflow) + } + + // Budgeted, because the batches live in this execution's mutable state and + // the size limit on that terminates the workflow instead of refusing. + created, err := stream.NewStream(ctx, stream.NewStreamRequest{ + Attached: true, + Budget: &streamlib.StreamBudget{ + MaxItems: int64(limits.OwnedStreamMaxItems), + MaxBytes: int64(limits.OwnedStreamMaxBytes), + }, + }) + if err != nil { + return nil, err + } + w.Streams[name] = chasm.NewComponentField(ctx, created) + return created, nil +} + +// toLibraryRecords shapes a command's records for the store. +// +// The producer id is cleared rather than copied: an empty id is how a reader +// tells the owning workflow's records from an outside producer's, and only this +// path writes on the workflow's behalf. The kind is settled here as well as in +// the store, because the store settles it in place and the command's records +// belong to the worker's request. +func toLibraryRecords(in []*streampb.StreamRecord) []*streamlib.StreamRecord { + out := make([]*streamlib.StreamRecord, len(in)) + for i, m := range in { + kind := m.GetKind() + if kind == streampb.STREAM_RECORD_KIND_UNSPECIFIED { + kind = streampb.STREAM_RECORD_KIND_DATA + } + out[i] = &streamlib.StreamRecord{ + Body: m.GetBody(), + Metadata: m.GetMetadata(), + Topic: m.GetTopic(), + Kind: kind, + ProducerId: "", + Attempt: m.GetAttempt(), + Sequence: m.GetSequence(), + } + } + return out +} + +// streamLibrary registers the stream commands with the workflow registry. +type streamLibrary struct { + config *stream.Config +} + +func newStreamLibrary(config *stream.Config) *streamLibrary { + return &streamLibrary{config: config} +} + +func (l *streamLibrary) CommandHandlers() map[enumspb.CommandType]CommandHandler { + return map[enumspb.CommandType]CommandHandler{ + enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS: func( + chasmCtx chasm.MutableContext, + wf *Workflow, + validator Validator, + command *commandpb.Command, + opts CommandHandlerOptions, + ) error { + limits := l.config.LimitsFor(chasmCtx.NamespaceEntry().Name().String()) + return handleAppendStreamRecordsCommand(chasmCtx, wf, validator, command, opts, limits) + }, + enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM: handleSubscribeStreamCommand, + } +} + +func (l *streamLibrary) EventDefinitions() []EventDefinition { + return []EventDefinition{streamSubscribedEvent{}, streamRecordsAppendedEvent{}} +} diff --git a/chasm/lib/workflow/stream_commands_test.go b/chasm/lib/workflow/stream_commands_test.go new file mode 100644 index 00000000000..994e5c92bd2 --- /dev/null +++ b/chasm/lib/workflow/stream_commands_test.go @@ -0,0 +1,41 @@ +package workflow + +import ( + "testing" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + streampb "go.temporal.io/api/stream/v1" +) + +// An empty producer id is how a reader tells the owning workflow's records from +// an outside producer's. The command path is the only writer on the workflow's +// behalf, so it decides the field rather than trusting what the worker sent, +// while the attempt and sequence stay the worker's to number. +func TestPublishedRecordsBelongToTheWorkflow(t *testing.T) { + got := toLibraryRecords([]*streampb.StreamRecord{ + { + Body: &commonpb.Payload{Data: []byte("token")}, + Metadata: map[string]*commonpb.Payload{"k": {Data: []byte("v")}}, + Topic: "tokens", + Kind: streampb.STREAM_RECORD_KIND_FINISH, + ProducerId: "impostor", + Attempt: 3, + Sequence: 9, + }, + {Body: &commonpb.Payload{Data: []byte("kindless")}}, + }) + require.Len(t, got, 2) + + require.Equal(t, "token", string(got[0].GetBody().GetData())) + require.Equal(t, "v", string(got[0].GetMetadata()["k"].GetData())) + require.Equal(t, "tokens", got[0].GetTopic()) + require.Equal(t, streampb.STREAM_RECORD_KIND_FINISH, got[0].GetKind()) + require.Empty(t, got[0].GetProducerId(), "the workflow is the producer here") + require.Equal(t, int64(3), got[0].GetAttempt()) + require.Equal(t, int64(9), got[0].GetSequence()) + + require.Equal(t, streampb.STREAM_RECORD_KIND_DATA, got[1].GetKind(), + "a record with no kind is data") + require.Empty(t, got[1].GetProducerId()) +} diff --git a/chasm/lib/workflow/stream_cursor_test.go b/chasm/lib/workflow/stream_cursor_test.go new file mode 100644 index 00000000000..dfe88da5ae0 --- /dev/null +++ b/chasm/lib/workflow/stream_cursor_test.go @@ -0,0 +1,400 @@ +package workflow + +import ( + "testing" + + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +func newStreamCursorTestContext() chasm.MutableContext { + return &chasm.MockMutableContext{ + MockContext: chasm.MockContext{ + HandleExecutionKey: func() chasm.ExecutionKey { + return chasm.ExecutionKey{ + NamespaceID: "ns-1", + BusinessID: "wf-1", + RunID: "run-1", + } + }, + }, + } +} + +// Built directly rather than through NewStream, which wires a visibility field +// needing a live context. +func newAttachedStream(t *testing.T, ctx chasm.MutableContext, count int) *stream.Stream { + t.Helper() + + s := &stream.Stream{ + State: &streamlib.StreamState{ + Producers: make(map[string]*streamlib.ProducerCursor), + Consumers: make(map[string]*streamlib.ConsumerCursor), + }, + } + + messages := make([]*streamlib.StreamRecord, count) + for i := range messages { + messages[i] = &streamlib.StreamRecord{Kind: streampb.STREAM_RECORD_KIND_DATA} + } + _, err := s.AddMessages(ctx, stream.AddMessagesRequest{Records: messages}) + require.NoError(t, err) + + return s +} + +// Subscribing registers the consumer on the stream, which decides both whether +// an append is worth waking it for and what retention may not take. A range +// this workflow consumes goes into its History, and a replay is asked to +// reproduce it, so the stream holds those messages while the subscription is +// active and releases them when it is not. +func TestSubscribeRegistersTheConsumer(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + owned := newAttachedStream(t, ctx, 4) + w.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(ctx, owned), + } + + start, err := w.SubscribeToOwnedStream(ctx, DefaultStreamName, 0, stream.DefaultLimits()) + require.NoError(t, err) + require.Equal(t, int64(0), start) + + consumer := owned.State.GetConsumers()[streamConsumerID(DefaultStreamName)] + require.NotNil(t, consumer, "the stream has to know who is reading it") + require.Equal(t, int64(0), consumer.GetOffset()) + require.True(t, consumer.GetActive()) + + require.Equal(t, int64(0), consumer.GetReplayFloor()) + + // And it holds the floor for as long as it is subscribed. + require.ErrorContains(t, owned.Truncate(ctx, 1), "still depends on offset 0") +} + +func TestSubscribeFromTheTailResolvesToHead(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + owned := newAttachedStream(t, ctx, 4) + w.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(ctx, owned), + } + + start, err := w.SubscribeToOwnedStream(ctx, DefaultStreamName, -1, stream.DefaultLimits()) + require.NoError(t, err) + require.Equal(t, int64(4), start, "a negative offset means from wherever the stream is now") +} + +// A workflow reads a topic by name before anything has been written to it, so +// subscribing has to bring the stream into being the way a first write does. +func TestSubscribeCreatesTheStreamItNames(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + + start, err := w.SubscribeToOwnedStream(ctx, "inputs", 0, stream.DefaultLimits()) + require.NoError(t, err) + require.Equal(t, int64(0), start) + + field, ok := w.Streams["inputs"] + require.True(t, ok, "the subscribed name is now an owned stream") + state, err := field.Get(ctx).Snapshot(ctx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(0), state.GetHeadOffset()) + require.Len(t, state.GetConsumers(), 1, "the subscription pinned the new stream") +} + +// Committing a delivered range moves the consumer's cursor on the stream, so +// the stream knows how far this reader has got. +func TestCommitStreamCursorsAdvancesTheConsumer(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + owned := newAttachedStream(t, ctx, 4) + w.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(ctx, owned), + } + + _, err := w.SubscribeToOwnedStream(ctx, DefaultStreamName, 0, stream.DefaultLimits()) + require.NoError(t, err) + + cursor := w.StreamCursors[DefaultStreamName].Get(ctx) + require.NoError(t, cursor.StagePending(ctx, 0, 3)) + + recorded := w.CommitStreamCursors(ctx) + require.Len(t, recorded, 1) + require.Equal(t, int64(0), recorded[0].GetFromOffset()) + require.Equal(t, int64(3), recorded[0].GetToOffset()) + + require.Equal(t, int64(3), + owned.State.GetConsumers()[streamConsumerID(DefaultStreamName)].GetOffset(), + "the stream must see how far the consumer has read") +} + +// An idle task records an empty range, which must leave the consumer alone. +func TestCommitStreamCursorsWithAnEmptyRangeHoldsTheConsumer(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + owned := newAttachedStream(t, ctx, 4) + w.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(ctx, owned), + } + + _, err := w.SubscribeToOwnedStream(ctx, DefaultStreamName, 0, stream.DefaultLimits()) + require.NoError(t, err) + + cursor := w.StreamCursors[DefaultStreamName].Get(ctx) + require.NoError(t, cursor.StagePending(ctx, 0, 0)) + + recorded := w.CommitStreamCursors(ctx) + require.Len(t, recorded, 1, "an empty range is still recorded") + require.Equal(t, recorded[0].GetFromOffset(), recorded[0].GetToOffset()) + + require.Equal(t, int64(0), + owned.State.GetConsumers()[streamConsumerID(DefaultStreamName)].GetOffset(), + "consuming nothing must not move the consumer") +} + +// Two publishes in one workflow task each write their own batch, keyed by the +// offset it starts at, so neither collides with the other and a retry of +// either addresses the same key it wrote before. +func TestPublishStagesEachBatchAtItsOwnOffset(t *testing.T) { + ctx := newStreamCursorTestContext() + + // A backend, because the handler writes the publish event and that event is + // part of what the command owes. + backend := &chasm.MockNodeBackend{ + HandleAddHistoryEvent: func( + t enumspb.EventType, set func(*historypb.HistoryEvent), + ) *historypb.HistoryEvent { + e := &historypb.HistoryEvent{EventType: t} + set(e) + return e + }, + } + w := &Workflow{MSPointer: chasm.NewMSPointer(backend)} + opts := CommandHandlerOptions{WorkflowTaskCompletedEventID: 10} + + publish := &commandpb.Command{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("x")}}, + {Body: &commonpb.Payload{Data: []byte("y")}}, + }, + }, + }, + } + + limits := stream.DefaultLimits() + require.NoError(t, handleAppendStreamRecordsCommand(ctx, w, allowAnySize{}, publish, opts, limits)) + require.NoError(t, handleAppendStreamRecordsCommand(ctx, w, allowAnySize{}, publish, opts, limits)) + + // Both publishes committed with the workflow task, so the batches are on + // the component keyed by the offsets they start at. + owned := w.Streams[DefaultStreamName].Get(ctx) + require.Len(t, owned.Batches, 2) + _, ok := owned.Batches[0] + require.True(t, ok) + _, ok = owned.Batches[2] + require.True(t, ok) + require.Equal(t, int64(4), owned.State.GetHeadOffset()) +} + +type allowAnySize struct{} + +func (allowAnySize) IsValidPayloadSize(int) bool { return true } + +// A consumer that falls behind a truncating stream must be told, not handed +// what is left with a hole in it. +// +// Being outrun is possible again once the subscription is released, which is +// deliberate: a floor that nothing ever gave up would keep every message for +// as long as a consumer had ever existed. The trade is that being outrun has +// to be loud. +func TestConsumerOutrunByTruncationIsToldSo(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + owned := newAttachedStream(t, ctx, 4) + w.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(ctx, owned), + } + + _, err := w.SubscribeToOwnedStream(ctx, DefaultStreamName, 0, stream.DefaultLimits()) + require.NoError(t, err) + + // Someone decides these messages are no longer needed, and only then can + // the stream move past where this consumer is sitting. + owned.DeregisterConsumer(ctx, streamConsumerID(DefaultStreamName)) + err = owned.Truncate(ctx, 3) + require.NoError(t, err, "a released floor must not keep holding") + + cursor := w.StreamCursors[DefaultStreamName].Get(ctx) + require.Less(t, cursor.Offset(), owned.State.GetBaseOffset()) + + state, err := owned.Snapshot(ctx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(3), state.GetBaseOffset(), + "the floor moved, which is what the consumer has to find out about") +} + +func newStreamCursorTestContextForRun(runID string) chasm.MutableContext { + return &chasm.MockMutableContext{ + MockContext: chasm.MockContext{ + HandleExecutionKey: func() chasm.ExecutionKey { + return chasm.ExecutionKey{NamespaceID: "ns-1", BusinessID: "wf-1", RunID: runID} + }, + }, + } +} + +func subscribedEvent(streamID string, startOffset int64) *historypb.HistoryEvent { + return &historypb.HistoryEvent{ + EventType: enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED, + Attributes: &historypb.HistoryEvent_WorkflowStreamSubscribedEventAttributes{ + WorkflowStreamSubscribedEventAttributes: &historypb.WorkflowStreamSubscribedEventAttributes{ + StreamId: streamID, + StartOffset: startOffset, + }, + }, + } +} + +// A run rebuilt from its history, which is what a reset produces, gets its +// cursors back from the events alone: the subscribe event places the cursor +// and each completed task's recorded range moves it. +func TestRebuildRecreatesTheCursorFromItsEvents(t *testing.T) { + ctx := newStreamCursorTestContext() + w := &Workflow{} + + require.NoError(t, streamSubscribedEvent{}.Apply(ctx, w, subscribedEvent("inputs", 1))) + cursor := w.StreamCursors["inputs"].Get(ctx) + require.Equal(t, int64(1), cursor.StartOffset()) + require.Equal(t, int64(1), cursor.Offset()) + require.False(t, cursor.IsExternal(), "the event cannot say where the stream lives") + + require.NoError(t, w.ApplyConsumedStreamRanges(ctx, []*streampb.StreamRange{ + {StreamId: "inputs", FromOffset: 1, ToOffset: 4}, + {StreamId: "out-of-band", FromOffset: 3, ToOffset: 9}, + })) + require.Equal(t, int64(4), cursor.Offset()) + require.Equal(t, int64(1), cursor.StartOffset(), "where reading began does not move") + outOfBand, ok := w.StreamCursors["out-of-band"] + require.True(t, ok, "a recorded range proves a subscription the events never mentioned") + require.Equal(t, int64(3), outOfBand.Get(ctx).StartOffset()) + require.Equal(t, int64(9), outOfBand.Get(ctx).Offset()) + + // The same subscribe event applied twice, as a resubscribe would leave in + // History, must not rewind the cursor. + require.NoError(t, streamSubscribedEvent{}.Apply(ctx, w, subscribedEvent("inputs", 1))) + require.Equal(t, int64(4), w.StreamCursors["inputs"].Get(ctx).Offset()) +} + +// A reset run's cursor on a stream the base run owned gets a stream of the +// reset run's own, starting where the cursor stands, so the ranges below it +// stay in the base run and everything from here on is the reset run's. +func TestResetRunInheritsAnOwnedStreamAtItsCursor(t *testing.T) { + baseCtx := newStreamCursorTestContextForRun("base-run") + base := &Workflow{} + base.Streams = chasm.Map[string, *stream.Stream]{ + DefaultStreamName: chasm.NewComponentField(baseCtx, newAttachedStream(t, baseCtx, 4)), + } + _, err := base.SubscribeToOwnedStream(baseCtx, DefaultStreamName, 0, stream.DefaultLimits()) + require.NoError(t, err) + + resetCtx := newStreamCursorTestContextForRun("reset-run") + reset := &Workflow{} + require.NoError(t, + streamSubscribedEvent{}.Apply(resetCtx, reset, subscribedEvent(DefaultStreamName, 0))) + require.NoError(t, reset.ApplyConsumedStreamRanges(resetCtx, []*streampb.StreamRange{ + {StreamId: DefaultStreamName, FromOffset: 0, ToOffset: 2}, + })) + + require.NoError(t, reset.InheritStreamsOnReset(resetCtx, base, baseCtx, stream.DefaultLimits())) + + cursor := reset.StreamCursors[DefaultStreamName].Get(resetCtx) + require.False(t, cursor.IsExternal()) + require.Equal(t, int64(2), cursor.Offset()) + + own := reset.OwnedStream(resetCtx, DefaultStreamName) + require.NotNil(t, own, "the reset run reads and writes a stream of its own") + state, err := own.Snapshot(resetCtx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(2), state.GetBaseOffset(), "the stream continues the offset space") + require.Equal(t, int64(2), state.GetHeadOffset()) + require.NotNil(t, state.GetBudget(), "an owned stream is budgeted like one created by a publish") + pin := state.GetConsumers()[streamConsumerID(DefaultStreamName)] + require.NotNil(t, pin, "the reset run pins its own stream") + require.Equal(t, "reset-run", pin.GetRunId()) + require.Equal(t, int64(2), pin.GetReplayFloor()) + + // The base run's stream is untouched: it still holds what the reset run's + // history refers to. + baseState, err := base.OwnedStream(baseCtx, DefaultStreamName).Snapshot(baseCtx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(0), baseState.GetBaseOffset()) + require.Equal(t, int64(4), baseState.GetHeadOffset()) + + // A publish on the reset run lands after the inherited position. + result, err := own.AddMessages(resetCtx, stream.AddMessagesRequest{ + Records: []*streamlib.StreamRecord{{Kind: streampb.STREAM_RECORD_KIND_DATA}}, + Limits: stream.DefaultLimits(), + }) + require.NoError(t, err) + require.Equal(t, int64(2), result.FirstOffset) +} + +// A reset run's cursor on a stream in another execution stays on that stream +// and learns what the base run knew of its frontier. +func TestResetRunInheritsAnExternalCursorAsExternal(t *testing.T) { + baseCtx := newStreamCursorTestContextForRun("base-run") + base := &Workflow{} + _, err := base.SubscribeToExternalStream(baseCtx, ExternalStreamSubscription{ + StreamID: "shared", StartOffset: 0, KnownHead: 7, + }) + require.NoError(t, err) + + resetCtx := newStreamCursorTestContextForRun("reset-run") + reset := &Workflow{} + require.NoError(t, streamSubscribedEvent{}.Apply(resetCtx, reset, subscribedEvent("shared", 0))) + require.NoError(t, reset.ApplyConsumedStreamRanges(resetCtx, []*streampb.StreamRange{ + {StreamId: "shared", FromOffset: 0, ToOffset: 3}, + })) + + require.NoError(t, reset.InheritStreamsOnReset(resetCtx, base, baseCtx, stream.DefaultLimits())) + + cursor := reset.StreamCursors["shared"].Get(resetCtx) + require.True(t, cursor.IsExternal()) + require.Equal(t, int64(3), cursor.Offset()) + require.Equal(t, int64(7), cursor.KnownHead(), "the frontier the base run last knew carries over") + require.Nil(t, reset.OwnedStream(resetCtx, "shared"), "no stream of its own for an external one") +} + +// A subscription made through the service leaves no event, so a reset run whose +// history records nothing for it is given the cursor from the base run, where +// that subscription began. +func TestResetRunCarriesASubscriptionTheEventsNeverMentioned(t *testing.T) { + baseCtx := newStreamCursorTestContextForRun("base-run") + base := &Workflow{} + base.Streams = chasm.Map[string, *stream.Stream]{ + "inputs": chasm.NewComponentField(baseCtx, newAttachedStream(t, baseCtx, 4)), + } + _, err := base.SubscribeToOwnedStream(baseCtx, "inputs", 1, stream.DefaultLimits()) + require.NoError(t, err) + + resetCtx := newStreamCursorTestContextForRun("reset-run") + reset := &Workflow{} + require.NoError(t, reset.InheritStreamsOnReset(resetCtx, base, baseCtx, stream.DefaultLimits())) + + cursor := reset.StreamCursors["inputs"].Get(resetCtx) + require.Equal(t, int64(1), cursor.StartOffset()) + require.Equal(t, int64(1), cursor.Offset()) + state, err := reset.OwnedStream(resetCtx, "inputs").Snapshot(resetCtx, struct{}{}) + require.NoError(t, err) + require.Equal(t, int64(1), state.GetBaseOffset()) +} diff --git a/chasm/lib/workflow/workflow.go b/chasm/lib/workflow/workflow.go index 2b5409a4147..225ba0e1cec 100644 --- a/chasm/lib/workflow/workflow.go +++ b/chasm/lib/workflow/workflow.go @@ -2,15 +2,20 @@ package workflow import ( "fmt" + "slices" + "strings" commonpb "go.temporal.io/api/common/v1" failurepb "go.temporal.io/api/failure/v1" historypb "go.temporal.io/api/history/v1" "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" "go.temporal.io/server/chasm" "go.temporal.io/server/chasm/lib/callback" callbackspb "go.temporal.io/server/chasm/lib/callback/gen/callbackpb/v1" "go.temporal.io/server/chasm/lib/nexusoperation" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" chasmworkflowpb "go.temporal.io/server/chasm/lib/workflow/gen/workflowpb/v1" "go.temporal.io/server/service/history/historybuilder" "google.golang.org/protobuf/types/known/emptypb" @@ -39,6 +44,441 @@ type Workflow struct { // Updates indexed by update ID, used to store the update components. Updates chasm.Map[string, *WorkflowUpdate] + + // Streams the workflow owns, keyed by stream name. Co-located with the + // workflow so publishing rides its commit rather than crossing executions. + Streams chasm.Map[string, *stream.Stream] + + // Positions in streams the workflow consumes, keyed by stream name. Held + // here rather than on the stream so that folding in a delivered range + // commits with the event that records it. + StreamCursors chasm.Map[string, *stream.Cursor] + + // Subscribe commands whose stream is in another execution, so the addressing + // has to be looked up before a cursor can be made. In memory only, drained + // by the flush before commit. + pendingStreamSubscriptions []PendingStreamSubscription +} + +// PendingStreamSubscription is a subscribe command whose stream lives in +// another execution, waiting for the flush to look up its addressing. +type PendingStreamSubscription struct { + StreamID string + StartOffset int64 + // The workflow already holds a cursor for this stream. The subscription + // itself is done, but the command still needs its event, because that is + // what a replaying worker matches the re-issued command against. + AlreadySubscribed bool + + // The event this command already wrote, waiting on its start offset. In + // memory only, like the rest of this struct. + Event *historypb.HistoryEvent +} + +// StagePendingSubscription records a subscription for the flush to resolve. +func (w *Workflow) StagePendingSubscription(sub PendingStreamSubscription) { + w.pendingStreamSubscriptions = append(w.pendingStreamSubscriptions, sub) +} + +// DrainStreamSubscriptions returns and clears the staged subscriptions. +func (w *Workflow) DrainStreamSubscriptions() []PendingStreamSubscription { + out := w.pendingStreamSubscriptions + w.pendingStreamSubscriptions = nil + return out +} + +// streamConsumerID names this workflow's pin on a stream it owns. An attached +// stream has exactly one consumer, but the stream's map is keyed by consumer, +// so the entry still needs a stable name. +func streamConsumerID(streamName string) string { + return "workflow:" + streamName +} + +// SubscribeToOwnedStream registers this workflow as a consumer of a stream it +// owns, returning the offset the subscription actually starts from. +// +// A negative start offset means "from wherever the stream is now". That is +// resolved here and stored, so the first recorded range begins at a fact rather +// than at a reading that would land somewhere else on replay. +func (w *Workflow) SubscribeToOwnedStream( + mctx chasm.MutableContext, + name string, + startOffset int64, + limits stream.Limits, +) (int64, error) { + // Created here as well as on first write, so a workflow can start reading a + // topic before anything has been published to it. An outside producer that + // arrives later appends to the same stream. + owned, err := w.streamNamed(mctx, name, limits) + if err != nil { + return 0, err + } + + if w.StreamCursors == nil { + w.StreamCursors = make(chasm.Map[string, *stream.Cursor]) + } + if existing, ok := w.StreamCursors[name]; ok { + // Resubscribing must not rewind a cursor: ranges below it are already + // recorded in History, and moving back would replay them as new. + return existing.Get(mctx).Offset(), nil + } + + // Pin the stream's floor in the same transaction as the cursor. Registered + // separately it could be lost while the cursor survived, and truncation + // would then be free to take a range the cursor still points at. + key := mctx.ExecutionKey() + startOffset, err = owned.RegisterConsumer(mctx, stream.ConsumerRegistration{ + ConsumerID: streamConsumerID(name), + WorkflowID: key.BusinessID, + RunID: key.RunID, + Offset: startOffset, + MaxConsumers: limits.MaxConsumersPerStream, + }) + if err != nil { + return 0, err + } + + cursor, err := stream.NewCursor(mctx, stream.NewCursorRequest{ + StreamID: name, + StartOffset: startOffset, + }) + if err != nil { + return 0, err + } + w.StreamCursors[name] = chasm.NewComponentField(mctx, cursor) + return startOffset, nil +} + +// ExternalStreamSubscription describes a stream in another execution, with the +// start offset already resolved and the frontier as it was when the consumer +// was registered there. +type ExternalStreamSubscription struct { + StreamID string + StartOffset int64 + KnownHead int64 +} + +// SubscribeToExternalStream registers this workflow as a consumer of a stream +// it does not own, returning the offset the subscription starts from. +func (w *Workflow) SubscribeToExternalStream( + mctx chasm.MutableContext, + req ExternalStreamSubscription, +) (int64, error) { + if w.StreamCursors == nil { + w.StreamCursors = make(chasm.Map[string, *stream.Cursor]) + } + if existing, ok := w.StreamCursors[req.StreamID]; ok { + // Resubscribing must not rewind: ranges below the cursor are already + // recorded in History, and moving back would replay them as new. + return existing.Get(mctx).Offset(), nil + } + + cursor, err := stream.NewCursor(mctx, stream.NewCursorRequest{ + StreamID: req.StreamID, + External: true, + StartOffset: req.StartOffset, + }) + if err != nil { + return 0, err + } + cursor.AdvanceKnownHead(mctx, req.KnownHead) + w.StreamCursors[req.StreamID] = chasm.NewComponentField(mctx, cursor) + return req.StartOffset, nil +} + +// ExportStreamSubscriptions returns the subscriptions a successor run has to +// inherit. +// +// Only subscriptions to streams in other executions are exported. A stream this +// workflow owns lives in this execution and does not survive the run +// transition, so carrying a cursor for one would leave the successor pointing +// at a stream it cannot reach. +func (w *Workflow) ExportStreamSubscriptions(ctx chasm.Context) []ExternalStreamSubscription { + var out []ExternalStreamSubscription + for _, field := range w.StreamCursors { + cursor := field.Get(ctx) + if !cursor.IsExternal() { + continue + } + out = append(out, ExternalStreamSubscription{ + StreamID: cursor.StreamID(), + StartOffset: cursor.Offset(), + KnownHead: cursor.KnownHead(), + }) + } + // Stable order, so a successor's state does not depend on map iteration. + slices.SortFunc(out, func(a, b ExternalStreamSubscription) int { + return strings.Compare(a.StreamID, b.StreamID) + }) + return out +} + +// ImportStreamSubscriptions installs subscriptions inherited from the run this +// one continues. The offset carries over unchanged: offsets are global to the +// stream, so the successor resumes exactly where its predecessor stopped and +// the stream itself is untouched. +func (w *Workflow) ImportStreamSubscriptions( + mctx chasm.MutableContext, + subscriptions []ExternalStreamSubscription, +) error { + for _, sub := range subscriptions { + if _, err := w.SubscribeToExternalStream(mctx, sub); err != nil { + return err + } + } + return nil +} + +// ApplyConsumedStreamRanges puts the cursors where the completed event says +// they stood, for a run being rebuilt from its history. +// +// A range for a stream with no cursor belongs to a subscription made out of +// band, through the service rather than by a command, which leaves no event of +// its own. The range is proof the subscription was live, so the cursor is +// created from it: the first range a subscription records begins where it +// started reading. +func (w *Workflow) ApplyConsumedStreamRanges( + mctx chasm.MutableContext, + ranges []*streampb.StreamRange, +) error { + for _, recorded := range ranges { + field, ok := w.StreamCursors[recorded.GetStreamId()] + if !ok { + cursor, err := stream.NewCursor(mctx, stream.NewCursorRequest{ + StreamID: recorded.GetStreamId(), + StartOffset: recorded.GetFromOffset(), + }) + if err != nil { + return err + } + if w.StreamCursors == nil { + w.StreamCursors = make(chasm.Map[string, *stream.Cursor]) + } + field = chasm.NewComponentField(mctx, cursor) + w.StreamCursors[recorded.GetStreamId()] = field + } + field.Get(mctx).Restore(mctx, recorded.GetToOffset()) + } + return nil +} + +// InheritStreamsOnReset finishes the cursors a reset run rebuilt from its +// history with what the events could not say, read from the run it was reset +// from. +// +// Every subscription the base run held is carried. One the rebuild recreated +// keeps the position its events gave it; one the events never mentioned, made +// out of band and never delivered to before the reset point, starts where it +// started in the base run. A cursor on a stream in another execution keeps +// reading that stream; it is marked so and given the frontier the base run +// last knew. A cursor on a stream the base run owned gets a stream of this +// run's own, starting at the offset the cursor stands at: the ranges below it +// are in the base run's stream, which is where replay re-reads them, and +// everything from here on is this run's. Continuing the offset space is what +// keeps a range in this run's History unambiguous about which run holds it. +func (w *Workflow) InheritStreamsOnReset( + mctx chasm.MutableContext, + base *Workflow, + baseCtx chasm.Context, + limits stream.Limits, +) error { + if w.StreamCursors == nil { + w.StreamCursors = make(chasm.Map[string, *stream.Cursor]) + } + if err := w.carryBaseCursors(mctx, base, baseCtx); err != nil { + return err + } + + names := make([]string, 0, len(w.StreamCursors)) + for name := range w.StreamCursors { + names = append(names, name) + } + slices.Sort(names) + + for _, name := range names { + cursor := w.StreamCursors[name].Get(mctx) + if baseCursor := cursorNamed(base, baseCtx, name); baseCursor != nil && baseCursor.IsExternal() { + cursor.MarkExternal(mctx, baseCursor.KnownHead()) + continue + } + if err := w.ownStreamFrom(mctx, name, cursor.Offset(), limits); err != nil { + return err + } + } + return nil +} + +// cursorNamed returns a workflow's cursor by stream name, or nil when the +// workflow is absent or holds none by that name. +func cursorNamed(w *Workflow, ctx chasm.Context, name string) *stream.Cursor { + if w == nil { + return nil + } + field, ok := w.StreamCursors[name] + if !ok { + return nil + } + return field.Get(ctx) +} + +// carryBaseCursors creates a cursor for every subscription the base run held +// that the rebuild did not recreate, starting where it started in the base run. +func (w *Workflow) carryBaseCursors( + mctx chasm.MutableContext, + base *Workflow, + baseCtx chasm.Context, +) error { + if base == nil { + return nil + } + for name, field := range base.StreamCursors { + if _, ok := w.StreamCursors[name]; ok { + continue + } + baseCursor := field.Get(baseCtx) + cursor, err := stream.NewCursor(mctx, stream.NewCursorRequest{ + StreamID: baseCursor.StreamID(), + StartOffset: baseCursor.StartOffset(), + }) + if err != nil { + return err + } + w.StreamCursors[name] = chasm.NewComponentField(mctx, cursor) + } + return nil +} + +// ownStreamFrom gives this run a stream of its own by that name, beginning at +// the given offset and pinned by this run's consumer there, unless it has one. +func (w *Workflow) ownStreamFrom( + mctx chasm.MutableContext, + name string, + offset int64, + limits stream.Limits, +) error { + if _, ok := w.Streams[name]; ok { + return nil + } + if w.Streams == nil { + w.Streams = make(chasm.Map[string, *stream.Stream]) + } + created, err := stream.NewStream(mctx, stream.NewStreamRequest{ + Attached: true, + StartOffset: offset, + Budget: &streamlib.StreamBudget{ + MaxItems: int64(limits.OwnedStreamMaxItems), + MaxBytes: int64(limits.OwnedStreamMaxBytes), + }, + }) + if err != nil { + return err + } + key := mctx.ExecutionKey() + if _, err := created.RegisterConsumer(mctx, stream.ConsumerRegistration{ + ConsumerID: streamConsumerID(name), + WorkflowID: key.BusinessID, + RunID: key.RunID, + Offset: offset, + MaxConsumers: limits.MaxConsumersPerStream, + }); err != nil { + return err + } + w.Streams[name] = chasm.NewComponentField(mctx, created) + return nil +} + +// AdvanceKnownHead records how far a stream in another execution has moved. +// +// A workflow cannot read that frontier itself while closing its own +// transaction, so the stream pushes it here. Writing it dirties this execution, +// and the transaction close then sees the cursor is behind and schedules a +// workflow task, which is the same path an owned stream takes. +func (w *Workflow) AdvanceKnownHead(mctx chasm.MutableContext, streamID string, head int64) error { + field, ok := w.StreamCursors[streamID] + if !ok { + return serviceerror.NewNotFoundf("workflow does not consume stream %q", streamID) + } + field.Get(mctx).AdvanceKnownHead(mctx, head) + return nil +} + +// StreamCursorsBehind reports whether any subscription still has offsets it has +// not been given. +// +// This is the one place a stream wakes a workflow. Publishing deliberately +// never does, because a stream item is data produced by an execution rather +// than a decision input to it. An active subscription is different: the +// workflow asked to be told, so leaving it to wait for some unrelated task +// would make delivery depend on traffic that has nothing to do with the stream. +func (w *Workflow) StreamCursorsBehind(ctx chasm.Context) bool { + for name, field := range w.StreamCursors { + cursor := field.Get(ctx) + + // An external stream's frontier is whatever it last pushed here: this + // execution cannot read the real one without reaching into another. + if cursor.IsExternal() { + if cursor.Offset() < cursor.KnownHead() { + return true + } + continue + } + + owned, ok := w.Streams[name] + if !ok { + continue + } + state, err := owned.Get(ctx).Snapshot(ctx, struct{}{}) + if err != nil { + continue + } + if cursor.Offset() < state.GetHeadOffset() { + return true + } + } + return false +} + +// CommitStreamCursors folds every staged range into its cursor and returns the +// ranges to record. Called while the workflow task's transaction is open, so +// the advance and the event that carries the range land together. +// +// A cursor with nothing staged is skipped, but a cursor staged with an empty +// range is not: replay has to see that the subscription was live and observed +// nothing. +func (w *Workflow) CommitStreamCursors(mctx chasm.MutableContext) []*streampb.StreamRange { + if w.StreamCursors == nil { + return nil + } + + names := make([]string, 0, len(w.StreamCursors)) + for name := range w.StreamCursors { + names = append(names, name) + } + // Recorded order has to be stable, or replay compares against a different + // event than the one the original execution wrote. + slices.Sort(names) + + var recorded []*streampb.StreamRange + for _, name := range names { + cursor := w.StreamCursors[name].Get(mctx) + from, to, ok := cursor.Commit(mctx) + if !ok { + continue + } + + // Let the floor follow the cursor. Anything below it is recorded as + // consumed, so nothing needs to re-read it. + if field, ok := w.Streams[name]; ok { + field.Get(mctx).AdvanceConsumer(mctx, streamConsumerID(name), to) + } + + recorded = append(recorded, &streampb.StreamRange{ + StreamId: cursor.StreamID(), + FromOffset: from, + ToOffset: to, + }) + } + return recorded } func NewWorkflow( @@ -317,3 +757,58 @@ func (w *Workflow) HasAnyBufferedEvent(filter historybuilder.BufferedEventFilter func (w *Workflow) WorkflowTypeName() string { return w.GetWorkflowTypeName() } + +// OwnedStreamState returns the state of a stream this workflow owns, or nil if +// it owns none by that name. +// +// An attached stream has no id of its own, so this is the only way to see its +// frontier from outside the execution. Reading it needs the owner's component, +// which is why it lives here rather than on the stream. +// +// Absent is not an error. An owned stream is created by the first publish to +// it, so a reader that arrives before the workflow has published anything is +// the ordinary case rather than a mistake, and from outside the execution +// "not created yet" and "never will be" are the same observation. +func (w *Workflow) OwnedStreamState( + ctx chasm.Context, + name string, +) (*streamlib.StreamState, error) { + field, ok := w.Streams[name] + if !ok { + return nil, nil + } + return field.Get(ctx).Snapshot(ctx, struct{}{}) +} + +// OwnedStream returns the attached stream itself, or nil when the workflow has +// not created it yet. Reads that need the payload and not just the frontier go +// through here, so both come from one view of the component. +func (w *Workflow) OwnedStream( + ctx chasm.Context, + name string, +) *stream.Stream { + field, ok := w.Streams[name] + if !ok { + return nil + } + return field.Get(ctx) +} + +// AppendToOwnedStream appends to a stream this workflow owns on behalf of a +// writer outside the execution. +// +// The workflow's own publishes go through the command handler, which advances +// the frontier inside the Workflow Task's commit. This is the other producer: +// it advances the same frontier in a transition of its own, so the two are +// serialized by the execution rather than by anything the stream does. +func (w *Workflow) AppendToOwnedStream( + mctx chasm.MutableContext, + name string, + req stream.AddMessagesRequest, +) (stream.AddMessagesResult, error) { + s, err := w.streamNamed(mctx, name, req.Limits) + if err != nil { + return stream.AddMessagesResult{}, err + } + return s.AddMessages(mctx, req) +} diff --git a/client/history/client_gen.go b/client/history/client_gen.go index c594c7f17cd..7475fa3369e 100644 --- a/client/history/client_gen.go +++ b/client/history/client_gen.go @@ -399,6 +399,26 @@ func (c *clientImpl) GetShard( return response, nil } +func (c *clientImpl) GetStreamReplaySlices( + ctx context.Context, + request *historyservice.GetStreamReplaySlicesRequest, + opts ...grpc.CallOption, +) (*historyservice.GetStreamReplaySlicesResponse, error) { + shardID := c.shardIDFromWorkflowID(request.GetNamespaceId(), request.GetExecution().GetWorkflowId()) + var response *historyservice.GetStreamReplaySlicesResponse + op := func(ctx context.Context, client historyservice.HistoryServiceClient) error { + var err error + ctx, cancel := c.createContext(ctx) + defer cancel() + response, err = client.GetStreamReplaySlices(ctx, request, opts...) + return err + } + if err := c.executeWithRedirect(ctx, shardID, op); err != nil { + return nil, err + } + return response, nil +} + func (c *clientImpl) GetWorkflowExecutionHistory( ctx context.Context, request *historyservice.GetWorkflowExecutionHistoryRequest, diff --git a/client/history/metric_client_gen.go b/client/history/metric_client_gen.go index 8d4cad72aa5..78ccfda73a6 100644 --- a/client/history/metric_client_gen.go +++ b/client/history/metric_client_gen.go @@ -317,6 +317,20 @@ func (c *metricClient) GetShard( return c.client.GetShard(ctx, request, opts...) } +func (c *metricClient) GetStreamReplaySlices( + ctx context.Context, + request *historyservice.GetStreamReplaySlicesRequest, + opts ...grpc.CallOption, +) (_ *historyservice.GetStreamReplaySlicesResponse, retError error) { + + metricsHandler, startTime := c.startMetricsRecording(ctx, "HistoryClientGetStreamReplaySlices") + defer func() { + c.finishMetricsRecording(metricsHandler, startTime, retError) + }() + + return c.client.GetStreamReplaySlices(ctx, request, opts...) +} + func (c *metricClient) GetWorkflowExecutionHistory( ctx context.Context, request *historyservice.GetWorkflowExecutionHistoryRequest, diff --git a/client/history/retryable_client_gen.go b/client/history/retryable_client_gen.go index 31e48612095..a06b9118827 100644 --- a/client/history/retryable_client_gen.go +++ b/client/history/retryable_client_gen.go @@ -356,6 +356,21 @@ func (c *retryableClient) GetShard( return resp, err } +func (c *retryableClient) GetStreamReplaySlices( + ctx context.Context, + request *historyservice.GetStreamReplaySlicesRequest, + opts ...grpc.CallOption, +) (*historyservice.GetStreamReplaySlicesResponse, error) { + var resp *historyservice.GetStreamReplaySlicesResponse + op := func(ctx context.Context) error { + var err error + resp, err = c.client.GetStreamReplaySlices(ctx, request, opts...) + return err + } + err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable) + return resp, err +} + func (c *retryableClient) GetWorkflowExecutionHistory( ctx context.Context, request *historyservice.GetWorkflowExecutionHistoryRequest, diff --git a/cmd/tools/getproto/files.go b/cmd/tools/getproto/files.go index 38b6ef67622..3b1e31ca412 100644 --- a/cmd/tools/getproto/files.go +++ b/cmd/tools/getproto/files.go @@ -21,12 +21,14 @@ import ( history "go.temporal.io/api/history/v1" namespace "go.temporal.io/api/namespace/v1" nexus "go.temporal.io/api/nexus/v1" + nexusoperation "go.temporal.io/api/nexusoperation/v1" protocol "go.temporal.io/api/protocol/v1" query "go.temporal.io/api/query/v1" replication "go.temporal.io/api/replication/v1" rules "go.temporal.io/api/rules/v1" schedule "go.temporal.io/api/schedule/v1" sdk "go.temporal.io/api/sdk/v1" + stream "go.temporal.io/api/stream/v1" taskqueue "go.temporal.io/api/taskqueue/v1" update "go.temporal.io/api/update/v1" version "go.temporal.io/api/version/v1" @@ -82,6 +84,7 @@ func init() { importMap["temporal/api/history/v1/message.proto"] = history.File_temporal_api_history_v1_message_proto importMap["temporal/api/namespace/v1/message.proto"] = namespace.File_temporal_api_namespace_v1_message_proto importMap["temporal/api/nexus/v1/message.proto"] = nexus.File_temporal_api_nexus_v1_message_proto + importMap["temporal/api/nexusoperation/v1/message.proto"] = nexusoperation.File_temporal_api_nexusoperation_v1_message_proto importMap["temporal/api/protocol/v1/message.proto"] = protocol.File_temporal_api_protocol_v1_message_proto importMap["temporal/api/query/v1/message.proto"] = query.File_temporal_api_query_v1_message_proto importMap["temporal/api/replication/v1/message.proto"] = replication.File_temporal_api_replication_v1_message_proto @@ -91,6 +94,7 @@ func init() { importMap["temporal/api/sdk/v1/task_complete_metadata.proto"] = sdk.File_temporal_api_sdk_v1_task_complete_metadata_proto importMap["temporal/api/sdk/v1/user_metadata.proto"] = sdk.File_temporal_api_sdk_v1_user_metadata_proto importMap["temporal/api/sdk/v1/worker_config.proto"] = sdk.File_temporal_api_sdk_v1_worker_config_proto + importMap["temporal/api/stream/v1/message.proto"] = stream.File_temporal_api_stream_v1_message_proto importMap["temporal/api/taskqueue/v1/message.proto"] = taskqueue.File_temporal_api_taskqueue_v1_message_proto importMap["temporal/api/update/v1/message.proto"] = update.File_temporal_api_update_v1_message_proto importMap["temporal/api/version/v1/message.proto"] = version.File_temporal_api_version_v1_message_proto diff --git a/cmd/tools/protogen/main.go b/cmd/tools/protogen/main.go index cf2c00b2e6e..251f2a26adb 100644 --- a/cmd/tools/protogen/main.go +++ b/cmd/tools/protogen/main.go @@ -165,16 +165,65 @@ func newGenerator() (*generator, error) { return &gen, nil } +// removeExistingGenDirs clears out the previous run's output so a proto that +// was deleted does not leave its Go behind. +// +// Only generated files go. A gen package sometimes needs a hand-written file +// beside the generated ones, because a method has to be declared in the same +// package as the type it is on, and wiping the directory deleted those without +// saying so. Empty directories are then pruned, which is what removing a proto +// used to rely on. func (g *generator) removeExistingGenDirs() error { for _, dir := range g.chasmLibDirs { genDir := filepath.Join(dir, "gen") - if err := os.RemoveAll(genDir); err != nil { - return fmt.Errorf("error removing directory %s: %w", genDir, err) + if !exists(genDir) { + continue + } + if err := filepath.Walk(genDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() || !strings.HasSuffix(info.Name(), ".pb.go") { + return nil + } + return os.Remove(path) + }); err != nil { + return fmt.Errorf("error removing generated files under %s: %w", genDir, err) + } + if err := pruneEmptyDirs(genDir); err != nil { + return fmt.Errorf("error pruning empty directories under %s: %w", genDir, err) } } return nil } +// pruneEmptyDirs removes dir and any descendant left with nothing in it, +// deepest first. +func pruneEmptyDirs(dir string) error { + entries, err := os.ReadDir(dir) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + for _, entry := range entries { + if entry.IsDir() { + if err := pruneEmptyDirs(filepath.Join(dir, entry.Name())); err != nil { + return err + } + } + } + remaining, err := os.ReadDir(dir) + if err != nil { + return err + } + if len(remaining) == 0 { + return os.Remove(dir) + } + return nil +} + func (g *generator) backupProtos() error { if exists(g.protoOut) { if err := os.Rename(g.protoOut, g.protoBackup); err != nil { diff --git a/common/api/metadata.go b/common/api/metadata.go index 41843262284..d7d4dbef5fe 100644 --- a/common/api/metadata.go +++ b/common/api/metadata.go @@ -64,6 +64,9 @@ const ( MatchingServicePrefix = "/temporal.server.api.matchingservice.v1.MatchingService/" // Technically not a gRPC service, but still using this format for metadata. NexusServicePrefix = "/temporal.api.nexusservice.v1.NexusService/" + // The stream service is served on the frontend next to the workflow + // service, so its methods need the same authorization metadata. + StreamServicePrefix = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/" ) var ( @@ -213,10 +216,46 @@ var ( "CompleteNexusOperation": {Scope: ScopeNamespace, Access: AccessWrite, Polling: PollingNone}, "CompleteNexusOperationChasm": {Scope: ScopeNamespace, Access: AccessWrite, Polling: PollingNone}, } + // Every stream request carries its namespace inside `frontend_request`, + // exposed through a hand-written `GetNamespace()`, which is what namespace + // scope needs. Closing, truncating and deleting a stream are ordinary + // writes here; whether they should need an operator is a policy call this + // table does not make. The two internal calls History makes on itself are + // admin so that no namespace-level role can reach them through a frontend. + streamServiceMetadata = map[string]MethodMetadata{ + "CreateStream": namespaceWrite, + "AddMessages": namespaceWrite, + "FinishWriting": namespaceWrite, + "SubscribeWorkflow": namespaceWrite, + "PollMessages": namespaceReadPoll, + "DescribeStream": namespaceRead, + "PollWorkflowMessages": namespaceReadPoll, + "DescribeWorkflowStream": namespaceRead, + "AddWorkflowMessages": namespaceWrite, + "RegisterStreamConsumer": namespaceAdmin, + "AdvanceConsumerHead": namespaceAdmin, + "CloseStream": namespaceWrite, + "TruncateStream": namespaceWrite, + "ListStreams": namespaceRead, + "DeleteStream": namespaceWrite, + } + + namespaceRead = MethodMetadata{ + Scope: ScopeNamespace, Access: AccessReadOnly, Polling: PollingNone, + } + namespaceReadPoll = MethodMetadata{ + Scope: ScopeNamespace, Access: AccessReadOnly, Polling: PollingCapable, + } + namespaceWrite = MethodMetadata{ + Scope: ScopeNamespace, Access: AccessWrite, Polling: PollingNone, + } + namespaceAdmin = MethodMetadata{ + Scope: ScopeNamespace, Access: AccessAdmin, Polling: PollingNone, + } ) // GetMethodMetadata gets metadata for a given API method in one of the services exported by -// frontend (WorkflowService, OperatorService, AdminService). +// frontend (WorkflowService, OperatorService, AdminService, StreamService). func GetMethodMetadata(fullApiName string) MethodMetadata { switch { case strings.HasPrefix(fullApiName, WorkflowServicePrefix): @@ -225,6 +264,8 @@ func GetMethodMetadata(fullApiName string) MethodMetadata { return operatorServiceMetadata[MethodName(fullApiName)] case strings.HasPrefix(fullApiName, NexusServicePrefix): return nexusServiceMetadata[MethodName(fullApiName)] + case strings.HasPrefix(fullApiName, StreamServicePrefix): + return streamServiceMetadata[MethodName(fullApiName)] case strings.HasPrefix(fullApiName, AdminServicePrefix): return MethodMetadata{Scope: ScopeCluster, Access: AccessAdmin} default: diff --git a/common/api/metadata_stream_test.go b/common/api/metadata_stream_test.go new file mode 100644 index 00000000000..a914bdea5c4 --- /dev/null +++ b/common/api/metadata_stream_test.go @@ -0,0 +1,72 @@ +package api_test + +// An external test package, because the generated stream package depends on +// this one and an internal test importing it would be a cycle. + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/require" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/api" + "go.temporal.io/server/common/testing/temporalapi" +) + +// The access each stream method declares. Kept as a table so a new method +// fails here until someone decides what it needs, and so a change of mind +// shows up in the diff. +var expectedStreamAccess = map[string]api.Access{ + "CreateStream": api.AccessWrite, + "AddMessages": api.AccessWrite, + "FinishWriting": api.AccessWrite, + "SubscribeWorkflow": api.AccessWrite, + "PollMessages": api.AccessReadOnly, + "DescribeStream": api.AccessReadOnly, + "PollWorkflowMessages": api.AccessReadOnly, + "DescribeWorkflowStream": api.AccessReadOnly, + "AddWorkflowMessages": api.AccessWrite, + "RegisterStreamConsumer": api.AccessAdmin, + "AdvanceConsumerHead": api.AccessAdmin, + "CloseStream": api.AccessWrite, + "TruncateStream": api.AccessWrite, + "ListStreams": api.AccessReadOnly, + "DeleteStream": api.AccessWrite, +} + +func TestStreamServiceMetadata(t *testing.T) { + var server streampb.StreamServiceServer + seen := make(map[string]struct{}) + temporalapi.WalkExportedMethods(&server, func(method reflect.Method) { + seen[method.Name] = struct{}{} + md := api.GetMethodMetadata(api.StreamServicePrefix + method.Name) + + expected, ok := expectedStreamAccess[method.Name] + require.Truef(t, ok, + "%s has no entry in expectedStreamAccess: decide its access and add it", method.Name) + require.Equalf(t, expected, md.Access, "%s access", method.Name) + require.Equalf(t, api.ScopeNamespace, md.Scope, "%s scope", method.Name) + + // Namespace scope is only enforceable if the interceptors can find the + // namespace on the request, and these requests carry it through a method + // rather than a top-level field. + requestType := method.Type.In(1) + getter, ok := requestType.MethodByName("GetNamespace") + require.Truef(t, ok, "%s request has no GetNamespace()", method.Name) + require.Equal(t, reflect.TypeFor[string](), getter.Type.Out(0)) + }) + + for name := range expectedStreamAccess { + _, ok := seen[name] + require.Truef(t, ok, "%s is in expectedStreamAccess but not on the service", name) + } +} + +func TestStreamPollsAreMarkedAsPolling(t *testing.T) { + for _, name := range []string{"PollMessages", "PollWorkflowMessages"} { + md := api.GetMethodMetadata(api.StreamServicePrefix + name) + require.Equalf(t, api.PollingCapable, md.Polling, "%s blocks only when asked to", name) + } + md := api.GetMethodMetadata(api.StreamServicePrefix + "DescribeStream") + require.Equal(t, api.PollingNone, md.Polling) +} diff --git a/common/api/metadata_test.go b/common/api/metadata_test.go index 6b7791a6cd5..7921c7d92e9 100644 --- a/common/api/metadata_test.go +++ b/common/api/metadata_test.go @@ -84,6 +84,15 @@ func TestGetMethodMetadata(t *testing.T) { assert.Equal(t, ScopeCluster, md.Scope) assert.Equal(t, AccessAdmin, md.Access) + md = GetMethodMetadata(StreamServicePrefix + "AddWorkflowMessages") + require.Equal(t, ScopeNamespace, md.Scope) + require.Equal(t, AccessWrite, md.Access) + + md = GetMethodMetadata(StreamServicePrefix + "PollWorkflowMessages") + require.Equal(t, ScopeNamespace, md.Scope) + require.Equal(t, AccessReadOnly, md.Access) + require.Equal(t, PollingCapable, md.Polling) + md = GetMethodMetadata("/OtherService/Method1") assert.Equal(t, ScopeUnknown, md.Scope) assert.Equal(t, AccessUnknown, md.Access) diff --git a/common/metrics/otel_metrics_handler_test.go b/common/metrics/otel_metrics_handler_test.go index e186e79ec9f..9cfc5aa0acb 100644 --- a/common/metrics/otel_metrics_handler_test.go +++ b/common/metrics/otel_metrics_handler_test.go @@ -195,6 +195,10 @@ func TestMeter(t *testing.T) { cmpopts.IgnoreFields(metricdata.DataPoint[int64]{}, "StartTime", "Time"), cmpopts.IgnoreFields(metricdata.DataPoint[float64]{}, "StartTime", "Time"), cmpopts.IgnoreFields(metricdata.HistogramDataPoint[int64]{}, "StartTime", "Time", "Bounds"), + // The SDK hands back either a nil or an allocated-but-empty exemplar + // slice depending on whether its reservoir was ever touched, so the + // two have to compare equal here. + cmpopts.EquateEmpty(), ); diff != "" { t.Errorf("mismatch (-want, +got):\n%s", diff) } @@ -263,6 +267,7 @@ func TestMeter_TimerInSeconds(t *testing.T) { return a1.Equals(&a2) }), cmpopts.IgnoreFields(metricdata.HistogramDataPoint[float64]{}, "StartTime", "Time", "Bounds"), + cmpopts.EquateEmpty(), ); diff != "" { t.Errorf("mismatch (-want, +got):\n%s", diff) } diff --git a/common/rpc/interceptor/logtags/history_service_server_gen.go b/common/rpc/interceptor/logtags/history_service_server_gen.go index 038ccbf9c40..43dcc9e7b17 100644 --- a/common/rpc/interceptor/logtags/history_service_server_gen.go +++ b/common/rpc/interceptor/logtags/history_service_server_gen.go @@ -141,6 +141,13 @@ func (wt *WorkflowTags) extractFromHistoryServiceServerMessage(message any) []ta return nil case *historyservice.GetShardResponse: return nil + case *historyservice.GetStreamReplaySlicesRequest: + return []tag.Tag{ + tag.WorkflowID(r.GetExecution().GetWorkflowId()), + tag.WorkflowRunID(r.GetExecution().GetRunId()), + } + case *historyservice.GetStreamReplaySlicesResponse: + return nil case *historyservice.GetWorkflowExecutionHistoryRequest: return []tag.Tag{ tag.WorkflowID(r.GetRequest().GetExecution().GetWorkflowId()), diff --git a/common/rpc/interceptor/redirection_test.go b/common/rpc/interceptor/redirection_test.go index 11e6df3a681..66bf8f1c548 100644 --- a/common/rpc/interceptor/redirection_test.go +++ b/common/rpc/interceptor/redirection_test.go @@ -11,6 +11,7 @@ import ( "go.temporal.io/api/serviceerror" "go.temporal.io/api/workflowservice/v1" persistencespb "go.temporal.io/server/api/persistence/v1" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" "go.temporal.io/server/client" "go.temporal.io/server/common/clock" "go.temporal.io/server/common/cluster" @@ -698,3 +699,82 @@ func (s *redirectionInterceptorSuite) TestHandleGlobalAPIInvocation_RemoteRoutin s.Len(failureMetrics, 1) s.Equal(int64(1), failureMetrics[0].Value) } + +// streamNamespaceActiveElsewhere registers a global namespace whose active +// cluster is the alternative one, so a call for it has to be forwarded. +func (s *redirectionInterceptorSuite) streamNamespaceActiveElsewhere() namespace.Name { + namespaceName := namespace.Name("stream-namespace-active-elsewhere") + namespaceEntry := namespace.NewGlobalNamespaceForTest( + &persistencespb.NamespaceInfo{Id: uuid.NewString(), Name: namespaceName.String()}, + &persistencespb.NamespaceConfig{Retention: timestamp.DurationFromDays(1)}, + &persistencespb.NamespaceReplicationConfig{ + ActiveClusterName: cluster.TestAlternativeClusterName, + Clusters: []string{ + cluster.TestCurrentClusterName, + cluster.TestAlternativeClusterName, + }, + }, + 1, + ) + s.namespaceCache.EXPECT().GetNamespace(namespaceName).Return(namespaceEntry, nil).AnyTimes() + return namespaceName +} + +// A stream call registered as redirectable is forwarded to the namespace's +// active cluster, resolved from the namespace inside `frontend_request`. +func (s *redirectionInterceptorSuite) TestStreamAPI_ForwardedWhenRegistered() { + namespaceName := s.streamNamespaceActiveElsewhere() + info := &grpc.UnaryServerInfo{ + FullMethod: streampb.StreamService_AddWorkflowMessages_FullMethodName, + } + req := &streampb.AddWorkflowMessagesRequest{ + FrontendRequest: &streampb.AddWorkflowMessagesInput{ + Namespace: namespaceName.String(), + WorkflowId: "wf", + }, + } + redirector := s.redirector.WithRedirectResponses(map[string]func() any{ + info.FullMethod: func() any { return &streampb.AddWorkflowMessagesResponse{} }, + }) + + grpcConn := &mockClientConnInterface{ + Suite: &s.Suite, + targetMethod: info.FullMethod, + targetResponse: &streampb.AddWorkflowMessagesResponse{}, + } + s.clientBean.EXPECT().GetRemoteFrontendClient(cluster.TestAlternativeClusterName). + Return(grpcConn, nil, nil).Times(1) + + resp, err := redirector.Intercept(context.Background(), req, info, + func(context.Context, any) (any, error) { + s.Fail("a call for a namespace active elsewhere must not be served locally") + return nil, nil + }) + s.NoError(err) + s.IsType(&streampb.AddWorkflowMessagesResponse{}, resp) +} + +// Without registration a stream call is served wherever it lands, which is +// what the bare interceptor does for any service other than WorkflowService. +func (s *redirectionInterceptorSuite) TestStreamAPI_ServedLocallyWhenNotRegistered() { + namespaceName := s.streamNamespaceActiveElsewhere() + info := &grpc.UnaryServerInfo{ + FullMethod: streampb.StreamService_AddWorkflowMessages_FullMethodName, + } + req := &streampb.AddWorkflowMessagesRequest{ + FrontendRequest: &streampb.AddWorkflowMessagesInput{ + Namespace: namespaceName.String(), + WorkflowId: "wf", + }, + } + + served := false + resp, err := s.redirector.Intercept(context.Background(), req, info, + func(context.Context, any) (any, error) { + served = true + return &streampb.AddWorkflowMessagesResponse{}, nil + }) + s.NoError(err) + s.True(served) + s.IsType(&streampb.AddWorkflowMessagesResponse{}, resp) +} diff --git a/common/util.go b/common/util.go index 87e02bbc63a..f67c0daa7e7 100644 --- a/common/util.go +++ b/common/util.go @@ -544,6 +544,7 @@ func CreateMatchingPollWorkflowTaskQueueResponse(historyResponse *historyservice StartedTime: historyResponse.StartedTime, Queries: historyResponse.Queries, Messages: historyResponse.Messages, + StreamSlices: historyResponse.StreamSlices, History: historyResponse.History, NextPageToken: historyResponse.NextPageToken, RawHistory: historyResponse.RawHistoryBytes, diff --git a/go.mod b/go.mod index 7a9d0965bba..2be924061ca 100644 --- a/go.mod +++ b/go.mod @@ -63,8 +63,8 @@ require ( go.opentelemetry.io/otel/exporters/prometheus v0.56.0 go.opentelemetry.io/otel/log v0.20.0 go.opentelemetry.io/otel/metric v1.44.0 - go.opentelemetry.io/otel/sdk v1.43.0 - go.opentelemetry.io/otel/sdk/metric v1.43.0 + go.opentelemetry.io/otel/sdk v1.44.0 + go.opentelemetry.io/otel/sdk/metric v1.44.0 go.opentelemetry.io/otel/trace v1.44.0 go.temporal.io/api v1.63.5 go.temporal.io/auto-scaled-workers v0.0.0-20260811170210-91f6fe1d10ab @@ -81,7 +81,7 @@ require ( golang.org/x/text v0.40.0 golang.org/x/time v0.15.0 google.golang.org/api v0.276.0 - google.golang.org/grpc v1.80.0 + google.golang.org/grpc v1.83.1 google.golang.org/protobuf v1.36.11 gopkg.in/validator.v2 v2.0.1 gopkg.in/yaml.v3 v3.0.1 @@ -109,7 +109,7 @@ require ( ) require ( - cel.dev/expr v0.25.1 // indirect + cel.dev/expr v0.25.2 // indirect cloud.google.com/go v0.123.0 // indirect; indirect e cloud.google.com/go/auth v0.20.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect @@ -120,7 +120,7 @@ require ( cloud.google.com/go/run v1.19.0 // indirect dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.2.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -199,14 +199,14 @@ require ( github.com/sirupsen/logrus v1.9.4 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spf13/pflag v1.0.10 // indirect - github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.7.0 // indirect github.com/stretchr/objx v0.5.3 // indirect github.com/twmb/murmur3 v1.1.8 // indirect github.com/uber-common/bark v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 go.opentelemetry.io/proto/otlp v1.10.0 @@ -219,8 +219,8 @@ require ( golang.org/x/sys v0.47.0 // indirect golang.org/x/term v0.45.0 // indirect google.golang.org/genproto v0.0.0-20260420184626-e10c466a9529 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/api v0.35.4 // indirect @@ -239,3 +239,5 @@ require ( ) tool golang.org/x/perf/cmd/benchstat + +replace go.temporal.io/api => github.com/moedash/api-go v1.63.6-0.20260921082525-9a6aa5f95be8 diff --git a/go.sum b/go.sum index 95797622c25..13b45018247 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= -cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= @@ -31,8 +31,8 @@ filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 h1:l7+6kwRMJNwdCvYdDl7Eax+wzEYHSnNY7zrrfbhDdTA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= @@ -321,6 +321,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/moedash/api-go v1.63.6-0.20260921082525-9a6aa5f95be8 h1:WdG6n/8Da2RC5y3t3/vdpq0P4wOBbOQX+C+C9TiChew= +github.com/moedash/api-go v1.63.6-0.20260921082525-9a6aa5f95be8/go.mod h1:acM0I9WPuYg8W3Pd9jOZvEgi7mRUttUQ4+e7fowKVnM= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= @@ -382,8 +384,8 @@ github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= -github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4= +github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -443,8 +445,8 @@ go.opentelemetry.io/collector/internal/testutil v0.150.0 h1:J4PLQGPfbLVaL5eI1aMc go.opentelemetry.io/collector/internal/testutil v0.150.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE= go.opentelemetry.io/collector/pdata v1.56.0 h1:W+QAfN2Iz8SNss1T5JNzRWFnw+7oP1vXBQH9ZuOJkXY= go.opentelemetry.io/collector/pdata v1.56.0/go.mod h1:usR9utboXufbD1rp1oJy+3smQXXpZ+CsI3WN7QsiOs0= -go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= -go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0 h1:NmLfL734pJhM0JKaYd2Y28+nY9dPRWYAAbxhRCrKXPw= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= @@ -465,10 +467,12 @@ go.opentelemetry.io/otel/log v0.20.0 h1:/5i0vuHxCLWUfChWG41K9wkM0jafruPw9NU1/RCJ go.opentelemetry.io/otel/log v0.20.0/go.mod h1:wOcMcjsZpG8x7Bak7IhSi/lg8wscV2C1VdrKCLPlt0E= go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA= +go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= @@ -479,8 +483,6 @@ go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0 h1:R go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0/go.mod h1:I89cynRj8y+383o7tEQVg2SVA6SRgDVIouWPUVXjx0U= go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0 h1:CQvJSldHRUN6Z8jsUeYv8J0lXRvygALXIzsmAeCcZE0= go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0/go.mod h1:xSQ+mEfJe/GjK1LXEyVOoSI1N9JV9ZI923X5kup43W4= -go.temporal.io/api v1.63.5 h1:c11+kPYHkXXL3UiShPdbMD+xtvqGsbTibUA9ypmiCa4= -go.temporal.io/api v1.63.5/go.mod h1:SrlW2JMwVlDP4nRWSNznUFqnSHd+YeMDS1BkYo63HCQ= go.temporal.io/auto-scaled-workers v0.0.0-20260811170210-91f6fe1d10ab h1:99wXW0317BBi49d6xgMdA0EZtvA+xbBUWV4HsTEGEcg= go.temporal.io/auto-scaled-workers v0.0.0-20260811170210-91f6fe1d10ab/go.mod h1:hhHijO9XRPIkAflLJJHix61M9FzbRPqk8fSydkcLkqw= go.temporal.io/sdk v1.44.0 h1:suitPDukX74rW3/N1FqvEbZTZVJJsxMKhv0KMa/j7pU= @@ -632,12 +634,12 @@ google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= google.golang.org/genproto v0.0.0-20260420184626-e10c466a9529 h1:QoMBg0moLIlB/eucPzc+ID5SgPZWuirtjAn3l8nW2Dg= google.golang.org/genproto v0.0.0-20260420184626-e10c466a9529/go.mod h1:EjLmDZ8liSLBrCTK5vP+bGIxRQHE3ovGvOI0CzGk1PI= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 h1:zUWMZsvo/IJcD1t6MNCPO/azZTwz0TvwCBqr5aifoVY= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529/go.mod h1:a5OGAgyRr4lqco7AG9hQM9Fwh0N2ZV4grR0eXFEsXQg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= +google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/proto/internal/temporal/server/api/historyservice/v1/request_response.proto b/proto/internal/temporal/server/api/historyservice/v1/request_response.proto index de813adcf43..40fe5e92ef7 100644 --- a/proto/internal/temporal/server/api/historyservice/v1/request_response.proto +++ b/proto/internal/temporal/server/api/historyservice/v1/request_response.proto @@ -14,6 +14,7 @@ import "temporal/api/history/v1/message.proto"; import "temporal/api/nexus/v1/message.proto"; import "temporal/api/protocol/v1/message.proto"; import "temporal/api/query/v1/message.proto"; +import "temporal/api/stream/v1/message.proto"; import "temporal/api/taskqueue/v1/message.proto"; import "temporal/api/workflow/v1/message.proto"; import "temporal/api/workflowservice/v1/request_response.proto"; @@ -122,6 +123,22 @@ message StartWorkflowExecutionResponse { string first_execution_run_id = 7; } +// Asks for the stream ranges a workflow's completed tasks recorded, re-read from +// their streams, for a task that is built without RecordWorkflowTaskStarted. +// A query dispatched straight through matching is the one such task. +message GetStreamReplaySlicesRequest { + option (routing).workflow_id = "execution.workflow_id"; + + string namespace_id = 1; + temporal.api.common.v1.WorkflowExecution execution = 2; +} + +message GetStreamReplaySlicesResponse { + // Every slice is tagged with the completed event that recorded its range. + // Empty when the workflow consumes no stream. + repeated temporal.api.stream.v1.StreamSlice stream_slices = 1; +} + message GetMutableStateRequest { option (routing).workflow_id = "execution.workflow_id"; @@ -301,6 +318,10 @@ message RecordWorkflowTaskStartedResponse { // as raw_history_bytes (field 21) will be the only field used. temporal.api.history.v1.History raw_history = 20 [deprecated = true]; repeated bytes raw_history_bytes = 21; + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + repeated temporal.api.stream.v1.StreamSlice stream_slices = 22; } // RecordWorkflowTaskStartedResponseWithRawHistory is wire-compatible with RecordWorkflowTaskStartedResponse. @@ -345,6 +366,10 @@ message RecordWorkflowTaskStartedResponseWithRawHistory { // instead of a proto-decoded History. This avoids matching service having to decode history. repeated bytes raw_history = 20 [deprecated = true]; repeated bytes raw_history_bytes = 21; + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + repeated temporal.api.stream.v1.StreamSlice stream_slices = 22; } message RecordActivityTaskStartedRequest { diff --git a/proto/internal/temporal/server/api/historyservice/v1/service.proto b/proto/internal/temporal/server/api/historyservice/v1/service.proto index 58b0019b9f7..d19d6b13e7a 100644 --- a/proto/internal/temporal/server/api/historyservice/v1/service.proto +++ b/proto/internal/temporal/server/api/historyservice/v1/service.proto @@ -32,6 +32,13 @@ service HistoryService { option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_LONG_POLL; } + // Returns the stream ranges the workflow's completed tasks recorded, re-read + // from their streams and tagged with the event that recorded each, so a task + // built without RecordWorkflowTaskStarted can still replay a consumer. + rpc GetStreamReplaySlices(GetStreamReplaySlicesRequest) returns (GetStreamReplaySlicesResponse) { + option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD; + } + // Reset the sticky task queue related information in mutable state of a given workflow. // Things cleared are: // 1. StickyTaskQueue 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 33bae6d5c71..afe058cef5b 100644 --- a/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto +++ b/proto/internal/temporal/server/api/matchingservice/v1/request_response.proto @@ -12,6 +12,7 @@ import "temporal/api/history/v1/message.proto"; import "temporal/api/nexus/v1/message.proto"; import "temporal/api/protocol/v1/message.proto"; import "temporal/api/query/v1/message.proto"; +import "temporal/api/stream/v1/message.proto"; import "temporal/api/taskqueue/v1/message.proto"; import "temporal/api/worker/v1/message.proto"; import "temporal/api/workflowservice/v1/request_response.proto"; @@ -62,6 +63,10 @@ message PollWorkflowTaskQueueResponse { // Raw history bytes sent from matching service when history.sendRawHistoryBetweenInternalServices is enabled. // Matching client will deserialize this to History when it receives the response. temporal.api.history.v1.History raw_history = 22; + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + repeated temporal.api.stream.v1.StreamSlice stream_slices = 23; } // PollWorkflowTaskQueueResponseWithRawHistory is wire-compatible with PollWorkflowTaskQueueResponse. @@ -112,6 +117,10 @@ message PollWorkflowTaskQueueResponseWithRawHistory { // When matching client deserializes this to PollWorkflowTaskQueueResponse, this field // will be automatically deserialized to the raw_history field as History. repeated bytes raw_history = 22; + // Slices of the streams this Workflow is consuming, each covering the offset + // range the task may deliver. Payloads ride here and never enter History; + // only the consumed range is recorded, on WorkflowTaskCompleted. + repeated temporal.api.stream.v1.StreamSlice stream_slices = 23; } message PollActivityTaskQueueRequest { diff --git a/service/frontend/configs/quotas.go b/service/frontend/configs/quotas.go index beaf12baa2a..b93c0fa9731 100644 --- a/service/frontend/configs/quotas.go +++ b/service/frontend/configs/quotas.go @@ -22,6 +22,10 @@ const ( PollWorkflowHistoryAPIName = "/temporal.api.workflowservice.v1.WorkflowService/PollWorkflowExecutionHistory" // PollActivityExecutionAPIName is used instead of DescribeActivityExecution if LongPollToken is set in request. PollActivityExecutionAPIName = "/temporal.api.workflowservice.v1.WorkflowService/PollActivityExecutionDescription" + + // The stream service is served on the same frontend server as the workflow + // service and shares its rate limiters. + streamServicePrefix = "/temporal.server.chasm.lib.stream.proto.v1.StreamService/" ) var ( @@ -61,6 +65,10 @@ var ( // Dispatching a Nexus task is a potentially long running RPC, it's classified in the same bucket as QueryWorkflow. DispatchNexusTaskByNamespaceAndTaskQueueAPIName: 1, DispatchNexusTaskByEndpointAPIName: 1, + + // Stream reads block only when asked to wait for new records. + streamServicePrefix + "PollMessages": 1, + streamServicePrefix + "PollWorkflowMessages": 1, } // PollTaskAPISet is the set of API methods for which NamespaceRateLimitInterceptor will @@ -208,6 +216,26 @@ var ( // Informational API that aren't required for the temporal service to function OpenAPIV3APIName: 5, OpenAPIV2APIName: 5, + + // Stream service. Appends and subscriptions are external events like a + // signal; closing, truncating and deleting change state; describes are + // status reads; the two polls sit with the other polls. + streamServicePrefix + "CreateStream": 1, + streamServicePrefix + "AddMessages": 1, + streamServicePrefix + "FinishWriting": 1, + streamServicePrefix + "SubscribeWorkflow": 1, + streamServicePrefix + "AddWorkflowMessages": 1, + streamServicePrefix + "CloseStream": 2, + streamServicePrefix + "TruncateStream": 2, + streamServicePrefix + "DeleteStream": 2, + streamServicePrefix + "DescribeStream": 3, + streamServicePrefix + "DescribeWorkflowStream": 3, + streamServicePrefix + "PollMessages": 4, + streamServicePrefix + "PollWorkflowMessages": 4, + // History calls these on itself; the frontend answers them with + // Unimplemented, so they only ever cost a refusal. + streamServicePrefix + "RegisterStreamConsumer": 5, + streamServicePrefix + "AdvanceConsumerHead": 5, } ExecutionAPIPrioritiesOrdered = []int{0, 1, 2, 3, 4, 5} @@ -233,6 +261,9 @@ var ( "/temporal.api.workflowservice.v1.WorkflowService/ListDeployments": 1, "/temporal.api.workflowservice.v1.WorkflowService/GetDeploymentReachability": 1, "/temporal.api.workflowservice.v1.WorkflowService/ListWorkerDeployments": 1, + + // Answered from visibility on the frontend, like the other lists. + streamServicePrefix + "ListStreams": 1, } VisibilityAPIPrioritiesOrdered = []int{0, 1} diff --git a/service/frontend/configs/quotas_test.go b/service/frontend/configs/quotas_test.go index efb5c49291d..5e3d028df76 100644 --- a/service/frontend/configs/quotas_test.go +++ b/service/frontend/configs/quotas_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.temporal.io/api/workflowservice/v1" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/api" "go.temporal.io/server/common/headers" "go.temporal.io/server/common/log" "go.temporal.io/server/common/quotas" @@ -121,6 +123,9 @@ func (s *quotasSuite) TestVisibilityAPIs() { apiToPriority[apiName] = VisibilityAPIToPriority[apiName] } } + // The one stream method answered from visibility. + listStreams := streamServicePrefix + "ListStreams" + apiToPriority[listStreams] = VisibilityAPIToPriority[listStreams] s.Equal(apiToPriority, VisibilityAPIToPriority) } @@ -171,6 +176,27 @@ func (s *quotasSuite) TestAllAPIs() { s.Truef(ok, "missing priority for API: %q", CompleteNexusOperation) } +// Every stream method has a priority, the two polls are counted as +// long-running, and the one list is a visibility read. +func (s *quotasSuite) TestStreamServiceAPIs() { + var service streampb.StreamServiceServer + temporalapi.WalkExportedMethods(&service, func(m reflect.Method) { + apiName := streamServicePrefix + m.Name + _, inExecution := APIToPriority[apiName] + _, inVisibility := VisibilityAPIToPriority[apiName] + s.Truef(inExecution || inVisibility, "missing priority for API: %v", m.Name) + s.Falsef(inExecution && inVisibility, "API in two limiters: %v", m.Name) + }) + + for _, poll := range []string{"PollMessages", "PollWorkflowMessages"} { + _, ok := ExecutionAPICountLimitOverride[streamServicePrefix+poll] + s.Truef(ok, "%s can block, so it counts against concurrent long polls", poll) + } + s.Equal(1, VisibilityAPIToPriority[streamServicePrefix+"ListStreams"]) + s.Equal(streamServicePrefix, api.StreamServicePrefix, + "the quota table and the authorization table have to agree on the service name") +} + func (s *quotasSuite) TestOperatorPriority_Execution() { limiter := NewExecutionPriorityRateLimiter(testRateBurstFn, testOperatorRPSRatioFn) s.testOperatorPrioritized(limiter, "DescribeWorkflowExecution") diff --git a/service/frontend/fx.go b/service/frontend/fx.go index 651551de210..470506c4ce3 100644 --- a/service/frontend/fx.go +++ b/service/frontend/fx.go @@ -14,6 +14,7 @@ import ( nexusoperationpb "go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1" chasmscheduler "go.temporal.io/server/chasm/lib/scheduler" "go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream/service" chasmtests "go.temporal.io/server/chasm/lib/tests" chasmworkflow "go.temporal.io/server/chasm/lib/workflow" "go.temporal.io/server/client" @@ -146,6 +147,7 @@ var Module = fx.Options( chasmworkflow.Module, chasmcallback.Module, activity.FrontendModule, + chasmstream.FrontendModule, fx.Provide(visibility.ChasmVisibilityManagerProvider), fx.Provide(chasm.ChasmVisibilityInterceptorProvider), ) @@ -158,6 +160,7 @@ func NewServiceProvider( handler Handler, adminHandler *AdminHandler, operatorHandler *OperatorHandlerImpl, + streamHandler *chasmstream.FrontendHandler, versionChecker *VersionChecker, visibilityMgr manager.VisibilityManager, logger log.SnTaggedLogger, @@ -173,6 +176,7 @@ func NewServiceProvider( handler, adminHandler, operatorHandler, + streamHandler, versionChecker, visibilityMgr, logger, @@ -412,7 +416,7 @@ func RedirectionInterceptorProvider( metricsHandler, timeSource, clusterMetadata, - ) + ).WithRedirectResponses(chasmstream.RedirectableMethods()) } func BusinessIDInterceptorProvider( diff --git a/service/frontend/service.go b/service/frontend/service.go index f48d86c33bc..62da8849873 100644 --- a/service/frontend/service.go +++ b/service/frontend/service.go @@ -13,6 +13,8 @@ import ( "go.temporal.io/server/chasm/lib/activity" chasmcallback "go.temporal.io/server/chasm/lib/callback" chasmnexus "go.temporal.io/server/chasm/lib/nexusoperation" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream/service" "go.temporal.io/server/common/callbacks" "go.temporal.io/server/common/dynamicconfig" "go.temporal.io/server/common/log" @@ -458,6 +460,7 @@ type Service struct { handler Handler adminHandler *AdminHandler operatorHandler *OperatorHandlerImpl + streamHandler *chasmstream.FrontendHandler versionChecker *VersionChecker visibilityManager manager.VisibilityManager server *grpc.Server @@ -477,6 +480,7 @@ func NewService( handler Handler, adminHandler *AdminHandler, operatorHandler *OperatorHandlerImpl, + streamHandler *chasmstream.FrontendHandler, versionChecker *VersionChecker, visibilityMgr manager.VisibilityManager, logger log.Logger, @@ -492,6 +496,7 @@ func NewService( handler: handler, adminHandler: adminHandler, operatorHandler: operatorHandler, + streamHandler: streamHandler, versionChecker: versionChecker, visibilityManager: visibilityMgr, logger: logger, @@ -509,6 +514,7 @@ func (s *Service) Start() { workflowservice.RegisterWorkflowServiceServer(s.server, s.handler) adminservice.RegisterAdminServiceServer(s.server, s.adminHandler) operatorservice.RegisterOperatorServiceServer(s.server, s.operatorHandler) + streampb.RegisterStreamServiceServer(s.server, s.streamHandler) reflection.Register(s.server) diff --git a/service/frontend/workflow_handler.go b/service/frontend/workflow_handler.go index 2a1230a3c04..16c4c7d081a 100644 --- a/service/frontend/workflow_handler.go +++ b/service/frontend/workflow_handler.go @@ -1197,6 +1197,7 @@ func (wh *WorkflowHandler) PollWorkflowTaskQueue(ctx context.Context, request *w StartedTime: matchingResp.StartedTime, Queries: matchingResp.Queries, Messages: matchingResp.Messages, + StreamSlices: matchingResp.StreamSlices, PollerScalingDecision: matchingResp.PollerScalingDecision, }, nil } diff --git a/service/history/api/command_attr_validator.go b/service/history/api/command_attr_validator.go index 8c48b0f99f1..257135405d9 100644 --- a/service/history/api/command_attr_validator.go +++ b/service/history/api/command_attr_validator.go @@ -661,7 +661,13 @@ func (v *CommandAttrValidator) ValidateCommandSequence( enumspb.COMMAND_TYPE_MODIFY_WORKFLOW_PROPERTIES, enumspb.COMMAND_TYPE_PROTOCOL_MESSAGE, enumspb.COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION, - enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION: + enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION, + // Publishing to a stream the workflow owns. Not a close command: + // it appends and returns, scheduling nothing further. + enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + // Subscribing to a stream. Also not closing: it records a cursor + // and the workflow carries on. + enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM: // noop case enumspb.COMMAND_TYPE_CONTINUE_AS_NEW_WORKFLOW_EXECUTION, enumspb.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION, diff --git a/service/history/api/recordworkflowtaskstarted/api.go b/service/history/api/recordworkflowtaskstarted/api.go index e88a3c6c9c3..2c096720dc0 100644 --- a/service/history/api/recordworkflowtaskstarted/api.go +++ b/service/history/api/recordworkflowtaskstarted/api.go @@ -51,6 +51,11 @@ func Invoke( var workflowKey definition.WorkflowKey var resp *historyservice.RecordWorkflowTaskStartedResponseWithRawHistory + var streamAddresses map[string]streamOrigin + // Set when a stream range the task depends on cannot be served. The task + // is failed inside the transaction, so the failure has to be persisted + // and reported to matching afterwards rather than returned as the error. + var streamFailure *rangeUnavailable err = api.GetAndUpdateWorkflowWithNew( ctx, @@ -102,6 +107,19 @@ func Invoke( if err != nil { return nil, err } + // Redelivers whatever range is already staged, so a + // duplicate of the same request hands back the same slice. + resp.StreamSlices, streamAddresses, err = deliverStreamSlices( + ctx, shardContext, mutableState) + if errors.As(err, &streamFailure) { + if err := failTaskForStreams(mutableState, workflowTask, streamFailure); err != nil { + return nil, err + } + return updateAction, nil + } + if err != nil { + return nil, err + } updateAction.Noop = true return updateAction, nil } @@ -238,6 +256,19 @@ func Invoke( return nil, err } + resp.StreamSlices, streamAddresses, err = deliverStreamSlices( + ctx, shardContext, mutableState) + if errors.As(err, &streamFailure) { + if err := failTaskForStreams(mutableState, workflowTask, streamFailure); err != nil { + return nil, err + } + updateAction.Noop = false + return updateAction, nil + } + if err != nil { + return nil, err + } + return updateAction, nil }, nil, @@ -248,6 +279,11 @@ func Invoke( if err != nil { return nil, err } + if streamFailure != nil { + // The failure is in History and the next attempt is scheduled, so this + // task is stale; matching drops it rather than retrying it. + return nil, serviceerrors.NewObsoleteMatchingTask(streamFailure.Error()) + } maxHistoryPageSize := int32(config.HistoryMaxPageSize(namespaceEntry.Name().String())) err = setHistoryForRecordWfTaskStartedResp( @@ -264,9 +300,64 @@ func Invoke( if err != nil { return nil, err } + + // After the history is attached, because the ranges to re-supply are read + // out of the events being sent. + err = attachReplaySlices(ctx, shardContext, workflowKey, streamAddresses, maxHistoryPageSize, resp) + if errors.As(err, &streamFailure) { + // The task is already started and its lock released, so failing it is + // a transaction of its own. + if err := failStartedTaskForStreams( + ctx, shardContext, workflowConsistencyChecker, workflowKey, + scheduledEventID, requestID, streamFailure, + ); err != nil { + return nil, err + } + return nil, serviceerrors.NewObsoleteMatchingTask(streamFailure.Error()) + } + if err != nil { + return nil, err + } return resp, nil } +// failStartedTaskForStreams fails a task that started but cannot be replayed, +// provided it is still the task this request started. +func failStartedTaskForStreams( + ctx context.Context, + shardContext historyi.ShardContext, + workflowConsistencyChecker api.WorkflowConsistencyChecker, + workflowKey definition.WorkflowKey, + scheduledEventID int64, + requestID string, + cause *rangeUnavailable, +) error { + return api.GetAndUpdateWorkflowWithNew( + ctx, + nil, + workflowKey, + func(workflowLease api.WorkflowLease) (*api.UpdateWorkflowAction, error) { + mutableState := workflowLease.GetMutableState() + if !mutableState.IsWorkflowExecutionRunning() { + return nil, consts.ErrWorkflowCompleted + } + workflowTask := mutableState.GetWorkflowTaskByID(scheduledEventID) + if workflowTask == nil || workflowTask.RequestID != requestID || + workflowTask.StartedEventID == common.EmptyEventID { + // Something else already resolved the task. + return &api.UpdateWorkflowAction{Noop: true}, nil + } + if err := failTaskForStreams(mutableState, workflowTask, cause); err != nil { + return nil, err + } + return &api.UpdateWorkflowAction{}, nil + }, + nil, + shardContext, + workflowConsistencyChecker, + ) +} + func setHistoryForRecordWfTaskStartedResp( ctx context.Context, shardContext historyi.ShardContext, @@ -400,6 +491,7 @@ func CreateRecordWorkflowTaskStartedResponse( Queries: rawResp.Queries, Clock: rawResp.Clock, Messages: rawResp.Messages, + StreamSlices: rawResp.StreamSlices, Version: rawResp.Version, NextPageToken: rawResp.NextPageToken, }, nil diff --git a/service/history/api/recordworkflowtaskstarted/stream_routing.go b/service/history/api/recordworkflowtaskstarted/stream_routing.go new file mode 100644 index 00000000000..546160a3476 --- /dev/null +++ b/service/history/api/recordworkflowtaskstarted/stream_routing.go @@ -0,0 +1,102 @@ +package recordworkflowtaskstarted + +import ( + "context" + + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "google.golang.org/protobuf/proto" +) + +type streamClientContextKey struct{} + +// WithStreamClient supplies shard routing for calls that reach a stream in +// another execution from inside a workflow task's transaction. +func WithStreamClient(ctx context.Context, client streamlib.StreamServiceClient) context.Context { + if client == nil { + return ctx + } + return context.WithValue(ctx, streamClientContextKey{}, client) +} + +// StreamClientFromContext returns the routed client installed by the engine. +func StreamClientFromContext(ctx context.Context) (streamlib.StreamServiceClient, bool) { + client, ok := ctx.Value(streamClientContextKey{}).(streamlib.StreamServiceClient) + return client, ok +} + +// WithRoutedDeadline bounds a routed call made while the workflow lock is held. +func WithRoutedDeadline(ctx context.Context) (context.Context, context.CancelFunc) { + return context.WithTimeout(ctx, stream.RoutedCallTimeout) +} + +func readExternalWindow( + ctx context.Context, + namespaceID, streamID string, + from, to int64, +) (stream.Window, error) { + if to <= from { + return stream.Window{To: from}, nil + } + limit := int32(min(to-from, int64(stream.DefaultMaxMessagesPerPoll))) + client, ok := StreamClientFromContext(ctx) + if !ok { + // Hand-built engines in component tests have no service client. + return chasm.ReadComponent(ctx, + chasm.NewComponentRef[*stream.Stream](chasm.ExecutionKey{ + NamespaceID: namespaceID, + BusinessID: streamID, + }), + (*stream.Stream).ReadWindow, + stream.WindowRequest{From: from, MaxMessages: limit}) + } + + callCtx, cancel := WithRoutedDeadline(ctx) + defer cancel() + response, err := client.PollMessages(callCtx, &streamlib.PollMessagesRequest{ + NamespaceId: namespaceID, + FrontendRequest: &streamlib.PollMessagesInput{ + StreamId: streamID, FromOffset: from, MaxMessages: limit, + }, + }) + if err != nil { + return stream.Window{}, err + } + out := response.GetFrontendResponse() + if out == nil || out.GetNextOffset() < from || out.GetNextOffset() > to || + out.GetNextOffset() > out.GetHeadOffset() || + int64(len(out.GetRecords())) != out.GetNextOffset()-from { + return stream.Window{}, serviceerror.NewDataLoss( + "stream read returned an invalid contiguous range") + } + for index, message := range out.GetRecords() { + if message == nil || message.GetOffset() != from+int64(index) { + return stream.Window{}, serviceerror.NewDataLoss( + "stream read returned a missing or reordered offset") + } + } + w := stream.Window{ + State: &streamlib.StreamState{ + HeadOffset: out.GetHeadOffset(), + Closed: out.GetClosed(), + CloseReason: out.GetCloseReason(), + }, + To: out.GetNextOffset(), + Limit: int(limit), + RunID: out.GetRunId(), + } + if len(out.GetRecords()) == 0 { + return w, nil + } + data, err := proto.Marshal(&streamlib.StreamRecordBatch{Records: out.GetRecords()}) + if err != nil { + return stream.Window{}, err + } + w.Blobs = []*commonpb.DataBlob{{EncodingType: enumspb.ENCODING_TYPE_PROTO3, Data: data}} + w.Starts = []int64{from} + return w, nil +} diff --git a/service/history/api/recordworkflowtaskstarted/stream_routing_test.go b/service/history/api/recordworkflowtaskstarted/stream_routing_test.go new file mode 100644 index 00000000000..4d91e339a6b --- /dev/null +++ b/service/history/api/recordworkflowtaskstarted/stream_routing_test.go @@ -0,0 +1,163 @@ +package recordworkflowtaskstarted + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common/definition" + "go.uber.org/mock/gomock" + "google.golang.org/grpc" +) + +type routedStreamClient struct { + streamlib.StreamServiceClient + poll func(context.Context, *streamlib.PollMessagesRequest) (*streamlib.PollMessagesResponse, error) +} + +func (c *routedStreamClient) PollMessages( + ctx context.Context, request *streamlib.PollMessagesRequest, _ ...grpc.CallOption, +) (*streamlib.PollMessagesResponse, error) { + return c.poll(ctx, request) +} + +func TestExternalStreamLiveAndReplayUseRoutedPayloadRead(t *testing.T) { + for _, replay := range []bool{false, true} { + t.Run(map[bool]string{false: "live", true: "replay"}[replay], func(t *testing.T) { + calls := 0 + client := &routedStreamClient{poll: func( + ctx context.Context, req *streamlib.PollMessagesRequest, + ) (*streamlib.PollMessagesResponse, error) { + calls++ + require.Equal(t, "namespace-id", req.GetNamespaceId()) + require.Equal(t, "remote-source", req.GetFrontendRequest().GetStreamId()) + require.EqualValues(t, 4, req.GetFrontendRequest().GetFromOffset()) + require.EqualValues(t, 2, req.GetFrontendRequest().GetMaxMessages()) + require.False(t, req.GetFrontendRequest().GetWaitNewMessages()) + require.Empty(t, req.GetFrontendRequest().GetTopics()) + return &streamlib.PollMessagesResponse{FrontendResponse: &streamlib.PollMessagesOutput{ + NextOffset: 6, HeadOffset: 9, + Records: []*streamlib.StreamRecord{ + { + Offset: 4, + Kind: streampb.STREAM_RECORD_KIND_DATA, + Body: &commonpb.Payload{Data: []byte("a")}, + }, + { + Offset: 5, + Kind: streampb.STREAM_RECORD_KIND_DATA, + Body: &commonpb.Payload{Data: []byte("b")}, + }, + }, + }}, nil + }} + // No local engine is installed, so a read that resolved the source + // through the local controller instead of the routed client fails. + ctx := WithStreamClient(context.Background(), client) + var window stream.Window + var err error + if replay { + window, err = readRecordedRange(ctx, + definition.NewWorkflowKey("namespace-id", "consumer", "consumer-run"), + streamOrigin{external: true}, "consumer-run", "remote-source", 4, 6) + } else { + window, err = readWindowFor(ctx, nil, nil, "namespace-id", "input", true, "remote-source", 4, 6) + } + require.NoError(t, err) + require.Equal(t, 1, calls) + messages, next, err := stream.CollectRecords( + window.Blobs, window.Starts, 4, window.To, window.Limit, nil) + require.NoError(t, err) + require.EqualValues(t, 6, next) + require.Len(t, messages, 2) + require.Equal(t, []byte("a"), messages[0].GetBody().GetData()) + require.Equal(t, []byte("b"), messages[1].GetBody().GetData()) + }) + } +} + +func TestExternalStreamRoutedReadRejectsCorruptOrExpandedRange(t *testing.T) { + cases := map[string]*streamlib.PollMessagesOutput{ + "missing-response": nil, + "skipped-offset": { + NextOffset: 6, HeadOffset: 9, + Records: []*streamlib.StreamRecord{{Offset: 4}, {Offset: 6}}, + }, + "short-count": { + NextOffset: 6, HeadOffset: 9, + Records: []*streamlib.StreamRecord{{Offset: 4}}, + }, + "past-requested-frontier": { + NextOffset: 7, HeadOffset: 9, + Records: []*streamlib.StreamRecord{{Offset: 4}, {Offset: 5}, {Offset: 6}}, + }, + "past-committed-head": { + NextOffset: 6, HeadOffset: 5, + Records: []*streamlib.StreamRecord{{Offset: 4}, {Offset: 5}}, + }, + } + for name, response := range cases { + t.Run(name, func(t *testing.T) { + client := &routedStreamClient{poll: func( + context.Context, *streamlib.PollMessagesRequest, + ) (*streamlib.PollMessagesResponse, error) { + return &streamlib.PollMessagesResponse{FrontendResponse: response}, nil + }} + ctx := WithStreamClient(context.Background(), client) + _, err := readExternalWindow(ctx, "ns", "source", 4, 6) + var integrity *serviceerror.DataLoss + require.ErrorAs(t, err, &integrity) + }) + } +} + +func TestExternalStreamRoutedReadPropagatesSourceFailure(t *testing.T) { + want := errors.New("source shard unavailable") + client := &routedStreamClient{poll: func( + context.Context, *streamlib.PollMessagesRequest, + ) (*streamlib.PollMessagesResponse, error) { + return nil, want + }} + _, err := readExternalWindow(WithStreamClient(context.Background(), client), "ns", "source", 4, 6) + require.ErrorIs(t, err, want) +} + +func TestOwnedLiveStreamNeverReentersThroughRoutedClient(t *testing.T) { + client := &routedStreamClient{poll: func( + context.Context, *streamlib.PollMessagesRequest, + ) (*streamlib.PollMessagesResponse, error) { + t.Fatal("owned stream read re-entered the consumer through an RPC") + return nil, nil + }} + window, err := readWindowFor(WithStreamClient(context.Background(), client), nil, + &chasmworkflow.Workflow{}, "ns", "owned", false, "owned", 4, 6) + require.NoError(t, err) + require.EqualValues(t, 4, window.To) +} + +func TestOwnedReplayPinsConsumerRun(t *testing.T) { + engine := chasm.NewMockEngine(gomock.NewController(t)) + engine.EXPECT().ReadComponent(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func( + _ context.Context, + ref chasm.ComponentRef, + _ func(chasm.Context, chasm.Component) error, + _ ...chasm.TransitionOption, + ) error { + require.Equal(t, "consumer-run", ref.RunID) + require.Equal(t, "consumer", ref.BusinessID) + return nil + }) + _, err := readRecordedRange(chasm.NewEngineContext(context.Background(), engine), + definition.NewWorkflowKey("ns", "consumer", "consumer-run"), + streamOrigin{name: "owned"}, "consumer-run", "owned", 4, 6) + require.NoError(t, err) +} diff --git a/service/history/api/recordworkflowtaskstarted/stream_slices.go b/service/history/api/recordworkflowtaskstarted/stream_slices.go new file mode 100644 index 00000000000..c4f8f5ae3ac --- /dev/null +++ b/service/history/api/recordworkflowtaskstarted/stream_slices.go @@ -0,0 +1,805 @@ +package recordworkflowtaskstarted + +import ( + "context" + "errors" + "fmt" + "slices" + + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/chasm" + "go.temporal.io/server/chasm/lib/stream" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common" + "go.temporal.io/server/common/definition" + "go.temporal.io/server/common/failure" + "go.temporal.io/server/common/locks" + "go.temporal.io/server/common/persistence" + "go.temporal.io/server/common/persistence/serialization" + "go.temporal.io/server/service/history/api" + "go.temporal.io/server/service/history/consts" + historyi "go.temporal.io/server/service/history/interfaces" + "go.temporal.io/server/service/history/workflow" + "google.golang.org/protobuf/proto" +) + +// rangeUnavailable says a stream range this consumer depends on can no longer be +// served: the stream was truncated or deleted past it, or re-supplying it would +// exceed what one response may carry. Retrying the request would only ask the +// same stream again, so the workflow task is failed with it instead. +type rangeUnavailable struct { + msg string +} + +func (e *rangeUnavailable) Error() string { + return e.msg +} + +func unavailablef(format string, args ...any) error { + return &rangeUnavailable{msg: fmt.Sprintf(format, args...)} +} + +// unavailableIfGone tells a read failure that means the range is gone for good +// from one worth retrying. A shard that is moving or a store that timed out is +// the second kind and keeps its own error. +func unavailableIfGone(err error, format string, args ...any) error { + var precondition *serviceerror.FailedPrecondition + var notFound *serviceerror.NotFound + if errors.As(err, &precondition) || errors.As(err, ¬Found) { + return unavailablef(format+": %v", append(args, err)...) + } + return err +} + +// failTaskForStreams records why the task cannot be started and schedules the +// next attempt. The event is what an operator sees; a bare error to matching +// would only make the task come back. +func failTaskForStreams( + ms historyi.MutableState, + workflowTask *historyi.WorkflowTaskInfo, + cause *rangeUnavailable, +) error { + if _, err := ms.AddWorkflowTaskFailedEvent( + workflowTask, + enumspb.WORKFLOW_TASK_FAILED_CAUSE_STREAM_RANGE_UNAVAILABLE, + failure.NewServerFailure(cause.Error(), true), + consts.IdentityHistoryService, + nil, + "", + "", + "", + 0, + ); err != nil { + return err + } + ms.FlushBufferedEvents() + return workflow.ScheduleWorkflowTask(ms) +} + +// streamOrigin says where a subscribed stream lives, which decides how its +// payload is read: an external stream from its own execution, an owned one +// from the consumer's. +type streamOrigin struct { + external bool + // The name the consumer knows the stream by, which is how an owned one is + // found on the consumer's own component. + name string + + // Where the subscription began, and how far its completed tasks have + // committed. Together they say exactly which offsets replay owes the + // worker, so a re-supply that comes up short can be detected instead of + // silently handing the workflow less than it originally saw. + start int64 + committed int64 +} + +// streamOrigins describes every stream the workflow consumes from a read-only +// view of its component, for a task that is built without delivering anything +// and so has no other way of learning what a cold replay owes it. +func streamOrigins( + ctx context.Context, + ms historyi.MutableState, +) (map[string]streamOrigin, error) { + if !ms.HasChasmWorkflowComponent() { + return nil, nil + } + wf, chasmCtx, err := ms.ChasmWorkflowComponentReadOnly(ctx) + if err != nil { + return nil, err + } + if len(wf.StreamCursors) == 0 { + return nil, nil + } + addresses := make(map[string]streamOrigin, len(wf.StreamCursors)) + for name, field := range wf.StreamCursors { + cursor := field.Get(chasmCtx) + addresses[cursor.StreamID()] = streamOrigin{ + external: cursor.IsExternal(), + name: name, + start: cursor.StartOffset(), + committed: cursor.Offset(), + } + } + return addresses, nil +} + +// deliveryFrontier is the offset a delivery clips to. For a stream this +// execution owns it is read directly; for one in another execution it is +// whatever that stream last pushed here, because reading the real value would +// mean reaching across executions while this transaction is open. +func deliveryFrontier( + chasmCtx chasm.Context, + wf *chasmworkflow.Workflow, + name string, + cursor *stream.Cursor, +) (int64, error) { + if cursor.IsExternal() { + return cursor.KnownHead(), nil + } + field, ok := wf.Streams[name] + if !ok { + return 0, serviceerror.NewFailedPreconditionf( + "workflow consumes stream %q, which it neither owns nor subscribed to externally", name) + } + state, err := field.Get(chasmCtx).Snapshot(chasmCtx, struct{}{}) + if err != nil { + return 0, err + } + + // A consumer that fell behind a truncating stream is told so rather than + // handed the rest and left with a hole it cannot see. The floor protects + // an active consumer, so reaching this means the subscription was released + // and the stream moved on. + if cursor.Offset() < state.GetBaseOffset() { + return 0, unavailablef( + "stream %q was truncated past this consumer: it is at offset %d and the stream "+ + "now starts at %d", name, cursor.Offset(), state.GetBaseOffset()) + } + return state.GetHeadOffset(), nil +} + +// readDeliverable reads the next run of a stream for the task being started +// and returns it with the run id of the execution that holds the stream. +func readDeliverable( + ctx context.Context, + chasmCtx chasm.Context, + wf *chasmworkflow.Workflow, + namespaceID string, + name string, + cursor *stream.Cursor, + from, to int64, + limits stream.Limits, +) ([]*streampb.StreamRecord, int64, string, error) { + if to <= from { + return nil, from, "", nil + } + w, err := readWindowFor(ctx, chasmCtx, wf, namespaceID, name, cursor.IsExternal(), + cursor.StreamID(), from, to) + if err != nil { + return nil, 0, "", unavailableIfGone(err, + "stream %q no longer holds offsets [%d,%d) this consumer is due", + cursor.StreamID(), from, to) + } + // The collected run is contiguous from `from`, so the byte cap recomputes + // the same end offset the read would have reported. + collected, _, err := stream.CollectRecords( + w.Blobs, w.Starts, from, w.To, limits.MaxConsumeItemsPerTask, nil) + if err != nil { + return nil, 0, "", err + } + // Cap before converting: the byte budget applies to the run as stored, and + // trimming decides how far the recorded range reaches. + collected, readTo := stream.CapByBytes(collected, from, limits.MaxConsumeBytesPerTask) + return stream.ToAPIRecords(collected), readTo, w.RunID, nil +} + +// readWindowFor reads a range from whichever component holds it. +// +// Standalone external streams use the routed service client. That RPC only +// reads the source execution and never calls back into the locked consumer. +// Owned streams must use the already-loaded component: re-entering this +// execution through an RPC would contend with the lock already held. +func readWindowFor( + ctx context.Context, + chasmCtx chasm.Context, + wf *chasmworkflow.Workflow, + namespaceID string, + name string, + external bool, + streamID string, + from, to int64, +) (stream.Window, error) { + req := stream.WindowRequest{From: from, MaxMessages: int32(to - from)} + if !external { + s := wf.OwnedStream(chasmCtx, name) + if s == nil { + return stream.Window{To: from}, nil + } + return s.ReadWindow(chasmCtx, req) + } + return readExternalWindow(ctx, namespaceID, streamID, from, to) +} + +// DeliverStreamSlices hands the next range to a task built outside this +// package. The inline task returned by RespondWorkflowTaskCompleted is built by +// its own handler, so without this a subscribed workflow gets no data on the +// dispatch path every current SDK asks for. +// +// Only the live range. That task is always sticky, so the worker still holds +// the execution and has no ranges to replay. +func DeliverStreamSlices( + ctx context.Context, + shardContext historyi.ShardContext, + ms historyi.MutableState, +) ([]*streampb.StreamSlice, error) { + live, _, err := deliverStreamSlices(ctx, shardContext, ms) + return live, err +} + +// deliverStreamSlices hands the next range of every stream this workflow +// consumes to the task being started, and stages that range on the cursor so +// the event closing the task can record what was delivered. +// +// The payload read runs with the workflow lock held. That is the price of +// deciding a range and staging it in one transaction: staged first and read +// after, a failed read would leave a range that the worker never received but +// that the completion would still record as consumed. +func deliverStreamSlices( + ctx context.Context, + shardContext historyi.ShardContext, + ms historyi.MutableState, +) ([]*streampb.StreamSlice, map[string]streamOrigin, error) { + if !ms.HasChasmWorkflowComponent() { + return nil, nil, nil + } + // Read-only first. Reaching the component mutably marks it dirty, and a + // workflow with no subscription should not pay a node in its transaction + // for every task it runs. + if readOnly, _, err := ms.ChasmWorkflowComponentReadOnly(ctx); err != nil { + return nil, nil, err + } else if len(readOnly.StreamCursors) == 0 { + return nil, nil, nil + } + + wf, chasmCtx, err := ms.ChasmWorkflowComponent(ctx) + if err != nil { + return nil, nil, err + } + + names := make([]string, 0, len(wf.StreamCursors)) + for name := range wf.StreamCursors { + names = append(names, name) + } + // Delivery order has to be stable, because the completion records these + // ranges in the order they were produced. + slices.Sort(names) + + limits := shardContext.GetConfig().Stream.LimitsFor(ms.GetNamespaceEntry().Name().String()) + maxItems := limits.MaxConsumeItemsPerTask + consumer := ms.GetWorkflowKey() + + slicesOut := make([]*streampb.StreamSlice, 0, len(names)) + addresses := make(map[string]streamOrigin, len(names)) + for _, name := range names { + cursor := wf.StreamCursors[name].Get(chasmCtx) + + head, err := deliveryFrontier(chasmCtx, wf, name, cursor) + if err != nil { + return nil, nil, err + } + + // A range already staged is redelivered unchanged. The same task can be + // started more than once, and letting the second attempt pick up newer + // data would hand the workflow a different range than the one the + // completion is going to record. + from, to, restaged := cursor.Pending() + if !restaged { + from = cursor.Offset() + // Clip to the frontier, which is the committed head for an owned + // stream and the last pushed head for an external one. + to = min(from+int64(maxItems), head) + } + + records, next, ownerRunID, err := readDeliverable( + ctx, chasmCtx, wf, consumer.NamespaceID, name, cursor, from, to, limits) + if err != nil { + return nil, nil, err + } + if !cursor.IsExternal() { + ownerRunID = consumer.RunID + } + + if restaged { + // The staged range is the one the completion will record, so the + // worker has to be handed exactly that. A re-read that comes back + // short would otherwise deliver less than history claims was + // consumed, and replay would then disagree with the original run. + if next != to { + return nil, nil, serviceerror.NewInternalf( + "stream %q staged range [%d,%d) re-read as [%d,%d)", + cursor.StreamID(), from, to, from, next) + } + } else if err := cursor.StagePending(chasmCtx, from, next); err != nil { + return nil, nil, err + } + + // Attached even when empty. A task that saw nothing still has to record + // that it saw nothing, and the slice is what the completion reads. + slicesOut = append(slicesOut, &streampb.StreamSlice{ + StreamId: cursor.StreamID(), + RunId: ownerRunID, + FromOffset: from, + ToOffset: next, + Records: records, + }) + addresses[cursor.StreamID()] = streamOrigin{ + external: cursor.IsExternal(), + name: name, + start: cursor.StartOffset(), + committed: cursor.Offset(), + } + } + return slicesOut, addresses, nil +} + +// Bounds on one cold replay's re-supply. History holds offsets and not payloads, +// so replaying a consumer means re-reading every range its completed tasks +// recorded, and that grows with the workflow's whole life rather than with the +// task being started. A consumer past these bounds cannot be replayed by this +// path; its task is failed with a cause that says so rather than retried. +const ( + maxReplayRecords = 100_000 + maxReplayBytes = 64 << 20 + // Pages of history walked to find the recorded ranges. Empty ranges cost + // nothing to attach but each page is a store read under a request deadline. + maxReplayPages = 256 +) + +// ownedRange names a range of a stream the consumer owns. +type ownedRange struct { + name string + req stream.WindowRequest +} + +// readRecordedRange re-supplies a range a completed task recorded. +// +// It runs after the execution lock is released, so an owned stream is read +// back through the engine, from the run that holds it: the consumer itself, or +// the run the consumer was reset from for a range recorded before the reset. +// Standalone sources use the routed service client, since their shards can +// belong to a different history host. +func readRecordedRange( + ctx context.Context, + consumer definition.WorkflowKey, + origin streamOrigin, + ownerRunID string, + streamID string, + from, to int64, +) (stream.Window, error) { + req := stream.WindowRequest{From: from, MaxMessages: int32(to - from)} + if origin.external { + return readExternalWindow(ctx, consumer.NamespaceID, streamID, from, to) + } + return chasm.ReadComponent(ctx, + chasm.NewComponentRef[*chasmworkflow.Workflow](chasm.ExecutionKey{ + NamespaceID: consumer.NamespaceID, + BusinessID: consumer.WorkflowID, + RunID: ownerRunID, + }), + func(wf *chasmworkflow.Workflow, cctx chasm.Context, r ownedRange) (stream.Window, error) { + s := wf.OwnedStream(cctx, r.name) + if s == nil { + return stream.Window{To: r.req.From}, nil + } + return s.ReadWindow(cctx, r.req) + }, + ownedRange{name: origin.name, req: req}) +} + +// replaySupply collects what one cold replay owes the worker: the ranges every +// completed task recorded, re-read from their streams, within one response's +// budget. +type replaySupply struct { + ctx context.Context + consumer definition.WorkflowKey + addresses map[string]streamOrigin + + records int + bytes int + // How far the recorded ranges reach, per stream, so the coverage check + // can tell a complete re-supply from a short one. + reached map[string]int64 + slices []*streampb.StreamSlice + + // Ranges recorded since the last reset point, waiting to learn which run's + // stream holds them. A reset copies the base run's history into the new + // run, so the ranges before the reset point were consumed from the base + // run's owned streams, and the run they belong to is only named by the + // event that marks the reset point, after them in the history. Ranges + // after the last reset point belong to the consumer itself. + pending []recordedRange +} + +// recordedRange is one consumed range and the completion that recorded it. +type recordedRange struct { + eventID int64 + recorded *streampb.StreamRange +} + +// attachReplaySlices re-supplies the payloads for ranges that earlier workflow +// tasks recorded, keyed by the event that recorded each one. +// +// History holds offsets and never payloads, which is the property the whole +// design rests on. The cost lands here: a worker replaying from History has to +// be handed the same bytes those tasks were given, and the only place they +// exist is the stream itself. The response field alone cannot carry this, +// because it is built once per delivery while a cache miss replays every prior +// task, so each range travels with the id of the event that recorded it. +// +// The response carries one page of history. The recording events of a consumer +// that has lived longer than a page are on the pages after it, so every page is +// read here. Empty ranges are recorded too and have to travel with their +// events, which is why the walk cannot stop once the committed offset is found. +func attachReplaySlices( + ctx context.Context, + shardContext historyi.ShardContext, + consumer definition.WorkflowKey, + addresses map[string]streamOrigin, + pageSize int32, + resp *historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, +) error { + // Only a workflow with a live subscription has anything to re-supply, and + // that is exactly when delivery attached a slice for the current task. So + // this costs nothing for every other workflow. + if len(addresses) == 0 { + return nil + } + + // A sticky task means the worker still holds the execution, so it has + // nothing to replay. Its history begins at the previous task's completion, + // and that event carries the range that task already consumed, so + // re-supplying it here would hand the workflow the same records twice. + if resp.GetStickyExecutionEnabled() { + return nil + } + + events, err := eventsOfResponse(resp) + if err != nil { + return err + } + supply := &replaySupply{ + ctx: ctx, + consumer: consumer, + addresses: addresses, + reached: make(map[string]int64, len(addresses)), + } + if err := supply.collect(events); err != nil { + return err + } + + pages := 1 + token := resp.GetNextPageToken() + for len(token) > 0 { + pages++ + if pages > maxReplayPages { + return unavailablef( + "replaying workflow %q needs more than %d pages of history to find the stream "+ + "ranges its tasks consumed", consumer.GetWorkflowID(), maxReplayPages) + } + continuation, err := api.DeserializeHistoryToken(token) + if err != nil { + return err + } + // Read raw and decode here. The first page may have been read either + // way, and only the raw reader accepts the token both produce. + blobs, _, next, err := persistence.ReadFullPageRawEvents( + ctx, shardContext.GetExecutionManager(), &persistence.ReadHistoryBranchRequest{ + BranchToken: continuation.GetBranchToken(), + MinEventID: continuation.GetFirstEventId(), + MaxEventID: continuation.GetNextEventId(), + PageSize: int(pageSize), + NextPageToken: continuation.GetPersistenceToken(), + ShardID: shardContext.GetShardID(), + }) + if err != nil { + return err + } + pageEvents, err := decodeEventBlobs(blobs) + if err != nil { + return err + } + if err := supply.collect(pageEvents); err != nil { + return err + } + if len(next) == 0 { + break + } + continuation.PersistenceToken = next + if token, err = api.SerializeHistoryToken(continuation); err != nil { + return err + } + } + + if err := supply.finish(); err != nil { + return err + } + if err := supply.checkCoverage(); err != nil { + return err + } + resp.StreamSlices = append(resp.StreamSlices, supply.slices...) + return nil +} + +// ReplaySlicesForQuery re-supplies the recorded ranges for a query dispatched +// straight through matching. +// +// Such a query carries the workflow's whole history to a worker that may never +// have seen the execution, exactly like a task after a cache miss, but it is +// built without RecordWorkflowTaskStarted and so never passes through the +// delivery above. The history is read from the branch rather than from a +// response, which is the only difference from the task path. +// +// The lease is held only long enough to read the cursors and the branch, and +// released before any page or stream is read, as on the task path. A range the +// stream can no longer serve is a failed precondition here rather than a failed +// task, because there is no task to fail: the query is refused and the +// workflow's next real task will fail with the cause. +func ReplaySlicesForQuery( + ctx context.Context, + shardContext historyi.ShardContext, + workflowConsistencyChecker api.WorkflowConsistencyChecker, + workflowKey definition.WorkflowKey, + pageSize int32, +) ([]*streampb.StreamSlice, error) { + lease, err := workflowConsistencyChecker.GetWorkflowLease( + ctx, nil, workflowKey, locks.PriorityHigh) + if err != nil { + return nil, err + } + ms := lease.GetMutableState() + addresses, err := streamOrigins(ctx, ms) + if err != nil || len(addresses) == 0 { + lease.GetReleaseFn()(nil) + return nil, err + } + branchToken, err := ms.GetCurrentBranchToken() + if err != nil { + lease.GetReleaseFn()(nil) + return nil, err + } + nextEventID := ms.GetNextEventID() + consumer := ms.GetWorkflowKey() + lease.GetReleaseFn()(nil) + + supply := &replaySupply{ + ctx: ctx, + consumer: consumer, + addresses: addresses, + reached: make(map[string]int64, len(addresses)), + } + var token []byte + for pages := 1; ; pages++ { + if pages > maxReplayPages { + return nil, unavailablef( + "replaying workflow %q needs more than %d pages of history to find the stream "+ + "ranges its tasks consumed", consumer.GetWorkflowID(), maxReplayPages) + } + blobs, _, next, err := persistence.ReadFullPageRawEvents( + ctx, shardContext.GetExecutionManager(), &persistence.ReadHistoryBranchRequest{ + BranchToken: branchToken, + MinEventID: common.FirstEventID, + MaxEventID: nextEventID, + PageSize: int(pageSize), + NextPageToken: token, + ShardID: shardContext.GetShardID(), + }) + if err != nil { + return nil, err + } + events, err := decodeEventBlobs(blobs) + if err != nil { + return nil, err + } + if err := supply.collect(events); err != nil { + return nil, err + } + if len(next) == 0 { + break + } + token = next + } + if err := supply.finish(); err != nil { + return nil, err + } + if err := supply.checkCoverage(); err != nil { + return nil, err + } + return supply.slices, nil +} + +// AsRefusal turns a range that cannot be served into the error a caller with +// no task to fail should return. Any other error is handed back unchanged. +func AsRefusal(err error) error { + var unavailable *rangeUnavailable + if errors.As(err, &unavailable) { + return serviceerror.NewFailedPrecondition(unavailable.Error()) + } + return err +} + +// collect gathers every range the events on one page recorded and re-reads the +// ones whose run it can name. A reset point names the run for everything +// gathered before it. +func (s *replaySupply) collect(events []*historypb.HistoryEvent) error { + for _, event := range events { + if attrs := event.GetWorkflowTaskFailedEventAttributes(); attrs != nil && + attrs.GetCause() == enumspb.WORKFLOW_TASK_FAILED_CAUSE_RESET_WORKFLOW && + attrs.GetBaseRunId() != "" { + if err := s.flush(attrs.GetBaseRunId()); err != nil { + return err + } + continue + } + for _, recorded := range event.GetWorkflowTaskCompletedEventAttributes().GetConsumedStreamRanges() { + if _, ok := s.addresses[recorded.GetStreamId()]; !ok { + // A subscription the workflow has since dropped. The range is + // still part of its history, but nothing is consuming it now. + continue + } + s.pending = append(s.pending, recordedRange{eventID: event.GetEventId(), recorded: recorded}) + } + } + return nil +} + +// finish re-reads the ranges recorded after the last reset point, which the +// consumer's own streams hold. Called once every page has been walked. +func (s *replaySupply) finish() error { + return s.flush(s.consumer.RunID) +} + +// flush re-reads every range gathered since the last reset point from the run +// named for it, in the order the tasks recorded them. +func (s *replaySupply) flush(ownerRunID string) error { + for _, r := range s.pending { + address := s.addresses[r.recorded.GetStreamId()] + records, runID, err := s.recordsFor(address, ownerRunID, r.recorded) + if err != nil { + return err + } + + if to := r.recorded.GetToOffset(); to > s.reached[r.recorded.GetStreamId()] { + s.reached[r.recorded.GetStreamId()] = to + } + + // Attached even when empty: the task observed nothing, and replay + // has to reproduce that rather than infer it from an absence. + s.slices = append(s.slices, &streampb.StreamSlice{ + StreamId: r.recorded.GetStreamId(), + RunId: runID, + FromOffset: r.recorded.GetFromOffset(), + ToOffset: r.recorded.GetToOffset(), + Records: records, + WorkflowTaskCompletedEventId: r.eventID, + }) + } + s.pending = nil + return nil +} + +// recordsFor re-reads one recorded range, or returns nothing for a range that +// recorded an empty observation. The run id is the execution holding the +// stream: for an owned stream the run named for the range, for a standalone +// one whatever run the read reports. +func (s *replaySupply) recordsFor( + address streamOrigin, + ownerRunID string, + recorded *streampb.StreamRange, +) ([]*streampb.StreamRecord, string, error) { + if recorded.GetToOffset() <= recorded.GetFromOffset() { + if address.external { + ownerRunID = "" + } + return nil, ownerRunID, nil + } + + w, err := readRecordedRange(s.ctx, s.consumer, address, ownerRunID, + recorded.GetStreamId(), recorded.GetFromOffset(), recorded.GetToOffset()) + if err != nil { + // Truncation and deletion are the reachable causes, and neither is + // recoverable for this workflow: without the bytes it can never + // replay, and without replaying it can never start another task. + return nil, "", unavailableIfGone(err, + "workflow %q cannot replay: stream %q no longer holds offsets [%d,%d) that one "+ + "of its completed tasks consumed", + s.consumer.GetWorkflowID(), recorded.GetStreamId(), + recorded.GetFromOffset(), recorded.GetToOffset()) + } + if address.external { + ownerRunID = w.RunID + } + collected, _, err := stream.CollectRecords( + w.Blobs, w.Starts, + recorded.GetFromOffset(), recorded.GetToOffset(), + int(recorded.GetToOffset()-recorded.GetFromOffset()), nil) + if err != nil { + return nil, "", err + } + records := stream.ToAPIRecords(collected) + + s.records += len(records) + for _, m := range records { + s.bytes += proto.Size(m) + } + // Bounded because every prior task's range is re-read into one response, so + // a long-lived consumer's cold replay grows with its whole history. Refused + // rather than trimmed: a short re-supply is what replay cannot survive. + if s.records > maxReplayRecords || s.bytes > maxReplayBytes { + return nil, "", unavailablef( + "replaying workflow %q needs more than %d records or %d bytes of stream history "+ + "to re-supply; the consumed ranges cannot be re-delivered in one response", + s.consumer.GetWorkflowID(), maxReplayRecords, maxReplayBytes) + } + return records, ownerRunID, nil +} + +// checkCoverage refuses a re-supply that stops short of what the cursor says +// the consumer consumed. With every page read, a shortfall means History and +// the cursor disagree, and handing the worker less than the first run saw is +// the one outcome replay cannot survive. +func (s *replaySupply) checkCoverage() error { + for streamID, address := range s.addresses { + got, ok := s.reached[streamID] + if !ok { + got = address.start + } + if got < address.committed { + return unavailablef( + "workflow %q consumed stream %q through offset %d but its history only records "+ + "through %d", s.consumer.GetWorkflowID(), streamID, address.committed, got) + } + } + return nil +} + +// eventsOfResponse reads the events the response is carrying, whichever of the +// three representations it happens to be using. +func eventsOfResponse( + resp *historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, +) ([]*historypb.HistoryEvent, error) { + if resp.GetHistory() != nil { + return resp.GetHistory().GetEvents(), nil + } + + raw := resp.GetRawHistoryBytes() + if len(raw) == 0 { + //nolint:staticcheck // SA1019: still populated while the newer field rolls out. + raw = resp.GetRawHistory() + } + blobs := make([]*commonpb.DataBlob, 0, len(raw)) + for _, batch := range raw { + blobs = append(blobs, &commonpb.DataBlob{ + EncodingType: enumspb.ENCODING_TYPE_PROTO3, + Data: batch, + }) + } + return decodeEventBlobs(blobs) +} + +func decodeEventBlobs(blobs []*commonpb.DataBlob) ([]*historypb.HistoryEvent, error) { + serializer := serialization.NewSerializer() + var events []*historypb.HistoryEvent + for _, blob := range blobs { + batchEvents, err := serializer.DeserializeEvents(blob) + if err != nil { + return nil, err + } + events = append(events, batchEvents...) + } + return events, nil +} diff --git a/service/history/api/recordworkflowtaskstarted/stream_slices_test.go b/service/history/api/recordworkflowtaskstarted/stream_slices_test.go new file mode 100644 index 00000000000..f0e63b2a107 --- /dev/null +++ b/service/history/api/recordworkflowtaskstarted/stream_slices_test.go @@ -0,0 +1,125 @@ +package recordworkflowtaskstarted + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/server/chasm" + "go.temporal.io/server/common/definition" + "go.uber.org/mock/gomock" +) + +func completedWithRange(eventID int64, from, to int64) *historypb.HistoryEvent { + return &historypb.HistoryEvent{ + EventId: eventID, + EventType: enumspb.EVENT_TYPE_WORKFLOW_TASK_COMPLETED, + Attributes: &historypb.HistoryEvent_WorkflowTaskCompletedEventAttributes{ + WorkflowTaskCompletedEventAttributes: &historypb.WorkflowTaskCompletedEventAttributes{ + ConsumedStreamRanges: []*streampb.StreamRange{ + {StreamId: "output", FromOffset: from, ToOffset: to}, + }, + }, + }, + } +} + +func resetPoint(eventID int64, baseRunID string) *historypb.HistoryEvent { + return &historypb.HistoryEvent{ + EventId: eventID, + EventType: enumspb.EVENT_TYPE_WORKFLOW_TASK_FAILED, + Attributes: &historypb.HistoryEvent_WorkflowTaskFailedEventAttributes{ + WorkflowTaskFailedEventAttributes: &historypb.WorkflowTaskFailedEventAttributes{ + Cause: enumspb.WORKFLOW_TASK_FAILED_CAUSE_RESET_WORKFLOW, + BaseRunId: baseRunID, + NewRunId: "reset-run", + }, + }, + } +} + +// A reset copies the base run's history into the new run. The ranges recorded +// before the reset point were consumed from the base run's own stream, so +// replay has to read them from that run and say so on the slice, while the +// ranges recorded after it are the reset run's own. A reset of a reset run +// leaves two such points, one per run in the chain. +func TestReplayReadsRangesBeforeAResetFromTheRunThatHoldsThem(t *testing.T) { + var readFrom []string + engine := chasm.NewMockEngine(gomock.NewController(t)) + engine.EXPECT().ReadComponent(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func( + _ context.Context, + ref chasm.ComponentRef, + _ func(chasm.Context, chasm.Component) error, + _ ...chasm.TransitionOption, + ) error { + require.Equal(t, "consumer", ref.BusinessID) + readFrom = append(readFrom, ref.RunID) + return nil + }).AnyTimes() + + supply := &replaySupply{ + ctx: chasm.NewEngineContext(context.Background(), engine), + consumer: definition.NewWorkflowKey("ns", "consumer", "reset-run"), + addresses: map[string]streamOrigin{"output": {name: "output"}}, + reached: map[string]int64{}, + } + + // First page: the oldest run's era ends with the first reset point. + require.NoError(t, supply.collect([]*historypb.HistoryEvent{ + completedWithRange(4, 0, 2), + completedWithRange(8, 2, 2), + resetPoint(10, "first-run"), + })) + // Second page: the middle run's era, then the reset that made this run. + require.NoError(t, supply.collect([]*historypb.HistoryEvent{ + completedWithRange(14, 2, 5), + resetPoint(16, "second-run"), + completedWithRange(20, 5, 5), + completedWithRange(24, 5, 7), + })) + require.NoError(t, supply.finish()) + require.NoError(t, supply.checkCoverage()) + + require.Equal(t, []string{"first-run", "second-run", "reset-run"}, readFrom, + "every non-empty range is read from the run whose era recorded it") + + runs := make([]string, 0, len(supply.slices)) + events := make([]int64, 0, len(supply.slices)) + for _, slice := range supply.slices { + runs = append(runs, slice.GetRunId()) + events = append(events, slice.GetWorkflowTaskCompletedEventId()) + } + require.Equal(t, []int64{4, 8, 14, 20, 24}, events, "slices keep the order the tasks ran in") + require.Equal(t, []string{"first-run", "first-run", "second-run", "reset-run", "reset-run"}, runs, + "an empty range names its era's run too") +} + +// Without a reset point every owned range is the consumer's own. +func TestReplayWithoutAResetReadsFromTheConsumer(t *testing.T) { + engine := chasm.NewMockEngine(gomock.NewController(t)) + engine.EXPECT().ReadComponent(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func( + _ context.Context, + ref chasm.ComponentRef, + _ func(chasm.Context, chasm.Component) error, + _ ...chasm.TransitionOption, + ) error { + require.Equal(t, "consumer-run", ref.RunID) + return nil + }).Times(1) + + supply := &replaySupply{ + ctx: chasm.NewEngineContext(context.Background(), engine), + consumer: definition.NewWorkflowKey("ns", "consumer", "consumer-run"), + addresses: map[string]streamOrigin{"output": {name: "output"}}, + reached: map[string]int64{}, + } + require.NoError(t, supply.collect([]*historypb.HistoryEvent{completedWithRange(4, 0, 3)})) + require.NoError(t, supply.finish()) + require.Len(t, supply.slices, 1) + require.Equal(t, "consumer-run", supply.slices[0].GetRunId()) +} diff --git a/service/history/api/respondworkflowtaskcompleted/api.go b/service/history/api/respondworkflowtaskcompleted/api.go index a569e0ecc26..46386b602d6 100644 --- a/service/history/api/respondworkflowtaskcompleted/api.go +++ b/service/history/api/respondworkflowtaskcompleted/api.go @@ -452,6 +452,34 @@ func (handler *WorkflowTaskCompletedHandler) Invoke( return nil, err } + // Subscriptions to streams in other executions, resolved here for the + // same reason: the command handler has nowhere to look the addressing + // up from, and by delivery time the cursor has to already exist. + // + // Skipped once the task has failed. Registering a consumer is a durable + // write on the stream's own execution, and this workflow's side of it + // is about to be rolled back, which would leave a pin on someone else's + // stream with no cursor behind it and nothing to release it. A failed + // command does not return an error, so this has to be checked here + // rather than inferred from err. + if workflowTaskHandler.workflowTaskFailedCause == nil && !workflowTaskHandler.stopProcessing { + err = resolveStagedStreamSubscriptions( + ctx, + ms, + ms.GetWorkflowKey().NamespaceID, + handler.config.Stream.LimitsFor(namespaceEntry.Name().String()), + workflowTaskHandler.stagedStreamSubscriptions, + ) + if failWFTErr, ok := errors.AsType[chasmworkflow.FailWorkflowTaskError](err); ok { + // A refused subscription fails the task the way a refused + // command does, so the cause lands in History. + err = workflowTaskHandler.failWorkflowTask(failWFTErr.Cause, failWFTErr) + } + if err != nil { + return nil, err + } + } + // Worker must respond with Update Accepted or Update Rejected message on every Update Requested // message that were delivered on specific WT, when completing this WT. // If worker ignored the update request (old SDK or SDK bug), then server rejects this update. @@ -805,6 +833,14 @@ func (handler *WorkflowTaskCompletedHandler) Invoke( // sticky is always enabled when worker request for new workflow task from RespondWorkflowTaskCompleted resp.StartedResponse.StickyExecutionEnabled = true + // The poll path delivers from its own handler, so this one has to ask + // as well or a subscribed workflow gets an inline task with no data. + resp.StartedResponse.StreamSlices, err = recordworkflowtaskstarted.DeliverStreamSlices( + ctx, handler.shardContext, ms) + if err != nil { + return nil, err + } + resp.NewWorkflowTask, err = handler.withNewWorkflowTask(ctx, namespaceEntry.Name(), req, resp.StartedResponse) if err != nil { return nil, err @@ -977,6 +1013,7 @@ func (handler *WorkflowTaskCompletedHandler) createPollWorkflowTaskQueueResponse StartedTime: matchingResp.StartedTime, Queries: matchingResp.Queries, Messages: matchingResp.Messages, + StreamSlices: matchingResp.StreamSlices, } return resp, nil diff --git a/service/history/api/respondworkflowtaskcompleted/stream_appends.go b/service/history/api/respondworkflowtaskcompleted/stream_appends.go new file mode 100644 index 00000000000..fa73426b14c --- /dev/null +++ b/service/history/api/respondworkflowtaskcompleted/stream_appends.go @@ -0,0 +1,153 @@ +package respondworkflowtaskcompleted + +import ( + "context" + "errors" + + enumspb "go.temporal.io/api/enums/v1" + "go.temporal.io/api/serviceerror" + "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/service/history/api/recordworkflowtaskstarted" + historyi "go.temporal.io/server/service/history/interfaces" +) + +// resolveStagedStreamSubscriptions turns subscribe commands for streams in +// other executions into cursors on this workflow. +// +// The lookup cannot happen in the command handler, which runs under the state +// lock with nowhere to do I/O from, and it cannot happen at delivery either, +// because by then the cursor has to already exist. So it happens here, between +// the commands and the commit. +// +// The pin goes on the stream before the cursor goes on the workflow, and that +// order is the guarantee. Interrupted after the first write there is a pin +// holding storage nothing reads, which costs space. The other order would leave +// a cursor no truncation floor protects, and truncation would be free to take a +// range it still points at. +// +// The pin is taken through the routed service client. The engine on this +// request context resolves shards through the local controller, which refuses +// any shard this host does not own, so a stream living elsewhere in the +// cluster can only be reached by going back out through the service. +// +// A refusal, such as a stream that does not exist or an offset below its floor, +// comes back as a workflow task failure so the worker sees a cause rather than +// retrying the same command. A pin already taken for an earlier subscription +// in the same task stays on its stream; the notify task releases it when it +// finds this workflow does not consume that stream. +func resolveStagedStreamSubscriptions( + ctx context.Context, + ms historyi.MutableState, + namespaceID string, + limits stream.Limits, + staged []chasmworkflow.PendingStreamSubscription, +) error { + if len(staged) == 0 { + return nil + } + + wf, chasmCtx, err := ms.ChasmWorkflowComponent(ctx) + if err != nil { + return err + } + + for _, pending := range staged { + // Already subscribed, so only the event is owed. Re-registering would + // re-run the pin write with the original start offset, which would drag + // the stream's truncation floor back to where this consumer began. + if pending.AlreadySubscribed { + cursor, ok := wf.StreamCursors[pending.StreamID] + if !ok { + return serviceerror.NewInternalf( + "stream %q was marked already subscribed but has no cursor", pending.StreamID) + } + chasmworkflow.RecordStreamSubscribedOffset( + pending.Event, cursor.Get(chasmCtx).Offset()) + continue + } + + // A stream this workflow owns needs no lookup and no pin registration: + // it is in this execution, and its cursor commits with everything else. + if _, owned := wf.Streams[pending.StreamID]; owned { + startOffset, err := wf.SubscribeToOwnedStream( + chasmCtx, pending.StreamID, pending.StartOffset, limits) + if err != nil { + return chasmworkflow.StreamAdmissionFailure( + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SUBSCRIBE_STREAM_ATTRIBUTES, err) + } + chasmworkflow.RecordStreamSubscribedOffset(pending.Event, startOffset) + continue + } + + pin, err := registerExternalConsumer(ctx, ms, namespaceID, pending) + if err != nil { + var notFound *serviceerror.NotFound + if !errors.As(err, ¬Found) { + return chasmworkflow.StreamAdmissionFailure( + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SUBSCRIBE_STREAM_ATTRIBUTES, err) + } + // No execution holds a stream by this id, so the name is one of this + // workflow's own that nothing has written to yet. A reader has to be + // able to subscribe before the first record arrives, so the stream + // is created here and the subscription lands on it. + startOffset, err := wf.SubscribeToOwnedStream( + chasmCtx, pending.StreamID, pending.StartOffset, limits) + if err != nil { + return chasmworkflow.StreamAdmissionFailure( + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SUBSCRIBE_STREAM_ATTRIBUTES, err) + } + chasmworkflow.RecordStreamSubscribedOffset(pending.Event, startOffset) + continue + } + + if _, err := wf.SubscribeToExternalStream(chasmCtx, chasmworkflow.ExternalStreamSubscription{ + StreamID: pending.StreamID, + StartOffset: pin.GetStartOffset(), + KnownHead: pin.GetKnownHead(), + }); err != nil { + return err + } + + // Completed after the cursor exists. The event was written where the + // command was, but nothing outside this transaction sees either until + // the commit below, so a crash in between leaves no event claiming a + // subscription that was never made. + chasmworkflow.RecordStreamSubscribedOffset(pending.Event, pin.GetStartOffset()) + } + return nil +} + +// registerExternalConsumer takes the pin on the stream's own shard and returns +// the resolved start offset and the frontier as of registration. +func registerExternalConsumer( + ctx context.Context, + ms historyi.MutableState, + namespaceID string, + pending chasmworkflow.PendingStreamSubscription, +) (*streamlib.RegisterStreamConsumerOutput, error) { + client, ok := recordworkflowtaskstarted.StreamClientFromContext(ctx) + if !ok { + return nil, serviceerror.NewInternal( + "stream service client is not available on the workflow task completion path") + } + + key := ms.GetWorkflowKey() + callCtx, cancel := recordworkflowtaskstarted.WithRoutedDeadline(ctx) + defer cancel() + registered, err := client.RegisterStreamConsumer(callCtx, &streamlib.RegisterStreamConsumerRequest{ + NamespaceId: namespaceID, + FrontendRequest: &streamlib.RegisterStreamConsumerInput{ + Namespace: ms.GetNamespaceEntry().Name().String(), + StreamId: pending.StreamID, + ConsumerWorkflowId: key.WorkflowID, + ConsumerRunId: key.RunID, + StartOffset: pending.StartOffset, + }, + }) + if err != nil { + return nil, err + } + return registered.GetFrontendResponse(), nil +} diff --git a/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler.go b/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler.go index 4e8da517eae..8baf1728e6d 100644 --- a/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler.go +++ b/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler.go @@ -61,6 +61,9 @@ type ( workflowTaskDeployment *deploymentpb.Deployment // internal state + // Subscribe commands for streams in other executions, resolved before + // this workflow task commits. + stagedStreamSubscriptions []chasmworkflow.PendingStreamSubscription hasBufferedEventsOrMessages bool workflowTaskFailedCause *workflowTaskFailedCause activityNotStartedCancelled bool @@ -354,6 +357,12 @@ func (handler *workflowTaskCompletedHandler) handleCommand( return nil, chasmErr } err = chasmHandler(chasmCtx, chasmWorkflow, validator, command, handlerOpts) + // A subscribe to a stream in another execution stages itself, + // since a command handler holds the state lock and has no + // context for the lookup it needs. Collect them for the + // resolution that has to precede this task's commit. + handler.stagedStreamSubscriptions = append( + handler.stagedStreamSubscriptions, chasmWorkflow.DrainStreamSubscriptions()...) // Fall back to the HSM handler either when the command type is not supported by CHASM (disabled // feature flag) or when the targeted entity is not owned by the CHASM tree (e.g. an operation // scheduled in HSM before the flag was flipped on). diff --git a/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler_test.go b/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler_test.go index 501cf4dc51e..d0293e1a2dc 100644 --- a/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler_test.go +++ b/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler_test.go @@ -81,6 +81,9 @@ func TestCommandProtocolMessage(t *testing.T) { out.ms.EXPECT().VisitUpdates(gomock.Any()).AnyTimes() out.ms.EXPECT().GetNamespaceEntry().Return(tests.LocalNamespaceEntry).AnyTimes() out.ms.EXPECT().GetCurrentVersion().Return(tests.LocalNamespaceEntry.FailoverVersion(tests.WorkflowID)).AnyTimes() + out.ms.EXPECT().GetExecutionInfo().Return(&persistencespb.WorkflowExecutionInfo{ + WorkflowTaskAttempt: 1, + }).AnyTimes() dcClient := dynamicconfig.StaticClient(nil) if opts.chasmEnabled { diff --git a/service/history/configs/config.go b/service/history/configs/config.go index 2e197e0e43c..f802367292b 100644 --- a/service/history/configs/config.go +++ b/service/history/configs/config.go @@ -3,6 +3,7 @@ package configs import ( "go.temporal.io/server/chasm/lib/callback" "go.temporal.io/server/chasm/lib/nexusoperation" + "go.temporal.io/server/chasm/lib/stream" "go.temporal.io/server/common" "go.temporal.io/server/common/dynamicconfig" "go.temporal.io/server/common/health" @@ -253,6 +254,7 @@ type Config struct { HistoryCountLimitWarn dynamicconfig.IntPropertyFnWithNamespaceFilter HistoryCountSuggestContinueAsNew dynamicconfig.IntPropertyFnWithNamespaceFilter HistoryMaxPageSize dynamicconfig.IntPropertyFnWithNamespaceFilter + Stream *stream.Config MutableStateActivityFailureSizeLimitError dynamicconfig.IntPropertyFnWithNamespaceFilter MutableStateActivityFailureSizeLimitWarn dynamicconfig.IntPropertyFnWithNamespaceFilter MutableStateSizeLimitError dynamicconfig.IntPropertyFn @@ -711,6 +713,7 @@ func NewConfig( HistoryCountLimitWarn: dynamicconfig.HistoryCountLimitWarn.Get(dc), HistoryCountSuggestContinueAsNew: dynamicconfig.HistoryCountSuggestContinueAsNew.Get(dc), HistoryMaxPageSize: dynamicconfig.HistoryMaxPageSize.Get(dc), + Stream: stream.NewConfig(dc), MutableStateActivityFailureSizeLimitError: dynamicconfig.MutableStateActivityFailureSizeLimitError.Get(dc), MutableStateActivityFailureSizeLimitWarn: dynamicconfig.MutableStateActivityFailureSizeLimitWarn.Get(dc), MutableStateSizeLimitError: dynamicconfig.MutableStateSizeLimitError.Get(dc), diff --git a/service/history/fx.go b/service/history/fx.go index dcf233185fe..0b004c3ab3e 100644 --- a/service/history/fx.go +++ b/service/history/fx.go @@ -11,6 +11,7 @@ import ( "go.temporal.io/server/chasm/lib/callback" chasmnexus "go.temporal.io/server/chasm/lib/nexusoperation" "go.temporal.io/server/chasm/lib/scheduler" + chasmstream "go.temporal.io/server/chasm/lib/stream/service" chasmtests "go.temporal.io/server/chasm/lib/tests" chasmworkflow "go.temporal.io/server/chasm/lib/workflow" "go.temporal.io/server/common" @@ -123,6 +124,7 @@ var Module = fx.Options( hsmnexusoperations.Module, fx.Invoke(hsmnexusworkflow.RegisterCommandHandlers), activity.HistoryModule, + chasmstream.HistoryModule, scheduler.Module, callback.Module, chasmnexus.Module, diff --git a/service/history/handler.go b/service/history/handler.go index d25e52b32bc..f63609d89f9 100644 --- a/service/history/handler.go +++ b/service/history/handler.go @@ -880,6 +880,33 @@ func (h *Handler) GetMutableState(ctx context.Context, request *historyservice.G return resp, nil } +// GetStreamReplaySlices re-supplies the stream ranges a workflow's completed tasks recorded. +func (h *Handler) GetStreamReplaySlices( + ctx context.Context, + request *historyservice.GetStreamReplaySlicesRequest, +) (*historyservice.GetStreamReplaySlicesResponse, error) { + namespaceID := namespace.ID(request.GetNamespaceId()) + if namespaceID == "" { + return nil, h.convertError(errNamespaceNotSet) + } + + workflowID := request.GetExecution().GetWorkflowId() + shardContext, err := h.controller.GetShardByNamespaceWorkflow(namespaceID, workflowID) + if err != nil { + return nil, h.convertError(err) + } + engine, err := shardContext.GetEngine(ctx) + if err != nil { + return nil, h.convertError(err) + } + + resp, err := engine.GetStreamReplaySlices(ctx, request) + if err != nil { + return nil, h.convertError(err) + } + return resp, nil +} + // PollMutableState - returns the id of the next event in the execution's history func (h *Handler) PollMutableState(ctx context.Context, request *historyservice.PollMutableStateRequest) (*historyservice.PollMutableStateResponse, error) { namespaceID := namespace.ID(request.GetNamespaceId()) @@ -2540,6 +2567,9 @@ func (h *Handler) UnpauseWorkflowExecution(ctx context.Context, request *history return unpauseResp, nil } +// StartNexusOperation is the History Service's StartNexusOperation endpoint is for dispatching requests +// to the System Nexus Endpoint, distinct from the Frontend Service's `nexus_handler.go` which +// starts Nexus operations by sending Nexus tasks directly to workers via the Matching Service. func (h *Handler) StartNexusOperation( ctx context.Context, req *historyservice.StartNexusOperationRequest, @@ -2602,16 +2632,29 @@ func (h *Handler) StartNexusOperation( h.logger.Error("failed to encode payload", tag.Error(err), tag.RequestID(requestID)) return nil, serviceerror.NewInternal("internal error (request ID: " + requestID + ")") } + var payload *commonpb.Payload if len(ps.GetPayloads()) == 1 { payload = ps.GetPayloads()[0] } + // Responses from the System Nexus Endpoint are server generated, so we must mark them as system payloads. if payload != nil { if payload.Metadata == nil { payload.Metadata = make(map[string][]byte, 1) } + + // Responses from the System Nexus Endpoint have to be protobufs. + encoding := string(payload.Metadata["encoding"]) + if encoding != "binary/protobuf" { + return nil, serviceerror.NewFailedPreconditionf("system payload must be encoded as binary/protobuf but got %s", encoding) + } + if _, ok := payload.Metadata["messageType"]; !ok { + return nil, serviceerror.NewFailedPrecondition("system payload missing messageType metadata key") + } + payload.Metadata[commonnexus.SystemPayloadMetadataKey] = []byte("true") } + response.Variant = &nexuspb.StartOperationResponse_SyncSuccess{ SyncSuccess: &nexuspb.StartOperationResponse_Sync{ Payload: payload, diff --git a/service/history/handler_test.go b/service/history/handler_test.go index e0c3df1b9f0..3394f59206e 100644 --- a/service/history/handler_test.go +++ b/service/history/handler_test.go @@ -450,3 +450,31 @@ func TestStartNexusOperation_SystemNexusEndpointPayloadMetadataFlag(t *testing.T }) } } + +func TestStartNexusOperation_SystemNexusEndpointRejectsNonProtoResponse(t *testing.T) { + registry := nexus.NewServiceRegistry() + registry.MustRegister(chasmtests.NewTestServiceNexusService()) + nexusHandler, err := registry.NewHandler() + require.NoError(t, err) + + h := Handler{ + logger: log.NewNoopLogger(), + nexusHandler: nexusHandler, + } + + // TestOperationStringOutput returns a string, which the data converter encodes as JSON + // instead of protobuf. The System Nexus Endpoint only accepts protobuf-encoded responses. + resp, err := h.StartNexusOperation(context.Background(), &historyservice.StartNexusOperationRequest{ + Request: &nexuspb.StartOperationRequest{ + Service: "TestService", + Operation: "TestOperationStringOutput", + RequestId: "test-request-id", + Payload: payload.EncodeString("Temporal"), + }, + }) + require.Nil(t, resp) + + var failedPrecondition *serviceerror.FailedPrecondition + require.ErrorAs(t, err, &failedPrecondition) + require.ErrorContains(t, err, "system payload must be encoded as binary/protobuf but got json/plain") +} diff --git a/service/history/history_engine.go b/service/history/history_engine.go index aab1aa4b67b..43407e3c359 100644 --- a/service/history/history_engine.go +++ b/service/history/history_engine.go @@ -14,6 +14,7 @@ import ( replicationspb "go.temporal.io/server/api/replication/v1" workflowspb "go.temporal.io/server/api/workflow/v1" "go.temporal.io/server/chasm" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" chasmworkflow "go.temporal.io/server/chasm/lib/workflow" "go.temporal.io/server/client" "go.temporal.io/server/common" @@ -22,6 +23,7 @@ import ( "go.temporal.io/server/common/collection" "go.temporal.io/server/common/definition" "go.temporal.io/server/common/headers" + "go.temporal.io/server/common/locks" "go.temporal.io/server/common/log" "go.temporal.io/server/common/log/tag" "go.temporal.io/server/common/metrics" @@ -106,6 +108,7 @@ import ( type ( engineOptions struct { workflowResendScheduler workflowresend.Scheduler + streamClient streampb.StreamServiceClient } // EngineOption adds optional history engine dependencies without adding required parameters. @@ -147,6 +150,7 @@ type ( workflowConsistencyChecker api.WorkflowConsistencyChecker workflowResendScheduler workflowresend.Scheduler chasmEngine chasm.Engine + streamClient streampb.StreamServiceClient versionChecker headers.VersionChecker versionCache worker_versioning.VersionMembershipAndReactivationStatusCache workerDeploymentClient workerdeployment.Client @@ -170,6 +174,13 @@ func WithWorkflowResendScheduler(scheduler workflowresend.Scheduler) EngineOptio } } +// WithStreamClient routes standalone stream reads to their history shard owner. +func WithStreamClient(streamClient streampb.StreamServiceClient) EngineOption { + return func(options *engineOptions) { + options.streamClient = streamClient + } +} + func applyEngineOptions(options []EngineOption) engineOptions { var result engineOptions for _, option := range options { @@ -264,6 +275,7 @@ func NewEngineWithShardContext( outboundQueueCBPool: outboundQueueCBPool, testHooks: testHooks, chasmEngine: chasmEngine, + streamClient: engineOptions.streamClient, versionCache: versionCache, workerDeploymentClient: workerDeploymentClient, routingInfoCache: routingInfoCache, @@ -527,6 +539,43 @@ func (e *historyEngineImpl) PollMutableState( }, nil } +// GetStreamReplaySlices re-supplies the stream ranges the workflow's completed +// tasks recorded, for a query task built outside RecordWorkflowTaskStarted. +func (e *historyEngineImpl) GetStreamReplaySlices( + ctx context.Context, + request *historyservice.GetStreamReplaySlicesRequest, +) (*historyservice.GetStreamReplaySlicesResponse, error) { + namespaceID := namespace.ID(request.GetNamespaceId()) + if err := api.ValidateNamespaceUUID(namespaceID); err != nil { + return nil, err + } + nsEntry, err := e.shardContext.GetNamespaceRegistry().GetNamespaceByID(namespaceID) + if err != nil { + return nil, err + } + runID := request.GetExecution().GetRunId() + if runID == "" { + runID, err = e.workflowConsistencyChecker.GetCurrentWorkflowRunID( + ctx, request.GetNamespaceId(), request.GetExecution().GetWorkflowId(), locks.PriorityHigh) + if err != nil { + return nil, err + } + } + workflowKey := definition.NewWorkflowKey( + request.GetNamespaceId(), request.GetExecution().GetWorkflowId(), runID) + slices, err := recordworkflowtaskstarted.ReplaySlicesForQuery( + ctx, + e.shardContext, + e.workflowConsistencyChecker, + workflowKey, + int32(e.config.HistoryMaxPageSize(nsEntry.Name().String())), + ) + if err != nil { + return nil, recordworkflowtaskstarted.AsRefusal(err) + } + return &historyservice.GetStreamReplaySlicesResponse{StreamSlices: slices}, nil +} + func (e *historyEngineImpl) QueryWorkflow( ctx context.Context, request *historyservice.QueryWorkflowRequest, @@ -601,7 +650,7 @@ func (e *historyEngineImpl) RecordWorkflowTaskStarted( request *historyservice.RecordWorkflowTaskStartedRequest, ) (*historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, error) { return recordworkflowtaskstarted.Invoke( - ctx, + recordworkflowtaskstarted.WithStreamClient(ctx, e.streamClient), request, e.shardContext, e.config, @@ -628,7 +677,7 @@ func (e *historyEngineImpl) RespondWorkflowTaskCompleted( e.matchingClient, e.versionCache, ) - return h.Invoke(ctx, req) + return h.Invoke(recordworkflowtaskstarted.WithStreamClient(ctx, e.streamClient), req) } // RespondWorkflowTaskFailed fails a workflow task diff --git a/service/history/history_engine_factory.go b/service/history/history_engine_factory.go index a2dd26c2324..fb75ae56779 100644 --- a/service/history/history_engine_factory.go +++ b/service/history/history_engine_factory.go @@ -3,6 +3,7 @@ package history import ( "go.opentelemetry.io/otel/trace" "go.temporal.io/server/chasm" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" chasmworkflow "go.temporal.io/server/chasm/lib/workflow" "go.temporal.io/server/client" "go.temporal.io/server/common/persistence" @@ -53,6 +54,7 @@ type ( PersistenceRateLimiter replication.PersistenceRateLimiter TestHooks testhooks.TestHooks ChasmEngine chasm.Engine + StreamClient streampb.StreamServiceClient VersionMembershipCache worker_versioning.VersionMembershipAndReactivationStatusCache WorkerDeploymentClient workerdeployment.Client RoutingInfoCache worker_versioning.RoutingInfoCache @@ -97,5 +99,6 @@ func (f *historyEngineFactory) CreateEngine( f.TestHooks, f.ChasmEngine, WithWorkflowResendScheduler(f.WorkflowResendScheduler), + WithStreamClient(f.StreamClient), ) } diff --git a/service/history/historybuilder/event_factory.go b/service/history/historybuilder/event_factory.go index 058cb55b4ed..a40bac21f26 100644 --- a/service/history/historybuilder/event_factory.go +++ b/service/history/historybuilder/event_factory.go @@ -10,6 +10,7 @@ import ( failurepb "go.temporal.io/api/failure/v1" historypb "go.temporal.io/api/history/v1" sdkpb "go.temporal.io/api/sdk/v1" + streampb "go.temporal.io/api/stream/v1" taskqueuepb "go.temporal.io/api/taskqueue/v1" updatepb "go.temporal.io/api/update/v1" workflowpb "go.temporal.io/api/workflow/v1" @@ -162,6 +163,7 @@ func (b *EventFactory) CreateWorkflowTaskCompletedEvent( deploymentName string, deployment *deploymentpb.Deployment, behavior enumspb.VersioningBehavior, + streamCursors []*streampb.StreamRange, ) *historypb.HistoryEvent { event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_TASK_COMPLETED, b.timeSource.Now()) event.Attributes = &historypb.HistoryEvent_WorkflowTaskCompletedEventAttributes{ @@ -176,6 +178,9 @@ func (b *EventFactory) CreateWorkflowTaskCompletedEvent( WorkerDeploymentName: deploymentName, DeploymentVersion: worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(deployment), VersioningBehavior: behavior, + // Offsets only. The payloads the task consumed rode the task + // response, so History grows with tasks rather than with messages. + ConsumedStreamRanges: streamCursors, }, } diff --git a/service/history/historybuilder/event_store.go b/service/history/historybuilder/event_store.go index a6fb18a4b9e..540b471ac91 100644 --- a/service/history/historybuilder/event_store.go +++ b/service/history/historybuilder/event_store.go @@ -331,7 +331,9 @@ func (b *EventStore) bufferEvent( enumspb.EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES, enumspb.EVENT_TYPE_WORKFLOW_PROPERTIES_MODIFIED, enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED, - enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED: + enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED: // do not buffer event if event is directly generated from a corresponding command return false diff --git a/service/history/historybuilder/history_builder.go b/service/history/historybuilder/history_builder.go index 4690a0e92b1..c24e00f3c20 100644 --- a/service/history/historybuilder/history_builder.go +++ b/service/history/historybuilder/history_builder.go @@ -10,6 +10,7 @@ import ( failurepb "go.temporal.io/api/failure/v1" historypb "go.temporal.io/api/history/v1" sdkpb "go.temporal.io/api/sdk/v1" + streampb "go.temporal.io/api/stream/v1" taskqueuepb "go.temporal.io/api/taskqueue/v1" updatepb "go.temporal.io/api/update/v1" workflowpb "go.temporal.io/api/workflow/v1" @@ -236,6 +237,7 @@ func (b *HistoryBuilder) AddWorkflowTaskCompletedEvent( deploymentName string, deployment *deploymentpb.Deployment, behavior enumspb.VersioningBehavior, + streamCursors []*streampb.StreamRange, ) *historypb.HistoryEvent { event := b.CreateWorkflowTaskCompletedEvent( scheduledEventID, @@ -248,6 +250,7 @@ func (b *HistoryBuilder) AddWorkflowTaskCompletedEvent( deploymentName, deployment, behavior, + streamCursors, ) event, _ = b.add(event) return event diff --git a/service/history/historybuilder/history_builder_categorization_test.go b/service/history/historybuilder/history_builder_categorization_test.go index 228824a50e5..43b6aed58e0 100644 --- a/service/history/historybuilder/history_builder_categorization_test.go +++ b/service/history/historybuilder/history_builder_categorization_test.go @@ -1277,6 +1277,7 @@ func (s *sutTestingAdapter) AddWorkflowTaskCompletedEvent(_ ...eventConfig) *his "", nil, enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED, + nil, ) } diff --git a/service/history/historybuilder/history_builder_test.go b/service/history/historybuilder/history_builder_test.go index d7b13d5fd6c..d9f47866976 100644 --- a/service/history/historybuilder/history_builder_test.go +++ b/service/history/historybuilder/history_builder_test.go @@ -704,6 +704,7 @@ func (s *historyBuilderSuite) TestWorkflowTaskCompleted() { "", nil, enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED, + nil, ) s.Equal(event, s.flush()) protorequire.ProtoEqual(s.T(), &historypb.HistoryEvent{ @@ -2272,6 +2273,8 @@ func (s *historyBuilderSuite) TestBufferEvent() { enumspb.EVENT_TYPE_WORKFLOW_PROPERTIES_MODIFIED: true, enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED: true, enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED: true, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED: true, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED: true, } // events corresponding to message from client will be assigned an event ID immediately @@ -2321,7 +2324,8 @@ func (s *historyBuilderSuite) TestBufferEvent() { commandType := enumspb.CommandType(ct) // Unspecified is not counted. // ProtocolMessage command doesn't have corresponding event. - if commandType == enumspb.COMMAND_TYPE_UNSPECIFIED || commandType == enumspb.COMMAND_TYPE_PROTOCOL_MESSAGE { + if commandType == enumspb.COMMAND_TYPE_UNSPECIFIED || + commandType == enumspb.COMMAND_TYPE_PROTOCOL_MESSAGE { continue } commandsWithEventsCount++ diff --git a/service/history/interfaces/engine.go b/service/history/interfaces/engine.go index 1c03f0e583f..669595c3098 100644 --- a/service/history/interfaces/engine.go +++ b/service/history/interfaces/engine.go @@ -29,6 +29,7 @@ type ( StartWorkflowExecution(ctx context.Context, request *historyservice.StartWorkflowExecutionRequest) (*historyservice.StartWorkflowExecutionResponse, error) GetMutableState(ctx context.Context, request *historyservice.GetMutableStateRequest) (*historyservice.GetMutableStateResponse, error) PollMutableState(ctx context.Context, request *historyservice.PollMutableStateRequest) (*historyservice.PollMutableStateResponse, error) + GetStreamReplaySlices(ctx context.Context, request *historyservice.GetStreamReplaySlicesRequest) (*historyservice.GetStreamReplaySlicesResponse, error) DescribeMutableState(ctx context.Context, request *historyservice.DescribeMutableStateRequest) (*historyservice.DescribeMutableStateResponse, error) ResetStickyTaskQueue(ctx context.Context, resetRequest *historyservice.ResetStickyTaskQueueRequest) (*historyservice.ResetStickyTaskQueueResponse, error) DescribeWorkflowExecution(ctx context.Context, request *historyservice.DescribeWorkflowExecutionRequest) (*historyservice.DescribeWorkflowExecutionResponse, error) diff --git a/service/history/interfaces/engine_mock.go b/service/history/interfaces/engine_mock.go index b2ca488f358..5936e91939b 100644 --- a/service/history/interfaces/engine_mock.go +++ b/service/history/interfaces/engine_mock.go @@ -280,6 +280,21 @@ func (mr *MockEngineMockRecorder) GetReplicationTasksIter(ctx, pollingCluster, m return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReplicationTasksIter", reflect.TypeOf((*MockEngine)(nil).GetReplicationTasksIter), ctx, pollingCluster, minInclusiveTaskID, maxExclusiveTaskID) } +// GetStreamReplaySlices mocks base method. +func (m *MockEngine) GetStreamReplaySlices(ctx context.Context, request *historyservice.GetStreamReplaySlicesRequest) (*historyservice.GetStreamReplaySlicesResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStreamReplaySlices", ctx, request) + ret0, _ := ret[0].(*historyservice.GetStreamReplaySlicesResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStreamReplaySlices indicates an expected call of GetStreamReplaySlices. +func (mr *MockEngineMockRecorder) GetStreamReplaySlices(ctx, request any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStreamReplaySlices", reflect.TypeOf((*MockEngine)(nil).GetStreamReplaySlices), ctx, request) +} + // GetWorkflowExecutionHistory mocks base method. func (m *MockEngine) GetWorkflowExecutionHistory(ctx context.Context, request *historyservice.GetWorkflowExecutionHistoryRequest) (*historyservice.GetWorkflowExecutionHistoryResponseWithRaw, error) { m.ctrl.T.Helper() diff --git a/service/history/interfaces/mutable_state.go b/service/history/interfaces/mutable_state.go index 632c0fbfb38..b806c4097d0 100644 --- a/service/history/interfaces/mutable_state.go +++ b/service/history/interfaces/mutable_state.go @@ -366,6 +366,15 @@ type ( ChasmEnabled() bool ChasmSignalBacklinksEnabled() bool ChasmWorkflowComponent(ctx context.Context) (*chasmworkflow.Workflow, chasm.MutableContext, error) + // HasChasmWorkflowComponent reports whether a workflow component is + // actually reachable. Archetype alone does not answer this: a workflow + // predating CHASM reports the workflow archetype while carrying a tree + // that holds no components. + HasChasmWorkflowComponent() bool + // HasPendingStreamData reports whether a stream subscription still has + // offsets to deliver, which is the only case where stream traffic + // schedules a workflow task. + HasPendingStreamData() bool ChasmWorkflowComponentReadOnly(ctx context.Context) (*chasmworkflow.Workflow, chasm.Context, error) // Ensures that the chasm workflow component is installed in the mutable state CHASM tree. // Must be called before adding any components to the tree. diff --git a/service/history/interfaces/mutable_state_mock.go b/service/history/interfaces/mutable_state_mock.go index 15a5b7221da..4cf77df6e5d 100644 --- a/service/history/interfaces/mutable_state_mock.go +++ b/service/history/interfaces/mutable_state_mock.go @@ -3052,6 +3052,20 @@ func (mr *MockMutableStateMockRecorder) HasBufferedEvents() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasBufferedEvents", reflect.TypeOf((*MockMutableState)(nil).HasBufferedEvents)) } +// HasChasmWorkflowComponent mocks base method. +func (m *MockMutableState) HasChasmWorkflowComponent() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasChasmWorkflowComponent") + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasChasmWorkflowComponent indicates an expected call of HasChasmWorkflowComponent. +func (mr *MockMutableStateMockRecorder) HasChasmWorkflowComponent() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasChasmWorkflowComponent", reflect.TypeOf((*MockMutableState)(nil).HasChasmWorkflowComponent)) +} + // HasCompletedAnyWorkflowTask mocks base method. func (m *MockMutableState) HasCompletedAnyWorkflowTask() bool { m.ctrl.T.Helper() @@ -3080,6 +3094,20 @@ func (mr *MockMutableStateMockRecorder) HasParentExecution() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasParentExecution", reflect.TypeOf((*MockMutableState)(nil).HasParentExecution)) } +// HasPendingStreamData mocks base method. +func (m *MockMutableState) HasPendingStreamData() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasPendingStreamData") + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasPendingStreamData indicates an expected call of HasPendingStreamData. +func (mr *MockMutableStateMockRecorder) HasPendingStreamData() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasPendingStreamData", reflect.TypeOf((*MockMutableState)(nil).HasPendingStreamData)) +} + // HasPendingWorkflowTask mocks base method. func (m *MockMutableState) HasPendingWorkflowTask() bool { m.ctrl.T.Helper() diff --git a/service/history/ndc/workflow_resetter.go b/service/history/ndc/workflow_resetter.go index 8266d05288b..992b2ae9b55 100644 --- a/service/history/ndc/workflow_resetter.go +++ b/service/history/ndc/workflow_resetter.go @@ -254,6 +254,10 @@ func (r *workflowResetterImpl) ResetWorkflow( defer func() { resetWorkflow.GetReleaseFn()(retError) }() resetMS := resetWorkflow.GetMutableState() + err = r.inheritStreams(ctx, namespaceEntry, baseWorkflow.GetMutableState(), resetMS) + if err != nil { + return err + } if err := reapplyEventsFn(ctx, resetMS); err != nil { return err } @@ -287,6 +291,45 @@ func (r *workflowResetterImpl) ResetWorkflow( return nil } +// inheritStreams completes the stream cursors the rebuild recreated from the +// reset run's events with what only the base run's state can say: which +// streams live in other executions, and the frontier those last pushed. A +// cursor on a stream the base run owned gets a stream of the reset run's own, +// continuing the offset space from where the cursor stands. +func (r *workflowResetterImpl) inheritStreams( + ctx context.Context, + namespaceEntry *namespace.Namespace, + baseMS historyi.MutableState, + resetMS historyi.MutableState, +) error { + if !resetMS.HasChasmWorkflowComponent() { + return nil + } + // Read-only first: a reset run with no subscription should not pay a node + // in its first transaction for a check that finds nothing. + readOnly, _, err := resetMS.ChasmWorkflowComponentReadOnly(ctx) + if err != nil { + return err + } + if len(readOnly.StreamCursors) == 0 { + return nil + } + + var base *chasmworkflow.Workflow + var baseCtx chasm.Context + if baseMS.HasChasmWorkflowComponent() { + if base, baseCtx, err = baseMS.ChasmWorkflowComponentReadOnly(ctx); err != nil { + return err + } + } + reset, resetCtx, err := resetMS.ChasmWorkflowComponent(ctx) + if err != nil { + return err + } + limits := r.shardContext.GetConfig().Stream.LimitsFor(namespaceEntry.Name().String()) + return reset.InheritStreamsOnReset(resetCtx, base, baseCtx, limits) +} + func (r *workflowResetterImpl) prepareResetWorkflow( ctx context.Context, namespaceID namespace.ID, diff --git a/service/history/stream_routing_test.go b/service/history/stream_routing_test.go new file mode 100644 index 00000000000..397829bc3ce --- /dev/null +++ b/service/history/stream_routing_test.go @@ -0,0 +1,18 @@ +package history + +import ( + "testing" + + "github.com/stretchr/testify/require" + streampb "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" +) + +type testStreamRoutingClient struct { + streampb.StreamServiceClient +} + +func TestWithStreamClient(t *testing.T) { + client := &testStreamRoutingClient{} + options := applyEngineOptions([]EngineOption{WithStreamClient(client)}) + require.Same(t, client, options.streamClient) +} diff --git a/service/history/workflow/mutable_state_impl.go b/service/history/workflow/mutable_state_impl.go index 069c3e37a24..e297187ad89 100644 --- a/service/history/workflow/mutable_state_impl.go +++ b/service/history/workflow/mutable_state_impl.go @@ -22,6 +22,7 @@ import ( historypb "go.temporal.io/api/history/v1" rulespb "go.temporal.io/api/rules/v1" "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" taskqueuepb "go.temporal.io/api/taskqueue/v1" updatepb "go.temporal.io/api/update/v1" workerpb "go.temporal.io/api/worker/v1" @@ -672,6 +673,98 @@ func (ms *MutableStateImpl) mustInitHSM() { ms.stateMachineNode = stateMachineNode } +// commitStreamCursors folds each staged range into its cursor and returns the +// ranges to record. Called as the completed event is built, so the advance and +// the event carrying the range are in one transaction: split apart, a crash +// between them would either redeliver a range or skip it with nothing in +// History to say so. +func (ms *MutableStateImpl) commitStreamCursors() ([]*streampb.StreamRange, error) { + if !ms.HasChasmWorkflowComponent() { + return nil, nil + } + // Reaching the component through a mutable context marks it dirty, which + // would add a node to the transaction of every workflow that has no + // subscription at all. Ask read-only first, and take the write path only + // when there is something to fold in. + // + // The background context matches EnsureChasmWorkflowComponent: it only + // reaches components already in memory. + wf, _, err := ms.ChasmWorkflowComponentReadOnly(context.Background()) + if err != nil { + return nil, err + } + if len(wf.StreamCursors) == 0 { + return nil, nil + } + + wf, chasmCtx, err := ms.ChasmWorkflowComponent(context.Background()) + if err != nil { + return nil, err + } + return wf.CommitStreamCursors(chasmCtx), nil +} + +// carryStreamSubscriptionsTo hands this run's subscriptions to the run that +// continues it. +// +// A cursor is workflow state, so without this a continue-as-new would silently +// end a subscription the workflow never cancelled: the stream would keep its +// consumer pin and keep pushing to the workflow id, and the successor would +// have nowhere to put it. +func (ms *MutableStateImpl) carryStreamSubscriptionsTo(newMutableState *MutableStateImpl) error { + if !ms.HasChasmWorkflowComponent() { + return nil + } + wf, chasmCtx, err := ms.ChasmWorkflowComponentReadOnly(context.Background()) + if err != nil { + return err + } + subscriptions := wf.ExportStreamSubscriptions(chasmCtx) + if len(subscriptions) == 0 { + return nil + } + + newMutableState.EnsureChasmWorkflowComponent(context.Background()) + newWorkflow, newChasmCtx, err := newMutableState.ChasmWorkflowComponent(context.Background()) + if err != nil { + return err + } + return newWorkflow.ImportStreamSubscriptions(newChasmCtx, subscriptions) +} + +// HasPendingStreamData reports whether a subscription of this workflow has +// offsets left to deliver, which is the one condition under which stream +// traffic schedules a workflow task. +// +// Called on every transaction close for every workflow, almost none of which +// have a subscription, so it resolves the root component once rather than +// asking whether it exists and then asking for it. +func (ms *MutableStateImpl) HasPendingStreamData() bool { + node, ok := ms.chasmTree.(*chasm.Node) + if !ok { + return false + } + chasmCtx := chasm.NewContext(context.Background(), node) + rootComponent, err := node.ComponentByPath(chasmCtx, nil) + if err != nil { + return false + } + wf, ok := rootComponent.(*chasmworkflow.Workflow) + if !ok { + return false + } + return wf.StreamCursorsBehind(chasmCtx) +} + +func (ms *MutableStateImpl) HasChasmWorkflowComponent() bool { + node, ok := ms.chasmTree.(*chasm.Node) + if !ok { + return false + } + _, err := node.ComponentByPath(chasm.NewContext(context.Background(), node), nil) + return err == nil +} + func (ms *MutableStateImpl) IsWorkflow() bool { return ms.chasmTree.ArchetypeID() == chasm.WorkflowArchetypeID } @@ -6394,6 +6487,10 @@ func (ms *MutableStateImpl) AddContinueAsNewEvent( return nil, nil, err } + if err = ms.carryStreamSubscriptionsTo(newMutableState); err != nil { + return nil, nil, err + } + if err = ms.ApplyWorkflowExecutionContinuedAsNewEvent( batchID, continueAsNewEvent, @@ -7939,6 +8036,25 @@ func (ms *MutableStateImpl) closeTransactionHandleWorkflowTaskScheduling( } } + // A stream subscription with offsets left to deliver. Handled here rather + // than at workflow task completion so it also covers the transaction that + // registers a subscription against a stream that already has data, which + // completes no workflow task of its own. + // + // The pending-task check comes first because it is cheap: a workflow that + // already owes a task needs no further reason to run, so the subscription + // state is only consulted when the answer could change something. + if !ms.HasPendingWorkflowTask() && + !ms.IsWorkflowExecutionStatusPaused() && + ms.HasPendingStreamData() { + if _, err := ms.AddWorkflowTaskScheduledEvent( + false, + enumsspb.WORKFLOW_TASK_TYPE_NORMAL, + ); err != nil { + return err + } + } + return nil } diff --git a/service/history/workflow/mutable_state_rebuilder.go b/service/history/workflow/mutable_state_rebuilder.go index 6e1fb1cc892..55edf9745c4 100644 --- a/service/history/workflow/mutable_state_rebuilder.go +++ b/service/history/workflow/mutable_state_rebuilder.go @@ -261,6 +261,9 @@ func (b *MutableStateRebuilderImpl) applyEvents( ); err != nil { return nil, err } + if err := b.applyConsumedStreamRanges(ctx, event); err != nil { + return nil, err + } case enumspb.EVENT_TYPE_WORKFLOW_TASK_TIMED_OUT: if err := b.mutableState.ApplyWorkflowTaskTimedOutEvent( @@ -732,6 +735,26 @@ func (b *MutableStateRebuilderImpl) applyStateMachineEvent( return b.applyHSMEvent(event) } +// applyConsumedStreamRanges moves the stream cursors to where the completed +// event says they stood. The cursors are CHASM state and the ranges ride the +// event, so a run rebuilt from its history, a reset run above all, ends up with +// its cursors exactly where the events put them. +func (b *MutableStateRebuilderImpl) applyConsumedStreamRanges( + ctx context.Context, + event *historypb.HistoryEvent, +) error { + ranges := event.GetWorkflowTaskCompletedEventAttributes().GetConsumedStreamRanges() + if len(ranges) == 0 || !b.mutableState.ChasmEnabled() { + return nil + } + b.mutableState.EnsureChasmWorkflowComponent(ctx) + wf, chasmCtx, err := b.mutableState.ChasmWorkflowComponent(ctx) + if err != nil { + return err + } + return wf.ApplyConsumedStreamRanges(chasmCtx, ranges) +} + // applyHSMEvent applies an event to the HSM tree func (b *MutableStateRebuilderImpl) applyHSMEvent(event *historypb.HistoryEvent) error { def, ok := b.shard.StateMachineRegistry().EventDefinition(event.GetEventType()) diff --git a/service/history/workflow/workflow_task_state_machine.go b/service/history/workflow/workflow_task_state_machine.go index 72123c71bfa..9ecc63b75ae 100644 --- a/service/history/workflow/workflow_task_state_machine.go +++ b/service/history/workflow/workflow_task_state_machine.go @@ -826,6 +826,11 @@ func (m *workflowTaskStateMachine) AddWorkflowTaskCompletedEvent( //nolint:staticcheck // SA1019 deprecated Deployment will clean up later wftDeployment := worker_versioning.DeploymentOrVersion(request.Deployment, wftDeploymentVersion) + streamCursors, err := m.ms.commitStreamCursors() + if err != nil { + return nil, err + } + // Now write the completed event event := m.ms.hBuilder.AddWorkflowTaskCompletedEvent( workflowTask.ScheduledEventID, @@ -838,6 +843,7 @@ func (m *workflowTaskStateMachine) AddWorkflowTaskCompletedEvent( deploymentName, wftDeployment, vb, + streamCursors, ) override := m.ms.GetExecutionInfo().GetVersioningInfo().GetVersioningOverride() @@ -849,7 +855,7 @@ func (m *workflowTaskStateMachine) AddWorkflowTaskCompletedEvent( } wftScheduleToClose := event.GetEventTime().AsTime().Sub(workflowTask.ScheduledTime) - err := m.afterAddWorkflowTaskCompletedEvent(event, limits, wftScheduleToClose) + err = m.afterAddWorkflowTaskCompletedEvent(event, limits, wftScheduleToClose) if err != nil { return nil, err } diff --git a/service/matching/matching_engine.go b/service/matching/matching_engine.go index 049da260866..b67e036559b 100644 --- a/service/matching/matching_engine.go +++ b/service/matching/matching_engine.go @@ -19,6 +19,7 @@ import ( enumspb "go.temporal.io/api/enums/v1" historypb "go.temporal.io/api/history/v1" "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" taskqueuepb "go.temporal.io/api/taskqueue/v1" "go.temporal.io/api/workflowservice/v1" deploymentspb "go.temporal.io/server/api/deployment/v1" @@ -754,6 +755,16 @@ pollLoop: return emptyPollWorkflowTaskQueueResponse, nil } + // After the history, so every range the history records is + // re-supplied. Read the other way round a task could complete in + // between and the worker would see a recorded range with no bytes. + streamSlices, err := e.getStreamSlicesForQueryTask( + ctx, req.GetNamespaceId(), task, isStickyEnabled) + if err != nil { + _ = e.deliverQueryResult(task.query.taskID, &queryResult{internalError: err}) + return emptyPollWorkflowTaskQueueResponse, nil + } + resp := &historyservice.RecordWorkflowTaskStartedResponse{ PreviousStartedEventId: mutableStateResp.PreviousStartedEventId, NextEventId: mutableStateResp.NextEventId, @@ -765,6 +776,7 @@ pollLoop: Attempt: 1, History: hist, NextPageToken: nextPageToken, + StreamSlices: streamSlices, } // Local query match. Emit the dispatch latency metric. This metric does not include the query response time. @@ -863,6 +875,33 @@ pollLoop: } } +// getStreamSlicesForQueryTask asks History for the stream ranges the +// workflow's history records, re-read from their streams. +// +// A query task is built here without RecordWorkflowTaskStarted, so the +// delivery that attaches those ranges to an ordinary task never runs for it. +// Only a non-sticky query needs them: a sticky one goes to a worker that still +// holds the execution and has nothing to replay. +func (e *matchingEngineImpl) getStreamSlicesForQueryTask( + ctx context.Context, + namespaceID string, + task *internalTask, + isStickyEnabled bool, +) ([]*streampb.StreamSlice, error) { + if isStickyEnabled { + return nil, nil + } + resp, err := e.historyClient.GetStreamReplaySlices(ctx, + &historyservice.GetStreamReplaySlicesRequest{ + NamespaceId: namespaceID, + Execution: task.workflowExecution(), + }) + if err != nil { + return nil, err + } + return resp.GetStreamSlices(), nil +} + func (e *matchingEngineImpl) getHistoryForQueryTask( ctx context.Context, nsID namespace.ID, @@ -3367,6 +3406,7 @@ func (e *matchingEngineImpl) convertPollWorkflowTaskQueueResponse( StartedTime: resp.StartedTime, Queries: resp.Queries, Messages: resp.Messages, + StreamSlices: resp.StreamSlices, History: history, NextPageToken: resp.NextPageToken, PollerScalingDecision: resp.PollerScalingDecision, diff --git a/service/matching/matching_engine_test.go b/service/matching/matching_engine_test.go index 62cce1c554c..69163759c38 100644 --- a/service/matching/matching_engine_test.go +++ b/service/matching/matching_engine_test.go @@ -28,6 +28,7 @@ import ( nexuspb "go.temporal.io/api/nexus/v1" querypb "go.temporal.io/api/query/v1" "go.temporal.io/api/serviceerror" + streampb "go.temporal.io/api/stream/v1" taskqueuepb "go.temporal.io/api/taskqueue/v1" "go.temporal.io/api/workflowservice/v1" clockspb "go.temporal.io/server/api/clock/v1" @@ -6166,6 +6167,72 @@ func TestConvertPollWorkflowTaskQueueResponse_FieldMapping(t *testing.T) { assert.Equal(t, inputResp.History.Events[0].EventId, result.History.Events[0].EventId) } +// A non-sticky query task asks History for the recorded stream ranges; a +// sticky one does not, since its worker still holds the execution. +func TestGetStreamSlicesForQueryTask(t *testing.T) { + t.Parallel() + + nsID := namespace.ID("test-namespace-id") + task := &internalTask{ + namespace: namespace.Name("test-namespace"), + event: &genericTaskInfo{ + AllocatedTaskInfo: &persistencespb.AllocatedTaskInfo{ + Data: &persistencespb.TaskInfo{ + NamespaceId: nsID.String(), + WorkflowId: "test-workflow-id", + RunId: "test-run-id", + }, + }, + }, + } + resupplied := []*streampb.StreamSlice{{ + StreamId: "output", RunId: "test-run-id", FromOffset: 0, ToOffset: 2, + WorkflowTaskCompletedEventId: 4, + }} + + t.Run("sticky asks nothing", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + mockHistoryClient := historyservicemock.NewMockHistoryServiceClient(ctrl) + engine := &matchingEngineImpl{historyClient: mockHistoryClient, logger: log.NewNoopLogger()} + + slices, err := engine.getStreamSlicesForQueryTask(context.Background(), nsID.String(), task, true) + require.NoError(t, err) + require.Empty(t, slices) + }) + + t.Run("non-sticky carries what History re-supplies", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + mockHistoryClient := historyservicemock.NewMockHistoryServiceClient(ctrl) + mockHistoryClient.EXPECT().GetStreamReplaySlices(gomock.Any(), + &historyservice.GetStreamReplaySlicesRequest{ + NamespaceId: nsID.String(), + Execution: task.workflowExecution(), + }).Return(&historyservice.GetStreamReplaySlicesResponse{StreamSlices: resupplied}, nil). + Times(1) + engine := &matchingEngineImpl{historyClient: mockHistoryClient, logger: log.NewNoopLogger()} + + slices, err := engine.getStreamSlicesForQueryTask( + context.Background(), nsID.String(), task, false) + require.NoError(t, err) + require.Len(t, slices, 1) + require.Equal(t, int64(4), slices[0].GetWorkflowTaskCompletedEventId()) + }) + + t.Run("a refusal fails the query", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + mockHistoryClient := historyservicemock.NewMockHistoryServiceClient(ctrl) + mockHistoryClient.EXPECT().GetStreamReplaySlices(gomock.Any(), gomock.Any()).Return( + nil, serviceerror.NewFailedPrecondition("stream no longer holds the range")).Times(1) + engine := &matchingEngineImpl{historyClient: mockHistoryClient, logger: log.NewNoopLogger()} + + _, err := engine.getStreamSlicesForQueryTask(context.Background(), nsID.String(), task, false) + require.ErrorContains(t, err, "no longer holds") + }) +} + func TestGetHistoryForQueryTask(t *testing.T) { t.Parallel() diff --git a/service/matching/wire_compat_test.go b/service/matching/wire_compat_test.go new file mode 100644 index 00000000000..f55255343e4 --- /dev/null +++ b/service/matching/wire_compat_test.go @@ -0,0 +1,178 @@ +package matching + +import ( + "fmt" + "slices" + "testing" + + "github.com/stretchr/testify/require" + "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/api/matchingservice/v1" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" +) + +// Each started-task response exists twice, once carrying History and once +// carrying raw bytes, so matching can forward a task without deserializing it. +// The two are only interchangeable while every field number means the same +// thing on both sides. That invariant is stated in a proto comment, which is +// easy to satisfy on one copy and forget on the other, and a mismatch stays +// invisible until history.sendRawHistoryBetweenInternalServices is enabled. +func TestStartedResponsePairsStayWireCompatible(t *testing.T) { + t.Run("history service", func(t *testing.T) { + // raw_history is a History on one side and repeated bytes on the other, + // which is the whole point of keeping two messages. + require.Empty(t, wireCompatDiff( + &historyservice.RecordWorkflowTaskStartedResponse{}, + &historyservice.RecordWorkflowTaskStartedResponseWithRawHistory{}, + 20, + )) + }) + + t.Run("matching service", func(t *testing.T) { + require.Empty(t, wireCompatDiff( + &matchingservice.PollWorkflowTaskQueueResponse{}, + &matchingservice.PollWorkflowTaskQueueResponseWithRawHistory{}, + 22, + )) + }) +} + +// Without a negative control the check above passes just as happily when it has +// stopped inspecting anything. Drop the exemption and the one field the pair is +// allowed to disagree on has to be reported. +func TestWireCompatDiffDetectsAMismatch(t *testing.T) { + diff := wireCompatDiff( + &historyservice.RecordWorkflowTaskStartedResponse{}, + &historyservice.RecordWorkflowTaskStartedResponseWithRawHistory{}, + ) + require.Len(t, diff, 1) + require.Contains(t, diff[0], "field 20") + require.Contains(t, diff[0], "raw_history") +} + +// wireCompatDiff reports every way the two messages would disagree on the wire, +// ignoring the field numbers named in typeMayDiffer. +func wireCompatDiff( + a proto.Message, + b proto.Message, + typeMayDiffer ...protoreflect.FieldNumber, +) []string { + exempt := make(map[protoreflect.FieldNumber]struct{}, len(typeMayDiffer)) + for _, number := range typeMayDiffer { + exempt[number] = struct{}{} + } + + aName := a.ProtoReflect().Descriptor().Name() + bName := b.ProtoReflect().Descriptor().Name() + aFields := fieldsByNumber(a) + bFields := fieldsByNumber(b) + + var problems []string + report := func(format string, args ...any) { + problems = append(problems, fmt.Sprintf(format, args...)) + } + + for _, number := range sortedFieldNumbers(aFields) { + aField := aFields[number] + bField, ok := bFields[number] + if !ok { + report("field %d (%s) is on %s but missing from %s", number, aField.Name(), aName, bName) + continue + } + if aField.Name() != bField.Name() { + report("field %d is %s on %s and %s on %s", number, aField.Name(), aName, bField.Name(), bName) + continue + } + if _, ok := exempt[number]; ok { + continue + } + + // A map field's value type is a synthesized entry message nested in its + // parent, so its full name always differs across the pair. Compare what + // actually goes on the wire instead. + if aField.IsMap() { + if !bField.IsMap() { + report("field %d (%s) is a map on %s only", number, aField.Name(), aName) + continue + } + if aField.MapKey().Kind() != bField.MapKey().Kind() { + report("field %d (%s) has a different map key type on each side", number, aField.Name()) + } + problem := valueTypeDiff(aField.MapValue(), bField.MapValue(), number, aField.Name()) + if problem != "" { + report("%s", problem) + } + continue + } + + if aField.Cardinality() != bField.Cardinality() { + report("field %d (%s) is %s on %s and %s on %s", + number, aField.Name(), aField.Cardinality(), aName, bField.Cardinality(), bName) + continue + } + if problem := valueTypeDiff(aField, bField, number, aField.Name()); problem != "" { + report("%s", problem) + } + } + + for _, number := range sortedFieldNumbers(bFields) { + if _, ok := aFields[number]; !ok { + report("field %d (%s) is on %s but missing from %s", + number, bFields[number].Name(), bName, aName) + } + } + + return problems +} + +func valueTypeDiff( + a protoreflect.FieldDescriptor, + b protoreflect.FieldDescriptor, + number protoreflect.FieldNumber, + name protoreflect.Name, +) string { + if a.Kind() != b.Kind() { + return fmt.Sprintf("field %d (%s) is %s on one side and %s on the other", + number, name, a.Kind(), b.Kind()) + } + + switch a.Kind() { + case protoreflect.MessageKind, protoreflect.GroupKind: + if a.Message().FullName() != b.Message().FullName() { + return fmt.Sprintf("field %d (%s) refers to %s on one side and %s on the other", + number, name, a.Message().FullName(), b.Message().FullName()) + } + case protoreflect.EnumKind: + if a.Enum().FullName() != b.Enum().FullName() { + return fmt.Sprintf("field %d (%s) refers to %s on one side and %s on the other", + number, name, a.Enum().FullName(), b.Enum().FullName()) + } + default: + // Scalars are fully described by the kind equality checked above. + } + return "" +} + +func fieldsByNumber(m proto.Message) map[protoreflect.FieldNumber]protoreflect.FieldDescriptor { + fields := m.ProtoReflect().Descriptor().Fields() + byNumber := make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor, fields.Len()) + for i := range fields.Len() { + field := fields.Get(i) + byNumber[field.Number()] = field + } + return byNumber +} + +// Field order drives the order of reported problems, which keeps a failure +// message stable between runs. +func sortedFieldNumbers( + fields map[protoreflect.FieldNumber]protoreflect.FieldDescriptor, +) []protoreflect.FieldNumber { + numbers := make([]protoreflect.FieldNumber, 0, len(fields)) + for number := range fields { + numbers = append(numbers, number) + } + slices.Sort(numbers) + return numbers +} diff --git a/tests/api_fork_test.go b/tests/api_fork_test.go new file mode 100644 index 00000000000..8e39bb7109b --- /dev/null +++ b/tests/api_fork_test.go @@ -0,0 +1,59 @@ +package tests + +import ( + "testing" + + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/api/workflowservice/v1" + "google.golang.org/protobuf/proto" +) + +// The api fork has to round-trip the new shapes over the wire, not merely +// compile. A field added without its descriptor would compile and silently +// drop on marshal. +func TestApiForkCarriesStreamShapes(t *testing.T) { + require.Equal(t, enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, enumspb.CommandType(19)) + + cmd := &commandpb.Command{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + StreamId: "s1", + Records: []*streampb.StreamRecord{{Topic: "tokens"}}, + }, + }, + } + b, err := proto.Marshal(cmd) + require.NoError(t, err) + var back commandpb.Command + require.NoError(t, proto.Unmarshal(b, &back)) + require.Equal(t, "s1", back.GetAppendStreamRecordsCommandAttributes().GetStreamId()) + require.Equal(t, "tokens", + back.GetAppendStreamRecordsCommandAttributes().GetRecords()[0].GetTopic()) + + resp := &workflowservice.PollWorkflowTaskQueueResponse{ + StreamSlices: []*streampb.StreamSlice{{StreamId: "s1", FromOffset: 4, ToOffset: 7}}, + } + rb, err := proto.Marshal(resp) + require.NoError(t, err) + var rback workflowservice.PollWorkflowTaskQueueResponse + require.NoError(t, proto.Unmarshal(rb, &rback)) + require.Equal(t, int64(7), rback.GetStreamSlices()[0].GetToOffset()) + + attrs := &historypb.WorkflowTaskCompletedEventAttributes{ + ConsumedStreamRanges: []*streampb.StreamRange{{StreamId: "s1", FromOffset: 4, ToOffset: 4}}, + } + ab, err := proto.Marshal(attrs) + require.NoError(t, err) + var aback historypb.WorkflowTaskCompletedEventAttributes + require.NoError(t, proto.Unmarshal(ab, &aback)) + // An empty range has to survive the round trip: it is the fact that a + // subscription observed nothing, which replay must reproduce. + require.Len(t, aback.GetConsumedStreamRanges(), 1) + require.Equal(t, + aback.GetConsumedStreamRanges()[0].GetFromOffset(), aback.GetConsumedStreamRanges()[0].GetToOffset()) +} diff --git a/tests/mixedbrain/go.mod b/tests/mixedbrain/go.mod index dde79a7698e..c87866e7f25 100644 --- a/tests/mixedbrain/go.mod +++ b/tests/mixedbrain/go.mod @@ -9,7 +9,7 @@ require ( github.com/temporalio/omes v0.0.0-20260529203146-c6ee1f56c726 go.temporal.io/api v1.63.5 go.temporal.io/server v0.0.0-00010101000000-000000000000 - google.golang.org/grpc v1.80.0 + google.golang.org/grpc v1.83.1 google.golang.org/protobuf v1.36.11 ) @@ -26,8 +26,8 @@ require ( golang.org/x/net v0.57.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.40.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tests/mixedbrain/go.sum b/tests/mixedbrain/go.sum index f235f9afc83..e04f1505577 100644 --- a/tests/mixedbrain/go.sum +++ b/tests/mixedbrain/go.sum @@ -49,10 +49,10 @@ go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.temporal.io/api v1.63.5 h1:c11+kPYHkXXL3UiShPdbMD+xtvqGsbTibUA9ypmiCa4= @@ -71,12 +71,12 @@ golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 h1:zUWMZsvo/IJcD1t6MNCPO/azZTwz0TvwCBqr5aifoVY= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529/go.mod h1:a5OGAgyRr4lqco7AG9hQM9Fwh0N2ZV4grR0eXFEsXQg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= +google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tests/nexus_workflow_test.go b/tests/nexus_workflow_test.go index 72a016951b9..78eff713361 100644 --- a/tests/nexus_workflow_test.go +++ b/tests/nexus_workflow_test.go @@ -54,6 +54,12 @@ import ( "google.golang.org/protobuf/types/known/durationpb" ) +const ( + dataBlobMessageType = "temporal.api.common.v1.DataBlob" + payloadsMessageType = "temporal.api.common.v1.Payloads" + protobufEncoding = "binary/protobuf" +) + type NexusWorkflowTestSuite struct { parallelsuite.Suite[*NexusWorkflowTestSuite] } @@ -3283,6 +3289,9 @@ func (s *NexusWorkflowTestSuite) TestNexusOperationSystemEndpoint(chasmEnabled b result := completedEvent.GetNexusOperationCompletedEventAttributes().Result s.NotNil(result) s.Equal([]byte("true"), result.GetMetadata()[commonnexus.SystemPayloadMetadataKey]) + // TestOperation returns a proto message, so the result must be proto encoded, not JSON. + s.Equal([]byte(dataBlobMessageType), result.GetMetadata()["messageType"]) + s.Equal([]byte(protobufEncoding), result.GetMetadata()["encoding"]) // Complete the workflow _, err = env.FrontendClient().RespondWorkflowTaskCompleted(ctx, &workflowservice.RespondWorkflowTaskCompletedRequest{ @@ -3302,9 +3311,10 @@ func (s *NexusWorkflowTestSuite) TestNexusOperationSystemEndpoint(chasmEnabled b }, }) s.NoError(err) - var response string + var response commonpb.DataBlob s.NoError(run.Get(ctx, &response)) - s.Equal("Hello, Temporal", response) + data := response.Data + s.Equal("Hello, Temporal", string(data)) } // NOTE: This test cannot use the SDK workflow package because there is a restriction that prevents setting the @@ -3361,9 +3371,10 @@ func (s *NexusWorkflowTestSuite) TestNexusOperationSystemEndpoint_PayloadMetadat completedEvent := s.RequireHistoryEvent(pollResp.History.Events, enumspb.EVENT_TYPE_NEXUS_OPERATION_COMPLETED) result := completedEvent.GetNexusOperationCompletedEventAttributes().Result s.NotNil(result) - // TestOperationWithPayload's response embeds a nested Payload, so the system payload metadata - // flag must be set. + // TestOperationWithPayload's response embeds a nested Payload, so the system payload metadata flag must be set. s.Equal([]byte("true"), result.GetMetadata()[commonnexus.SystemPayloadMetadataKey]) + s.Equal([]byte(payloadsMessageType), result.GetMetadata()["messageType"]) + s.Equal([]byte(protobufEncoding), result.GetMetadata()["encoding"]) // Complete the workflow _, err = env.FrontendClient().RespondWorkflowTaskCompleted(s.Context(), &workflowservice.RespondWorkflowTaskCompletedRequest{ diff --git a/tests/sdk_server_host_test.go b/tests/sdk_server_host_test.go new file mode 100644 index 00000000000..2278f350960 --- /dev/null +++ b/tests/sdk_server_host_test.go @@ -0,0 +1,81 @@ +package tests + +import ( + "context" + "encoding/json" + "errors" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + enumspb "go.temporal.io/api/enums/v1" + "go.temporal.io/server/common/namespace" + "go.temporal.io/server/tests/testcore" +) + +// TestSDKValidationServerHost is not a test. It keeps a dedicated cluster up so +// an SDK's own test suite can run against a server built from this tree, and +// tears it down when the caller writes the shutdown file. Opt-in like the +// other measurement tooling; nothing in a normal run should start a cluster +// and hold it for hours. +func TestSDKValidationServerHost(t *testing.T) { + if os.Getenv("TEMPORAL_STREAM_BENCH") != "1" { + t.Skip("set TEMPORAL_STREAM_BENCH=1 to run") + } + readyPath := os.Getenv("AI198_SDK_SERVER_READY_FILE") + stopPath := os.Getenv("AI198_SDK_SERVER_STOP_FILE") + if readyPath == "" || stopPath == "" { + t.Skip("SDK validation host needs explicit ready and shutdown paths") + } + _, err := os.Stat(stopPath) + require.ErrorIs(t, err, os.ErrNotExist, "a stale shutdown file must not silently stop this host") + env := testcore.NewEnv(t, testcore.WithDedicatedCluster()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = env.RegisterNamespace( + ctx, namespace.Name("default"), 1, enumspb.ARCHIVAL_STATE_DISABLED, "", "") + require.NoError(t, err) + config := env.GetTestClusterConfig() + metadata := map[string]any{ + "status": "running", "pid": os.Getpid(), "target": env.FrontendGRPCAddress(), + "namespace": "default", + "persistence": "SQLite", + "history_hosts": config.HistoryConfig.NumHistoryHosts, + "history_shards": config.HistoryConfig.NumHistoryShards, + "started_utc": time.Now().UTC().Format(time.RFC3339), + "shutdown_file": stopPath, + "source_provenance": "../server-source-provenance.json", + "configuration": "tests/testcore dedicated test-cluster defaults; " + + "namespace default added for SDK clients", + } + writeMetadata := func() { + data, marshalErr := json.MarshalIndent(metadata, "", " ") + require.NoError(t, marshalErr) + require.NoError(t, os.WriteFile(readyPath, append(data, '\n'), 0o644)) + } + writeMetadata() + t.Logf("SDK validation server ready at %s in namespace default; shutdown file %s", + env.FrontendGRPCAddress(), stopPath) + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + deadline := time.NewTimer(2 * time.Hour) + defer deadline.Stop() + for { + select { + case <-ticker.C: + if _, statErr := os.Stat(stopPath); statErr == nil { + metadata["status"] = "stopping" + metadata["stopped_utc"] = time.Now().UTC().Format(time.RFC3339) + writeMetadata() + return + } else if !errors.Is(statErr, os.ErrNotExist) { + require.NoError(t, statErr) + } + case <-deadline.C: + metadata["status"] = "maximum-runtime-reached" + writeMetadata() + return + } + } +} diff --git a/tests/stream_consume_test.go b/tests/stream_consume_test.go new file mode 100644 index 00000000000..4b372a0bbc4 --- /dev/null +++ b/tests/stream_consume_test.go @@ -0,0 +1,1113 @@ +package tests + +import ( + "context" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/protobuf/types/known/durationpb" +) + +// Path C: a workflow consuming a stream. The slice rides the workflow task and +// only the offsets it covered are written to History, so consumption costs no +// event of its own no matter how many messages it carried. +func TestStreamWorkflowConsumesWithoutHistoryPayloads(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-consume-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + we, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + // What each task was handed, in the order the tasks ran. + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + if task > 1 { + return nil, nil + } + // First task publishes; nothing is subscribed yet, so it consumes + // nothing. + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("first-token")}, Topic: "tokens"}, + {Body: &commonpb.Payload{Data: []byte("second-token")}, Topic: "tokens"}, + {Body: &commonpb.Payload{Data: []byte("third-token")}, Topic: "tokens"}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Empty(t, delivered[0], "nothing is subscribed on the first task") + + // Subscribe from the start of the stream. + sub, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, + WorkflowId: id, + StreamName: chasmworkflow.DefaultStreamName, + StartOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, int64(0), sub.GetFrontendResponse().GetStartOffset()) + + // Resubscribing must not rewind. Ranges below the cursor are already in + // History, and moving back would replay them as if they were new. + sub2, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 2, + }, + }) + require.NoError(t, err) + require.Equal(t, int64(0), sub2.GetFrontendResponse().GetStartOffset(), + "a second subscribe must report the cursor already registered") + + // Second task: the published range should arrive on the task itself. + signalWorkflow(t, s, id, we.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + slice := currentSlice(t, delivered[1]) + require.Equal(t, int64(0), slice.GetFromOffset()) + require.Equal(t, int64(3), slice.GetToOffset()) + require.Len(t, slice.GetRecords(), 3) + require.Equal(t, "first-token", string(slice.GetRecords()[0].GetBody().GetData())) + require.Equal(t, "third-token", string(slice.GetRecords()[2].GetBody().GetData())) + + // Third task: the cursor is caught up, so the range is empty. An empty + // range is still delivered and still recorded, because a task that saw + // nothing is a fact replay has to reproduce. + signalWorkflow(t, s, id, we.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + idleSlice := currentSlice(t, delivered[2]) + require.Equal(t, int64(3), idleSlice.GetFromOffset(), "a caught-up subscription is still attached") + require.Equal(t, int64(3), idleSlice.GetToOffset()) + require.Empty(t, idleSlice.GetRecords()) + + events := env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}) + recorded := recordedCursors(events) + + // One record per completed task from the subscription onward, including the + // one that consumed nothing. + require.Len(t, recorded, 2) + require.Equal(t, int64(0), recorded[0].GetFromOffset()) + require.Equal(t, int64(3), recorded[0].GetToOffset()) + require.Equal(t, int64(3), recorded[1].GetFromOffset()) + require.Equal(t, int64(3), recorded[1].GetToOffset(), + "the idle task must record the empty range rather than omit it") + + // The point of the design: offsets are in History, payloads are not. + for _, e := range events { + require.NotContains(t, e.String(), "first-token", + "a consumed payload must never reach History, found in %v", e.GetEventType()) + require.NotContains(t, e.String(), "third-token", + "a consumed payload must never reach History, found in %v", e.GetEventType()) + } +} + +func recordedCursors(events []*historypb.HistoryEvent) []*streampb.StreamRange { + var out []*streampb.StreamRange + for _, e := range events { + attrs := e.GetWorkflowTaskCompletedEventAttributes() + out = append(out, attrs.GetConsumedStreamRanges()...) + } + return out +} + +func signalWorkflow(t *testing.T, s *streamTestEnv, workflowID, runID string) { + t.Helper() + _, err := s.env.FrontendClient().SignalWorkflowExecution( + s.ctx(), + &workflowservice.SignalWorkflowExecutionRequest{ + Namespace: s.ns, + WorkflowExecution: &commonpb.WorkflowExecution{WorkflowId: workflowID, RunId: runID}, + SignalName: "wake", + Identity: "tester", + RequestId: uuid.NewString(), + }, + ) + require.NoError(t, err) +} + +// Publishing never wakes a workflow, but an active subscription does. Without +// this the rest of a stream arrives only when something unrelated happens to +// schedule a task. +func TestStreamSubscriptionSchedulesItsOwnWorkflowTask(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-wake-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + publish := func(bodies ...string) []*commandpb.Command { + messages := make([]*streampb.StreamRecord, len(bodies)) + for i, b := range bodies { + messages[i] = &streampb.StreamRecord{Body: &commonpb.Payload{Data: []byte(b)}, Topic: "tokens"} + } + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: messages, + }, + }, + }} + } + + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + switch task { + case 1: + return publish("warmup"), nil + case 2: + // Published while subscribed and caught up, so completing this + // task leaves the cursor behind head. + return publish("alpha", "beta"), nil + default: + return nil, nil + } + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + // Subscribe at the tail, so nothing is owed yet. + sub, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, + StreamName: chasmworkflow.DefaultStreamName, StartOffset: -1, + }, + }) + require.NoError(t, err) + require.Equal(t, int64(1), sub.GetFrontendResponse().GetStartOffset()) + + signalWorkflow(t, s, id, "") + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Equal(t, int64(1), currentSlice(t, delivered[1]).GetToOffset(), + "nothing new at the tail yet") + + // No signal this time. The subscription owes two offsets, so completing the + // previous task has to have scheduled this one. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Len(t, delivered, 3) + woken := currentSlice(t, delivered[2]) + require.Equal(t, int64(1), woken.GetFromOffset()) + require.Equal(t, int64(3), woken.GetToOffset()) + require.Len(t, woken.GetRecords(), 2) + require.Equal(t, "alpha", string(woken.GetRecords()[0].GetBody().GetData())) + + // And it has to stop. A wake condition that stayed true would spin the + // workflow on empty tasks forever. + pollCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + idle, err := env.FrontendClient().PollWorkflowTaskQueue( + pollCtx, + &workflowservice.PollWorkflowTaskQueueRequest{ + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + }, + ) + if err == nil { + require.Empty(t, idle.GetTaskToken(), + "a caught-up subscription must not keep scheduling tasks") + } +} + +// Subscribing to a stream that already has data is the other case where the +// workflow is owed a task it did not ask for by any other means. +func TestSubscribingToABacklogSchedulesAWorkflowTask(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-backlog-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + if task > 1 { + return nil, nil + } + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("backlog-1")}, Topic: "tokens"}, + {Body: &commonpb.Payload{Data: []byte("backlog-2")}, Topic: "tokens"}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // No signal. Subscribing behind the head is itself a reason to run. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Len(t, delivered, 2) + backlog := currentSlice(t, delivered[1]) + require.Equal(t, int64(0), backlog.GetFromOffset()) + require.Equal(t, int64(2), backlog.GetToOffset()) +} + +// History records the offsets a task consumed and never the payloads, so a +// worker replaying that task has to be handed the bytes again. The response +// field alone cannot do it: it is built once per delivery while a cache miss +// replays every prior task, so each re-supplied range travels with the id of +// the event that recorded it. +func TestReplayGetsTheConsumedRangesBackFromTheStream(t *testing.T) { + // Dedicated, because forcing the replay path means evicting the cached + // workflow context, and CloseShard is not allowed on a shared cluster. + env := testcore.NewEnv(t, testcore.WithDedicatedCluster()) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-replay-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + we, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + if task > 1 { + return nil, nil + } + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("replay-me-1")}, Topic: "tokens"}, + {Body: &commonpb.Payload{Data: []byte("replay-me-2")}, Topic: "tokens"}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // Consume the range. This is the task replay will have to reproduce. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Len(t, currentSlice(t, delivered[1]).GetRecords(), 2) + + consumedAt := completedEventWithCursors(t, env.GetHistory(s.ns, + &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()})) + + // Drop the cached context so the next task is served with full history, + // which is the replay path. + env.CloseShard(env.NamespaceID().String(), id) + + signalWorkflow(t, s, id, we.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + replayed := sliceForEvent(delivered[2], consumedAt) + require.NotNil(t, replayed, + "the replayed task must carry the range recorded at event %d", consumedAt) + require.Equal(t, int64(0), replayed.GetFromOffset()) + require.Equal(t, int64(2), replayed.GetToOffset()) + require.Len(t, replayed.GetRecords(), 2, "the payloads have to come back from the stream") + require.Equal(t, "replay-me-1", string(replayed.GetRecords()[0].GetBody().GetData())) + require.Equal(t, "replay-me-2", string(replayed.GetRecords()[1].GetBody().GetData())) +} + +// completedEventWithCursors returns the id of the first WorkflowTaskCompleted +// event that recorded a non-empty consumed range. +func completedEventWithCursors(t *testing.T, events []*historypb.HistoryEvent) int64 { + t.Helper() + for _, e := range events { + for _, c := range e.GetWorkflowTaskCompletedEventAttributes().GetConsumedStreamRanges() { + if c.GetToOffset() > c.GetFromOffset() { + return e.GetEventId() + } + } + } + t.Fatal("no completed event recorded a consumed range") + return 0 +} + +// currentSlice picks the slice for the task about to run. Slices carrying an +// event id belong to tasks being replayed, and a response can hold both. +func currentSlice(t *testing.T, slices []*streampb.StreamSlice) *streampb.StreamSlice { + t.Helper() + for _, s := range slices { + if s.GetWorkflowTaskCompletedEventId() == 0 { + return s + } + } + t.Fatal("no slice for the current task") + return nil +} + +func sliceForEvent(slices []*streampb.StreamSlice, eventID int64) *streampb.StreamSlice { + for _, s := range slices { + if s.GetWorkflowTaskCompletedEventId() == eventID { + return s + } + } + return nil +} + +// The shape the feature exists for: a producer writing off-shard and a workflow +// consuming it, with no relationship between them beyond the stream. +// +// A consuming workflow cannot read another execution's frontier while closing +// its own transaction, so the stream pushes it. The push dirties the consumer, +// whose transaction close then sees it is behind and schedules a workflow task. +// +// The payload is read from the stream's own execution, which can live on +// another shard, so delivery has to route the read rather than resolve the +// stream locally. +func TestWorkflowConsumesAStreamItDoesNotOwn(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "external-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + id := "stream-wf-external-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + we, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + var delivered [][]*streampb.StreamSlice + + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, + StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // The subscription has to reach the stream, or truncation could take a + // range the cursor still points at. + desc, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + consumers := desc.GetFrontendResponse().GetState().GetConsumers() + require.Len(t, consumers, 1) + for _, c := range consumers { + require.True(t, c.GetExternal()) + require.True(t, c.GetActive()) + require.Equal(t, id, c.GetWorkflowId()) + } + + // An off-shard producer, unrelated to the workflow. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + { + Body: &commonpb.Payload{Data: []byte("from-outside-1")}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + }, + { + Body: &commonpb.Payload{Data: []byte("from-outside-2")}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + }, + }, + }, + }) + require.NoError(t, err) + + // The append alone has to produce a workflow task, with no signal and no + // other traffic against the workflow. + await.RequireTruef(t, func() bool { + events := env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}) + scheduled := 0 + for _, e := range events { + if e.GetEventType() == enumspb.EVENT_TYPE_WORKFLOW_TASK_SCHEDULED { + scheduled++ + } + } + return scheduled >= 2 + }, 20*time.Second, 200*time.Millisecond, "the append must schedule a workflow task on its own") + + // And it must reach a worker. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + got := currentSlice(t, delivered[1]) + require.Equal(t, streamID, got.GetStreamId()) + require.Equal(t, int64(0), got.GetFromOffset()) + require.Equal(t, int64(2), got.GetToOffset()) + require.Len(t, got.GetRecords(), 2) + require.Equal(t, "from-outside-1", string(got.GetRecords()[0].GetBody().GetData())) +} + +// A cursor is workflow state, so a continue-as-new has to carry it. Without +// that the subscription ends silently: the stream keeps its consumer pin and +// keeps pushing to the workflow id, and the successor run has nowhere to put +// what arrives. +func TestSubscriptionSurvivesContinueAsNew(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "carried-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + id := "stream-wf-can-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + if task == 2 { + // Continue as new, carrying nothing of its own. + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_CONTINUE_AS_NEW_WORKFLOW_EXECUTION, + Attributes: &commandpb.Command_ContinueAsNewWorkflowExecutionCommandAttributes{ + ContinueAsNewWorkflowExecutionCommandAttributes: &commandpb. + ContinueAsNewWorkflowExecutionCommandAttributes{ + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + }, + }, + }}, nil + } + return nil, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // First append, consumed by the original run. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("before-can")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + }, + }, + }) + require.NoError(t, err) + + // Task 2 receives it and continues as new. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + consumed := currentSlice(t, delivered[1]) + require.Equal(t, int64(1), consumed.GetToOffset()) + require.Len(t, consumed.GetRecords(), 1) + + // Drain the successor's first task, which carries nothing new. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + // Append again. Only a carried subscription can deliver this, and it must + // resume at offset 1 rather than replaying from the start. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("after-can")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + }, + }, + }) + require.NoError(t, err) + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + afterCAN := currentSlice(t, delivered[len(delivered)-1]) + require.Equal(t, int64(1), afterCAN.GetFromOffset(), + "the successor resumes where its predecessor stopped") + require.Equal(t, int64(2), afterCAN.GetToOffset()) + require.Len(t, afterCAN.GetRecords(), 1) + require.Equal(t, "after-can", string(afterCAN.GetRecords()[0].GetBody().GetData())) + + // The pin followed the subscription to the new run, with the floor where + // that run's cursor began. The predecessor's ranges are in a closed history + // that never replays, so nothing holds offset 0 any more. + described, err := env.FrontendClient().DescribeWorkflowExecution(s.ctx(), + &workflowservice.DescribeWorkflowExecutionRequest{ + Namespace: s.ns, Execution: &commonpb.WorkflowExecution{WorkflowId: id}, + }) + require.NoError(t, err) + successor := described.GetWorkflowExecutionInfo().GetExecution().GetRunId() + state := describeStream(t, s, streamID) + require.Len(t, state.GetConsumers(), 1, "one pin, keyed to the run that consumes") + for _, consumer := range state.GetConsumers() { + require.Equal(t, successor, consumer.GetRunId()) + require.Equal(t, int64(1), consumer.GetReplayFloor()) + } +} + +// A workflow subscribing itself, rather than being subscribed out of band. +// +// The command carries only the stream id and a start offset. The server +// resolves the offset against the stream's frontier: a workflow cannot read +// another execution's frontier without doing I/O, and a value it carried would +// be a reading rather than a fact, so it could differ on replay. +func TestWorkflowSubscribesToAStreamItself(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "self-sub-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + id := "stream-wf-selfsub-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + var delivered [][]*streampb.StreamSlice + task := 0 + + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + task++ + if task > 1 { + return nil, nil + } + // The workflow subscribes itself on its first task. + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM, + Attributes: &commandpb.Command_SubscribeStreamCommandAttributes{ + SubscribeStreamCommandAttributes: &commandpb.SubscribeStreamCommandAttributes{ + StreamId: streamID, + StartOffset: 0, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Empty(t, delivered[0], "nothing is subscribed until this task completes") + + // The subscription has to have reached the stream, or truncation could take + // a range the cursor still points at. + desc, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + require.Len(t, desc.GetFrontendResponse().GetState().GetConsumers(), 1, + "the command must have registered a consumer on the stream") + + // The subscription is recorded once, with the offset the server resolved. + // Without it nothing in History explains why this workflow starts receiving + // stream data, and a command that writes no event desynchronises the + // command-to-event matching every SDK's replay depends on. + subscribed := subscribedEvents(env.GetHistory(s.ns, + &commonpb.WorkflowExecution{WorkflowId: id})) + require.Len(t, subscribed, 1) + require.Equal(t, streamID, subscribed[0].GetStreamId()) + require.Equal(t, int64(0), subscribed[0].GetStartOffset()) + + // An off-shard producer, with no signal to the workflow. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("self-1")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + {Body: &commonpb.Payload{Data: []byte("self-2")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + }, + }, + }) + require.NoError(t, err) + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + got := currentSlice(t, delivered[1]) + require.Equal(t, streamID, got.GetStreamId()) + require.Equal(t, int64(0), got.GetFromOffset()) + require.Equal(t, int64(2), got.GetToOffset()) + require.Len(t, got.GetRecords(), 2) + require.Equal(t, "self-1", string(got.GetRecords()[0].GetBody().GetData())) +} + +func subscribedEvents( + events []*historypb.HistoryEvent, +) []*historypb.WorkflowStreamSubscribedEventAttributes { + var out []*historypb.WorkflowStreamSubscribedEventAttributes + for _, e := range events { + if attrs := e.GetWorkflowStreamSubscribedEventAttributes(); attrs != nil { + out = append(out, attrs) + } + } + return out +} + +// A second subscribe to a stream the workflow already holds registers nothing, +// but it still has to write an event. Every SDK matches issued commands against +// command-generated events by position, so a command producing no event leaves +// the machine that issued it unmatched and puts every later command out of step. +func TestResubscribingStillWritesItsEvent(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "resub-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + id := "stream-wf-resub-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + we, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + subscribe := []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM, + Attributes: &commandpb.Command_SubscribeStreamCommandAttributes{ + SubscribeStreamCommandAttributes: &commandpb.SubscribeStreamCommandAttributes{ + StreamId: streamID, StartOffset: 0, + }, + }, + }} + + task := 0 + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task > 2 { + return nil, nil + } + return subscribe, nil + }, + Logger: env.Logger, + T: t, + } + + // Two tasks, each issuing the same subscribe. The second registers nothing. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + _, err = env.FrontendClient().SignalWorkflowExecution( + s.ctx(), + &workflowservice.SignalWorkflowExecutionRequest{ + Namespace: s.ns, + WorkflowExecution: &commonpb.WorkflowExecution{WorkflowId: id}, + SignalName: "wake", + Identity: "tester", + RequestId: uuid.NewString(), + }, + ) + require.NoError(t, err) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + events := env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}) + var subscribed []*historypb.WorkflowStreamSubscribedEventAttributes + for _, e := range events { + if a := e.GetWorkflowStreamSubscribedEventAttributes(); a != nil { + subscribed = append(subscribed, a) + } + } + require.Len(t, subscribed, 2, "each subscribe command owes an event, even a repeat") + require.Equal(t, streamID, subscribed[1].GetStreamId()) + // The repeat reports where the cursor actually is, not the offset it asked + // for, so a replaying worker reads a fact rather than a request. + require.Equal(t, int64(0), subscribed[1].GetStartOffset()) +} + +// A subscribe followed by another command in the same Workflow Task. Every SDK +// matches issued commands against the events they produced by position, so the +// subscription's event has to sit where its command did, even though its start +// offset is only resolved after every command has run. +func TestStreamSubscribeEventKeepsCommandOrder(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "order-src-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + id := "stream-order-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-order"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + // Subscribe first, then publish. The publish event must come second. + return []*commandpb.Command{ + { + CommandType: enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM, + Attributes: &commandpb.Command_SubscribeStreamCommandAttributes{ + SubscribeStreamCommandAttributes: &commandpb.SubscribeStreamCommandAttributes{ + StreamId: streamID, StartOffset: 0, + }, + }, + }, + { + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("after subscribe")}}, + }, + }, + }, + }, + }, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + var order []enumspb.EventType + for _, e := range env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id}) { + switch e.GetEventType() { + case enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED: + order = append(order, e.GetEventType()) + default: + // Every other event is noise for this assertion. + } + } + require.Equal(t, []enumspb.EventType{ + enumspb.EVENT_TYPE_WORKFLOW_STREAM_SUBSCRIBED, + enumspb.EVENT_TYPE_WORKFLOW_STREAM_RECORDS_APPENDED, + }, order, "the events must be in the order their commands were issued") +} + +// An activity streaming tokens over the RPC has no reason to know about message +// kinds. A message appended with the kind left unset has to reach a subscribed +// workflow like any other, rather than take an offset and vanish. +func TestMessagesAppendedWithoutAKindReachTheWorkflow(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "kindless-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + execution, tq := startConsumer(t, s, "stream-wf-kindless-") + + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("no-kind-1")}}, + {Body: &commonpb.Payload{Data: []byte("no-kind-2")}}, + }, + }, + }) + require.NoError(t, err) + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + got := currentSlice(t, delivered[1]) + require.Equal(t, int64(2), got.GetToOffset()) + require.Equal(t, []string{"no-kind-1", "no-kind-2"}, apiBodies(got.GetRecords()), + "the slice must carry the messages, not just advance past them") +} diff --git a/tests/stream_consumer_lifecycle_test.go b/tests/stream_consumer_lifecycle_test.go new file mode 100644 index 00000000000..aa7a27704e0 --- /dev/null +++ b/tests/stream_consumer_lifecycle_test.go @@ -0,0 +1,182 @@ +package tests + +import ( + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/protobuf/types/known/durationpb" +) + +func completeWorkflowCommand() []*commandpb.Command { + attrs := &commandpb.CompleteWorkflowExecutionCommandAttributes{} + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION, + Attributes: &commandpb.Command_CompleteWorkflowExecutionCommandAttributes{ + CompleteWorkflowExecutionCommandAttributes: attrs, + }, + }} +} + +func describeStream(t *testing.T, s *streamTestEnv, streamID string) *streamlib.StreamState { + t.Helper() + desc, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + return desc.GetFrontendResponse().GetState() +} + +// subscribeConsumeAndComplete runs a consumer through one delivered range and +// then completes it, leaving its pin on the stream. +func subscribeConsumeAndComplete( + t *testing.T, s *streamTestEnv, streamID string, prefix string, +) *commonpb.WorkflowExecution { + t.Helper() + execution, tq := startConsumer(t, s, prefix) + task := 0 + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: s.env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 3 { + return completeWorkflowCommand(), nil + } + return nil, nil + }, + Logger: s.env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, Records: streamMsgs("tokens", "one", "two"), + }, + }) + require.NoError(t, err) + + // Consumes the range, then completes on the task after. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + state := describeStream(t, s, streamID) + require.Len(t, state.GetConsumers(), 1, "the completed run still holds its pin for now") + return execution +} + +// A consumer that completed can never replay, so the floor it held is a leak. +// The stream learns a consumer is gone when it next tries to tell it the +// frontier moved, and releases the pin then. +func TestACompletedConsumerReleasesItsFloor(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + streamID := "released-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + subscribeConsumeAndComplete(t, s, streamID, "stream-wf-released-") + + _, err := s.client.TruncateStream(s.ctx(), &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: streamID, NewBaseOffset: 2, + }, + }) + require.ErrorContains(t, err, "still depends on offset 0", + "the pin holds until the stream finds out") + + // The append is what makes the stream go and ask. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, Records: streamMsgs("tokens", "three"), + }, + }) + require.NoError(t, err) + await.RequireTrue(t, func() bool { + return len(describeStream(t, s, streamID).GetConsumers()) == 0 + }, 20*time.Second, 100*time.Millisecond) + + _, err = s.client.TruncateStream(s.ctx(), &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: streamID, NewBaseOffset: 2, + }, + }) + require.NoError(t, err, "nothing holds the floor once the consumer is gone") +} + +// A new run of the same workflow id is a new consumer. It subscribes at its +// own offset and takes over the pin, rather than inheriting a floor from a run +// that finished, which could be below the stream's base and refuse it. +func TestANewRunSubscribesFreshAfterThePreviousCompleted(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + streamID := "rerun-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + + first := subscribeConsumeAndComplete(t, s, streamID, "stream-wf-rerun-") + + // The same workflow id, started again after the first run completed. + second, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: first.GetWorkflowId(), + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: &taskqueuepb.TaskQueue{Name: first.GetWorkflowId() + "-tq2"}, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + require.NotEqual(t, first.GetRunId(), second.GetRunId()) + + sub, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: first.GetWorkflowId(), StreamId: streamID, StartOffset: 2, + }, + }) + require.NoError(t, err) + require.Equal(t, int64(2), sub.GetFrontendResponse().GetStartOffset(), + "the new run starts where it asked, not where the old run did") + + state := describeStream(t, s, streamID) + require.Len(t, state.GetConsumers(), 1, + "the old run's pin is replaced, not kept beside the new one") + for _, consumer := range state.GetConsumers() { + require.Equal(t, second.GetRunId(), consumer.GetRunId()) + require.Equal(t, int64(2), consumer.GetReplayFloor()) + } + + _, err = s.client.TruncateStream(s.ctx(), &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: streamID, NewBaseOffset: 2, + }, + }) + require.NoError(t, err, "only the new run's floor holds") +} diff --git a/tests/stream_publish_cost_test.go b/tests/stream_publish_cost_test.go new file mode 100644 index 00000000000..7195c575fbf --- /dev/null +++ b/tests/stream_publish_cost_test.go @@ -0,0 +1,307 @@ +package tests + +import ( + "fmt" + "os" + "strings" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + "go.temporal.io/server/tests/testcore" + "google.golang.org/protobuf/types/known/durationpb" +) + +// What the history event per publish costs. +// +// Every SDK matches commands to events positionally, so the publish command +// has to produce one. The objection is that unlike subscribing, which happens +// once, publishing happens per batch. This measures the per-batch price so the +// trade is decided on a number. +// +// The method is a marginal one. Each arm runs a workflow whose single workflow +// task carries N publish commands and then completes, so history holds the +// fixed opening and closing events plus exactly N publishes. Differencing +// against the N=0 arm cancels the fixed part and leaves the cost of one +// publish. Message size is varied against a fixed batch count to show whether +// payload bytes reach History at all. + +type publishCostArm struct { + name string + batches int + messagesPerBatch int + messageSize int + // Sends the same bytes as Signals instead, which is what a workflow + // streaming today has to do. The comparison is the point of the exercise. + viaSignal bool +} + +type publishCostResult struct { + arm publishCostArm + historyEvents int64 + historyBytes int64 +} + +func (r publishCostResult) messages() int { + return r.arm.batches * r.arm.messagesPerBatch +} + +// The published limits a per-batch event has to be judged against. +const ( + historyCountLimitError = 50 * 1024 + historySizeLimitError = 50 * 1024 * 1024 +) + +func TestStreamPublishHistoryCost(t *testing.T) { + if testing.Short() { + t.Skip("measurement, not a correctness check") + } + // Each arm holds a cluster of its own until the whole test returns, so ten + // arms outlast the dedicated pool. Opt in like the other measurements. + if os.Getenv("TEMPORAL_STREAM_BENCH") != "1" { + t.Skip("set TEMPORAL_STREAM_BENCH=1 to run") + } + + arms := []publishCostArm{ + // The control. Everything is differenced against this. + {name: "control", batches: 0}, + + // Batch count at a fixed message shape: is the cost linear, and what + // is the slope. + {name: "stream-b1", batches: 1, messagesPerBatch: 1, messageSize: 20}, + {name: "stream-b10", batches: 10, messagesPerBatch: 1, messageSize: 20}, + {name: "stream-b100", batches: 100, messagesPerBatch: 1, messageSize: 20}, + {name: "stream-b500", batches: 500, messagesPerBatch: 1, messageSize: 20}, + + // Same batch count, more messages inside each: the per-batch event + // should not notice. + {name: "stream-b100-m10", batches: 100, messagesPerBatch: 10, messageSize: 20}, + + // Same batch count, bigger messages: this is the claim that payloads + // never enter History, stated as a measurement. + {name: "stream-b100-s200", batches: 100, messagesPerBatch: 1, messageSize: 200}, + {name: "stream-b100-s2000", batches: 100, messagesPerBatch: 1, messageSize: 2000}, + + // What the same traffic costs through Signals today. + {name: "signal-b100-s20", batches: 100, messagesPerBatch: 1, messageSize: 20, viaSignal: true}, + { + name: "signal-b100-s2000", batches: 100, messagesPerBatch: 1, messageSize: 2000, + viaSignal: true, + }, + } + + results := make([]publishCostResult, 0, len(arms)) + byName := map[string]publishCostResult{} + for _, arm := range arms { + r := runPublishCostArm(t, arm) + results = append(results, r) + byName[arm.name] = r + } + reportPublishCost(t, results) + assertPublishCost(t, byName) +} + +// The report is the deliverable, but the properties it shows are the ones the +// design rests on, so they are asserted rather than left to be eyeballed. +func assertPublishCost(t *testing.T, byName map[string]publishCostResult) { + control := byName["control"] + marginalBytes := func(name string) int64 { + return byName[name].historyBytes - control.historyBytes + } + marginalEvents := func(name string) int64 { + return byName[name].historyEvents - control.historyEvents + } + + // One event per batch, not per message. b100-m10 publishes ten times the + // messages of b100 through the same hundred commands. + require.Equal(t, int64(100), marginalEvents("stream-b100")) + require.Equal(t, int64(100), marginalEvents("stream-b100-m10")) + require.Equal(t, int64(500), marginalEvents("stream-b500")) + + // Ten times the payload must not move History, which is the claim that + // bodies never enter it. Judged against what a leak would cost rather than + // against zero: event sizes wobble by a byte or two on varint widths, while + // 1800 extra bytes per message across a hundred batches would be six + // figures. + sizeDrift := marginalBytes("stream-b100-s2000") - marginalBytes("stream-b100-s200") + require.Less(t, max(sizeDrift, -sizeDrift), int64(2000), + "10x the payload moved the history cost, so payload is reaching History") + + // Ten times the messages through the same batches, within a byte or two of + // noise from varint widths. + require.InDelta(t, marginalBytes("stream-b100"), marginalBytes("stream-b100-m10"), 200, + "cost tracked message count rather than batch count") + + // The comparison that justifies the feature. Same traffic, and Signals are + // the only way to do this today. + require.Less(t, marginalBytes("stream-b100-s2000"), marginalBytes("signal-b100-s2000")/20, + "a stream publish should be far cheaper than the Signal it replaces") +} + +func runPublishCostArm(t *testing.T, arm publishCostArm) publishCostResult { + t.Helper() + env := testcore.NewEnv(t, testcore.WithDisableTestloggerFailure()) + + // Fixed-width regardless of the arm, because the workflow id and the task + // queue name derived from it are both carried in the opening events. Naming + // the arms in there would put ten bytes of arm-name difference into the very + // figure being differenced. + id := "publish-cost-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + ctx := testcore.NewContext() + + _, err := env.FrontendClient().StartWorkflowExecution( + ctx, + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: env.Namespace().String(), + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "publish-cost"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(60 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + body := []byte(strings.Repeat("x", arm.messageSize)) + + // Sent before the first workflow task is polled, so they land in history + // ahead of it and the single task still closes the workflow. + if arm.viaSignal { + for range arm.batches { + payloads := make([]*commonpb.Payload, 0, arm.messagesPerBatch) + for range arm.messagesPerBatch { + payloads = append(payloads, &commonpb.Payload{Data: body}) + } + _, err := env.FrontendClient().SignalWorkflowExecution( + ctx, + &workflowservice.SignalWorkflowExecutionRequest{ + Namespace: env.Namespace().String(), + WorkflowExecution: &commonpb.WorkflowExecution{WorkflowId: id}, + SignalName: "stream-item", + Input: &commonpb.Payloads{Payloads: payloads}, + Identity: "tester", + RequestId: uuid.NewString(), + }, + ) + require.NoError(t, err) + } + } + + //nolint:staticcheck // SA1019: only the deprecated poller emits raw commands. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: env.Namespace().String(), + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + commands := make([]*commandpb.Command, 0, arm.batches+1) + if !arm.viaSignal { + for range arm.batches { + messages := make([]*streampb.StreamRecord, 0, arm.messagesPerBatch) + for range arm.messagesPerBatch { + messages = append(messages, &streampb.StreamRecord{ + Body: &commonpb.Payload{Data: body}, + Topic: "progress", + }) + } + commands = append(commands, &commandpb.Command{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: messages, + }, + }, + }) + } + } + return append(commands, completeWorkflowCommand()...), nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + desc, err := env.FrontendClient().DescribeWorkflowExecution( + ctx, + &workflowservice.DescribeWorkflowExecutionRequest{ + Namespace: env.Namespace().String(), + Execution: &commonpb.WorkflowExecution{WorkflowId: id}, + }, + ) + require.NoError(t, err) + + return publishCostResult{ + arm: arm, + historyEvents: desc.GetWorkflowExecutionInfo().GetHistoryLength(), + historyBytes: desc.GetWorkflowExecutionInfo().GetHistorySizeBytes(), + } +} + +func reportPublishCost(t *testing.T, results []publishCostResult) { + var control publishCostResult + for _, r := range results { + if r.arm.name == "control" { + control = r + } + } + + t.Log("Cost of one history event per publish, measured by differencing against an empty run.") + t.Logf("Control: %d events, %d bytes.", control.historyEvents, control.historyBytes) + t.Log("") + t.Log("| arm | batches | msgs | msg size | events | bytes " + + "| events/batch | bytes/batch | bytes/msg |") + t.Log("|---|---|---|---|---|---|---|---|---|") + for _, r := range results { + if r.arm.batches == 0 { + continue + } + marginalEvents := r.historyEvents - control.historyEvents + marginalBytes := r.historyBytes - control.historyBytes + perMsg := "n/a" + if r.messages() > 0 { + perMsg = fmt.Sprintf("%.1f", float64(marginalBytes)/float64(r.messages())) + } + t.Logf("| %s | %d | %d | %d | %d | %d | %.2f | %.1f | %s |", + r.arm.name, r.arm.batches, r.messages(), r.arm.messageSize, + r.historyEvents, r.historyBytes, + float64(marginalEvents)/float64(r.arm.batches), + float64(marginalBytes)/float64(r.arm.batches), + perMsg) + } + t.Log("") + + // The ceilings the number has to be read against. An event per batch makes + // the event-count limit the binding one long before the size limit. + for _, r := range results { + if r.arm.batches == 0 || r.arm.viaSignal { + continue + } + marginalBytes := r.historyBytes - control.historyBytes + marginalEvents := r.historyEvents - control.historyEvents + if marginalEvents == 0 { + continue + } + bytesPerEvent := float64(marginalBytes) / float64(marginalEvents) + t.Logf("%s: %.0f bytes/event implies %d batches before the %d-event limit, "+ + "%d before the %dMB size limit", + r.arm.name, bytesPerEvent, + historyCountLimitError, + historyCountLimitError, + int(float64(historySizeLimitError)/bytesPerEvent), + historySizeLimitError/(1024*1024)) + } +} diff --git a/tests/stream_query_test.go b/tests/stream_query_test.go new file mode 100644 index 00000000000..20052370f49 --- /dev/null +++ b/tests/stream_query_test.go @@ -0,0 +1,137 @@ +package tests + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + querypb "go.temporal.io/api/query/v1" + "go.temporal.io/api/workflowservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common/payloads" + "go.temporal.io/server/tests/testcore" +) + +// A query with no workflow task in flight is dispatched straight through +// matching, on a task built without RecordWorkflowTaskStarted. That task +// carries the whole history to whichever worker polls it, which may never have +// seen the execution, so it has to carry the recorded ranges too or the worker +// cannot replay a consuming workflow far enough to answer. +// +// The query is answered by a second poller that took part in none of the +// earlier tasks, from the slices on the query task alone. +func TestQueryTaskCarriesTheConsumedRanges(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-query-") + + task := 0 + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + worker := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "worker", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 1 { + return publishCommand("answer-1", "answer-2"), nil + } + return nil, nil + }, + Logger: env.Logger, + T: t, + } + + _, err := worker.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // The subscription schedules the task that consumes the backlog. + _, err = worker.PollAndProcessWorkflowTask() + require.NoError(t, err) + consumedAt := completedEventWithCursors(t, env.GetHistory(s.ns, execution)) + + var queryTask *workflowservice.PollWorkflowTaskQueueResponse + //nolint:staticcheck // SA1019: consistent with the worker above. + coldWorker := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "cold-worker", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + t.Fatal("the query must arrive as a query task, not a workflow task") + return nil, nil + }, + QueryHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) (*commonpb.Payloads, error) { + queryTask = resp + // Answer from the task alone, which is all a replaying worker has. + var seen []string + for _, slice := range resp.GetStreamSlices() { + for _, record := range slice.GetRecords() { + seen = append(seen, string(record.GetBody().GetData())) + } + } + return payloads.EncodeString(strings.Join(seen, ",")), nil + }, + Logger: env.Logger, + T: t, + } + + type answer struct { + resp *workflowservice.QueryWorkflowResponse + err error + } + answered := make(chan answer, 1) + go func() { + resp, err := env.FrontendClient().QueryWorkflow(s.ctx(), &workflowservice.QueryWorkflowRequest{ + Namespace: s.ns, + Execution: execution, + Query: &querypb.WorkflowQuery{QueryType: "consumed"}, + }) + answered <- answer{resp: resp, err: err} + }() + + res, err := coldWorker.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.True(t, res.IsQueryTask, "the query is dispatched on its own task") + require.NotNil(t, queryTask.GetQuery()) + require.NotEmpty(t, queryTask.GetHistory().GetEvents(), "a non-sticky query carries full history") + + replayed := sliceForEvent(queryTask.GetStreamSlices(), consumedAt) + require.NotNil(t, replayed, "the query task carries the range recorded at event %d", consumedAt) + require.Equal(t, int64(0), replayed.GetFromOffset()) + require.Equal(t, int64(2), replayed.GetToOffset()) + require.Equal(t, execution.GetRunId(), replayed.GetRunId(), "the slice names the run holding the stream") + require.Equal(t, []string{"answer-1", "answer-2"}, apiBodies(replayed.GetRecords())) + + // Nothing on a query task is about to be consumed, so every slice is a + // re-supply for a completion the history already holds. + for _, slice := range queryTask.GetStreamSlices() { + require.NotZero(t, slice.GetWorkflowTaskCompletedEventId(), + "a query task must not carry an untagged slice, it starts no task") + } + + got := <-answered + require.NoError(t, got.err) + var result string + require.NoError(t, payloads.Decode(got.resp.GetQueryResult(), &result)) + require.Equal(t, "answer-1,answer-2", result, + "the query answer is computed from the re-supplied records") +} diff --git a/tests/stream_rejection_test.go b/tests/stream_rejection_test.go new file mode 100644 index 00000000000..be463629351 --- /dev/null +++ b/tests/stream_rejection_test.go @@ -0,0 +1,236 @@ +package tests + +import ( + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/api/workflowservice/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/tests/testcore" +) + +// A refused publish has to fail the workflow task with a cause, not the +// completion call. Failing the call leaves the worker retrying the same command +// against the same limit until the task times out, with nothing in History +// saying why. +func TestOverLimitPublishFailsTheWorkflowTask(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-reject-publish-") + + tooMany := make([]string, chasmstream.MaxRecordsPerBatch+1) + for i := range tooMany { + tooMany[i] = "x" + } + task := 0 + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 1 { + return publishCommand(tooMany...), nil + } + return publishCommand("fits"), nil + }, + Logger: env.Logger, + T: t, + } + + _, err := poller.PollAndProcessWorkflowTask() + require.Error(t, err, "the completion is rejected") + require.ErrorContains(t, err, "exceeds the limit") + + events := env.GetHistory(s.ns, execution) + failed := workflowTaskFailedWith(events, + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_APPEND_STREAM_RECORDS_ATTRIBUTES) + require.NotNil(t, failed, "the refusal is a workflow task failure with its own cause") + require.ErrorContains(t, err, failed.GetFailure().GetMessage()) + + desc, err := s.client.DescribeWorkflowStream(s.ctx(), &streamlib.DescribeWorkflowStreamRequest{ + FrontendRequest: &streamlib.DescribeWorkflowStreamInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + }, + }) + require.NoError(t, err) + require.Equal(t, int64(0), desc.GetFrontendResponse().GetState().GetHeadOffset(), + "a refused publish appends nothing") + + // The next attempt is a fresh task, and a publish that fits lands at the + // start of the stream. + _, err = poller.PollAndProcessWorkflowTask(testcore.WithExpectedAttemptCount(2)) + require.NoError(t, err) + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"fits"}, bodies(poll.GetFrontendResponse().GetRecords())) + require.Equal(t, []int64{0}, offsets(poll.GetFrontendResponse().GetRecords())) +} + +// A workflow reads a topic by name before anything has been written to it, so +// the subscribe has to bring the owned stream into being rather than fail the +// task. An outside producer that arrives later appends to that same stream, +// and its records reach the workflow carrying the identity it wrote. +func TestSubscribeToAnUnwrittenNameCreatesTheOwnedStream(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-subscribe-first-") + + name := "inputs-" + uuid.NewString() + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + if len(delivered) == 1 { + return subscribeCommand(name), nil + } + return nil, nil + }, + Logger: env.Logger, + T: t, + } + + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + events := env.GetHistory(s.ns, execution) + require.Nil(t, workflowTaskFailedWith(events, + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SUBSCRIBE_STREAM_ATTRIBUTES)) + subscribed := subscribedEvents(events) + require.Len(t, subscribed, 1) + require.Equal(t, name, subscribed[0].GetStreamId()) + require.Equal(t, int64(0), subscribed[0].GetStartOffset(), "the new stream starts empty") + + _, err = s.client.AddWorkflowMessages(s.ctx(), &streamlib.AddWorkflowMessagesRequest{ + FrontendRequest: &streamlib.AddWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamName: name, + Records: []*streamlib.StreamRecord{ + { + Body: &commonpb.Payload{Data: []byte("hello")}, Topic: name, + ProducerId: "model", Attempt: 2, Sequence: 0, + }, + { + Kind: streampb.STREAM_RECORD_KIND_FINISH, Topic: name, + ProducerId: "model", Attempt: 2, Sequence: -1, + }, + }, + }, + }) + require.NoError(t, err) + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + got := currentSlice(t, delivered[1]) + require.Equal(t, name, got.GetStreamId()) + require.Equal(t, int64(2), got.GetToOffset()) + + records := got.GetRecords() + require.Len(t, records, 2) + require.Equal(t, "hello", string(records[0].GetBody().GetData())) + require.Equal(t, streampb.STREAM_RECORD_KIND_DATA, records[0].GetKind(), + "a record with no kind is data") + require.Equal(t, "model", records[0].GetProducerId()) + require.Equal(t, int64(2), records[0].GetAttempt()) + require.Equal(t, int64(0), records[0].GetSequence()) + require.Equal(t, streampb.STREAM_RECORD_KIND_FINISH, records[1].GetKind(), + "a finish record is delivered like any other") + require.Equal(t, "model", records[1].GetProducerId()) + require.Equal(t, int64(-1), records[1].GetSequence()) +} + +// The guarantee the design is sold on: a publish commits with the workflow +// task, so a task that fails after publishing publishes nothing. +func TestPublishOnAFailedTaskLeavesNoTrace(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-reject-atomic-") + + // A ScheduleActivityTask with no task queue fails command validation, so the + // whole task is failed after the publish command already ran. + invalidTrailer := &commandpb.Command{ + CommandType: enumspb.COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK, + Attributes: &commandpb.Command_ScheduleActivityTaskCommandAttributes{ + ScheduleActivityTaskCommandAttributes: &commandpb.ScheduleActivityTaskCommandAttributes{ + ActivityId: "no-queue", + ActivityType: &commonpb.ActivityType{Name: "noop"}, + }, + }, + } + task := 0 + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 1 { + return append(publishCommand("lost-with-the-task"), invalidTrailer), nil + } + return publishCommand("first-to-land"), nil + }, + Logger: env.Logger, + T: t, + } + + _, err := poller.PollAndProcessWorkflowTask() + require.Error(t, err) + + events := env.GetHistory(s.ns, execution) + require.NotNil(t, workflowTaskFailedWith(events, + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_ACTIVITY_ATTRIBUTES)) + for _, e := range events { + require.Nil(t, e.GetWorkflowStreamRecordsAppendedEventAttributes(), + "a publish on a failed task leaves no event") + } + desc, err := s.client.DescribeWorkflowStream(s.ctx(), &streamlib.DescribeWorkflowStreamRequest{ + FrontendRequest: &streamlib.DescribeWorkflowStreamInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + }, + }) + require.NoError(t, err) + require.Equal(t, int64(0), desc.GetFrontendResponse().GetState().GetHeadOffset()) + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Empty(t, poll.GetFrontendResponse().GetRecords()) + + // The retry's publish is the first thing the stream ever holds. + _, err = poller.PollAndProcessWorkflowTask(testcore.WithExpectedAttemptCount(2)) + require.NoError(t, err) + poll, err = s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"first-to-land"}, bodies(poll.GetFrontendResponse().GetRecords())) + require.Equal(t, []int64{0}, offsets(poll.GetFrontendResponse().GetRecords())) +} diff --git a/tests/stream_replay_test.go b/tests/stream_replay_test.go new file mode 100644 index 00000000000..fbd8952e0a8 --- /dev/null +++ b/tests/stream_replay_test.go @@ -0,0 +1,349 @@ +package tests + +import ( + "context" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common/dynamicconfig" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/protobuf/types/known/durationpb" +) + +// startConsumer starts a workflow on its own task queue and returns the +// execution and the queue. +func startConsumer( + t *testing.T, s *streamTestEnv, prefix string, +) (*commonpb.WorkflowExecution, *taskqueuepb.TaskQueue) { + t.Helper() + id := prefix + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + we, err := s.env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + return &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}, tq +} + +func publishCommand(bodies ...string) []*commandpb.Command { + messages := make([]*streampb.StreamRecord, len(bodies)) + for i, b := range bodies { + messages[i] = &streampb.StreamRecord{Body: &commonpb.Payload{Data: []byte(b)}, Topic: "tokens"} + } + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: messages, + }, + }, + }} +} + +func apiBodies(msgs []*streampb.StreamRecord) []string { + out := make([]string, len(msgs)) + for i, m := range msgs { + out[i] = string(m.GetBody().GetData()) + } + return out +} + +// completedEventsWithCursors returns the ids of every WorkflowTaskCompleted +// event that recorded a consumed range, empty ones included. +func completedEventsWithCursors(events []*historypb.HistoryEvent) []int64 { + var out []int64 + for _, e := range events { + if len(e.GetWorkflowTaskCompletedEventAttributes().GetConsumedStreamRanges()) > 0 { + out = append(out, e.GetEventId()) + } + } + return out +} + +// The response to a started task carries one page of history. A consumer that +// has run longer than a page recorded its ranges on the pages after it, and a +// cold replay has to find every one of them or the worker replays against less +// than the first run saw. +func TestReplayFollowsHistoryPastTheFirstPage(t *testing.T) { + env := testcore.NewEnv(t, + testcore.WithDedicatedCluster(), + testcore.WithDynamicConfig(dynamicconfig.HistoryMaxPageSize, 4), + ) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-paged-replay-") + + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + if len(delivered) == 1 { + return publishCommand("page-1", "page-2"), nil + } + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // One task consumes the range, then several idle tasks push the event that + // recorded it well behind the first page of history. + for range 4 { + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + } + require.Len(t, currentSlice(t, delivered[1]).GetRecords(), 2) + + events := env.GetHistory(s.ns, execution) + recordedAt := completedEventsWithCursors(events) + require.Len(t, recordedAt, 4, "every task since the subscription recorded a range") + consumedAt := completedEventWithCursors(t, events) + require.Greater(t, len(events), 8, + "the history has to span more than one page for this to mean anything") + + env.CloseShard(env.NamespaceID().String(), execution.GetWorkflowId()) + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + replay := delivered[len(delivered)-1] + replayed := sliceForEvent(replay, consumedAt) + require.NotNil(t, replayed, "the range recorded on a later page must be re-supplied") + require.Equal(t, []string{"page-1", "page-2"}, apiBodies(replayed.GetRecords())) + require.Equal(t, execution.GetRunId(), replayed.GetRunId(), + "an owned stream's slice names the run that holds it") + for _, eventID := range recordedAt { + require.NotNil(t, sliceForEvent(replay, eventID), + "every recorded range, empty ones included, has to travel with its event") + } +} + +// pollInBackground keeps a poller on the queue until the returned stop +// function is called. Used where a task is expected never to reach the worker, +// because matching only asks history to start a task while someone polls. +func pollInBackground( + t *testing.T, env *testcore.TestEnv, ns string, tq *taskqueuepb.TaskQueue, +) func() { + t.Helper() + ctx, cancel := context.WithCancel(context.Background()) + done := make(chan struct{}) + go func() { + defer close(done) + for ctx.Err() == nil { + pollCtx, pollCancel := context.WithTimeout(ctx, 5*time.Second) + _, _ = env.FrontendClient().PollWorkflowTaskQueue( + pollCtx, + &workflowservice.PollWorkflowTaskQueueRequest{ + Namespace: ns, TaskQueue: tq, Identity: "tester", + }, + ) + pollCancel() + } + }() + return func() { + cancel() + <-done + } +} + +func workflowTaskFailedWith( + events []*historypb.HistoryEvent, + cause enumspb.WorkflowTaskFailedCause, +) *historypb.WorkflowTaskFailedEventAttributes { + for _, e := range events { + if attrs := e.GetWorkflowTaskFailedEventAttributes(); attrs != nil && attrs.GetCause() == cause { + return attrs + } + } + return nil +} + +// deleteStreamAndWait removes a standalone stream and waits until reads of it +// fail, since deletion completes in a task after the call returns. +func deleteStreamAndWait(t *testing.T, s *streamTestEnv, streamID string) { + t.Helper() + _, err := s.client.DeleteStream(s.ctx(), &streamlib.DeleteStreamRequest{ + FrontendRequest: &streamlib.DeleteStreamInput{ + Namespace: s.ns, StreamId: streamID, Force: true, + }, + }) + require.NoError(t, err) + await.RequireTrue(t, func() bool { + _, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + return err != nil + }, 20*time.Second, 100*time.Millisecond) +} + +// A consumer whose stream is gone before its next task starts cannot be handed +// the range it is due. That has to land in History as a failed task with a +// cause, not as a request matching retries forever. +func TestConsumerOfADeletedStreamFailsItsTaskLoudly(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "gone-live-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + execution, tq := startConsumer(t, s, "stream-wf-gone-live-") + + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // The append schedules the task that is owed the range. + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, Records: streamMsgs("tokens", "never-delivered"), + }, + }) + require.NoError(t, err) + await.RequireTrue(t, func() bool { + scheduled := 0 + for _, e := range env.GetHistory(s.ns, execution) { + if e.GetEventType() == enumspb.EVENT_TYPE_WORKFLOW_TASK_SCHEDULED { + scheduled++ + } + } + return scheduled >= 2 + }, 20*time.Second, 100*time.Millisecond) + + deleteStreamAndWait(t, s, streamID) + + stop := pollInBackground(t, env, s.ns, tq) + defer stop() + await.RequireTrue(t, func() bool { + return workflowTaskFailedWith(env.GetHistory(s.ns, execution), + enumspb.WORKFLOW_TASK_FAILED_CAUSE_STREAM_RANGE_UNAVAILABLE) != nil + }, 30*time.Second, 200*time.Millisecond) + + failed := workflowTaskFailedWith(env.GetHistory(s.ns, execution), + enumspb.WORKFLOW_TASK_FAILED_CAUSE_STREAM_RANGE_UNAVAILABLE) + require.Contains(t, failed.GetFailure().GetMessage(), streamID, + "the failure names the stream so an operator knows where to look") +} + +// A consumer whose recorded range can no longer be re-read cannot replay. The +// replay runs after the task started, so the failure is a transaction of its +// own, and it still has to end up in History with the cause. +func TestReplayOfADeletedStreamFailsTheTaskLoudly(t *testing.T) { + env := testcore.NewEnv(t, testcore.WithDedicatedCluster()) + s := newStreamTestEnvFrom(t, env) + + streamID := "gone-replay-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + execution, tq := startConsumer(t, s, "stream-wf-gone-replay-") + + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + _, err = s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, Records: streamMsgs("tokens", "consumed-once"), + }, + }) + require.NoError(t, err) + + // Consumed and recorded, which is what a replay will have to reproduce. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.Len(t, currentSlice(t, delivered[1]).GetRecords(), 1) + + deleteStreamAndWait(t, s, streamID) + + env.CloseShard(env.NamespaceID().String(), execution.GetWorkflowId()) + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + + stop := pollInBackground(t, env, s.ns, tq) + defer stop() + await.RequireTrue(t, func() bool { + return workflowTaskFailedWith(env.GetHistory(s.ns, execution), + enumspb.WORKFLOW_TASK_FAILED_CAUSE_STREAM_RANGE_UNAVAILABLE) != nil + }, 30*time.Second, 200*time.Millisecond) + + failed := workflowTaskFailedWith(env.GetHistory(s.ns, execution), + enumspb.WORKFLOW_TASK_FAILED_CAUSE_STREAM_RANGE_UNAVAILABLE) + require.Contains(t, failed.GetFailure().GetMessage(), "cannot replay") + require.Contains(t, failed.GetFailure().GetMessage(), streamID) +} diff --git a/tests/stream_reset_test.go b/tests/stream_reset_test.go new file mode 100644 index 00000000000..b6a48d523c9 --- /dev/null +++ b/tests/stream_reset_test.go @@ -0,0 +1,310 @@ +package tests + +import ( + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + "go.temporal.io/api/workflowservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// nthCompletedEvent returns the id of the n-th WorkflowTaskCompleted event, +// counting from one. +func nthCompletedEvent(t *testing.T, events []*historypb.HistoryEvent, n int) int64 { + t.Helper() + seen := 0 + for _, e := range events { + if e.GetEventType() == enumspb.EVENT_TYPE_WORKFLOW_TASK_COMPLETED { + seen++ + if seen == n { + return e.GetEventId() + } + } + } + t.Fatalf("history has %d completed tasks, wanted %d", seen, n) + return 0 +} + +func resetTo( + t *testing.T, s *streamTestEnv, execution *commonpb.WorkflowExecution, eventID int64, +) string { + t.Helper() + resp, err := s.env.FrontendClient().ResetWorkflowExecution(s.ctx(), + &workflowservice.ResetWorkflowExecutionRequest{ + Namespace: s.ns, + WorkflowExecution: execution, + Reason: "stream reset test", + WorkflowTaskFinishEventId: eventID, + RequestId: uuid.NewString(), + }) + require.NoError(t, err) + return resp.GetRunId() +} + +// A reset copies the base run's history into a new run, and that history +// records ranges the base run consumed from a stream it owned. The reset run +// replays them from the base run's stream, with each slice naming that run, +// and from the reset point on it consumes and publishes on a stream of its own +// that continues the offset space where the inherited cursor stood. +func TestResetReplaysTheBaseRunsRangesAndGoesOnWithItsOwnStream(t *testing.T) { + // Dedicated, because the cold replay at the end evicts the cached + // workflow context through CloseShard. + env := testcore.NewEnv(t, testcore.WithDedicatedCluster()) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-reset-") + + var delivered [][]*streampb.StreamSlice + var commands [][]*commandpb.Command + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + next := commands[0] + commands = commands[1:] + return next, nil + }, + Logger: env.Logger, + T: t, + } + runTask := func(cmds []*commandpb.Command) []*streampb.StreamSlice { + t.Helper() + commands = append(commands, cmds) + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + return delivered[len(delivered)-1] + } + + // Base run: publish two, subscribe, consume them, publish a third, consume it. + runTask(publishCommand("before-1", "before-2")) + _, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + require.NoError(t, err) + consumed := currentSlice(t, runTask(nil)) + require.Equal(t, []string{"before-1", "before-2"}, apiBodies(consumed.GetRecords())) + + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + runTask(publishCommand("before-3")) + third := currentSlice(t, runTask(nil)) + require.Equal(t, []string{"before-3"}, apiBodies(third.GetRecords())) + + baseEvents := env.GetHistory(s.ns, execution) + consumedAt := completedEventWithCursors(t, baseEvents) + + // Reset to the third task: the reset run keeps the first two completions, + // so its cursor stands at offset 2 and nothing of the third publish is its. + resetRunID := resetTo(t, s, execution, nthCompletedEvent(t, baseEvents, 3)) + resetRun := &commonpb.WorkflowExecution{WorkflowId: execution.GetWorkflowId(), RunId: resetRunID} + + // The reset run's first task replays the range recorded before the reset + // point from the base run's stream, and consumes nothing new of its own. + first := runTask(nil) + replayed := sliceForEvent(first, consumedAt) + require.NotNil(t, replayed, "the copied completion at event %d is re-supplied", consumedAt) + require.Equal(t, execution.GetRunId(), replayed.GetRunId(), + "a range recorded before the reset point is read from the base run") + require.Equal(t, int64(0), replayed.GetFromOffset()) + require.Equal(t, int64(2), replayed.GetToOffset()) + require.Equal(t, []string{"before-1", "before-2"}, apiBodies(replayed.GetRecords())) + live := currentSlice(t, first) + require.Equal(t, resetRunID, live.GetRunId(), + "from the reset point on the stream is the reset run's") + require.Equal(t, int64(2), live.GetFromOffset(), "the inherited cursor keeps its position") + require.Equal(t, int64(2), live.GetToOffset()) + + // The reset run publishes and consumes on its own stream, whose offsets + // continue from where the cursor stood. + signalWorkflow(t, s, execution.GetWorkflowId(), resetRunID) + runTask(publishCommand("after-1")) + own := currentSlice(t, runTask(nil)) + require.Equal(t, resetRunID, own.GetRunId()) + require.Equal(t, int64(2), own.GetFromOffset()) + require.Equal(t, int64(3), own.GetToOffset()) + require.Equal(t, []string{"after-1"}, apiBodies(own.GetRecords())) + + // Seen from outside: the base run still holds every record its history + // refers to, and the reset run's stream starts at the inherited offset. + basePoll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + OwnerRunId: execution.GetRunId(), FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"before-1", "before-2", "before-3"}, + bodies(basePoll.GetFrontendResponse().GetRecords())) + + resetPoll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + OwnerRunId: resetRunID, FromOffset: 2, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"after-1"}, bodies(resetPoll.GetFrontendResponse().GetRecords())) + require.Equal(t, []int64{2}, offsets(resetPoll.GetFrontendResponse().GetRecords())) + + _, err = s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + OwnerRunId: resetRunID, FromOffset: 0, + }, + }) + require.Equal(t, codes.FailedPrecondition, status.Code(err), + "a reader following the chain into the reset run has to start at the offset it begins at") + + // A cold replay of the reset run re-supplies both eras from the runs that + // hold them, tagged with the completions that recorded them. + env.CloseShard(env.NamespaceID().String(), execution.GetWorkflowId()) + signalWorkflow(t, s, execution.GetWorkflowId(), resetRunID) + cold := runTask(nil) + fromBase := sliceForEvent(cold, consumedAt) + require.NotNil(t, fromBase) + require.Equal(t, execution.GetRunId(), fromBase.GetRunId()) + require.Equal(t, []string{"before-1", "before-2"}, apiBodies(fromBase.GetRecords())) + ownAt := completedEventWithCursorsAfter(t, env.GetHistory(s.ns, resetRun), consumedAt) + fromReset := sliceForEvent(cold, ownAt) + require.NotNil(t, fromReset) + require.Equal(t, resetRunID, fromReset.GetRunId()) + require.Equal(t, int64(2), fromReset.GetFromOffset()) + require.Equal(t, int64(3), fromReset.GetToOffset()) + require.Equal(t, []string{"after-1"}, apiBodies(fromReset.GetRecords())) + + // The base run names its successor, which is how a client following the + // chain finds the reset run. + described, err := env.FrontendClient().DescribeWorkflowExecution(s.ctx(), + &workflowservice.DescribeWorkflowExecutionRequest{Namespace: s.ns, Execution: execution}) + require.NoError(t, err) + require.Equal(t, enumspb.WORKFLOW_EXECUTION_STATUS_TERMINATED, + described.GetWorkflowExecutionInfo().GetStatus()) + require.Equal(t, resetRunID, described.GetWorkflowExtendedInfo().GetResetRunId()) +} + +// completedEventWithCursorsAfter returns the id of the first WorkflowTaskCompleted +// event after the given one that recorded a non-empty consumed range. +func completedEventWithCursorsAfter( + t *testing.T, events []*historypb.HistoryEvent, after int64, +) int64 { + t.Helper() + for _, e := range events { + if e.GetEventId() <= after { + continue + } + for _, c := range e.GetWorkflowTaskCompletedEventAttributes().GetConsumedStreamRanges() { + if c.GetToOffset() > c.GetFromOffset() { + return e.GetEventId() + } + } + } + t.Fatal("no completed event after the given one recorded a consumed range") + return 0 +} + +// A reset terminates the base run. Its pin on a stream in another execution is +// released the way a closed run's is, when the stream next tells its consumers +// the frontier moved and finds the run over, and the reset run, which carries +// the subscription on, takes the pin over with the floor its cursor began at. +func TestResetHandsTheExternalPinToTheResetRun(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "reset-shared-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + execution, tq := startConsumer(t, s, "stream-wf-reset-ext-") + + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + return nil, nil + }, + Logger: env.Logger, + T: t, + } + runTask := func() []*streampb.StreamSlice { + t.Helper() + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + return delivered[len(delivered)-1] + } + + runTask() + _, err := s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + _, err = s.add(s.ctx(), t, streamID, + &streamlib.AddMessagesInput{Records: streamMsgs("t", "one", "two")}) + require.NoError(t, err) + consumed := currentSlice(t, runTask()) + require.Equal(t, int64(2), consumed.GetToOffset()) + + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + runTask() + baseEvents := env.GetHistory(s.ns, execution) + consumedAt := completedEventWithCursors(t, baseEvents) + + resetRunID := resetTo(t, s, execution, nthCompletedEvent(t, baseEvents, 3)) + + // The reset run replays the base run's range from the standalone stream + // and stands at the same offset. + first := runTask() + replayed := sliceForEvent(first, consumedAt) + require.NotNil(t, replayed) + require.Equal(t, []string{"one", "two"}, apiBodies(replayed.GetRecords())) + require.Equal(t, int64(2), currentSlice(t, first).GetFromOffset()) + + // The pin is still the base run's until the stream next notifies. + before := describeStream(t, s, streamID) + require.Len(t, before.GetConsumers(), 1) + for _, consumer := range before.GetConsumers() { + require.Equal(t, execution.GetRunId(), consumer.GetRunId()) + } + + // An append pushes the frontier at the pinned run, finds it terminated, and + // hands the pin to the run that now carries the subscription. + _, err = s.add(s.ctx(), t, streamID, + &streamlib.AddMessagesInput{Records: streamMsgs("t", "three")}) + require.NoError(t, err) + afterReset := currentSlice(t, runTask()) + require.Equal(t, int64(2), afterReset.GetFromOffset(), + "the reset run resumes where the base stopped") + require.Equal(t, int64(3), afterReset.GetToOffset()) + require.Equal(t, []string{"three"}, apiBodies(afterReset.GetRecords())) + + after := describeStream(t, s, streamID) + require.Len(t, after.GetConsumers(), 1, "one pin, keyed to the run that consumes") + for _, consumer := range after.GetConsumers() { + require.Equal(t, resetRunID, consumer.GetRunId()) + require.Equal(t, int64(0), consumer.GetReplayFloor(), + "the floor is where the inherited subscription began, which its replay depends on") + } +} diff --git a/tests/stream_retention_test.go b/tests/stream_retention_test.go new file mode 100644 index 00000000000..1d4bb3d9c5e --- /dev/null +++ b/tests/stream_retention_test.go @@ -0,0 +1,272 @@ +package tests + +import ( + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/durationpb" +) + +// A range a workflow consumed is part of that workflow's recovery: the offsets +// are in its History and a replay is asked to reproduce them from the stream. +// Deleting those messages succeeds immediately and fails much later, during a +// replay nobody is watching, so the stream refuses instead. +func TestTruncationRefusesToDropWhatAConsumerNeedsToReplay(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "retained-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + _, err := s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("one")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + {Body: &commonpb.Payload{Data: []byte("two")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + {Body: &commonpb.Payload{Data: []byte("three")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + }, + }, + }) + require.NoError(t, err) + + id := "stream-retention-wf-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + _, err = env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + _ *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: id, StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + // The floor is where the subscription started. It holds from the moment of + // subscribing, before anything has been delivered, because the first range + // the workflow will record begins there. + truncate := func() error { + _, err := s.client.TruncateStream(s.ctx(), &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: streamID, NewBaseOffset: 2, + }, + }) + return err + } + require.ErrorContains(t, truncate(), "still depends on offset 0") + + // Delivering and recording the range does not move the floor either. + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + require.ErrorContains(t, truncate(), "still depends on offset 0") + + desc, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + state := desc.GetFrontendResponse().GetState() + require.Equal(t, int64(0), state.GetBaseOffset(), "the messages must still be there") + for _, consumer := range state.GetConsumers() { + require.Equal(t, int64(0), consumer.GetReplayFloor(), + "the floor is where the subscription started, not where it has read to") + } +} + +// The refusal is about a consumer's recovery, so a stream nobody is consuming +// truncates exactly as before. Without this, the fix would be a storage leak +// wearing a correctness argument. +func TestTruncationStillWorksWithNoConsumer(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "unwatched-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + _, err := s.client.AddMessages(s.ctx(), &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: s.ns, StreamId: streamID, + Records: []*streamlib.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("one")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + {Body: &commonpb.Payload{Data: []byte("two")}, Kind: streampb.STREAM_RECORD_KIND_DATA}, + }, + }, + }) + require.NoError(t, err) + + _, err = s.client.TruncateStream(s.ctx(), &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: streamID, NewBaseOffset: 2, + }, + }) + require.NoError(t, err) + + desc, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + require.Equal(t, int64(2), desc.GetFrontendResponse().GetState().GetBaseOffset()) +} + +// A closed stream past its retention is still held by a consumer that is +// running: its History depends on the ranges it consumed. Deletion waits and +// asks again, and goes through once the consumer is gone. +func TestRetentionWaitsForAnActiveConsumer(t *testing.T) { + env := testcore.NewEnv(t, + testcore.WithDynamicConfig(chasmstream.RetentionRecheckIntervalSetting, time.Second), + ) + s := newStreamTestEnvFrom(t, env) + + streamID := "retained-until-read-" + uuid.NewString() + _, err := s.client.CreateStream(s.ctx(), &streamlib.CreateStreamRequest{ + FrontendRequest: &streamlib.CreateStreamInput{ + Namespace: s.ns, StreamId: streamID, + Lifecycle: &streamlib.StreamLifecycle{Retention: durationpb.New(time.Second)}, + }, + }) + require.NoError(t, err) + + execution, tq := startConsumer(t, s, "stream-wf-retained-") + task := 0 + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 2 { + return completeWorkflowCommand(), nil + } + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + _, err = s.client.CloseStream(s.ctx(), &streamlib.CloseStreamRequest{ + FrontendRequest: &streamlib.CloseStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) + + // Well past retention, and the stream is still there because the consumer + // is still running. The assertion is that nothing happens, which only the + // deadline passing can show. + time.Sleep(3 * time.Second) //nolint:forbidigo // waiting for retention to elapse is the test. + state := describeStream(t, s, streamID) + require.True(t, state.GetClosed()) + require.Len(t, state.GetConsumers(), 1) + + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + // The next recheck finds the consumer gone and lets retention through. + await.RequireTrue(t, func() bool { + _, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + return err != nil + }, 20*time.Second, 200*time.Millisecond) +} + +// Deleting a stream a running workflow consumes succeeds now and fails that +// workflow at its next replay, so the caller has to say it means it. +func TestDeleteStreamRefusesWhileAConsumerIsActive(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + streamID := "guarded-stream-" + uuid.NewString() + s.create(s.ctx(), t, streamID) + execution, tq := startConsumer(t, s, "stream-wf-guarded-") + //nolint:staticcheck // SA1019: consistent with the other stream tests. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return nil, nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + _, err = s.client.SubscribeWorkflow(s.ctx(), &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), StreamId: streamID, StartOffset: 0, + }, + }) + require.NoError(t, err) + + _, err = s.client.DeleteStream(s.ctx(), &streamlib.DeleteStreamRequest{ + FrontendRequest: &streamlib.DeleteStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.Equal(t, codes.FailedPrecondition, status.Code(err)) + require.ErrorContains(t, err, execution.GetWorkflowId(), "the refusal names the consumer") + + _, err = s.client.DeleteStream(s.ctx(), &streamlib.DeleteStreamRequest{ + FrontendRequest: &streamlib.DeleteStreamInput{Namespace: s.ns, StreamId: streamID, Force: true}, + }) + require.NoError(t, err) + await.RequireTrue(t, func() bool { + _, err := s.client.DescribeStream(s.ctx(), &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + return err != nil + }, 20*time.Second, 100*time.Millisecond) +} diff --git a/tests/stream_routing_cross_host_test.go b/tests/stream_routing_cross_host_test.go new file mode 100644 index 00000000000..f2bf31a3ee4 --- /dev/null +++ b/tests/stream_routing_cross_host_test.go @@ -0,0 +1,384 @@ +package tests + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + "go.temporal.io/server/api/adminservice/v1" + "go.temporal.io/server/api/historyservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/common/testing/testlogger" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" +) + +// crossHostTopology is a two-host History cluster with the shards it was +// confirmed to split, plus the consumer and source shards each case uses. +type crossHostTopology struct { + cluster *testcore.TestCluster + config *testcore.TestClusterConfig + ns string + nsID string + consumerHost string + remoteHost string + consumerShard int32 + localSource int32 + remoteSource int32 +} + +// A consumer on one History host reading a stream that lives on another. Every +// step that spans the two executions has to route rather than resolve the far +// shard locally: registering the pin, being told the frontier moved, reading +// the payload for the live task, and re-reading it for a cold replay. +// +// The subscription is made two ways, over the RPC and from the workflow's own +// command, because they take different paths to the stream's shard. +func TestStreamRoutedCrossHostDeliveryAndReplay(t *testing.T) { + logger := testlogger.NewTestLogger(t, testlogger.FailOnExpectedErrorOnly) + topo := newCrossHostTopology(t, logger) + artifacts := newRoutingArtifacts(t) + + ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) + defer cancel() + artifacts.writeJSON("topology", topo.shardsByHost(ctx, t)) + + frontend := topo.cluster.FrontendClient() + conn, err := grpc.NewClient(topo.cluster.Host().FrontendGRPCAddress(), + grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, conn.Close()) }) + streams := streamlib.NewStreamServiceClient(conn) + + ownerConn, err := grpc.NewClient(topo.consumerHost, + grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, ownerConn.Close()) }) + owner := historyservice.NewHistoryServiceClient(ownerConn) + + cases := []struct { + name string + crossHost bool + viaCommand bool + }{ + {name: "same-host", crossHost: false}, + {name: "cross-host", crossHost: true}, + {name: "cross-host-command", crossHost: true, viaCommand: true}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + id := topo.idOnShard(t, tc.name+"-consumer", topo.consumerShard) + source := topo.idOnShard(t, tc.name+"-source", topo.sourceShard(tc.crossHost)) + _, err := streams.CreateStream(ctx, &streamlib.CreateStreamRequest{ + FrontendRequest: &streamlib.CreateStreamInput{Namespace: topo.ns, StreamId: source}, + }) + require.NoError(t, err) + + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + started, err := frontend.StartWorkflowExecution( + ctx, + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: topo.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "cross-host-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(2 * time.Minute), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + }, + ) + require.NoError(t, err) + execution := &commonpb.WorkflowExecution{WorkflowId: id, RunId: started.GetRunId()} + + var delivered [][]*streampb.StreamSlice + //nolint:staticcheck // SA1019: this test isolates the server response from SDK replay. + poller := &testcore.TaskPoller{ + Client: frontend, + Namespace: topo.ns, + TaskQueue: tq, + Identity: "cross-host-validation", + Logger: logger, + T: t, + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + delivered = append(delivered, resp.GetStreamSlices()) + if tc.viaCommand && len(delivered) == 1 { + return subscribeCommand(source), nil + } + return nil, nil + }, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + topo.requireOwner(ctx, t, id, topo.consumerHost) + topo.requireOwner(ctx, t, source, topo.hostFor(tc.crossHost)) + + if !tc.viaCommand { + _, err = streams.SubscribeWorkflow(ctx, &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: topo.ns, WorkflowId: id, StreamId: source, + }, + }) + require.NoError(t, err) + } + // Either way the pin has to have landed on the stream's own shard. + desc, err := streams.DescribeStream(ctx, &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: topo.ns, StreamId: source}, + }) + require.NoError(t, err) + require.Len(t, desc.GetFrontendResponse().GetState().GetConsumers(), 1) + + _, err = streams.AddMessages(ctx, &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: topo.ns, StreamId: source, + Records: streamMsgs("tokens", "retained-input"), + }, + }) + require.NoError(t, err) + + history := func() []*historypb.HistoryEvent { + return topo.history(ctx, t, execution) + } + latestScheduled := func() int64 { + var scheduled int64 + for _, event := range history() { + if event.GetEventType() == enumspb.EVENT_TYPE_WORKFLOW_TASK_SCHEDULED { + scheduled = event.GetEventId() + } + } + return scheduled + } + // The append alone has to produce the task, through the routed push. + await.RequireTrue(t, func() bool { return latestScheduled() > 2 }, + 10*time.Second, 20*time.Millisecond) + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + live := currentSlice(t, delivered[1]) + require.Equal(t, "retained-input", string(live.GetRecords()[0].GetBody().GetData())) + artifacts.writeProto(tc.name+"-live-slice", live) + artifacts.writeProto(tc.name+"-committed-history", &historypb.History{Events: history()}) + consumedAt := completedEventWithCursors(t, history()) + + // Evict the consumer, then start its next task by hand so the cold + // response can be inspected before matching hands it to a poller. + _, err = owner.CloseShard(ctx, &historyservice.CloseShardRequest{ShardId: topo.consumerShard}) + require.NoError(t, err) + _, err = frontend.SignalWorkflowExecution(ctx, &workflowservice.SignalWorkflowExecutionRequest{ + Namespace: topo.ns, + WorkflowExecution: execution, + SignalName: "cold-replay-boundary", + RequestId: uuid.NewString(), + }) + require.NoError(t, err) + response, err := owner.RecordWorkflowTaskStarted( + ctx, + &historyservice.RecordWorkflowTaskStartedRequest{ + NamespaceId: topo.nsID, + WorkflowExecution: execution, + ScheduledEventId: latestScheduled(), + RequestId: uuid.NewString(), + PollRequest: &workflowservice.PollWorkflowTaskQueueRequest{ + Namespace: topo.ns, TaskQueue: tq, Identity: "cross-host-validation", + }, + }, + ) + require.NoError(t, err) + artifacts.writeProto(tc.name+"-cold-response", response) + + replayed := sliceForEvent(response.GetStreamSlices(), consumedAt) + require.NotNil(t, replayed, "cold replay must re-supply the committed input range") + require.Equal(t, "retained-input", string(replayed.GetRecords()[0].GetBody().GetData())) + }) + } +} + +func subscribeCommand(streamID string) []*commandpb.Command { + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_SUBSCRIBE_STREAM, + Attributes: &commandpb.Command_SubscribeStreamCommandAttributes{ + SubscribeStreamCommandAttributes: &commandpb.SubscribeStreamCommandAttributes{ + StreamId: streamID, StartOffset: 0, + }, + }, + }} +} + +func newCrossHostTopology(t *testing.T, logger *testlogger.TestLogger) *crossHostTopology { + t.Helper() + config := &testcore.TestClusterConfig{ + HistoryConfig: testcore.HistoryConfig{NumHistoryHosts: 2, NumHistoryShards: 32}, + Persistence: testcore.GetPersistenceTestDefaults(), + WorkerConfig: testcore.WorkerConfig{DisableWorker: true}, + } + cluster, err := testcore.NewTestClusterFactory().NewCluster(t, config, logger) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, cluster.TearDownCluster()) }) + + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + frontend := cluster.FrontendClient() + ns := "validation-cross-host-" + uuid.NewString() + _, err = frontend.RegisterNamespace(ctx, &workflowservice.RegisterNamespaceRequest{ + Namespace: ns, WorkflowExecutionRetentionPeriod: durationpb.New(24 * time.Hour), + }) + require.NoError(t, err) + described, err := frontend.DescribeNamespace(ctx, &workflowservice.DescribeNamespaceRequest{ + Namespace: ns, + }) + require.NoError(t, err) + + topo := &crossHostTopology{ + cluster: cluster, + config: config, + ns: ns, + nsID: described.GetNamespaceInfo().GetId(), + } + hosts := topo.shardsByHost(ctx, t) + require.Len(t, hosts, 2, "must verify two actual owners, not merely configure two services") + for host, shards := range hosts { + if topo.consumerHost == "" && len(shards) >= 2 { + topo.consumerHost, topo.consumerShard, topo.localSource = host, shards[0], shards[1] + } + } + require.NotEmpty(t, topo.consumerHost) + for host, shards := range hosts { + if host != topo.consumerHost { + topo.remoteHost, topo.remoteSource = host, shards[0] + } + } + t.Logf("consumer shard %d on %s, local source shard %d, remote source shard %d on %s", + topo.consumerShard, topo.consumerHost, topo.localSource, topo.remoteSource, topo.remoteHost) + return topo +} + +// shardsByHost asks the admin service who owns every shard. +func (topo *crossHostTopology) shardsByHost(ctx context.Context, t *testing.T) map[string][]int32 { + t.Helper() + hosts := map[string][]int32{} + for shard := int32(1); shard <= topo.config.HistoryConfig.NumHistoryShards; shard++ { + host, err := topo.cluster.AdminClient().DescribeHistoryHost(ctx, + &adminservice.DescribeHistoryHostRequest{ShardId: shard}) + require.NoError(t, err) + require.NotEmpty(t, host.GetAddress()) + hosts[host.GetAddress()] = append(hosts[host.GetAddress()], shard) + } + return hosts +} + +func (topo *crossHostTopology) hostFor(crossHost bool) string { + if crossHost { + return topo.remoteHost + } + return topo.consumerHost +} + +func (topo *crossHostTopology) sourceShard(crossHost bool) int32 { + if crossHost { + return topo.remoteSource + } + return topo.localSource +} + +// idOnShard finds a business id that hashes to the wanted shard. +func (topo *crossHostTopology) idOnShard(t *testing.T, prefix string, target int32) string { + t.Helper() + shards := topo.config.HistoryConfig.NumHistoryShards + for i := range 10000 { + id := fmt.Sprintf("%s-%d", prefix, i) + if common.WorkflowIDToHistoryShard(topo.nsID, id, shards) == target { + return id + } + } + t.Fatal("could not select an id on the target shard") + return "" +} + +func (topo *crossHostTopology) requireOwner( + ctx context.Context, t *testing.T, businessID string, host string, +) { + t.Helper() + desc, err := topo.cluster.AdminClient().DescribeHistoryHost( + ctx, + &adminservice.DescribeHistoryHostRequest{ + Namespace: topo.ns, + WorkflowExecution: &commonpb.WorkflowExecution{WorkflowId: businessID}, + }, + ) + require.NoError(t, err) + require.Equal(t, host, desc.GetAddress()) +} + +func (topo *crossHostTopology) history( + ctx context.Context, t *testing.T, execution *commonpb.WorkflowExecution, +) []*historypb.HistoryEvent { + t.Helper() + resp, err := topo.cluster.FrontendClient().GetWorkflowExecutionHistory(ctx, + &workflowservice.GetWorkflowExecutionHistoryRequest{Namespace: topo.ns, Execution: execution}) + require.NoError(t, err) + require.Empty(t, resp.GetNextPageToken()) + return resp.GetHistory().GetEvents() +} + +// routingArtifacts writes the responses this test observed to a directory, for +// the SDK validation runs that compare them against what a worker receives. Off +// unless the measurement switch is set, like the other evidence collectors. +type routingArtifacts struct { + t *testing.T + dir string +} + +func newRoutingArtifacts(t *testing.T) *routingArtifacts { + t.Helper() + if os.Getenv("TEMPORAL_STREAM_BENCH") != "1" { + return &routingArtifacts{t: t} + } + dir := os.Getenv("AI198_ROUTING_RESULT_DIR") + if dir == "" { + dir = t.TempDir() + } + require.NoError(t, os.MkdirAll(dir, 0o755)) + return &routingArtifacts{t: t, dir: dir} +} + +func (a *routingArtifacts) writeJSON(name string, value any) { + if a.dir == "" { + return + } + encoded, err := json.MarshalIndent(value, "", " ") + require.NoError(a.t, err) + require.NoError(a.t, os.WriteFile(filepath.Join(a.dir, name+".json"), encoded, 0o644)) +} + +func (a *routingArtifacts) writeProto(name string, message proto.Message) { + if a.dir == "" { + return + } + encoded, err := protojson.MarshalOptions{Indent: " "}.Marshal(message) + require.NoError(a.t, err) + require.NoError(a.t, os.WriteFile(filepath.Join(a.dir, name+".json"), encoded, 0o644)) + binary, err := proto.Marshal(message) + require.NoError(a.t, err) + require.NoError(a.t, os.WriteFile(filepath.Join(a.dir, name+".pb"), binary, 0o644)) +} diff --git a/tests/stream_test.go b/tests/stream_test.go new file mode 100644 index 00000000000..9eae35308c3 --- /dev/null +++ b/tests/stream_test.go @@ -0,0 +1,656 @@ +package tests + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + streampb "go.temporal.io/api/stream/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +// End-to-end coverage of the native stream path: append through the frontend, +// read back by offset, and the lifecycle transitions around it. This is the +// path the benchmark will eventually compare against the Signal-and-Update +// baseline in streaming_baseline_test.go. + +const streamMaxBatch = chasmstream.MaxRecordsPerBatch + +type streamTestEnv struct { + env *testcore.TestEnv + client streamlib.StreamServiceClient + ns string + + // Guards cleanup: a test that races outside producers against the + // workflow asks for contexts from several goroutines at once. + mu sync.Mutex + cleanup []func() +} + +func newStreamTestEnv(t *testing.T) *streamTestEnv { + return newStreamTestEnvFrom(t, testcore.NewEnv(t)) +} + +// newStreamTestEnvFrom lets a test that needs its own env, for example one +// driving the raw task poller, still reach the stream API. +func newStreamTestEnvFrom(t *testing.T, env *testcore.TestEnv) *streamTestEnv { + + conn, err := grpc.NewClient(env.FrontendGRPCAddress(), + grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { _ = conn.Close() }) + + env2 := &streamTestEnv{ + env: env, client: streamlib.NewStreamServiceClient(conn), ns: env.Namespace().String(), + } + t.Cleanup(func() { + env2.mu.Lock() + defer env2.mu.Unlock() + for _, c := range env2.cleanup { + c() + } + }) + + return env2 +} + +func (s *streamTestEnv) ctx() context.Context { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + s.mu.Lock() + s.cleanup = append(s.cleanup, cancel) + s.mu.Unlock() + return ctx +} + +func (s *streamTestEnv) create(ctx context.Context, t *testing.T, streamID string) { + t.Helper() + _, err := s.client.CreateStream(ctx, &streamlib.CreateStreamRequest{ + FrontendRequest: &streamlib.CreateStreamInput{Namespace: s.ns, StreamId: streamID}, + }) + require.NoError(t, err) +} + +func (s *streamTestEnv) add( + ctx context.Context, t *testing.T, streamID string, in *streamlib.AddMessagesInput, +) (*streamlib.AddMessagesOutput, error) { + t.Helper() + in.Namespace = s.ns + in.StreamId = streamID + resp, err := s.client.AddMessages(ctx, &streamlib.AddMessagesRequest{FrontendRequest: in}) + if err != nil { + return nil, err + } + return resp.GetFrontendResponse(), nil +} + +func (s *streamTestEnv) poll( + ctx context.Context, t *testing.T, streamID string, from int64, topics ...string, +) *streamlib.PollMessagesOutput { + t.Helper() + resp, err := s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: s.ns, StreamId: streamID, FromOffset: from, Topics: topics, + }, + }) + require.NoError(t, err) + return resp.GetFrontendResponse() +} + +func streamMsgs(topic string, bodies ...string) []*streamlib.StreamRecord { + out := make([]*streamlib.StreamRecord, len(bodies)) + for i, b := range bodies { + out[i] = &streamlib.StreamRecord{ + Body: &commonpb.Payload{Data: []byte(b)}, + Topic: topic, + Kind: streampb.STREAM_RECORD_KIND_DATA, + } + } + return out +} + +func bodies(msgs []*streamlib.StreamRecord) []string { + out := make([]string, len(msgs)) + for i, m := range msgs { + out[i] = string(m.GetBody().GetData()) + } + return out +} + +func streamCtx(t *testing.T) context.Context { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + t.Cleanup(cancel) + return ctx +} + +func TestStreamAppendAndRead(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-append-read" + s.create(ctx, t, id) + + first, err := s.add(ctx, t, id, + &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b", "c")}) + require.NoError(t, err) + require.Equal(t, int64(0), first.GetFirstOffset()) + require.Equal(t, int64(3), first.GetNextOffset()) + + second, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "d")}) + require.NoError(t, err) + require.Equal(t, int64(3), second.GetFirstOffset()) + + all := s.poll(ctx, t, id, 0) + require.Equal(t, []string{"a", "b", "c", "d"}, bodies(all.GetRecords())) + require.Equal(t, int64(4), all.GetNextOffset()) + require.Equal(t, int64(4), all.GetHeadOffset()) + require.False(t, all.GetClosed()) + + // A reader owns its cursor, so resuming mid-stream is just another read. + tail := s.poll(ctx, t, id, 2) + require.Equal(t, []string{"c", "d"}, bodies(tail.GetRecords())) + + // Caught up returns empty rather than erroring. + caughtUp := s.poll(ctx, t, id, 4) + require.Empty(t, caughtUp.GetRecords()) + require.Equal(t, int64(4), caughtUp.GetNextOffset()) +} + +func TestStreamManyReadersAreIndependent(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-many-readers" + s.create(ctx, t, id) + + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b")}) + require.NoError(t, err) + + // No durable per-subscriber state, so reader count is not a state-machine + // concern and there is no equivalent of the 10-subscriber ceiling the + // Signal-and-Update pattern hits. + for range 25 { + got := s.poll(ctx, t, id, 0) + require.Equal(t, []string{"a", "b"}, bodies(got.GetRecords())) + } +} + +func TestStreamProducerDedup(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-dedup" + s.create(ctx, t, id) + + in := &streamlib.AddMessagesInput{ + Records: streamMsgs("", "a", "b"), ProducerId: "p1", Sequence: 1, + } + first, err := s.add(ctx, t, id, in) + require.NoError(t, err) + require.False(t, first.GetDeduplicated()) + + retry, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs("", "a", "b"), ProducerId: "p1", Sequence: 1, + }) + require.NoError(t, err) + require.True(t, retry.GetDeduplicated()) + require.Equal(t, first.GetFirstOffset(), retry.GetFirstOffset()) + + // The retry must not have appended a second copy. + got := s.poll(ctx, t, id, 0) + require.Equal(t, []string{"a", "b"}, bodies(got.GetRecords())) + + // Same sequence with different content is a client bug. Returning the + // recorded offsets would report success while dropping the data. + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs("", "different"), ProducerId: "p1", Sequence: 1, + }) + require.ErrorContains(t, err, "different content") +} + +func TestStreamTopicFilter(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-topics" + s.create(ctx, t, id) + + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("tokens", "t1")}) + require.NoError(t, err) + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("tools", "x1")}) + require.NoError(t, err) + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("tokens", "t2")}) + require.NoError(t, err) + + got := s.poll(ctx, t, id, 0, "tokens") + require.Equal(t, []string{"t1", "t2"}, bodies(got.GetRecords())) + // Offsets are global, so a filtered read still advances past what it skipped. + require.Equal(t, int64(3), got.GetNextOffset()) +} + +func TestStreamFinishWritingIsPerProducer(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-finish" + s.create(ctx, t, id) + + _, err := s.client.FinishWriting(ctx, &streamlib.FinishWritingRequest{ + FrontendRequest: &streamlib.FinishWritingInput{ + Namespace: s.ns, StreamId: id, ProducerId: "p1", + }, + }) + require.NoError(t, err) + + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs("", "a"), ProducerId: "p1", Sequence: 1, + }) + require.Error(t, err) + + // Finishing is per-producer, not a close, so others carry on. + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs("", "b"), ProducerId: "p2", Sequence: 1, + }) + require.NoError(t, err) +} + +func TestStreamCloseAndTruncate(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-lifecycle" + s.create(ctx, t, id) + + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b", "c")}) + require.NoError(t, err) + + _, err = s.client.TruncateStream(ctx, &streamlib.TruncateStreamRequest{ + FrontendRequest: &streamlib.TruncateStreamInput{ + Namespace: s.ns, StreamId: id, NewBaseOffset: 1, + }, + }) + require.NoError(t, err) + + // A reader below the floor gets a distinguishable error carrying the floor, + // so it can jump forward rather than fail. + _, err = s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{Namespace: s.ns, StreamId: id, FromOffset: 0}, + }) + require.ErrorContains(t, err, "truncated") + + _, err = s.client.CloseStream(ctx, &streamlib.CloseStreamRequest{ + FrontendRequest: &streamlib.CloseStreamInput{Namespace: s.ns, StreamId: id}, + }) + require.NoError(t, err) + + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "d")}) + require.Error(t, err) + + // Closed is a state a reader observes, not an error, and the data stays + // readable rather than requiring a shutdown handshake with the producer. + got := s.poll(ctx, t, id, 1) + require.True(t, got.GetClosed()) + require.Equal(t, []string{"b", "c"}, bodies(got.GetRecords())) +} + +func TestStreamReadStartingInsideABatch(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-mid-batch" + s.create(ctx, t, id) + + // One batch covering 0..2, a second covering 3. A node is addressed by the + // first offset of its batch, so reading from 2 has to find the node that + // contains it rather than the node whose ID equals it. Getting that wrong + // silently drops the messages before the boundary. + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b", "c")}) + require.NoError(t, err) + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "d")}) + require.NoError(t, err) + + for from, want := range map[int64][]string{ + 0: {"a", "b", "c", "d"}, + 1: {"b", "c", "d"}, + 2: {"c", "d"}, + 3: {"d"}, + } { + got := s.poll(ctx, t, id, from) + require.Equal(t, want, bodies(got.GetRecords()), "reading from offset %d", from) + require.Equal(t, int64(4), got.GetNextOffset()) + } +} + +func TestStreamBatchSizeIsBounded(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-batch-bound" + s.create(ctx, t, id) + + // The bound is not only admission control: it bounds how far a read has to + // step back to find the node containing an arbitrary offset. + tooMany := make([]string, streamMaxBatch+1) + for i := range tooMany { + tooMany[i] = "x" + } + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", tooMany...)}) + require.ErrorContains(t, err, "exceeds the limit") +} + +func (s *streamTestEnv) pollWait( + ctx context.Context, streamID string, from int64, +) (*streamlib.PollMessagesOutput, error) { + resp, err := s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: s.ns, StreamId: streamID, FromOffset: from, WaitNewMessages: true, + }, + }) + if err != nil { + return nil, err + } + return resp.GetFrontendResponse(), nil +} + +func TestStreamLongPollWakesOnAppend(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-longpoll-append" + s.create(ctx, t, id) + + type result struct { + out *streamlib.PollMessagesOutput + err error + } + done := make(chan result, 1) + go func() { + out, err := s.pollWait(ctx, id, 0) + done <- result{out, err} + }() + + // The poll is parked on an empty stream; the append is what releases it. + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a")}) + require.NoError(t, err) + + select { + case r := <-done: + require.NoError(t, r.err) + require.Equal(t, []string{"a"}, bodies(r.out.GetRecords())) + require.Equal(t, int64(1), r.out.GetNextOffset()) + case <-time.After(25 * time.Second): + t.Fatal("long poll did not wake on append") + } +} + +func TestStreamLongPollWakesOnClose(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-longpoll-close" + s.create(ctx, t, id) + + done := make(chan *streamlib.PollMessagesOutput, 1) + go func() { + out, err := s.pollWait(ctx, id, 0) + if err == nil { + done <- out + } + }() + + _, err := s.client.CloseStream(ctx, &streamlib.CloseStreamRequest{ + FrontendRequest: &streamlib.CloseStreamInput{Namespace: s.ns, StreamId: id}, + }) + require.NoError(t, err) + + // Closing has to release a parked reader, otherwise a consumer of a + // finished stream waits out the full timeout for no reason. + select { + case out := <-done: + require.True(t, out.GetClosed()) + require.Empty(t, out.GetRecords()) + case <-time.After(25 * time.Second): + t.Fatal("long poll did not wake on close") + } +} + +func TestStreamLongPollReturnsEmptyOnTimeout(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-longpoll-timeout" + s.create(ctx, t, id) + + // A timeout is an empty response, not an error: the caller polls again + // rather than distinguishing a quiet stream from a failure. + start := time.Now() + out, err := s.pollWait(ctx, id, 0) + require.NoError(t, err) + require.Empty(t, out.GetRecords()) + require.Equal(t, int64(0), out.GetNextOffset()) + require.False(t, out.GetClosed()) + require.Greater(t, time.Since(start), 5*time.Second, + "the poll should have parked, not returned immediately") +} + +func TestStreamLongPollReturnsImmediatelyWhenBehind(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-longpoll-behind" + s.create(ctx, t, id) + + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b")}) + require.NoError(t, err) + + // Waiting is only for a reader that is caught up. One that is behind must + // not be parked behind data that already exists. + start := time.Now() + out, err := s.pollWait(ctx, id, 0) + require.NoError(t, err) + require.Equal(t, []string{"a", "b"}, bodies(out.GetRecords())) + require.Less(t, time.Since(start), 5*time.Second) +} + +func TestStreamCapTruncatesAndReclaims(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-cap" + + _, err := s.client.CreateStream(ctx, &streamlib.CreateStreamRequest{ + FrontendRequest: &streamlib.CreateStreamInput{ + Namespace: s.ns, StreamId: id, + Lifecycle: &streamlib.StreamLifecycle{MaxItems: 4}, + }, + }) + require.NoError(t, err) + + for _, batch := range [][]string{{"a", "b"}, {"c", "d"}, {"e", "f"}} { + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", batch...)}) + require.NoError(t, err) + } + + // Six appended against a cap of four, so the floor advanced without anyone + // asking. Reading from the floor still works and returns exactly what the + // cap retained. + got := s.poll(ctx, t, id, 2) + require.Equal(t, []string{"c", "d", "e", "f"}, bodies(got.GetRecords())) + + // Below the floor is a distinguishable error, not silence. + _, err = s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{Namespace: s.ns, StreamId: id, FromOffset: 0}, + }) + require.ErrorContains(t, err, "truncated") +} + +func TestStreamClosedStaysReadable(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-closed-readable" + s.create(ctx, t, id) + + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "a", "b")}) + require.NoError(t, err) + _, err = s.client.CloseStream(ctx, &streamlib.CloseStreamRequest{ + FrontendRequest: &streamlib.CloseStreamInput{Namespace: s.ns, StreamId: id}, + }) + require.NoError(t, err) + + // Close seals, it does not delete. A consumer can finish draining without + // coordinating a shutdown with the producer, which is the handshake the + // signal-based implementation forces today. + got := s.poll(ctx, t, id, 0) + require.Equal(t, []string{"a", "b"}, bodies(got.GetRecords())) + require.True(t, got.GetClosed()) + + desc, err := s.client.DescribeStream(ctx, &streamlib.DescribeStreamRequest{ + FrontendRequest: &streamlib.DescribeStreamInput{Namespace: s.ns, StreamId: id}, + }) + require.NoError(t, err) + require.NotNil(t, desc.GetFrontendResponse().GetState().GetCloseTime()) +} + +func TestStreamListStreams(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + + created := []string{"list-a", "list-b", "list-c"} + for _, id := range created { + s.create(ctx, t, id) + } + + // Visibility is written by a task after the create commits, so this is + // eventually consistent by design rather than by accident. + await.RequireTrue(t, func() bool { + resp, err := s.client.ListStreams(ctx, &streamlib.ListStreamsRequest{ + FrontendRequest: &streamlib.ListStreamsInput{Namespace: s.ns}, + }) + if err != nil { + return false + } + found := make(map[string]bool) + for _, e := range resp.GetFrontendResponse().GetStreams() { + found[e.GetStreamId()] = true + } + for _, id := range created { + if !found[id] { + return false + } + } + return true + }, 20*time.Second, 250*time.Millisecond) +} + +// A capped poll must not read the whole stream to answer. The read is clipped +// to the offsets the caller can be given, so a reader asking for one message +// off a long stream does not pull the rest into the history host on its way. +func TestStreamPollReadsOnlyWhatItReturns(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-poll-cap" + s.create(ctx, t, id) + + for i := range 40 { + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs("", fmt.Sprintf("m%d", i)), + }) + require.NoError(t, err) + } + + got := s.pollMax(ctx, t, id, 0, 1) + require.Equal(t, []string{"m0"}, bodies(got.GetRecords())) + require.Equal(t, int64(1), got.GetNextOffset(), "a capped read advances only over what it gave") + require.Equal(t, int64(40), got.GetHeadOffset(), "the frontier is still reported in full") + + // Paging from there covers the rest, so the cap trims the read and not the stream. + got = s.pollMax(ctx, t, id, got.GetNextOffset(), 10) + require.Equal(t, []string{"m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10"}, + bodies(got.GetRecords())) + require.Equal(t, int64(11), got.GetNextOffset()) + + // A filter finding nothing in the page still has to leave the reader able to + // go on, and it must stop at the page rather than scanning to the head. + got = s.pollMaxTopics(ctx, t, id, 0, 5, "nothing-matches-this") + require.Empty(t, got.GetRecords()) + require.Equal(t, int64(5), got.GetNextOffset(), + "a filtered page advanced past its own bound, so the read ran to the head") +} + +// A stream id can be reused. The bytes belong to the execution, not to the +// name, so a reader of the new stream must never be served the old one's. +func TestStreamPollAfterIdIsReusedServesTheNewStream(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-reused-id" + + s.create(ctx, t, id) + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "old")}) + require.NoError(t, err) + // Read it back so the bytes are certain to be cached before the id is reused. + require.Equal(t, []string{"old"}, bodies(s.poll(ctx, t, id, 0).GetRecords())) + + _, err = s.client.DeleteStream(ctx, &streamlib.DeleteStreamRequest{ + FrontendRequest: &streamlib.DeleteStreamInput{Namespace: s.ns, StreamId: id}, + }) + require.NoError(t, err) + + s.create(ctx, t, id) + _, err = s.add(ctx, t, id, &streamlib.AddMessagesInput{Records: streamMsgs("", "new")}) + require.NoError(t, err) + + got := s.poll(ctx, t, id, 0) + require.Equal(t, []string{"new"}, bodies(got.GetRecords()), + "a reused id served bytes from the deleted stream") +} + +// A filtered read hands back messages whose offsets are not contiguous, which +// is why the offset rides on the message. A reader cannot count them. +func TestStreamFilteredReadReportsRealOffsets(t *testing.T) { + s := newStreamTestEnv(t) + ctx := streamCtx(t) + const id = "stream-filtered-offsets" + s.create(ctx, t, id) + + for i, topic := range []string{"a", "b", "a", "b", "a"} { + _, err := s.add(ctx, t, id, &streamlib.AddMessagesInput{ + Records: streamMsgs(topic, fmt.Sprintf("m%d", i)), + }) + require.NoError(t, err) + } + + got := s.pollMaxTopics(ctx, t, id, 0, 0, "a") + require.Equal(t, []string{"m0", "m2", "m4"}, bodies(got.GetRecords())) + require.Equal(t, []int64{0, 2, 4}, offsets(got.GetRecords())) +} + +func (s *streamTestEnv) pollMaxTopics( + ctx context.Context, t *testing.T, streamID string, from int64, maxMessages int32, + topics ...string, +) *streamlib.PollMessagesOutput { + t.Helper() + resp, err := s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: s.ns, StreamId: streamID, FromOffset: from, + MaxMessages: maxMessages, Topics: topics, + }, + }) + require.NoError(t, err) + return resp.GetFrontendResponse() +} + +func (s *streamTestEnv) pollMax( + ctx context.Context, t *testing.T, streamID string, from int64, maxMessages int32, +) *streamlib.PollMessagesOutput { + t.Helper() + resp, err := s.client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: s.ns, StreamId: streamID, FromOffset: from, MaxMessages: maxMessages, + }, + }) + require.NoError(t, err) + return resp.GetFrontendResponse() +} + +func offsets(msgs []*streamlib.StreamRecord) []int64 { + out := make([]int64, len(msgs)) + for i, m := range msgs { + out[i] = m.GetOffset() + } + return out +} diff --git a/tests/stream_workflow_test.go b/tests/stream_workflow_test.go new file mode 100644 index 00000000000..72242761f22 --- /dev/null +++ b/tests/stream_workflow_test.go @@ -0,0 +1,553 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + historypb "go.temporal.io/api/history/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + chasmstream "go.temporal.io/server/chasm/lib/stream" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/durationpb" +) + +// Path A: a workflow publishing to a stream it owns. The stream is co-located +// with the workflow, so the frontier advances in the workflow task's own +// commit, and History gets one fixed-size event naming the offset range rather +// than anything that was published. +// +// Driven through the raw task poller rather than an SDK, because emitting a new +// command type does not need one. +func TestStreamWorkflowPublishesWithARangeEvent(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-publish-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + we, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-publisher"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + published := false + // The newer taskpoller cannot emit an arbitrary command type, which is + // the whole point here. + //nolint:staticcheck // SA1019: deprecated poller is the only one that can. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + if published { + return completeWorkflowCommand(), nil + } + published = true + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("planning")}, Topic: "progress"}, + {Body: &commonpb.Payload{Data: []byte("calling tool")}, Topic: "progress"}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + // One event for the batch, holding the range and none of the payload. Two + // messages were published, so it has to name both of them and stop there. + events := env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}) + var added []*historypb.WorkflowStreamRecordsAppendedEventAttributes + for _, e := range events { + if a := e.GetWorkflowStreamRecordsAppendedEventAttributes(); a != nil { + added = append(added, a) + } + } + require.Len(t, added, 1, "one publish command writes one event") + require.Equal(t, int64(0), added[0].GetFirstOffset()) + require.Equal(t, int64(2), added[0].GetRecordCount()) + require.Equal(t, chasmworkflow.DefaultStreamName, added[0].GetStreamId(), + "an unnamed stream resolves to the default before it is recorded") + + // The bodies stay out of History. Asserted on the serialized event rather + // than on its fields, because a field this test forgot to check would still + // be carrying them. + raw, err := added[0].Marshal() + require.NoError(t, err) + require.NotContains(t, string(raw), "calling tool", + "the event must name the range, never carry the payload") + + // The bodies are readable from outside the workflow, which is the point of + // publishing them: an attached stream has no id, so it is addressed by its + // owner and its name. + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"planning", "calling tool"}, + bodies(poll.GetFrontendResponse().GetRecords())) + require.Equal(t, []int64{0, 1}, offsets(poll.GetFrontendResponse().GetRecords()), + "each message carries where it sits in the log, so a reader can resume between them") + require.Equal(t, int64(2), poll.GetFrontendResponse().GetNextOffset()) + require.Equal(t, int64(2), poll.GetFrontendResponse().GetHeadOffset()) + + // The topic filter applies to an attached stream the same as to any other, + // and offsets stay assigned over the unfiltered stream. + filtered, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, FromOffset: 0, Topics: []string{"nothing-here"}, + }, + }) + require.NoError(t, err) + require.Empty(t, filtered.GetFrontendResponse().GetRecords()) + require.Equal(t, int64(2), filtered.GetFrontendResponse().GetNextOffset(), + "a filtered page still advances the reader") + + // A stream the workflow has not published to reads as an empty one, which + // is what lets a reader attach before the first event. + unwritten, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, StreamName: "not-published-to-yet", FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Empty(t, unwritten.GetFrontendResponse().GetRecords()) + require.Equal(t, int64(0), unwritten.GetFrontendResponse().GetHeadOffset()) + require.False(t, unwritten.GetFrontendResponse().GetClosed()) + + // A workflow that does not exist is still an error, so a mistyped owner is + // not mistaken for a stream with nothing in it. + _, err = s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id + "-does-not-exist", FromOffset: 0, + }, + }) + require.ErrorContains(t, err, "not found") + + // An attached stream still has no standalone id, so the id-addressed read + // must not reach it. + streamID := we.GetRunId() + "/" + chasmworkflow.DefaultStreamName + _, err = s.client.PollMessages(s.ctx(), &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: s.ns, StreamId: streamID, FromOffset: 0, + }, + }) + require.ErrorContains(t, err, "stream not found", + "an attached stream is only reachable through its workflow") +} + +// A reader attached to a workflow's stream before the workflow published +// anything. This is the ordinary case for a UI that opens on a session and +// waits for the agent's first token, so the poll has to park on a stream that +// does not exist yet and wake when the workflow creates it. +func TestStreamWorkflowLongPollWakesOnPublish(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-longpoll-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-publisher"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + type result struct { + out *streamlib.PollMessagesOutput + err error + } + done := make(chan result, 1) + go func() { + resp, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, FromOffset: 0, WaitNewMessages: true, + }, + }) + done <- result{resp.GetFrontendResponse(), err} + }() + + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("first token")}}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + select { + case r := <-done: + require.NoError(t, r.err) + require.Equal(t, []string{"first token"}, bodies(r.out.GetRecords())) + require.Equal(t, int64(1), r.out.GetNextOffset()) + case <-time.After(25 * time.Second): + t.Fatal("the parked reader did not wake when the workflow published") + } +} + +// Two producers on one stream: the workflow, whose publishes ride its Workflow +// Task, and something outside it. This is the shape of an agent session, where +// a model activity produces the tokens and the workflow only brackets them. +func TestStreamWorkflowTakesAppendsFromOutsideToo(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-mixed-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-publisher"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + appendOutside := func(body string) *streamlib.AddMessagesOutput { + t.Helper() + resp, err := s.client.AddWorkflowMessages(s.ctx(), &streamlib.AddWorkflowMessagesRequest{ + FrontendRequest: &streamlib.AddWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, + Records: []*streamlib.StreamRecord{{ + Body: &commonpb.Payload{Data: []byte(body)}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + }}, + }, + }) + require.NoError(t, err) + return resp.GetFrontendResponse() + } + + // The first writer creates the stream, and here that is not the workflow. + first := appendOutside("token one") + require.Equal(t, int64(0), first.GetFirstOffset()) + + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("turn ended")}}, + }, + }, + }, + }}, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + // The workflow appended after the outside writer, so it has to continue the + // same log rather than start its own. + require.Equal(t, int64(2), appendOutside("token two").GetFirstOffset()) + + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"token one", "turn ended", "token two"}, + bodies(poll.GetFrontendResponse().GetRecords()), + "both producers write one ordered log") + + // The event names the offset the workflow's own publish landed at, which + // only holds if the workflow saw the outside writer's message first. + events := env.GetHistory(s.ns, &commonpb.WorkflowExecution{WorkflowId: id}) + var added []*historypb.WorkflowStreamRecordsAppendedEventAttributes + for _, e := range events { + if a := e.GetWorkflowStreamRecordsAppendedEventAttributes(); a != nil { + added = append(added, a) + } + } + require.Len(t, added, 1) + require.Equal(t, int64(1), added[0].GetFirstOffset()) +} + +// A reader tailing a workflow that ends has to be released. Nothing can be +// added to a stream inside a closed execution, so a reader parked on it would +// otherwise wait for a message that can never come. +func TestStreamWorkflowStreamClosesWithItsWorkflow(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + + id := "stream-wf-close-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + + _, err := env.FrontendClient().StartWorkflowExecution( + s.ctx(), + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: s.ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-publisher"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(100 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }, + ) + require.NoError(t, err) + + describe := func() *streamlib.StreamState { + t.Helper() + resp, err := s.client.DescribeWorkflowStream(s.ctx(), &streamlib.DescribeWorkflowStreamRequest{ + FrontendRequest: &streamlib.DescribeWorkflowStreamInput{ + Namespace: s.ns, WorkflowId: id, + }, + }) + require.NoError(t, err) + return resp.GetFrontendResponse().GetState() + } + + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return []*commandpb.Command{ + { + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: []*streampb.StreamRecord{ + {Body: &commonpb.Payload{Data: []byte("last word")}}, + }, + }, + }, + }, + completeWorkflowCommand()[0], + }, nil + }, + Logger: env.Logger, + T: t, + } + _, err = poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + require.True(t, describe().GetClosed(), "the stream of a completed workflow reads as closed") + + // Closed does not mean gone. Everything published before the workflow + // ended is still there to be read. + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: id, FromOffset: 0, WaitNewMessages: true, + }, + }) + require.NoError(t, err) + require.Equal(t, []string{"last word"}, bodies(poll.GetFrontendResponse().GetRecords())) + require.True(t, poll.GetFrontendResponse().GetClosed()) +} + +// An outside producer and the workflow's own publishes land in one log, with +// neither pinning the head against the other. Run concurrently, every append +// has to succeed and every message has to appear once, in a contiguous range. +func TestOutsideAppendsRaceTheWorkflowPublishWithoutFailing(t *testing.T) { + env := testcore.NewEnv(t) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-race-") + + const producers = 8 + const perProducer = 10 + const workflowTasks = 5 + + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + return publishCommand("from-workflow"), nil + }, + Logger: env.Logger, + T: t, + } + + errs := make(chan error, producers*perProducer) + var wg sync.WaitGroup + for p := range producers { + wg.Go(func() { + for i := range perProducer { + _, err := s.client.AddWorkflowMessages(s.ctx(), &streamlib.AddWorkflowMessagesRequest{ + FrontendRequest: &streamlib.AddWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), + Records: []*streamlib.StreamRecord{{ + Body: &commonpb.Payload{Data: fmt.Appendf(nil, "outside-%d-%d", p, i)}, + }}, + }, + }) + errs <- err + } + }) + } + for range workflowTasks { + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + } + wg.Wait() + close(errs) + for err := range errs { + require.NoError(t, err, "an outside append must not fail because the workflow published") + } + + total := producers*perProducer + workflowTasks + poll, err := s.client.PollWorkflowMessages(s.ctx(), &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), FromOffset: 0, + }, + }) + require.NoError(t, err) + require.Equal(t, int64(total), poll.GetFrontendResponse().GetHeadOffset()) + seen := make(map[string]int, total) + for _, body := range bodies(poll.GetFrontendResponse().GetRecords()) { + seen[body]++ + } + require.Len(t, seen, producers*perProducer+1, "every outside message appears exactly once") + require.Equal(t, workflowTasks, seen["from-workflow"]) +} + +// A stream a workflow owns has a budget, because its batches are the workflow's +// own mutable state. Past it the workflow's publish fails its task with a cause +// and an outside producer is told the stream is full, instead of the execution +// size limit terminating the workflow later. +func TestOwnedStreamRefusesAppendsPastItsBudget(t *testing.T) { + env := testcore.NewEnv(t, testcore.WithDynamicConfig(chasmstream.OwnedStreamMaxItemsSetting, 3)) + s := newStreamTestEnvFrom(t, env) + execution, tq := startConsumer(t, s, "stream-wf-budget-") + + task := 0 + //nolint:staticcheck // SA1019: deprecated poller is the only one that can emit the command. + poller := &testcore.TaskPoller{ + Client: env.FrontendClient(), + Namespace: s.ns, + TaskQueue: tq, + Identity: "tester", + WorkflowTaskHandler: func( + *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + task++ + if task == 1 { + return publishCommand("one", "two"), nil + } + return publishCommand("three", "four"), nil + }, + Logger: env.Logger, + T: t, + } + _, err := poller.PollAndProcessWorkflowTask() + require.NoError(t, err) + + signalWorkflow(t, s, execution.GetWorkflowId(), execution.GetRunId()) + _, err = poller.PollAndProcessWorkflowTask() + require.Error(t, err, "two more do not fit in a budget of three") + failed := workflowTaskFailedWith(env.GetHistory(s.ns, execution), + enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_APPEND_STREAM_RECORDS_ATTRIBUTES) + require.NotNil(t, failed) + require.Contains(t, failed.GetFailure().GetMessage(), "budget") + + appendOutside := func(bodies ...string) error { + messages := make([]*streamlib.StreamRecord, len(bodies)) + for i, b := range bodies { + messages[i] = &streamlib.StreamRecord{Body: &commonpb.Payload{Data: []byte(b)}} + } + _, err := s.client.AddWorkflowMessages(s.ctx(), &streamlib.AddWorkflowMessagesRequest{ + FrontendRequest: &streamlib.AddWorkflowMessagesInput{ + Namespace: s.ns, WorkflowId: execution.GetWorkflowId(), Records: messages, + }, + }) + return err + } + // The test client is a bare gRPC connection, so the code is what it sees. + require.Equal(t, codes.ResourceExhausted, status.Code(appendOutside("three", "four"))) + require.NoError(t, appendOutside("three"), "the last slot is still there for one that fits") + require.Equal(t, codes.ResourceExhausted, status.Code(appendOutside("four"))) +} diff --git a/tests/streaming_baseline_test.go b/tests/streaming_baseline_test.go new file mode 100644 index 00000000000..cfc36864d8b --- /dev/null +++ b/tests/streaming_baseline_test.go @@ -0,0 +1,470 @@ +package tests + +import ( + "context" + "fmt" + "os" + "slices" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.temporal.io/api/workflowservice/v1" + sdkclient "go.temporal.io/sdk/client" + "go.temporal.io/sdk/workflow" + "go.temporal.io/server/common/metrics" + "go.temporal.io/server/common/metrics/metricstest" + "go.temporal.io/server/tests/testcore" +) + +// Baseline measurements for today's Workflow Streams pattern: an Activity +// batches items into Signals and a consumer long-polls with an Update. AI-198 +// proposes replacing it, and a replacement cannot be justified without knowing +// what the current pattern actually costs. +// +// The two dimensions that matter are the flush interval and the subscriber +// count. The shipped guidance is a ~2s flush; the Native Streams 1-pager asks +// for 100ms to be practical. Running both shows the cost of closing that gap +// under the current design, which is the number the September check-in needs. +// +// The full matrix takes minutes, so it is opt-in via TEMPORAL_STREAM_BENCH=1. +// Without it a short configuration still runs, which keeps the harness honest +// without slowing the suite. + +const ( + streamBatchSignal = "stream_batch" + streamDoneSignal = "stream_done" + streamPollUpdate = "poll_events" + streamMessageSize = 20 +) + +type streamBaselineParams struct { + name string + flushInterval time.Duration + subscribers int + messageRate int // messages per second + duration time.Duration +} + +type streamBaselineResult struct { + params streamBaselineParams + + messagesSent int + messagesReceived int + pollRejections int64 + + historyBytes int64 + historyEvents int64 + // Set when the workload has no workflow at all, so the history columns are + // an absence rather than a measurement. Rendering them as 0.00 next to a + // measured figure reads as a comparison that was never made. + historyNotApplicable bool + + persistenceRequests int64 + persistenceByOp map[string]int64 + + latencyP50 time.Duration + latencyP99 time.Duration + + // Set when the run could not complete, for example because the workflow + // exceeded a history limit. That is itself a result worth reporting. + failure string +} + +// streamBaselineWorkflow mirrors the shipped pattern: Signals carry batches in, +// an Update long-polls them back out, and the workflow holds the buffer. +func streamBaselineWorkflow(ctx workflow.Context) error { + var buffer []string + done := false + + err := workflow.SetUpdateHandler(ctx, streamPollUpdate, + func(ctx workflow.Context, lastSeen int) ([]string, error) { + // The shape that makes this expensive: every poll is a durable + // state transition, even when it returns nothing new. + if err := workflow.Await(ctx, func() bool { + return len(buffer) > lastSeen || done + }); err != nil { + return nil, err + } + if lastSeen >= len(buffer) { + return nil, nil + } + out := make([]string, len(buffer)-lastSeen) + copy(out, buffer[lastSeen:]) + return out, nil + }) + if err != nil { + return err + } + + batches := workflow.GetSignalChannel(ctx, streamBatchSignal) + finish := workflow.GetSignalChannel(ctx, streamDoneSignal) + + for !done { + sel := workflow.NewSelector(ctx) + sel.AddReceive(batches, func(c workflow.ReceiveChannel, _ bool) { + var batch []string + c.Receive(ctx, &batch) + buffer = append(buffer, batch...) + }) + sel.AddReceive(finish, func(c workflow.ReceiveChannel, _ bool) { + c.Receive(ctx, nil) + done = true + }) + sel.Select(ctx) + } + + // Let any parked pollers observe the terminal state before exiting. + return workflow.Await(ctx, func() bool { return true }) +} + +func TestStreamingBaseline(t *testing.T) { + matrix := shortStreamBaselineMatrix() + if os.Getenv("TEMPORAL_STREAM_BENCH") == "1" { + matrix = fullStreamBaselineMatrix() + } + + results := make([]streamBaselineResult, 0, len(matrix)) + for _, p := range matrix { + t.Run(p.name, func(t *testing.T) { + results = append(results, runStreamBaseline(t, p)) + }) + } + reportStreamBaseline(t, results) +} + +func shortStreamBaselineMatrix() []streamBaselineParams { + return []streamBaselineParams{ + { + name: "flush2s_sub1", flushInterval: 2 * time.Second, subscribers: 1, + messageRate: 40, duration: 6 * time.Second, + }, + { + name: "flush100ms_sub1", flushInterval: 100 * time.Millisecond, subscribers: 1, + messageRate: 40, duration: 6 * time.Second, + }, + } +} + +func fullStreamBaselineMatrix() []streamBaselineParams { + var out []streamBaselineParams + for _, flush := range []time.Duration{2 * time.Second, 100 * time.Millisecond} { + for _, subs := range []int{1, 5, 25} { + out = append(out, streamBaselineParams{ + name: fmt.Sprintf("flush%s_sub%d", flush, subs), + flushInterval: flush, + subscribers: subs, + messageRate: 40, + duration: 50 * time.Second, + }) + } + } + return out +} + +func runStreamBaseline(t *testing.T, p streamBaselineParams) streamBaselineResult { + // Dedicated cluster so competing test load does not distort the timings. + // Metric capture is namespace-scoped because persistence_requests carries a + // namespace tag, which also attributes the counts to this workload rather + // than to cluster background traffic. + // + // Testlogger failure is off because a sustained-load run torn down while + // queues are still draining always logs shard-status errors on shutdown. + // The cost is losing the safety net that would catch a genuine server error + // during the run, so treat an anomalous result as a reason to re-run with + // the option removed rather than trusting it. + env := testcore.NewEnv(t, testcore.WithDisableTestloggerFailure()) + res := streamBaselineResult{params: p, persistenceByOp: map[string]int64{}} + + env.SdkWorker().RegisterWorkflow(streamBaselineWorkflow) + + ctx, cancel := context.WithTimeout(context.Background(), p.duration+2*time.Minute) + defer cancel() + + wfID := env.Tv().WorkflowID() + run, err := env.SdkClient().ExecuteWorkflow(ctx, sdkclient.StartWorkflowOptions{ + ID: wfID, + TaskQueue: env.WorkerTaskQueue(), + }, streamBaselineWorkflow) + require.NoError(t, err) + + // Started after workflow creation so cluster, namespace, and start costs do + // not inflate the per-message figures. Both designs pay those equally. + capture := env.StartNamespaceMetricCapture() + + sentAt := &sync.Map{} // message sequence -> generation time + var receivedTotal atomic.Int64 + var pollRejections atomic.Int64 + var consumers sync.WaitGroup + consumerLatencies := make([][]time.Duration, p.subscribers) + consumerCounts := make([]int, p.subscribers) + consumerCtx, stopConsumers := context.WithCancel(ctx) + defer stopConsumers() + + for i := range p.subscribers { + consumers.Add(1) + go func(idx int) { + defer consumers.Done() + lat, n := runStreamConsumer( + consumerCtx, env, wfID, run.GetRunID(), sentAt, &receivedTotal, &pollRejections) + consumerLatencies[idx] = lat + consumerCounts[idx] = n + }(i) + } + + res.messagesSent = runStreamProducer(ctx, t, env, wfID, run.GetRunID(), p, sentAt, &res) + + // Drain, then stop the consumers, and only then let the workflow finish, so + // that no consumer is ever polling an execution that is completing. One that + // is counts its own doomed polls as rejections and its client backoff as + // delivery latency, which measures the harness rather than the pattern. The + // workflow finishes last so the history numbers below are final rather than a + // mid-flight snapshot. A cell that fails to drain is reported rather than + // failed: hitting a limit is a real property of this pattern and is part of + // what the benchmark is measuring. + want := int64(res.messagesSent) * int64(p.subscribers) + if !waitForDrain(ctx, &receivedTotal, want, 15*time.Second) { + t.Logf("drained %d of %d expected deliveries before timeout", receivedTotal.Load(), want) + } + stopConsumers() + consumers.Wait() + require.NoError(t, + env.SdkClient().SignalWorkflow(ctx, wfID, run.GetRunID(), streamDoneSignal, nil)) + if err := run.Get(ctx, nil); err != nil { + t.Logf("workflow did not complete cleanly: %v", err) + } + + var all []time.Duration + for i := range p.subscribers { + all = append(all, consumerLatencies[i]...) + res.messagesReceived += consumerCounts[i] + } + res.pollRejections = pollRejections.Load() + res.latencyP50 = percentile(all, 0.50) + res.latencyP99 = percentile(all, 0.99) + + desc, err := env.FrontendClient().DescribeWorkflowExecution( + ctx, + &workflowservice.DescribeWorkflowExecutionRequest{ + Namespace: env.Namespace().String(), + Execution: env.Tv().WithWorkflowID(wfID).WorkflowExecution(), + }, + ) + if err == nil { + res.historyBytes = desc.GetWorkflowExecutionInfo().GetHistorySizeBytes() + res.historyEvents = desc.GetWorkflowExecutionInfo().GetHistoryLength() + } + + for _, rec := range capture.Metric(metrics.PersistenceRequests.Name()) { + res.persistenceRequests += recordingCount(rec) + if op, ok := rec.Tags["operation"]; ok { + res.persistenceByOp[op] += recordingCount(rec) + } + } + + return res +} + +func runStreamProducer( + ctx context.Context, + t *testing.T, + env *testcore.TestEnv, + wfID, runID string, + p streamBaselineParams, + sentAt *sync.Map, + res *streamBaselineResult, +) int { + payload := make([]byte, streamMessageSize) + for i := range payload { + payload[i] = 'x' + } + + // Messages are generated continuously and flushed on the interval, which is + // what an EventBatcher does. Latency is stamped at generation, not at + // flush: the time an item waits in the batcher is the dominant cost of a + // long flush interval, and stamping at flush would hide it entirely. + genTicker := time.NewTicker(time.Second / time.Duration(p.messageRate)) + defer genTicker.Stop() + flushTicker := time.NewTicker(p.flushInterval) + defer flushTicker.Stop() + deadline := time.Now().Add(p.duration) + + seq := 0 + var pending []string + + flush := func() bool { + if len(pending) == 0 { + return true + } + batch := pending + pending = nil + if err := env.SdkClient().SignalWorkflow(ctx, wfID, runID, streamBatchSignal, batch); err != nil { + // A history or signal limit is a legitimate outcome for this + // pattern, not a broken harness. Record it and stop. + res.failure = err.Error() + t.Logf("producer stopped after %d messages: %v", seq, err) + return false + } + return true + } + + for time.Now().Before(deadline) { + select { + case <-ctx.Done(): + return seq + case <-genTicker.C: + sentAt.Store(seq, time.Now()) + pending = append(pending, fmt.Sprintf("%d:%s", seq, payload)) + seq++ + case <-flushTicker.C: + if !flush() { + return seq + } + } + } + flush() + return seq +} + +func runStreamConsumer( + ctx context.Context, + env *testcore.TestEnv, + wfID, runID string, + sentAt *sync.Map, + receivedTotal *atomic.Int64, + rejections *atomic.Int64, +) ([]time.Duration, int) { + var latencies []time.Duration + var batch []string + lastSeen := 0 + + for ctx.Err() == nil { + handle, err := env.SdkClient().UpdateWorkflow(ctx, sdkclient.UpdateWorkflowOptions{ + WorkflowID: wfID, + RunID: runID, + UpdateName: streamPollUpdate, + Args: []any{lastSeen}, + WaitForStage: sdkclient.WorkflowUpdateStageCompleted, + }) + if err == nil { + err = handle.Get(ctx, &batch) + } + if err != nil { + // A rejected poll is a measurement, not a reason to stop. Killing + // the consumer here would report a server limit as consumer + // slowness, which is a different and much less useful claim. + rejections.Add(1) + select { + case <-ctx.Done(): + return latencies, lastSeen + case <-time.After(50 * time.Millisecond): + } + continue + } + received := time.Now() + for range batch { + if v, ok := sentAt.Load(lastSeen); ok { + latencies = append(latencies, received.Sub(v.(time.Time))) + } + lastSeen++ + receivedTotal.Add(1) + } + } + return latencies, lastSeen +} + +// historyPerMsg renders a per-message history figure, keeping a workload with +// no workflow distinct from one that measured zero. +func (r streamBaselineResult) historyPerMsg(v int64) string { + if r.historyNotApplicable { + return "no workflow" + } + if r.messagesSent == 0 { + return "n/a" + } + return fmt.Sprintf("%.2f", float64(v)/float64(r.messagesSent)) +} + +// waitForDrain polls until every consumer has caught up or the deadline passes. +// It reports rather than asserts, because a cell that cannot drain is a result. +func waitForDrain(ctx context.Context, got *atomic.Int64, want int64, timeout time.Duration) bool { + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + deadline := time.After(timeout) + for { + if got.Load() >= want { + return true + } + select { + case <-ctx.Done(): + return false + case <-deadline: + return false + case <-ticker.C: + } + } +} + +func recordingCount(rec *metricstest.CapturedRecording) int64 { + switch v := rec.Value.(type) { + case int64: + return v + case float64: + return int64(v) + default: + return 0 + } +} + +func percentile(d []time.Duration, q float64) time.Duration { + if len(d) == 0 { + return 0 + } + sorted := make([]time.Duration, len(d)) + copy(sorted, d) + slices.Sort(sorted) + idx := int(float64(len(sorted)-1) * q) + return sorted[idx] +} + +func reportStreamBaseline(t *testing.T, results []streamBaselineResult) { + // Emitted as markdown so the numbers can go straight into the design docs + // without being retyped, which is how transcription errors get in. + t.Log("Workflow Streams baseline: Signals in, polling Update out") + t.Log("") + t.Log("| scenario | msgs | delivered | rejected polls | hist events/msg | hist bytes/msg " + + "| persist ops/msg | p50 | p99 |") + t.Log("|---|---|---|---|---|---|---|---|---|") + for _, r := range results { + perMsg := func(v int64) string { + if r.messagesSent == 0 { + return "n/a" + } + return fmt.Sprintf("%.2f", float64(v)/float64(r.messagesSent)) + } + t.Logf("| %s | %d | %d | %d | %s | %s | %s | %s | %s |", + r.params.name, r.messagesSent, r.messagesReceived, r.pollRejections, + r.historyPerMsg(r.historyEvents), r.historyPerMsg(r.historyBytes), + perMsg(r.persistenceRequests), + r.latencyP50.Round(time.Millisecond), r.latencyP99.Round(time.Millisecond)) + } + t.Log("") + for _, r := range results { + if r.failure != "" { + t.Logf("%s did not complete: %s", r.params.name, r.failure) + } + if r.messagesSent > 0 && r.messagesReceived < r.messagesSent*r.params.subscribers { + t.Logf("%s under-delivered: %d of %d expected", + r.params.name, r.messagesReceived, r.messagesSent*r.params.subscribers) + } + } + t.Log("Totals are absolute, not rates: persist ops exclude cluster and workflow start.") + t.Log("Rejected polls are bounded by history.maxInFlightUpdates (default 10) and") + t.Log("history.maxTotalUpdates (default 2000), both per workflow execution.") + for _, r := range results { + t.Logf("%s raw: events=%d bytes=%d persistOps=%d byOp=%v", + r.params.name, r.historyEvents, r.historyBytes, r.persistenceRequests, r.persistenceByOp) + } +} diff --git a/tests/streaming_native_test.go b/tests/streaming_native_test.go new file mode 100644 index 00000000000..556f9ed6e0f --- /dev/null +++ b/tests/streaming_native_test.go @@ -0,0 +1,262 @@ +package tests + +import ( + "context" + "fmt" + "os" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" + commonpb "go.temporal.io/api/common/v1" + streampb "go.temporal.io/api/stream/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + "go.temporal.io/server/common/metrics" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +// The native-stream half of the comparison. It deliberately shares the workload +// shape, latency stamping, and metric capture with the Signal-and-Update +// baseline in streaming_baseline_test.go, because a benchmark whose two halves +// generate load differently measures the harness rather than the design. + +func runNativeStream(t *testing.T, p streamBaselineParams) streamBaselineResult { + env := testcore.NewEnv(t, testcore.WithDisableTestloggerFailure()) + res := streamBaselineResult{params: p, persistenceByOp: map[string]int64{}} + + conn, err := grpc.NewClient(env.FrontendGRPCAddress(), + grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + defer func() { _ = conn.Close() }() + client := streamlib.NewStreamServiceClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), p.duration+2*time.Minute) + defer cancel() + + ns := env.Namespace().String() + streamID := fmt.Sprintf("bench-%s", p.name) + created, err := client.CreateStream(ctx, &streamlib.CreateStreamRequest{ + FrontendRequest: &streamlib.CreateStreamInput{Namespace: ns, StreamId: streamID}, + }) + require.NoError(t, err) + runID := created.GetFrontendResponse().GetRunId() + + // Started after creation so cluster and namespace setup do not inflate the + // per-message figures, matching the baseline. + capture := env.StartNamespaceMetricCapture() + + sentAt := &sync.Map{} + var receivedTotal atomic.Int64 + var pollRejections atomic.Int64 + + consumerCtx, stopConsumers := context.WithCancel(ctx) + defer stopConsumers() + var consumers sync.WaitGroup + latencies := make([][]time.Duration, p.subscribers) + counts := make([]int, p.subscribers) + + for i := range p.subscribers { + consumers.Add(1) + go func(idx int) { + defer consumers.Done() + latencies[idx], counts[idx] = runNativeConsumer( + consumerCtx, client, ns, streamID, runID, sentAt, &receivedTotal, &pollRejections) + }(i) + } + + res.messagesSent = runNativeProducer(ctx, t, client, ns, streamID, runID, p, sentAt, &res) + + want := int64(res.messagesSent) * int64(p.subscribers) + if !waitForDrain(ctx, &receivedTotal, want, 15*time.Second) { + t.Logf("drained %d of %d expected deliveries before timeout", receivedTotal.Load(), want) + } + stopConsumers() + consumers.Wait() + + var all []time.Duration + for i := range p.subscribers { + all = append(all, latencies[i]...) + res.messagesReceived += counts[i] + } + res.pollRejections = pollRejections.Load() + res.latencyP50 = percentile(all, 0.50) + res.latencyP99 = percentile(all, 0.99) + + // This workload has no workflow: the producer and every consumer are external + // gRPC clients. So there is no execution to describe and no history figure to + // report, which is not the same claim as a measured zero and must not be + // rendered as one. What a publish from workflow code costs in history is + // measured against a control in stream_publish_cost_test.go. + res.historyNotApplicable = true + + for _, rec := range capture.Metric(metrics.PersistenceRequests.Name()) { + res.persistenceRequests += recordingCount(rec) + if op, ok := rec.Tags["operation"]; ok { + res.persistenceByOp[op] += recordingCount(rec) + } + } + return res +} + +func runNativeProducer( + ctx context.Context, + t *testing.T, + client streamlib.StreamServiceClient, + ns, streamID, runID string, + p streamBaselineParams, + sentAt *sync.Map, + res *streamBaselineResult, +) int { + payload := make([]byte, streamMessageSize) + for i := range payload { + payload[i] = 'x' + } + + genTicker := time.NewTicker(time.Second / time.Duration(p.messageRate)) + defer genTicker.Stop() + flushTicker := time.NewTicker(p.flushInterval) + defer flushTicker.Stop() + deadline := time.Now().Add(p.duration) + + seq := 0 + var pending []*streamlib.StreamRecord + sequence := int64(0) + + flush := func() bool { + if len(pending) == 0 { + return true + } + batch := pending + pending = nil + sequence++ + _, err := client.AddMessages(ctx, &streamlib.AddMessagesRequest{ + FrontendRequest: &streamlib.AddMessagesInput{ + Namespace: ns, StreamId: streamID, RunId: runID, Records: batch, + ProducerId: "bench", Sequence: sequence, + }, + }) + if err != nil { + res.failure = err.Error() + t.Logf("producer stopped after %d messages: %v", seq, err) + return false + } + return true + } + + for time.Now().Before(deadline) { + select { + case <-ctx.Done(): + return seq + case <-genTicker.C: + sentAt.Store(seq, time.Now()) + pending = append(pending, &streamlib.StreamRecord{ + Body: &commonpb.Payload{Data: payload}, + Kind: streampb.STREAM_RECORD_KIND_DATA, + }) + seq++ + case <-flushTicker.C: + if !flush() { + return seq + } + } + } + flush() + return seq +} + +func runNativeConsumer( + ctx context.Context, + client streamlib.StreamServiceClient, + ns, streamID, runID string, + sentAt *sync.Map, + receivedTotal *atomic.Int64, + rejections *atomic.Int64, +) ([]time.Duration, int) { + var out []time.Duration + lastSeen := int64(0) + + for ctx.Err() == nil { + resp, err := client.PollMessages(ctx, &streamlib.PollMessagesRequest{ + FrontendRequest: &streamlib.PollMessagesInput{ + Namespace: ns, StreamId: streamID, RunId: runID, + FromOffset: lastSeen, WaitNewMessages: true, + }, + }) + if err != nil { + rejections.Add(1) + select { + case <-ctx.Done(): + return out, int(lastSeen) + case <-time.After(50 * time.Millisecond): + } + continue + } + received := time.Now() + fr := resp.GetFrontendResponse() + for range fr.GetRecords() { + if v, ok := sentAt.Load(int(lastSeen)); ok { + out = append(out, received.Sub(v.(time.Time))) + } + lastSeen++ + receivedTotal.Add(1) + } + if next := fr.GetNextOffset(); next > lastSeen { + lastSeen = next + } + } + return out, int(lastSeen) +} + +// TestStreamingComparison runs both designs over the same workload and reports +// them together. This is the artifact the go/no-go decision needs. +func TestStreamingComparison(t *testing.T) { + matrix := shortStreamBaselineMatrix() + if os.Getenv("TEMPORAL_STREAM_BENCH") == "1" { + matrix = fullStreamBaselineMatrix() + } + + var baseline, native []streamBaselineResult + for _, p := range matrix { + t.Run("baseline/"+p.name, func(t *testing.T) { + baseline = append(baseline, runStreamBaseline(t, p)) + }) + t.Run("native/"+p.name, func(t *testing.T) { + native = append(native, runNativeStream(t, p)) + }) + } + + t.Log("Workflow Streams (Signals in, polling Update out) versus native streams") + t.Log("") + t.Log("| scenario | design | msgs | delivered | rejected | wf hist bytes/msg " + + "| persist ops/msg | p50 | p99 |") + t.Log("|---|---|---|---|---|---|---|---|---|") + for i := range baseline { + logComparisonRow(t, "signals+update", baseline[i]) + logComparisonRow(t, "native", native[i]) + } + + t.Log("") + for i := range baseline { + t.Logf("%s signals+update raw: persistOps=%d byOp=%v", + baseline[i].params.name, baseline[i].persistenceRequests, baseline[i].persistenceByOp) + t.Logf("%s native raw: persistOps=%d byOp=%v", + native[i].params.name, native[i].persistenceRequests, native[i].persistenceByOp) + } +} + +func logComparisonRow(t *testing.T, design string, r streamBaselineResult) { + perMsg := func(v int64) string { + if r.messagesSent == 0 { + return "n/a" + } + return fmt.Sprintf("%.2f", float64(v)/float64(r.messagesSent)) + } + t.Logf("| %s | %s | %d | %d | %d | %s | %s | %s | %s |", + r.params.name, design, r.messagesSent, r.messagesReceived, r.pollRejections, + r.historyPerMsg(r.historyBytes), perMsg(r.persistenceRequests), + r.latencyP50.Round(time.Millisecond), r.latencyP99.Round(time.Millisecond)) +} diff --git a/tests/testcore/onebox.go b/tests/testcore/onebox.go index 908241e475e..7d1c812e0e2 100644 --- a/tests/testcore/onebox.go +++ b/tests/testcore/onebox.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "maps" "math/rand" "net" "os" @@ -42,7 +43,7 @@ import ( type ( temporalImpl struct { clients - server temporal.Server + servers []temporal.Server logger log.Logger serverConfig *config.Config @@ -218,7 +219,7 @@ func newTemporal(t *testing.T, params *temporalParams) *temporalImpl { return impl } -func (c *temporalImpl) Start() error { +func (c *temporalImpl) Start() (retErr error) { // Worker is optional in functional tests; the other services are always // needed for a usable in-process cluster. services := []primitives.ServiceName{ @@ -231,7 +232,7 @@ func (c *temporalImpl) Start() error { } for _, serviceName := range services { numHosts := len(c.hostsByProtocolByService[grpcProtocol][serviceName].All) - if numHosts != 1 { + if numHosts != 1 && serviceName != primitives.HistoryService { return fmt.Errorf("onebox requires exactly one %s service node, got %d", serviceName, numHosts) } } @@ -291,23 +292,56 @@ func (c *temporalImpl) Start() error { ) defer cleanupHooks() - server, err := temporal.NewServer(options...) - if err != nil { - return fmt.Errorf("unable to construct temporal server: %w", err) - } - - if err := server.Start(); err != nil { - return fmt.Errorf("unable to start temporal server: %w", err) + defer func() { + if retErr != nil { + for _, server := range c.servers { + retErr = multierr.Append(retErr, server.Stop()) + } + c.servers = nil + } + }() + for index, address := range hostsByService[primitives.HistoryService].All { + serverOptions := options + if index > 0 { + // Additional History graphs share membership and persistence while + // binding their own RPC address. Never expose an arbitrary graph's + // CHASM engine through ChasmContext in this multi-host configuration. + extraConfig := cfg + extraConfig.Persistence = copyPersistenceConfig(cfg.Persistence) + extraConfig.Services = maps.Clone(cfg.Services) + bindIP, port := mustSplitHostPort(address) + extraConfig.Services[string(primitives.HistoryService)] = config.Service{ + RPC: config.RPC{BindOnIP: bindIP, GRPCPort: int(port)}, + } + extraHosts := maps.Clone(hostsByService) + historyHosts := extraHosts[primitives.HistoryService] + historyHosts.Self = address + extraHosts[primitives.HistoryService] = historyHosts + serverOptions = []temporal.ServerOption{ + temporal.WithConfig(&extraConfig), + temporal.ForServices([]string{string(primitives.HistoryService)}), + temporal.WithStaticHosts(extraHosts), + } + serverOptions = append(serverOptions, c.baseServerOptions...) + } + server, err := temporal.NewServer(serverOptions...) + if err != nil { + return fmt.Errorf("unable to construct temporal server: %w", err) + } + c.servers = append(c.servers, server) + if err := server.Start(); err != nil { + return fmt.Errorf("unable to start temporal server: %w", err) + } } - c.server = server return nil } func (c *temporalImpl) Stop() error { var errs []error - if c.server != nil { - errs = append(errs, c.server.Stop()) + for index := len(c.servers) - 1; index >= 0; index-- { + errs = append(errs, c.servers[index].Stop()) } + c.servers = nil errs = append(errs, c.close()...) return multierr.Combine(errs...) } diff --git a/tests/xdc/stream_failover_test.go b/tests/xdc/stream_failover_test.go new file mode 100644 index 00000000000..0e03ada39ac --- /dev/null +++ b/tests/xdc/stream_failover_test.go @@ -0,0 +1,349 @@ +package xdc + +import ( + "context" + "slices" + "strings" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + commandpb "go.temporal.io/api/command/v1" + commonpb "go.temporal.io/api/common/v1" + enumspb "go.temporal.io/api/enums/v1" + streampb "go.temporal.io/api/stream/v1" + taskqueuepb "go.temporal.io/api/taskqueue/v1" + "go.temporal.io/api/workflowservice/v1" + "go.temporal.io/server/api/adminservice/v1" + streamlib "go.temporal.io/server/chasm/lib/stream/gen/streampb/v1" + chasmworkflow "go.temporal.io/server/chasm/lib/workflow" + "go.temporal.io/server/common/dynamicconfig" + "go.temporal.io/server/common/testing/await" + "go.temporal.io/server/tests/testcore" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/types/known/durationpb" +) + +// streamFailoverBase drives one workflow that owns a stream with records and +// an active subscription on the active cluster, so each suite below can fail +// the namespace over and look at what the standby has. +type streamFailoverBase struct { + xdcBaseSuite +} + +// StreamFailoverSuite runs with state-based replication, the mode that carries +// a CHASM tree between clusters. +type StreamFailoverSuite struct { + streamFailoverBase +} + +// StreamEventReplicationSuite runs with event-based replication, where only +// what History events carry reaches the standby. +type StreamEventReplicationSuite struct { + streamFailoverBase +} + +func TestStreamFailoverSuite(t *testing.T) { + t.Parallel() + s := &StreamFailoverSuite{} + s.enableTransitionHistory = true + suite.Run(t, s) +} + +func TestStreamEventReplicationSuite(t *testing.T) { + t.Parallel() + s := &StreamEventReplicationSuite{} + s.enableTransitionHistory = false + suite.Run(t, s) +} + +func (s *streamFailoverBase) SetupSuite() { + s.dynamicConfigOverrides = map[dynamicconfig.Key]any{ + dynamicconfig.EnableChasm.Key(): true, + dynamicconfig.TransferProcessorMaxPollInterval.Key(): 1 * time.Second, + } + s.setupSuite() +} + +func (s *streamFailoverBase) SetupTest() { + s.setupTest() +} + +func (s *streamFailoverBase) TearDownSuite() { + s.tearDownSuite() +} + +func (s *streamFailoverBase) streamClient(clusterIndex int) streamlib.StreamServiceClient { + conn, err := grpc.NewClient(s.clusters[clusterIndex].Host().FrontendGRPCAddress(), + grpc.WithTransportCredentials(insecure.NewCredentials())) + s.NoError(err) + s.T().Cleanup(func() { _ = conn.Close() }) + return streamlib.NewStreamServiceClient(conn) +} + +// streamNodesOn lists the CHASM node paths of the execution on one cluster that +// belong to its streams and cursors, sorted, or nil when the execution is not +// there. A stream a workflow owns is `Streams#`, its records are data +// nodes under `Streams$$Batches#`, and the subscription is +// `StreamCursors#`. +func (s *streamFailoverBase) streamNodesOn( + ctx context.Context, clusterIndex int, ns string, execution *commonpb.WorkflowExecution, +) []string { + resp, err := s.clusters[clusterIndex].AdminClient().DescribeMutableState(ctx, + &adminservice.DescribeMutableStateRequest{Namespace: ns, Execution: execution}) + if err != nil { + return nil + } + var paths []string + for path := range resp.GetDatabaseMutableState().GetChasmNodes() { + if strings.Contains(path, "Stream") { + paths = append(paths, path) + } + } + slices.Sort(paths) + return paths +} + +func apiBodies(records []*streampb.StreamRecord) []string { + out := make([]string, 0, len(records)) + for _, r := range records { + out = append(out, string(r.GetBody().GetData())) + } + return out +} + +func storedBodies(records []*streamlib.StreamRecord) []string { + out := make([]string, 0, len(records)) + for _, r := range records { + out = append(out, string(r.GetBody().GetData())) + } + return out +} + +func publishCommand(bodies ...string) []*commandpb.Command { + records := make([]*streampb.StreamRecord, len(bodies)) + for i, b := range bodies { + records[i] = &streampb.StreamRecord{Body: &commonpb.Payload{Data: []byte(b)}} + } + return []*commandpb.Command{{ + CommandType: enumspb.COMMAND_TYPE_APPEND_STREAM_RECORDS, + Attributes: &commandpb.Command_AppendStreamRecordsCommandAttributes{ + AppendStreamRecordsCommandAttributes: &commandpb.AppendStreamRecordsCommandAttributes{ + Records: records, + }, + }, + }} +} + +// streamingWorkflow is one execution driven by a raw poller on whichever +// cluster is asked, handing each task the commands queued for it. +type streamingWorkflow struct { + s *streamFailoverBase + ns string + execution *commonpb.WorkflowExecution + tq *taskqueuepb.TaskQueue + + delivered [][]*streampb.StreamSlice + commands [][]*commandpb.Command +} + +func (w *streamingWorkflow) runTask( + clusterIndex int, cmds []*commandpb.Command, +) []*streampb.StreamSlice { + w.commands = append(w.commands, cmds) + //nolint:staticcheck // SA1019: only the deprecated poller can emit this command type. + poller := &testcore.TaskPoller{ + Client: w.s.clusters[clusterIndex].FrontendClient(), + Namespace: w.ns, + TaskQueue: w.tq, + Identity: "tester", + WorkflowTaskHandler: func( + resp *workflowservice.PollWorkflowTaskQueueResponse, + ) ([]*commandpb.Command, error) { + w.delivered = append(w.delivered, resp.GetStreamSlices()) + next := w.commands[0] + w.commands = w.commands[1:] + return next, nil + }, + Logger: w.s.logger, + T: w.s.T(), + } + _, err := poller.PollAndProcessWorkflowTask() + w.s.NoError(err) + return w.delivered[len(w.delivered)-1] +} + +func (w *streamingWorkflow) currentSlice(delivered []*streampb.StreamSlice) *streampb.StreamSlice { + for _, sl := range delivered { + if sl.GetWorkflowTaskCompletedEventId() == 0 { + return sl + } + } + w.s.FailNow("no slice for the current task") + return nil +} + +func (w *streamingWorkflow) signal(ctx context.Context, clusterIndex int) { + _, err := w.s.clusters[clusterIndex].FrontendClient().SignalWorkflowExecution(ctx, + &workflowservice.SignalWorkflowExecutionRequest{ + Namespace: w.ns, WorkflowExecution: w.execution, + SignalName: "wake", Identity: "tester", RequestId: uuid.NewString(), + }) + w.s.NoError(err) +} + +// startStreamingWorkflow runs a workflow on the active cluster through one +// publish of three records, a subscription to that stream and the task that +// consumes them, then returns it with the stream nodes the active cluster holds. +func (s *streamFailoverBase) startStreamingWorkflow( + ctx context.Context, ns string, +) (*streamingWorkflow, []string) { + id := "stream-failover-" + uuid.NewString() + tq := &taskqueuepb.TaskQueue{Name: id + "-tq", Kind: enumspb.TASK_QUEUE_KIND_NORMAL} + we, err := s.clusters[0].FrontendClient().StartWorkflowExecution(ctx, + &workflowservice.StartWorkflowExecutionRequest{ + RequestId: uuid.NewString(), + Namespace: ns, + WorkflowId: id, + WorkflowType: &commonpb.WorkflowType{Name: "stream-consumer"}, + TaskQueue: tq, + WorkflowRunTimeout: durationpb.New(300 * time.Second), + WorkflowTaskTimeout: durationpb.New(10 * time.Second), + Identity: "tester", + }) + s.NoError(err) + w := &streamingWorkflow{ + s: s, + ns: ns, + execution: &commonpb.WorkflowExecution{WorkflowId: id, RunId: we.GetRunId()}, + tq: tq, + } + + w.runTask(0, publishCommand("a", "b", "c")) + _, err = s.streamClient(0).SubscribeWorkflow(ctx, &streamlib.SubscribeWorkflowRequest{ + FrontendRequest: &streamlib.SubscribeWorkflowInput{ + Namespace: ns, WorkflowId: id, StreamName: chasmworkflow.DefaultStreamName, StartOffset: 0, + }, + }) + s.NoError(err) + consumed := w.currentSlice(w.runTask(0, nil)) + s.Equal([]string{"a", "b", "c"}, apiBodies(consumed.GetRecords())) + + activeNodes := s.streamNodesOn(ctx, 0, ns, w.execution) + s.Equal([]string{ + "StreamCursors", "StreamCursors#output", + "Streams", "Streams#output", "Streams$output$Batches", "Streams$output$Batches#0", + }, activeNodes, "the active cluster holds the stream, its one batch and the cursor") + return w, activeNodes +} + +// With state-based replication the stream follows the namespace to the +// standby with its records, its consumer state and the subscription, and the +// workflow keeps consuming and publishing there. +func (s *StreamFailoverSuite) TestStreamFollowsTheNamespaceToTheStandby() { + ns := s.createGlobalNamespace() + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + w, activeNodes := s.startStreamingWorkflow(ctx, ns) + + // The standby holds the same tree before the namespace moves. + await.Require(ctx, s.T(), func(t *await.T) { + require.Equal(t, activeNodes, s.streamNodesOn(ctx, 1, ns, w.execution), + "the standby's CHASM tree must carry the stream, its batches and the cursor") + }, replicationWaitTime, replicationCheckInterval) + + s.failover(ns, 0, s.clusters[1].ClusterName(), 2) + + // The records and the frontier are readable on the new active cluster. + described, err := s.streamClient(1).DescribeWorkflowStream(ctx, + &streamlib.DescribeWorkflowStreamRequest{ + FrontendRequest: &streamlib.DescribeWorkflowStreamInput{ + Namespace: ns, WorkflowId: w.execution.GetWorkflowId(), + }, + }) + s.NoError(err) + s.Equal(int64(3), described.GetFrontendResponse().GetState().GetHeadOffset()) + + polled, err := s.streamClient(1).PollWorkflowMessages(ctx, &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: ns, WorkflowId: w.execution.GetWorkflowId(), FromOffset: 0, + }, + }) + s.NoError(err) + s.Equal([]string{"a", "b", "c"}, storedBodies(polled.GetFrontendResponse().GetRecords())) + + // The workflow goes on consuming and publishing there. Its first task on + // the new cluster is a cold one, so the range it consumed before the + // failover is re-supplied from the replicated stream. + w.signal(ctx, 1) + afterFailover := w.runTask(1, publishCommand("d")) + var replayed *streampb.StreamSlice + for _, sl := range afterFailover { + if sl.GetWorkflowTaskCompletedEventId() != 0 && sl.GetToOffset() > sl.GetFromOffset() { + replayed = sl + } + } + s.NotNil(replayed, "the cold task on the new cluster re-supplies the consumed range") + s.Equal([]string{"a", "b", "c"}, apiBodies(replayed.GetRecords())) + s.Equal(int64(3), w.currentSlice(afterFailover).GetFromOffset()) + + next := w.currentSlice(w.runTask(1, nil)) + s.Equal(int64(3), next.GetFromOffset()) + s.Equal(int64(4), next.GetToOffset()) + s.Equal([]string{"d"}, apiBodies(next.GetRecords())) + + polled, err = s.streamClient(1).PollWorkflowMessages(ctx, &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: ns, WorkflowId: w.execution.GetWorkflowId(), FromOffset: 0, + }, + }) + s.NoError(err) + s.Equal([]string{"a", "b", "c", "d"}, storedBodies(polled.GetFrontendResponse().GetRecords())) +} + +// With event-based replication the standby rebuilds its state from History +// events, and the events carry the subscription and the offsets it consumed +// but never a record. So the standby ends up with the cursor and without the +// stream: the frontier reads as an unwritten stream, no record can be polled, +// and the workflow's first task there cannot find the stream its cursor names. +// Carrying the stream under this mode would take a replication task of its +// own for the component, the way state-based replication ships the CHASM +// tree; the appended event cannot carry it without putting payloads in History. +func (s *StreamEventReplicationSuite) TestStreamDoesNotReplicateUnderEventBasedReplicationYet() { + ns := s.createGlobalNamespace() + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + w, _ := s.startStreamingWorkflow(ctx, ns) + + // Every replication task has been acknowledged by the standby, so what it + // holds now is what this mode carries. + s.waitForClusterSynced() + await.Require(ctx, s.T(), func(t *await.T) { + require.Equal(t, []string{"StreamCursors", "StreamCursors#output"}, + s.streamNodesOn(ctx, 1, ns, w.execution), + "the standby rebuilds the cursor from the recorded ranges and nothing of the stream") + }, replicationWaitTime, replicationCheckInterval) + + s.failover(ns, 0, s.clusters[1].ClusterName(), 2) + + described, err := s.streamClient(1).DescribeWorkflowStream(ctx, + &streamlib.DescribeWorkflowStreamRequest{ + FrontendRequest: &streamlib.DescribeWorkflowStreamInput{ + Namespace: ns, WorkflowId: w.execution.GetWorkflowId(), + }, + }) + s.NoError(err) + s.Equal(int64(0), described.GetFrontendResponse().GetState().GetHeadOffset(), + "the new active cluster sees a stream nothing has written to") + + polled, err := s.streamClient(1).PollWorkflowMessages(ctx, &streamlib.PollWorkflowMessagesRequest{ + FrontendRequest: &streamlib.PollWorkflowMessagesInput{ + Namespace: ns, WorkflowId: w.execution.GetWorkflowId(), FromOffset: 0, + }, + }) + s.NoError(err) + s.Empty(polled.GetFrontendResponse().GetRecords(), "the records did not follow the namespace") +}