diff --git a/.gen/proto/matching/v1/service.pb.go b/.gen/proto/matching/v1/service.pb.go index 5de1f7d2463..dbe83f60179 100644 --- a/.gen/proto/matching/v1/service.pb.go +++ b/.gen/proto/matching/v1/service.pb.go @@ -50,20 +50,69 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -type TaskListPartitionConfig struct { - Version int64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - NumReadPartitions int32 `protobuf:"varint,2,opt,name=num_read_partitions,json=numReadPartitions,proto3" json:"num_read_partitions,omitempty"` - NumWritePartitions int32 `protobuf:"varint,3,opt,name=num_write_partitions,json=numWritePartitions,proto3" json:"num_write_partitions,omitempty"` +type TaskListPartition struct { + IsolationGroups []string `protobuf:"bytes,1,rep,name=isolation_groups,json=isolationGroups,proto3" json:"isolation_groups,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } +func (m *TaskListPartition) Reset() { *m = TaskListPartition{} } +func (m *TaskListPartition) String() string { return proto.CompactTextString(m) } +func (*TaskListPartition) ProtoMessage() {} +func (*TaskListPartition) Descriptor() ([]byte, []int) { + return fileDescriptor_826e827d3aabf7fc, []int{0} +} +func (m *TaskListPartition) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TaskListPartition) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TaskListPartition.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TaskListPartition) XXX_Merge(src proto.Message) { + xxx_messageInfo_TaskListPartition.Merge(m, src) +} +func (m *TaskListPartition) XXX_Size() int { + return m.Size() +} +func (m *TaskListPartition) XXX_DiscardUnknown() { + xxx_messageInfo_TaskListPartition.DiscardUnknown(m) +} + +var xxx_messageInfo_TaskListPartition proto.InternalMessageInfo + +func (m *TaskListPartition) GetIsolationGroups() []string { + if m != nil { + return m.IsolationGroups + } + return nil +} + +type TaskListPartitionConfig struct { + Version int64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + NumReadPartitions int32 `protobuf:"varint,2,opt,name=num_read_partitions,json=numReadPartitions,proto3" json:"num_read_partitions,omitempty"` // Deprecated: Do not use. + NumWritePartitions int32 `protobuf:"varint,3,opt,name=num_write_partitions,json=numWritePartitions,proto3" json:"num_write_partitions,omitempty"` // Deprecated: Do not use. + ReadPartitions map[int32]*TaskListPartition `protobuf:"bytes,4,rep,name=read_partitions,json=readPartitions,proto3" json:"read_partitions,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + WritePartitions map[int32]*TaskListPartition `protobuf:"bytes,5,rep,name=write_partitions,json=writePartitions,proto3" json:"write_partitions,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + func (m *TaskListPartitionConfig) Reset() { *m = TaskListPartitionConfig{} } func (m *TaskListPartitionConfig) String() string { return proto.CompactTextString(m) } func (*TaskListPartitionConfig) ProtoMessage() {} func (*TaskListPartitionConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{0} + return fileDescriptor_826e827d3aabf7fc, []int{1} } func (m *TaskListPartitionConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -99,6 +148,7 @@ func (m *TaskListPartitionConfig) GetVersion() int64 { return 0 } +// Deprecated: Do not use. func (m *TaskListPartitionConfig) GetNumReadPartitions() int32 { if m != nil { return m.NumReadPartitions @@ -106,6 +156,7 @@ func (m *TaskListPartitionConfig) GetNumReadPartitions() int32 { return 0 } +// Deprecated: Do not use. func (m *TaskListPartitionConfig) GetNumWritePartitions() int32 { if m != nil { return m.NumWritePartitions @@ -113,6 +164,20 @@ func (m *TaskListPartitionConfig) GetNumWritePartitions() int32 { return 0 } +func (m *TaskListPartitionConfig) GetReadPartitions() map[int32]*TaskListPartition { + if m != nil { + return m.ReadPartitions + } + return nil +} + +func (m *TaskListPartitionConfig) GetWritePartitions() map[int32]*TaskListPartition { + if m != nil { + return m.WritePartitions + } + return nil +} + type LoadBalancerHints struct { BacklogCount int64 `protobuf:"varint,1,opt,name=backlog_count,json=backlogCount,proto3" json:"backlog_count,omitempty"` RatePerSecond float64 `protobuf:"fixed64,2,opt,name=rate_per_second,json=ratePerSecond,proto3" json:"rate_per_second,omitempty"` @@ -125,7 +190,7 @@ func (m *LoadBalancerHints) Reset() { *m = LoadBalancerHints{} } func (m *LoadBalancerHints) String() string { return proto.CompactTextString(m) } func (*LoadBalancerHints) ProtoMessage() {} func (*LoadBalancerHints) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{1} + return fileDescriptor_826e827d3aabf7fc, []int{2} } func (m *LoadBalancerHints) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -183,7 +248,7 @@ func (m *PollForDecisionTaskRequest) Reset() { *m = PollForDecisionTaskR func (m *PollForDecisionTaskRequest) String() string { return proto.CompactTextString(m) } func (*PollForDecisionTaskRequest) ProtoMessage() {} func (*PollForDecisionTaskRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{2} + return fileDescriptor_826e827d3aabf7fc, []int{3} } func (m *PollForDecisionTaskRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -278,7 +343,7 @@ func (m *PollForDecisionTaskResponse) Reset() { *m = PollForDecisionTask func (m *PollForDecisionTaskResponse) String() string { return proto.CompactTextString(m) } func (*PollForDecisionTaskResponse) ProtoMessage() {} func (*PollForDecisionTaskResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{3} + return fileDescriptor_826e827d3aabf7fc, []int{4} } func (m *PollForDecisionTaskResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -469,7 +534,7 @@ func (m *PollForActivityTaskRequest) Reset() { *m = PollForActivityTaskR func (m *PollForActivityTaskRequest) String() string { return proto.CompactTextString(m) } func (*PollForActivityTaskRequest) ProtoMessage() {} func (*PollForActivityTaskRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{4} + return fileDescriptor_826e827d3aabf7fc, []int{5} } func (m *PollForActivityTaskRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -562,7 +627,7 @@ func (m *PollForActivityTaskResponse) Reset() { *m = PollForActivityTask func (m *PollForActivityTaskResponse) String() string { return proto.CompactTextString(m) } func (*PollForActivityTaskResponse) ProtoMessage() {} func (*PollForActivityTaskResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{5} + return fileDescriptor_826e827d3aabf7fc, []int{6} } func (m *PollForActivityTaskResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -742,7 +807,7 @@ func (m *AddDecisionTaskRequest) Reset() { *m = AddDecisionTaskRequest{} func (m *AddDecisionTaskRequest) String() string { return proto.CompactTextString(m) } func (*AddDecisionTaskRequest) ProtoMessage() {} func (*AddDecisionTaskRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{6} + return fileDescriptor_826e827d3aabf7fc, []int{7} } func (m *AddDecisionTaskRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -838,7 +903,7 @@ func (m *AddDecisionTaskResponse) Reset() { *m = AddDecisionTaskResponse func (m *AddDecisionTaskResponse) String() string { return proto.CompactTextString(m) } func (*AddDecisionTaskResponse) ProtoMessage() {} func (*AddDecisionTaskResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{7} + return fileDescriptor_826e827d3aabf7fc, []int{8} } func (m *AddDecisionTaskResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -894,7 +959,7 @@ func (m *AddActivityTaskRequest) Reset() { *m = AddActivityTaskRequest{} func (m *AddActivityTaskRequest) String() string { return proto.CompactTextString(m) } func (*AddActivityTaskRequest) ProtoMessage() {} func (*AddActivityTaskRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{8} + return fileDescriptor_826e827d3aabf7fc, []int{9} } func (m *AddActivityTaskRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1010,7 +1075,7 @@ func (m *ActivityTaskDispatchInfo) Reset() { *m = ActivityTaskDispatchIn func (m *ActivityTaskDispatchInfo) String() string { return proto.CompactTextString(m) } func (*ActivityTaskDispatchInfo) ProtoMessage() {} func (*ActivityTaskDispatchInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{9} + return fileDescriptor_826e827d3aabf7fc, []int{10} } func (m *ActivityTaskDispatchInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1099,7 +1164,7 @@ func (m *AddActivityTaskResponse) Reset() { *m = AddActivityTaskResponse func (m *AddActivityTaskResponse) String() string { return proto.CompactTextString(m) } func (*AddActivityTaskResponse) ProtoMessage() {} func (*AddActivityTaskResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{10} + return fileDescriptor_826e827d3aabf7fc, []int{11} } func (m *AddActivityTaskResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1149,7 +1214,7 @@ func (m *QueryWorkflowRequest) Reset() { *m = QueryWorkflowRequest{} } func (m *QueryWorkflowRequest) String() string { return proto.CompactTextString(m) } func (*QueryWorkflowRequest) ProtoMessage() {} func (*QueryWorkflowRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{11} + return fileDescriptor_826e827d3aabf7fc, []int{12} } func (m *QueryWorkflowRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1218,7 +1283,7 @@ func (m *QueryWorkflowResponse) Reset() { *m = QueryWorkflowResponse{} } func (m *QueryWorkflowResponse) String() string { return proto.CompactTextString(m) } func (*QueryWorkflowResponse) ProtoMessage() {} func (*QueryWorkflowResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{12} + return fileDescriptor_826e827d3aabf7fc, []int{13} } func (m *QueryWorkflowResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1275,7 +1340,7 @@ func (m *RespondQueryTaskCompletedRequest) Reset() { *m = RespondQueryTa func (m *RespondQueryTaskCompletedRequest) String() string { return proto.CompactTextString(m) } func (*RespondQueryTaskCompletedRequest) ProtoMessage() {} func (*RespondQueryTaskCompletedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{13} + return fileDescriptor_826e827d3aabf7fc, []int{14} } func (m *RespondQueryTaskCompletedRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1342,7 +1407,7 @@ func (m *RespondQueryTaskCompletedResponse) Reset() { *m = RespondQueryT func (m *RespondQueryTaskCompletedResponse) String() string { return proto.CompactTextString(m) } func (*RespondQueryTaskCompletedResponse) ProtoMessage() {} func (*RespondQueryTaskCompletedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{14} + return fileDescriptor_826e827d3aabf7fc, []int{15} } func (m *RespondQueryTaskCompletedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1385,7 +1450,7 @@ func (m *CancelOutstandingPollRequest) Reset() { *m = CancelOutstandingP func (m *CancelOutstandingPollRequest) String() string { return proto.CompactTextString(m) } func (*CancelOutstandingPollRequest) ProtoMessage() {} func (*CancelOutstandingPollRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{15} + return fileDescriptor_826e827d3aabf7fc, []int{16} } func (m *CancelOutstandingPollRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1452,7 +1517,7 @@ func (m *CancelOutstandingPollResponse) Reset() { *m = CancelOutstanding func (m *CancelOutstandingPollResponse) String() string { return proto.CompactTextString(m) } func (*CancelOutstandingPollResponse) ProtoMessage() {} func (*CancelOutstandingPollResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{16} + return fileDescriptor_826e827d3aabf7fc, []int{17} } func (m *CancelOutstandingPollResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1493,7 +1558,7 @@ func (m *DescribeTaskListRequest) Reset() { *m = DescribeTaskListRequest func (m *DescribeTaskListRequest) String() string { return proto.CompactTextString(m) } func (*DescribeTaskListRequest) ProtoMessage() {} func (*DescribeTaskListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{17} + return fileDescriptor_826e827d3aabf7fc, []int{18} } func (m *DescribeTaskListRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1549,7 +1614,7 @@ func (m *DescribeTaskListResponse) Reset() { *m = DescribeTaskListRespon func (m *DescribeTaskListResponse) String() string { return proto.CompactTextString(m) } func (*DescribeTaskListResponse) ProtoMessage() {} func (*DescribeTaskListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{18} + return fileDescriptor_826e827d3aabf7fc, []int{19} } func (m *DescribeTaskListResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1611,7 +1676,7 @@ func (m *ListTaskListPartitionsRequest) Reset() { *m = ListTaskListParti func (m *ListTaskListPartitionsRequest) String() string { return proto.CompactTextString(m) } func (*ListTaskListPartitionsRequest) ProtoMessage() {} func (*ListTaskListPartitionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{19} + return fileDescriptor_826e827d3aabf7fc, []int{20} } func (m *ListTaskListPartitionsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1666,7 +1731,7 @@ func (m *ListTaskListPartitionsResponse) Reset() { *m = ListTaskListPart func (m *ListTaskListPartitionsResponse) String() string { return proto.CompactTextString(m) } func (*ListTaskListPartitionsResponse) ProtoMessage() {} func (*ListTaskListPartitionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{20} + return fileDescriptor_826e827d3aabf7fc, []int{21} } func (m *ListTaskListPartitionsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1720,7 +1785,7 @@ func (m *GetTaskListsByDomainRequest) Reset() { *m = GetTaskListsByDomai func (m *GetTaskListsByDomainRequest) String() string { return proto.CompactTextString(m) } func (*GetTaskListsByDomainRequest) ProtoMessage() {} func (*GetTaskListsByDomainRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{21} + return fileDescriptor_826e827d3aabf7fc, []int{22} } func (m *GetTaskListsByDomainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1768,7 +1833,7 @@ func (m *GetTaskListsByDomainResponse) Reset() { *m = GetTaskListsByDoma func (m *GetTaskListsByDomainResponse) String() string { return proto.CompactTextString(m) } func (*GetTaskListsByDomainResponse) ProtoMessage() {} func (*GetTaskListsByDomainResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{22} + return fileDescriptor_826e827d3aabf7fc, []int{23} } func (m *GetTaskListsByDomainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1825,7 +1890,7 @@ func (m *UpdateTaskListPartitionConfigRequest) Reset() { *m = UpdateTask func (m *UpdateTaskListPartitionConfigRequest) String() string { return proto.CompactTextString(m) } func (*UpdateTaskListPartitionConfigRequest) ProtoMessage() {} func (*UpdateTaskListPartitionConfigRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{23} + return fileDescriptor_826e827d3aabf7fc, []int{24} } func (m *UpdateTaskListPartitionConfigRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1892,7 +1957,7 @@ func (m *UpdateTaskListPartitionConfigResponse) Reset() { *m = UpdateTas func (m *UpdateTaskListPartitionConfigResponse) String() string { return proto.CompactTextString(m) } func (*UpdateTaskListPartitionConfigResponse) ProtoMessage() {} func (*UpdateTaskListPartitionConfigResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{24} + return fileDescriptor_826e827d3aabf7fc, []int{25} } func (m *UpdateTaskListPartitionConfigResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1935,7 +2000,7 @@ func (m *RefreshTaskListPartitionConfigRequest) Reset() { *m = RefreshTa func (m *RefreshTaskListPartitionConfigRequest) String() string { return proto.CompactTextString(m) } func (*RefreshTaskListPartitionConfigRequest) ProtoMessage() {} func (*RefreshTaskListPartitionConfigRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{25} + return fileDescriptor_826e827d3aabf7fc, []int{26} } func (m *RefreshTaskListPartitionConfigRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2004,7 +2069,7 @@ func (m *RefreshTaskListPartitionConfigResponse) Reset() { func (m *RefreshTaskListPartitionConfigResponse) String() string { return proto.CompactTextString(m) } func (*RefreshTaskListPartitionConfigResponse) ProtoMessage() {} func (*RefreshTaskListPartitionConfigResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_826e827d3aabf7fc, []int{26} + return fileDescriptor_826e827d3aabf7fc, []int{27} } func (m *RefreshTaskListPartitionConfigResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2034,7 +2099,10 @@ func (m *RefreshTaskListPartitionConfigResponse) XXX_DiscardUnknown() { var xxx_messageInfo_RefreshTaskListPartitionConfigResponse proto.InternalMessageInfo func init() { + proto.RegisterType((*TaskListPartition)(nil), "uber.cadence.matching.v1.TaskListPartition") proto.RegisterType((*TaskListPartitionConfig)(nil), "uber.cadence.matching.v1.TaskListPartitionConfig") + proto.RegisterMapType((map[int32]*TaskListPartition)(nil), "uber.cadence.matching.v1.TaskListPartitionConfig.ReadPartitionsEntry") + proto.RegisterMapType((map[int32]*TaskListPartition)(nil), "uber.cadence.matching.v1.TaskListPartitionConfig.WritePartitionsEntry") proto.RegisterType((*LoadBalancerHints)(nil), "uber.cadence.matching.v1.LoadBalancerHints") proto.RegisterType((*PollForDecisionTaskRequest)(nil), "uber.cadence.matching.v1.PollForDecisionTaskRequest") proto.RegisterType((*PollForDecisionTaskResponse)(nil), "uber.cadence.matching.v1.PollForDecisionTaskResponse") @@ -2073,159 +2141,201 @@ func init() { } var fileDescriptor_826e827d3aabf7fc = []byte{ - // 2430 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x5b, 0x6f, 0x1c, 0x49, - 0xf5, 0x57, 0xfb, 0xee, 0x33, 0xf6, 0xd8, 0x2e, 0x7b, 0x9d, 0xce, 0x24, 0x76, 0x9c, 0xc9, 0x26, - 0xeb, 0xff, 0x9f, 0x65, 0x1c, 0x7b, 0x37, 0x21, 0x9b, 0x15, 0x04, 0x5f, 0x72, 0x19, 0xb4, 0x21, - 0xd9, 0x8e, 0x37, 0x91, 0x60, 0x95, 0xa6, 0x3c, 0x5d, 0xf6, 0x34, 0x9e, 0xe9, 0xee, 0x74, 0x55, - 0x8f, 0x77, 0x78, 0xe0, 0x01, 0x01, 0x42, 0xe2, 0x95, 0x7d, 0x07, 0x96, 0xcf, 0xc1, 0x33, 0x8f, - 0x3c, 0x22, 0xad, 0x90, 0x50, 0x24, 0x3e, 0x00, 0x48, 0x3c, 0x22, 0xa1, 0xba, 0xf4, 0x4c, 0xf7, - 0x4c, 0xf5, 0x5c, 0x6c, 0x67, 0x97, 0x07, 0xde, 0xdc, 0x55, 0xe7, 0x56, 0xa7, 0xce, 0x39, 0xbf, - 0x73, 0x6a, 0x0c, 0x37, 0xa2, 0x03, 0x12, 0x6e, 0x54, 0xb0, 0x43, 0xbc, 0x0a, 0xd9, 0xa8, 0x63, - 0x56, 0xa9, 0xba, 0xde, 0xd1, 0x46, 0x63, 0x73, 0x83, 0x92, 0xb0, 0xe1, 0x56, 0x48, 0x29, 0x08, - 0x7d, 0xe6, 0x23, 0x93, 0xd3, 0x95, 0x14, 0x5d, 0x29, 0xa6, 0x2b, 0x35, 0x36, 0x0b, 0xab, 0x47, - 0xbe, 0x7f, 0x54, 0x23, 0x1b, 0x82, 0xee, 0x20, 0x3a, 0xdc, 0x70, 0xa2, 0x10, 0x33, 0xd7, 0xf7, - 0x24, 0x67, 0xe1, 0x4a, 0xe7, 0x3e, 0x73, 0xeb, 0x84, 0x32, 0x5c, 0x0f, 0x14, 0x41, 0x97, 0x80, - 0x93, 0x10, 0x07, 0x01, 0x09, 0xa9, 0xda, 0x5f, 0x4b, 0x99, 0x88, 0x03, 0x97, 0x5b, 0x57, 0xf1, - 0xeb, 0xf5, 0xb6, 0x0a, 0x1d, 0xc5, 0xab, 0x88, 0x84, 0x4d, 0x45, 0x50, 0xd4, 0x11, 0x30, 0x4c, - 0x8f, 0x6b, 0x2e, 0x65, 0x8a, 0x66, 0x5d, 0x47, 0xa3, 0x9c, 0x60, 0x9f, 0xf8, 0xe1, 0x31, 0x09, - 0x15, 0xe5, 0xff, 0xf7, 0xa3, 0x3c, 0xac, 0xf9, 0x27, 0x8a, 0xf6, 0xaa, 0x8e, 0xb6, 0xea, 0x52, - 0xe6, 0xb7, 0x8c, 0x7b, 0x3b, 0x45, 0x42, 0xab, 0x38, 0x24, 0x4e, 0x37, 0xd5, 0xf5, 0x0c, 0xaa, - 0xf4, 0x29, 0x8a, 0x9f, 0x1b, 0x70, 0x61, 0x1f, 0xd3, 0xe3, 0x8f, 0x5c, 0xca, 0x9e, 0xe2, 0x90, - 0xb9, 0xfc, 0x26, 0x76, 0x7d, 0xef, 0xd0, 0x3d, 0x42, 0x26, 0x4c, 0x36, 0x48, 0x48, 0x5d, 0xdf, - 0x33, 0x8d, 0x35, 0x63, 0x7d, 0xd4, 0x8a, 0x3f, 0x51, 0x09, 0x16, 0xbd, 0xa8, 0x6e, 0x87, 0x04, - 0x3b, 0x76, 0x10, 0x73, 0x51, 0x73, 0x64, 0xcd, 0x58, 0x1f, 0xb7, 0x16, 0xbc, 0xa8, 0x6e, 0x11, - 0xec, 0xb4, 0xc4, 0x51, 0x74, 0x13, 0x96, 0x38, 0xfd, 0x49, 0xe8, 0x32, 0x92, 0x64, 0x18, 0x15, - 0x0c, 0xc8, 0x8b, 0xea, 0x2f, 0xf8, 0x56, 0x9b, 0xa3, 0xf8, 0x23, 0x58, 0xf8, 0xc8, 0xc7, 0xce, - 0x0e, 0xae, 0x61, 0xaf, 0x42, 0xc2, 0x47, 0xae, 0xc7, 0x28, 0xba, 0x06, 0xb3, 0x07, 0xb8, 0x72, - 0x5c, 0xf3, 0x8f, 0xec, 0x8a, 0x1f, 0x79, 0x4c, 0x99, 0x35, 0xa3, 0x16, 0x77, 0xf9, 0x1a, 0xba, - 0x01, 0x73, 0x21, 0xe6, 0x6a, 0x48, 0x68, 0x53, 0x52, 0xf1, 0x3d, 0x47, 0xd8, 0x65, 0x58, 0xb3, - 0x7c, 0xf9, 0x29, 0x09, 0x9f, 0x89, 0xc5, 0xe2, 0x3f, 0x0c, 0x28, 0x3c, 0xf5, 0x6b, 0xb5, 0x07, - 0x7e, 0xb8, 0x47, 0x2a, 0x2e, 0x3f, 0x17, 0x77, 0x84, 0x45, 0x5e, 0x45, 0x84, 0x32, 0x54, 0x86, - 0xc9, 0x50, 0xfe, 0x29, 0xb4, 0xe4, 0xb6, 0x36, 0x4a, 0xa9, 0x90, 0xc6, 0x81, 0x5b, 0x6a, 0x6c, - 0x96, 0xb2, 0x25, 0x58, 0x31, 0x3f, 0xba, 0x04, 0xd3, 0x8e, 0x5f, 0xc7, 0xae, 0x67, 0xbb, 0xd2, - 0x96, 0x69, 0x6b, 0x4a, 0x2e, 0x94, 0x1d, 0xbe, 0x19, 0xf8, 0xb5, 0x1a, 0x09, 0xf9, 0xe6, 0xa8, - 0xdc, 0x94, 0x0b, 0x65, 0x07, 0x5d, 0x87, 0xfc, 0xa1, 0x1f, 0x9e, 0xe0, 0xd0, 0x21, 0x8e, 0x7d, - 0x18, 0xfa, 0x75, 0x73, 0x4c, 0x50, 0xcc, 0xb6, 0x56, 0x1f, 0x84, 0x7e, 0x1d, 0xbd, 0x03, 0x73, - 0x2e, 0xf5, 0x6b, 0x22, 0x8b, 0xec, 0xa3, 0xd0, 0x8f, 0x02, 0x73, 0x5c, 0xd0, 0xe5, 0x5b, 0xcb, - 0x0f, 0xf9, 0x6a, 0xf1, 0x8f, 0x39, 0xb8, 0xa4, 0xb5, 0x98, 0x06, 0xbe, 0x47, 0x09, 0x5a, 0x01, - 0xe0, 0xf1, 0x61, 0x33, 0xff, 0x98, 0xc8, 0x4b, 0x9f, 0xb1, 0xa6, 0xf9, 0xca, 0x3e, 0x5f, 0x40, - 0x9f, 0x00, 0x8a, 0xc3, 0xd5, 0x26, 0x9f, 0x91, 0x4a, 0xc4, 0x25, 0x8b, 0x13, 0xe5, 0xb6, 0x6e, - 0x68, 0xdd, 0xf3, 0x42, 0x91, 0xdf, 0x8f, 0xa9, 0xad, 0x85, 0x93, 0xce, 0x25, 0xf4, 0x00, 0x66, - 0x5b, 0x62, 0x59, 0x33, 0x20, 0xc2, 0x0d, 0xb9, 0xad, 0xab, 0x3d, 0x25, 0xee, 0x37, 0x03, 0x62, - 0xcd, 0x9c, 0x24, 0xbe, 0xd0, 0x73, 0xb8, 0x18, 0x84, 0xa4, 0xe1, 0xfa, 0x11, 0xb5, 0x29, 0xc3, - 0x21, 0x23, 0x8e, 0x4d, 0x1a, 0xc4, 0x63, 0xdc, 0xb5, 0x63, 0x42, 0xe6, 0xa5, 0x92, 0x2c, 0x1e, - 0xa5, 0xb8, 0x78, 0x94, 0xca, 0x1e, 0xbb, 0xfd, 0xfe, 0x73, 0x5c, 0x8b, 0x88, 0xb5, 0x1c, 0x73, - 0x3f, 0x93, 0xcc, 0xf7, 0x39, 0x6f, 0xd9, 0x41, 0xeb, 0x30, 0xdf, 0x25, 0x6e, 0x5c, 0x44, 0x5e, - 0x9e, 0xa6, 0x29, 0x4d, 0x98, 0xc4, 0x8c, 0x91, 0x7a, 0xc0, 0xcc, 0x09, 0x11, 0xda, 0xf1, 0x27, - 0x2a, 0xc2, 0xac, 0x47, 0x3e, 0x63, 0x6d, 0x01, 0x93, 0x42, 0x40, 0x8e, 0x2f, 0xc6, 0xdc, 0xef, - 0x02, 0x4a, 0x85, 0xb7, 0x5d, 0x75, 0x3d, 0x66, 0x4e, 0x09, 0xc2, 0xf9, 0x64, 0x8c, 0xf3, 0x6c, - 0x40, 0x77, 0xc0, 0xa4, 0xcc, 0xad, 0x1c, 0x37, 0xdb, 0x57, 0x61, 0x13, 0x0f, 0x1f, 0xd4, 0x88, - 0x63, 0x4e, 0xaf, 0x19, 0xeb, 0x53, 0xd6, 0xb2, 0xdc, 0x6f, 0x39, 0xfa, 0xbe, 0xdc, 0x45, 0x77, - 0x60, 0x5c, 0x14, 0x3b, 0x13, 0x84, 0x4f, 0x8a, 0x3d, 0xfd, 0xfc, 0x31, 0xa7, 0xb4, 0x24, 0x03, - 0xb2, 0x60, 0xd6, 0x51, 0x71, 0x63, 0xbb, 0xde, 0xa1, 0x6f, 0xe6, 0x84, 0x84, 0x6f, 0xa6, 0x25, - 0xc8, 0x62, 0xc3, 0x85, 0xec, 0x87, 0xd8, 0xa3, 0x2e, 0xf1, 0x58, 0x1c, 0x6d, 0x65, 0xef, 0xd0, - 0xb7, 0x66, 0x9c, 0xc4, 0x17, 0x7a, 0x09, 0x97, 0xbb, 0x83, 0xca, 0x16, 0x61, 0xc8, 0xeb, 0x94, - 0x39, 0x23, 0x54, 0xac, 0x68, 0x8d, 0x8c, 0x2b, 0x97, 0x75, 0xb1, 0x2b, 0xaa, 0xe2, 0x2d, 0x5e, - 0xab, 0xa4, 0xd3, 0x79, 0x75, 0x24, 0x76, 0x5c, 0xd1, 0x66, 0x65, 0xad, 0x12, 0x5b, 0xcf, 0xf8, - 0xce, 0x73, 0x55, 0xdb, 0xae, 0xc2, 0xcc, 0x41, 0x88, 0xbd, 0x4a, 0x55, 0x65, 0x41, 0x5e, 0x64, - 0x41, 0x4e, 0xae, 0xc9, 0x3c, 0xd8, 0x86, 0x3c, 0xad, 0x54, 0x89, 0x13, 0xd5, 0x88, 0x63, 0x73, - 0x78, 0x32, 0xe7, 0x84, 0x91, 0x85, 0xae, 0xe8, 0xda, 0x8f, 0xb1, 0xcb, 0x9a, 0x6d, 0x71, 0xf0, - 0x35, 0xf4, 0x6d, 0x98, 0x89, 0x63, 0x4a, 0x08, 0x98, 0xef, 0x2b, 0x20, 0xa7, 0xe8, 0x05, 0xfb, - 0xa7, 0x30, 0xc9, 0x6f, 0xc4, 0x25, 0xd4, 0x5c, 0x58, 0x1b, 0x5d, 0xcf, 0x6d, 0xed, 0x94, 0xb2, - 0x00, 0xb7, 0xd4, 0x23, 0xe1, 0x4b, 0x1f, 0x4b, 0x21, 0xf7, 0x3d, 0x16, 0x36, 0xad, 0x58, 0x24, - 0x77, 0x19, 0xf3, 0x19, 0xae, 0xd9, 0x0a, 0x52, 0xec, 0x83, 0x26, 0x23, 0xd4, 0x44, 0x22, 0x12, - 0x17, 0xc4, 0xd6, 0x23, 0xb9, 0xb3, 0xc3, 0x37, 0xd0, 0xa7, 0x30, 0xdf, 0x2a, 0xea, 0x76, 0x45, - 0x80, 0x87, 0xb9, 0x28, 0x0e, 0xb4, 0x99, 0x6d, 0x56, 0x06, 0xea, 0x58, 0x73, 0x41, 0x07, 0x0c, - 0xfd, 0x10, 0x16, 0x6b, 0x3e, 0x76, 0xec, 0x03, 0x85, 0x05, 0x22, 0x2d, 0xa8, 0xb9, 0x24, 0x14, - 0x7c, 0x23, 0x5b, 0x41, 0x17, 0x7e, 0x58, 0x0b, 0xb5, 0x2e, 0x48, 0x79, 0x0c, 0xf3, 0x38, 0x62, - 0xbe, 0xb2, 0x5a, 0x66, 0xdc, 0x5b, 0x42, 0xf2, 0x35, 0x6d, 0xc4, 0x6d, 0x47, 0xcc, 0x97, 0x76, - 0x71, 0x7e, 0x2b, 0x8f, 0x53, 0xdf, 0x85, 0x97, 0x30, 0x93, 0x74, 0x29, 0x9a, 0x87, 0xd1, 0x63, - 0xd2, 0x14, 0x95, 0x74, 0xda, 0xe2, 0x7f, 0xf2, 0xe4, 0x6b, 0xf0, 0x6a, 0xa3, 0xca, 0xe6, 0x40, - 0xc9, 0x27, 0x18, 0xee, 0x8e, 0xdc, 0x31, 0x92, 0xa0, 0xb5, 0x5d, 0x61, 0x6e, 0xc3, 0x65, 0xcd, - 0xd3, 0x83, 0x96, 0x46, 0xc2, 0x7f, 0x23, 0x68, 0x7d, 0x0e, 0x2d, 0xd0, 0x4a, 0x5b, 0xfc, 0xb5, - 0x82, 0xd6, 0x15, 0xc8, 0x61, 0x65, 0x4d, 0xdb, 0x09, 0x10, 0x2f, 0x95, 0x1d, 0x8e, 0x6a, 0x2d, - 0x02, 0x81, 0x6a, 0x63, 0x3d, 0x50, 0xad, 0x75, 0x30, 0x81, 0x6a, 0x38, 0xf1, 0x85, 0xb6, 0x60, - 0xdc, 0xf5, 0x82, 0x88, 0x09, 0xef, 0xe4, 0xb6, 0x2e, 0xeb, 0x6f, 0x14, 0x37, 0x79, 0x6c, 0x5b, - 0x92, 0x54, 0x53, 0xa0, 0x26, 0xce, 0x5a, 0xa0, 0x26, 0x87, 0x2b, 0x50, 0xfb, 0x70, 0x31, 0x96, - 0x67, 0xf3, 0xf4, 0xaa, 0xf9, 0x94, 0x08, 0x41, 0x7e, 0x24, 0x21, 0x2d, 0xb7, 0x75, 0xb1, 0x4b, - 0xd6, 0x9e, 0x9a, 0x04, 0xac, 0xe5, 0x98, 0x77, 0xdf, 0xdf, 0xe5, 0x9c, 0xfb, 0x92, 0x11, 0x7d, - 0x1f, 0x96, 0x85, 0x92, 0x6e, 0x91, 0xd3, 0xfd, 0x44, 0x2e, 0x0a, 0xc6, 0x0e, 0x79, 0x0f, 0x60, - 0xa1, 0x4a, 0x70, 0xc8, 0x0e, 0x08, 0x66, 0x2d, 0x51, 0xd0, 0x4f, 0xd4, 0x7c, 0x8b, 0x27, 0x96, - 0x93, 0xc0, 0xfd, 0x5c, 0x1a, 0xf7, 0x5f, 0xc2, 0x6a, 0xfa, 0x26, 0x6c, 0xff, 0xd0, 0x66, 0x55, - 0x97, 0xda, 0x31, 0xc3, 0x4c, 0x5f, 0xc7, 0x16, 0x52, 0x37, 0xf3, 0xe4, 0x70, 0xbf, 0xea, 0xd2, - 0x6d, 0x25, 0xbf, 0x9c, 0x3c, 0x81, 0x43, 0x18, 0x76, 0x6b, 0x54, 0x60, 0x5b, 0xbf, 0x48, 0x69, - 0x1f, 0x62, 0x4f, 0x72, 0x75, 0xb7, 0x61, 0xf9, 0xd3, 0xb5, 0x61, 0xef, 0xc0, 0x5c, 0x4b, 0x8e, - 0xac, 0x18, 0x02, 0x1e, 0xa7, 0xad, 0x7c, 0xbc, 0xbc, 0x27, 0x56, 0xd1, 0x7b, 0x30, 0x51, 0x25, - 0xd8, 0x21, 0xa1, 0x42, 0xbf, 0x4b, 0x5a, 0x4d, 0x8f, 0x04, 0x89, 0xa5, 0x48, 0xb3, 0xd0, 0x60, - 0xe1, 0x5c, 0xd0, 0xe0, 0xcd, 0x02, 0x99, 0x0e, 0x6b, 0x96, 0x4e, 0x8d, 0x35, 0xc5, 0xbf, 0x8c, - 0xc1, 0xf2, 0xb6, 0xe3, 0xe8, 0x86, 0x97, 0x54, 0xf1, 0x36, 0x3a, 0x8a, 0xf7, 0x1b, 0x2a, 0x88, - 0x77, 0x61, 0xba, 0xdd, 0xb4, 0x8d, 0x0e, 0xd2, 0xb4, 0x4d, 0xb1, 0xb8, 0x47, 0xbb, 0x02, 0xb9, - 0x56, 0xb5, 0x50, 0xbd, 0xfa, 0xa8, 0x05, 0xf1, 0x52, 0xd9, 0xe9, 0x2c, 0x27, 0xaa, 0x08, 0xa8, - 0x84, 0x1d, 0x1f, 0xa2, 0x9c, 0x88, 0xd6, 0x3e, 0x4e, 0xdb, 0xbb, 0x30, 0x41, 0xfd, 0x28, 0xac, - 0xc8, 0xf2, 0x98, 0xef, 0x04, 0xe3, 0x44, 0x1f, 0x8b, 0xe9, 0xf1, 0x33, 0x41, 0x69, 0x29, 0x0e, - 0x0d, 0xca, 0x4d, 0xea, 0x50, 0x2e, 0xd0, 0x44, 0xd4, 0x94, 0xe8, 0xd8, 0xee, 0x67, 0x47, 0x94, - 0xfe, 0x56, 0x4b, 0x1d, 0x01, 0x26, 0x9b, 0xb6, 0xce, 0x28, 0x2b, 0xec, 0xc0, 0x92, 0x8e, 0x50, - 0xd3, 0x8a, 0x2c, 0x25, 0x5b, 0x91, 0xe9, 0x64, 0x9b, 0x71, 0x02, 0x17, 0xba, 0x6c, 0x50, 0x68, - 0xab, 0x4b, 0x11, 0xe3, 0xbc, 0x52, 0xa4, 0xf8, 0xcf, 0x71, 0x11, 0xd3, 0xba, 0xde, 0xe6, 0xeb, - 0x88, 0x69, 0x3e, 0xf9, 0x89, 0xeb, 0xb6, 0xdb, 0xaa, 0x25, 0xd2, 0xe7, 0xe5, 0xfa, 0x5e, 0x6c, - 0x40, 0x2a, 0xfa, 0xc7, 0xce, 0x14, 0xfd, 0xe3, 0xc3, 0x45, 0xff, 0xc4, 0xd9, 0xa3, 0x7f, 0xf2, - 0x1c, 0xa2, 0x7f, 0x4a, 0x17, 0xfd, 0x1e, 0x98, 0x38, 0x71, 0x95, 0x7b, 0x2e, 0x0d, 0x78, 0x54, - 0xf0, 0xb9, 0x4f, 0x21, 0xf6, 0x56, 0x8f, 0x2c, 0xc8, 0xe0, 0xb4, 0x32, 0x65, 0x6a, 0xb3, 0x0d, - 0x06, 0xc8, 0x36, 0x4d, 0xbc, 0x7d, 0x85, 0xd9, 0xf6, 0xe5, 0x28, 0x98, 0x59, 0x87, 0x45, 0xdf, - 0x83, 0xb9, 0x76, 0x03, 0x21, 0xa6, 0x55, 0x95, 0x6e, 0x7a, 0x5c, 0x56, 0x73, 0x99, 0x78, 0x52, - 0xb0, 0xda, 0x4d, 0xa0, 0xf8, 0xee, 0xea, 0xe9, 0x46, 0x86, 0xeb, 0xe9, 0x12, 0x5d, 0xce, 0xe8, - 0xb0, 0x5d, 0xce, 0xd8, 0xf9, 0x77, 0x39, 0xe3, 0xe7, 0xd3, 0xe5, 0x4c, 0x9c, 0x5b, 0x97, 0x33, - 0xa9, 0xeb, 0x72, 0x54, 0x2d, 0xd5, 0x4e, 0x2e, 0x6f, 0xb6, 0x96, 0x7e, 0x69, 0xc0, 0x92, 0x18, - 0x20, 0xe3, 0x53, 0xc4, 0x95, 0x74, 0xb7, 0x73, 0x4a, 0xfc, 0x3f, 0xed, 0xe1, 0x75, 0xbc, 0x03, - 0xce, 0x87, 0x67, 0xe9, 0x05, 0x06, 0x1b, 0x1f, 0x8b, 0x5f, 0x18, 0xf0, 0x56, 0x87, 0x85, 0xca, - 0xab, 0xf7, 0x60, 0x46, 0xbc, 0x56, 0xd9, 0x21, 0xa1, 0x51, 0x2d, 0x3e, 0x63, 0xef, 0x38, 0xc9, - 0x09, 0x0e, 0x4b, 0x30, 0xa0, 0x32, 0xe4, 0x63, 0x01, 0x3f, 0x26, 0x15, 0x46, 0x9c, 0x9e, 0xb3, - 0xba, 0x9c, 0xd1, 0x15, 0xa5, 0x35, 0xfb, 0x2a, 0xf9, 0x59, 0xfc, 0xbb, 0x01, 0x6b, 0xd2, 0x30, - 0x47, 0xd0, 0xf1, 0xf3, 0xee, 0xfa, 0xf5, 0xa0, 0x46, 0x38, 0xb1, 0x72, 0xe5, 0x93, 0xce, 0xfb, - 0xb8, 0xa5, 0x55, 0xd4, 0x4f, 0xce, 0x57, 0x70, 0x37, 0x17, 0x60, 0x52, 0xf0, 0xaa, 0x1e, 0x6d, - 0xda, 0x9a, 0xe0, 0x9f, 0x65, 0xa7, 0x78, 0x0d, 0xae, 0xf6, 0x30, 0x4f, 0x5e, 0x4c, 0xf1, 0xaf, - 0x06, 0x5c, 0xde, 0xe5, 0xdd, 0x76, 0xed, 0x49, 0xc4, 0x28, 0xc3, 0x9e, 0xe3, 0x7a, 0x47, 0x7c, - 0xb2, 0x1f, 0x08, 0xe2, 0x53, 0x6f, 0x0e, 0x23, 0x1d, 0x6f, 0x0e, 0x0f, 0x21, 0xdf, 0x3a, 0x54, - 0xfb, 0x0d, 0x39, 0x9f, 0x91, 0xd6, 0xf1, 0xc9, 0x64, 0x5a, 0xb3, 0xc4, 0xd7, 0x59, 0x70, 0xbc, - 0x78, 0x05, 0x56, 0x32, 0x8e, 0xa7, 0x1c, 0xf0, 0x53, 0xb8, 0xb0, 0x47, 0x68, 0x25, 0x74, 0x0f, - 0x48, 0x8b, 0x5d, 0x1d, 0xfd, 0x41, 0x67, 0x0c, 0xbc, 0xab, 0xd5, 0x9a, 0xc1, 0x3e, 0xd8, 0xd5, - 0x17, 0xff, 0x6d, 0x80, 0xd9, 0x2d, 0x41, 0xa5, 0xcd, 0x07, 0x30, 0x29, 0xdd, 0x49, 0x4d, 0x43, - 0x40, 0xe6, 0x95, 0xcc, 0xb7, 0x23, 0x12, 0x0a, 0x1c, 0x8e, 0xe9, 0xf9, 0x60, 0xd3, 0xf6, 0x3e, - 0x65, 0x98, 0x45, 0x54, 0xa5, 0xcc, 0xb5, 0x9e, 0xbe, 0x7b, 0x26, 0x48, 0xad, 0x3c, 0x4b, 0x7d, - 0xa3, 0x17, 0x9a, 0xb2, 0x38, 0xda, 0xc3, 0x29, 0x03, 0x57, 0x44, 0x0a, 0x2b, 0xe2, 0xa2, 0x3b, - 0xe9, 0x69, 0x7c, 0x0b, 0xcb, 0x30, 0xa1, 0x6a, 0xb9, 0x8c, 0x3e, 0xf5, 0x95, 0x8e, 0x8a, 0x91, - 0xe1, 0xa2, 0xe2, 0x97, 0x23, 0xb0, 0x9a, 0xa5, 0x55, 0xb9, 0xfe, 0x15, 0xac, 0xb4, 0x9f, 0x8a, - 0x5a, 0x8e, 0x4c, 0xfc, 0x4e, 0x26, 0x2f, 0xa4, 0x34, 0xd8, 0xe9, 0x1f, 0x13, 0x86, 0x1d, 0xcc, - 0xb0, 0x55, 0x48, 0xf6, 0x49, 0x69, 0xd5, 0x5c, 0x65, 0xeb, 0x25, 0x5f, 0xab, 0x72, 0xe4, 0x74, - 0x2a, 0x9d, 0xc4, 0xcc, 0x90, 0x56, 0x59, 0xbc, 0x05, 0x97, 0x1e, 0x92, 0x96, 0x1b, 0xe8, 0x4e, - 0x53, 0x02, 0x64, 0x1f, 0xdf, 0x17, 0xff, 0x30, 0x06, 0x97, 0xf5, 0x7c, 0xca, 0x7b, 0x3f, 0x37, - 0x60, 0x59, 0x73, 0x96, 0x3a, 0x0e, 0x94, 0xdf, 0x9e, 0x64, 0x83, 0x69, 0x2f, 0xc1, 0xa5, 0xbd, - 0x8e, 0xb3, 0x3c, 0xc6, 0x81, 0xec, 0x02, 0x17, 0x9d, 0xee, 0x1d, 0x61, 0x86, 0xe6, 0x16, 0xb9, - 0x19, 0x23, 0x67, 0x32, 0x63, 0xbb, 0xe3, 0x16, 0xdb, 0x66, 0xe0, 0xee, 0x9d, 0xc2, 0x4f, 0x78, - 0x8a, 0xeb, 0xed, 0xd6, 0x34, 0xa5, 0x8f, 0xd2, 0xaf, 0xd1, 0x3d, 0xba, 0xf1, 0xac, 0xba, 0x91, - 0x68, 0x64, 0xb9, 0xee, 0x2c, 0x63, 0xdf, 0xb4, 0xee, 0xe2, 0xef, 0x46, 0xe0, 0xed, 0x4f, 0x02, - 0x07, 0x33, 0x92, 0x55, 0x0e, 0x06, 0x01, 0x99, 0x33, 0x24, 0xfa, 0xf9, 0x61, 0x90, 0xae, 0xfe, - 0x8d, 0x9d, 0x47, 0xfd, 0x7b, 0x07, 0xae, 0xf7, 0x71, 0x91, 0x02, 0xaa, 0xdf, 0x8f, 0xc0, 0x75, - 0x8b, 0x1c, 0x86, 0x84, 0x56, 0xff, 0xe7, 0xcd, 0x2c, 0x6f, 0xae, 0xc3, 0x8d, 0x7e, 0x3e, 0x92, - 0xee, 0xdc, 0xfa, 0xd7, 0x0c, 0xe4, 0x1e, 0xab, 0x78, 0xde, 0x7e, 0x5a, 0x46, 0x3f, 0x33, 0x60, - 0x51, 0xf3, 0xab, 0x1c, 0x7a, 0x7f, 0xc8, 0x1f, 0xf1, 0xc4, 0x15, 0x14, 0x6e, 0x9d, 0xea, 0xa7, - 0xbf, 0xa4, 0x11, 0xc9, 0xa4, 0x1d, 0xc0, 0x08, 0xcd, 0xb4, 0x3c, 0x80, 0x11, 0xda, 0x09, 0xa8, - 0x01, 0x73, 0x1d, 0x0f, 0x4d, 0xe8, 0xe6, 0xb0, 0xef, 0x62, 0x85, 0xcd, 0x21, 0x38, 0x52, 0x7a, - 0x53, 0xe7, 0xbe, 0x39, 0xec, 0x0b, 0x41, 0x1f, 0xbd, 0xda, 0xf3, 0x06, 0x30, 0x9b, 0x1a, 0x5a, - 0x50, 0x29, 0x5b, 0x86, 0x6e, 0xfe, 0x2a, 0x6c, 0x0c, 0x4c, 0xaf, 0x34, 0xfe, 0xc6, 0x80, 0x8b, - 0x99, 0xad, 0x39, 0xba, 0x9b, 0x2d, 0xae, 0xdf, 0xb8, 0x51, 0xf8, 0xf0, 0x54, 0xbc, 0xca, 0xac, - 0x5f, 0x19, 0xf0, 0x96, 0xb6, 0x59, 0x46, 0xb7, 0xb3, 0xc5, 0xf6, 0x1a, 0x1e, 0x0a, 0xdf, 0x1a, - 0x9a, 0x4f, 0x99, 0xd2, 0x84, 0xf9, 0x4e, 0x80, 0x41, 0x9b, 0xc3, 0x80, 0x91, 0xd4, 0x7f, 0x0a, - 0xfc, 0x42, 0xbf, 0x36, 0x60, 0x59, 0xdf, 0x1b, 0xa2, 0x1e, 0xc7, 0xe9, 0xd9, 0xc3, 0x16, 0xee, - 0x0c, 0xcf, 0xa8, 0xac, 0xf9, 0x85, 0x01, 0x4b, 0xba, 0x4e, 0x04, 0xdd, 0x1a, 0xb6, 0x73, 0x91, - 0x96, 0xdc, 0x3e, 0x5d, 0xc3, 0x83, 0x7e, 0x6b, 0xc0, 0x4a, 0x4f, 0x9c, 0x42, 0xdf, 0xc9, 0x96, - 0x3c, 0x48, 0x0f, 0x50, 0xb8, 0x77, 0x6a, 0x7e, 0x65, 0xe2, 0x17, 0x06, 0xac, 0xf6, 0x2e, 0xfe, - 0xe8, 0x5e, 0xaf, 0xf4, 0x18, 0x00, 0x5a, 0x0b, 0xdf, 0x3d, 0xbd, 0x00, 0x69, 0xe5, 0xce, 0xc3, - 0x3f, 0xbd, 0x5e, 0x35, 0xfe, 0xfc, 0x7a, 0xd5, 0xf8, 0xdb, 0xeb, 0x55, 0xe3, 0x07, 0x1f, 0x1c, - 0xb9, 0xac, 0x1a, 0x1d, 0x94, 0x2a, 0x7e, 0x7d, 0x23, 0xf5, 0xcf, 0x81, 0xa5, 0x23, 0xe2, 0xc9, - 0xff, 0xa6, 0x4c, 0xfe, 0x43, 0xe7, 0x87, 0xf1, 0xdf, 0x8d, 0xcd, 0x83, 0x09, 0xb1, 0xfb, 0xde, - 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x09, 0xed, 0xcf, 0x40, 0xfe, 0x29, 0x00, 0x00, + // 2519 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x1c, 0x49, + 0x15, 0x57, 0xdb, 0x1e, 0x7f, 0xbc, 0xb1, 0xc7, 0x76, 0xd9, 0xeb, 0x74, 0x26, 0xb1, 0xe3, 0x4c, + 0x36, 0x59, 0x2f, 0x2c, 0xe3, 0xb5, 0x77, 0x13, 0xb2, 0x59, 0xb1, 0xc1, 0x1f, 0x71, 0x32, 0x68, + 0x43, 0xb2, 0x1d, 0x6f, 0x22, 0xc1, 0x2a, 0x4d, 0x79, 0xba, 0xec, 0x69, 0x3c, 0xd3, 0xdd, 0xe9, + 0xaa, 0xb6, 0xd7, 0x7b, 0xe0, 0x80, 0x00, 0x21, 0x71, 0x85, 0x3b, 0xb0, 0xfc, 0x1d, 0x9c, 0x39, + 0x72, 0x44, 0x5a, 0x21, 0x41, 0x24, 0xfe, 0x00, 0x90, 0x38, 0x22, 0xa1, 0xfa, 0xe8, 0x99, 0xee, + 0x99, 0xea, 0xf9, 0xb0, 0x9d, 0x2c, 0x07, 0x6e, 0xee, 0xaa, 0xf7, 0x5d, 0xef, 0xbd, 0xdf, 0xab, + 0x1a, 0xc3, 0x8d, 0x68, 0x8f, 0x84, 0xab, 0x55, 0xec, 0x10, 0xaf, 0x4a, 0x56, 0x1b, 0x98, 0x55, + 0x6b, 0xae, 0x77, 0xb0, 0x7a, 0xb4, 0xb6, 0x4a, 0x49, 0x78, 0xe4, 0x56, 0x49, 0x39, 0x08, 0x7d, + 0xe6, 0x23, 0x93, 0xd3, 0x95, 0x15, 0x5d, 0x39, 0xa6, 0x2b, 0x1f, 0xad, 0x15, 0x97, 0x0e, 0x7c, + 0xff, 0xa0, 0x4e, 0x56, 0x05, 0xdd, 0x5e, 0xb4, 0xbf, 0xea, 0x44, 0x21, 0x66, 0xae, 0xef, 0x49, + 0xce, 0xe2, 0x95, 0xf6, 0x7d, 0xe6, 0x36, 0x08, 0x65, 0xb8, 0x11, 0x28, 0x82, 0x0e, 0x01, 0xc7, + 0x21, 0x0e, 0x02, 0x12, 0x52, 0xb5, 0xbf, 0x9c, 0x32, 0x11, 0x07, 0x2e, 0xb7, 0xae, 0xea, 0x37, + 0x1a, 0x2d, 0x15, 0x3a, 0x8a, 0x17, 0x11, 0x09, 0x4f, 0x14, 0x41, 0x49, 0x47, 0xc0, 0x30, 0x3d, + 0xac, 0xbb, 0x94, 0x29, 0x9a, 0x15, 0x1d, 0x8d, 0x0a, 0x82, 0x7d, 0xec, 0x87, 0x87, 0x24, 0x54, + 0x94, 0xdf, 0xe8, 0x45, 0xb9, 0x5f, 0xf7, 0x8f, 0x15, 0xed, 0x55, 0x1d, 0x6d, 0xcd, 0xa5, 0xcc, + 0x6f, 0x1a, 0xf7, 0x66, 0x8a, 0x84, 0xd6, 0x70, 0x48, 0x9c, 0x4e, 0xaa, 0xeb, 0x19, 0x54, 0x69, + 0x2f, 0x4a, 0x1f, 0xc1, 0xec, 0x2e, 0xa6, 0x87, 0x1f, 0xbb, 0x94, 0x3d, 0xc6, 0x21, 0x73, 0xf9, + 0x41, 0xa0, 0xb7, 0x61, 0xc6, 0xa5, 0x7e, 0x5d, 0x9c, 0x8a, 0x7d, 0x10, 0xfa, 0x51, 0x40, 0x4d, + 0x63, 0x79, 0x78, 0x65, 0xc2, 0x9a, 0x6e, 0xae, 0xdf, 0x17, 0xcb, 0xa5, 0xbf, 0x8f, 0xc0, 0x85, + 0x0e, 0x01, 0x5b, 0xbe, 0xb7, 0xef, 0x1e, 0x20, 0x13, 0xc6, 0x8e, 0x48, 0x48, 0x5d, 0xdf, 0x33, + 0x8d, 0x65, 0x63, 0x65, 0xd8, 0x8a, 0x3f, 0xd1, 0x3a, 0xcc, 0x79, 0x51, 0xc3, 0x0e, 0x09, 0x76, + 0xec, 0x20, 0xe6, 0xa2, 0xe6, 0xd0, 0xb2, 0xb1, 0x92, 0xdb, 0x1c, 0x32, 0x0d, 0x6b, 0xd6, 0x8b, + 0x1a, 0x16, 0xc1, 0x4e, 0x53, 0x24, 0x45, 0xef, 0xc3, 0x3c, 0xe7, 0x39, 0x0e, 0x5d, 0x46, 0x92, + 0x4c, 0xc3, 0x4d, 0x26, 0xe4, 0x45, 0x8d, 0x67, 0x7c, 0x3b, 0xc1, 0xe5, 0xc1, 0x74, 0xbb, 0x96, + 0x91, 0xe5, 0xe1, 0x95, 0xfc, 0xfa, 0xbd, 0x72, 0x56, 0x86, 0x96, 0x33, 0xfc, 0x29, 0xa7, 0x0d, + 0xba, 0xe7, 0xb1, 0xf0, 0xc4, 0x2a, 0x84, 0x69, 0x2b, 0x5f, 0xc0, 0x4c, 0x87, 0x85, 0x39, 0xa1, + 0x70, 0x67, 0x70, 0x85, 0x6d, 0xce, 0x48, 0x8d, 0xd3, 0xc7, 0xe9, 0xd5, 0xa2, 0x07, 0x73, 0x1a, + 0xcb, 0xd0, 0x0c, 0x0c, 0x1f, 0x92, 0x13, 0x11, 0xf9, 0x9c, 0xc5, 0xff, 0x44, 0x1b, 0x90, 0x3b, + 0xc2, 0xf5, 0x88, 0x88, 0x38, 0xe7, 0xd7, 0xbf, 0x39, 0x80, 0x41, 0x96, 0xe4, 0xbc, 0x33, 0x74, + 0xdb, 0x28, 0xfa, 0x30, 0xaf, 0x33, 0xec, 0x95, 0x29, 0x2c, 0xfd, 0x08, 0x66, 0x3f, 0xf6, 0xb1, + 0xb3, 0x89, 0xeb, 0xd8, 0xab, 0x92, 0xf0, 0x81, 0xeb, 0x31, 0x8a, 0xae, 0xc1, 0xd4, 0x1e, 0xae, + 0x1e, 0xd6, 0xfd, 0x03, 0xbb, 0xea, 0x47, 0x1e, 0x53, 0x29, 0x36, 0xa9, 0x16, 0xb7, 0xf8, 0x1a, + 0xba, 0x01, 0xd3, 0x21, 0xe6, 0x87, 0x41, 0x42, 0x9b, 0x92, 0xaa, 0xef, 0x39, 0xc2, 0x14, 0xc3, + 0x9a, 0xe2, 0xcb, 0x8f, 0x49, 0xf8, 0x44, 0x2c, 0x96, 0xfe, 0x69, 0x40, 0xf1, 0xb1, 0x5f, 0xaf, + 0xef, 0xf8, 0xe1, 0x36, 0xa9, 0xba, 0x3c, 0x47, 0xb9, 0x45, 0x16, 0x79, 0x11, 0x11, 0xca, 0x50, + 0x05, 0xc6, 0x42, 0xf9, 0xa7, 0xd0, 0x92, 0x5f, 0x5f, 0x4d, 0x7b, 0x82, 0x03, 0x97, 0x3b, 0x91, + 0x2d, 0xc1, 0x8a, 0xf9, 0xd1, 0x25, 0x98, 0x70, 0xfc, 0x06, 0x76, 0x3d, 0xdb, 0x95, 0xb6, 0x4c, + 0x58, 0xe3, 0x72, 0xa1, 0xe2, 0xf0, 0xcd, 0xc0, 0xaf, 0xd7, 0x49, 0xc8, 0x37, 0x87, 0xe5, 0xa6, + 0x5c, 0xa8, 0x38, 0xe8, 0x3a, 0x14, 0xf6, 0xfd, 0xf0, 0x18, 0x87, 0x0e, 0x71, 0xec, 0xfd, 0xd0, + 0x6f, 0x98, 0x23, 0x82, 0x62, 0xaa, 0xb9, 0xba, 0x13, 0xfa, 0x0d, 0xf4, 0x16, 0x4c, 0xb7, 0xd5, + 0xae, 0x99, 0x13, 0x74, 0x85, 0x74, 0xe9, 0x96, 0xfe, 0x98, 0x87, 0x4b, 0x5a, 0x8b, 0x69, 0xe0, + 0x7b, 0x94, 0xa0, 0x45, 0x00, 0xde, 0x2b, 0x6c, 0xe6, 0x1f, 0x12, 0x59, 0xc0, 0x93, 0xd6, 0x04, + 0x5f, 0xd9, 0xe5, 0x0b, 0xe8, 0x53, 0x40, 0x71, 0xeb, 0xb2, 0xc9, 0xe7, 0xa4, 0x1a, 0x71, 0xc9, + 0xea, 0xa0, 0x6f, 0x68, 0xc3, 0xf3, 0x4c, 0x91, 0xdf, 0x8b, 0xa9, 0xad, 0xd9, 0xe3, 0xf6, 0x25, + 0xb4, 0x03, 0x53, 0x4d, 0xb1, 0xec, 0x24, 0x20, 0x22, 0x0c, 0xf9, 0xf5, 0xab, 0x5d, 0x25, 0xee, + 0x9e, 0x04, 0xc4, 0x9a, 0x3c, 0x4e, 0x7c, 0xa1, 0xa7, 0x70, 0x31, 0x08, 0xc9, 0x91, 0xeb, 0x47, + 0xd4, 0xa6, 0x0c, 0x87, 0x8c, 0x38, 0x36, 0x39, 0x22, 0x1e, 0xe3, 0xa1, 0x1d, 0x11, 0x32, 0x2f, + 0x95, 0x25, 0x90, 0x94, 0x63, 0x20, 0x29, 0x57, 0x3c, 0x76, 0xeb, 0xfd, 0xa7, 0x3c, 0xef, 0xac, + 0x85, 0x98, 0xfb, 0x89, 0x64, 0xbe, 0xc7, 0x79, 0x2b, 0x0e, 0x5a, 0x81, 0x99, 0x0e, 0x71, 0x39, + 0x91, 0x79, 0x05, 0x9a, 0xa6, 0x34, 0x61, 0x0c, 0x33, 0x46, 0x1a, 0x01, 0x33, 0x47, 0x45, 0x49, + 0xc4, 0x9f, 0xa8, 0x04, 0x53, 0x1e, 0xf9, 0x9c, 0xb5, 0x04, 0x8c, 0x09, 0x01, 0x79, 0xbe, 0x18, + 0x73, 0xbf, 0x03, 0x28, 0x95, 0xde, 0x76, 0xcd, 0xf5, 0x98, 0x39, 0x2e, 0x08, 0x67, 0x92, 0x39, + 0xce, 0xab, 0x01, 0xdd, 0x06, 0x93, 0x32, 0xb7, 0x7a, 0x78, 0xd2, 0x3a, 0x0a, 0x9b, 0x78, 0x78, + 0xaf, 0x4e, 0x1c, 0x73, 0x62, 0xd9, 0x58, 0x19, 0xb7, 0x16, 0xe4, 0x7e, 0x33, 0xd0, 0xf7, 0xe4, + 0x2e, 0xba, 0x0d, 0x39, 0x01, 0x7c, 0x26, 0x88, 0x98, 0x94, 0xba, 0xc6, 0xf9, 0x13, 0x4e, 0x69, + 0x49, 0x06, 0x64, 0xc1, 0x94, 0xa3, 0xf2, 0xc6, 0x76, 0xbd, 0x7d, 0xdf, 0xcc, 0x0b, 0x09, 0xdf, + 0x4a, 0x4b, 0x90, 0xc0, 0x23, 0x4a, 0x3c, 0xc4, 0x1e, 0x75, 0x89, 0xc7, 0xe2, 0x6c, 0xab, 0x78, + 0xfb, 0xbe, 0x35, 0xe9, 0x24, 0xbe, 0xd0, 0x73, 0xb8, 0xdc, 0x99, 0x54, 0xb6, 0x48, 0x43, 0x8e, + 0x59, 0xe6, 0xa4, 0x50, 0xb1, 0xa8, 0x35, 0x32, 0x6e, 0x21, 0xd6, 0xc5, 0x8e, 0xac, 0x8a, 0xb7, + 0x50, 0x19, 0xe6, 0x64, 0xd0, 0x39, 0x52, 0x12, 0x3b, 0x46, 0xa7, 0x29, 0x71, 0x3e, 0xb3, 0x62, + 0xeb, 0x09, 0xdf, 0x79, 0xaa, 0x70, 0xea, 0x2a, 0x4c, 0xee, 0x85, 0xd8, 0xab, 0xd6, 0x54, 0x15, + 0x14, 0x44, 0x15, 0xe4, 0xe5, 0x9a, 0xac, 0x83, 0x0d, 0x28, 0xd0, 0x6a, 0x8d, 0x38, 0x51, 0x9d, + 0x38, 0x36, 0x1f, 0x55, 0xcc, 0x69, 0x61, 0x64, 0xb1, 0x23, 0xbb, 0x76, 0xe3, 0x39, 0xc6, 0x9a, + 0x6a, 0x72, 0xf0, 0x35, 0xf4, 0x1d, 0x98, 0x8c, 0x73, 0x4a, 0x08, 0x98, 0xe9, 0x29, 0x20, 0xaf, + 0xe8, 0x05, 0xfb, 0x67, 0x30, 0xc6, 0x4f, 0xc4, 0x25, 0xd4, 0x9c, 0x15, 0x48, 0xb3, 0x99, 0xdd, + 0x67, 0xbb, 0x14, 0x7c, 0xf9, 0x13, 0x29, 0x44, 0xa2, 0x4c, 0x2c, 0x92, 0x87, 0x8c, 0xf9, 0x0c, + 0xd7, 0x6d, 0x35, 0x5e, 0xd8, 0x7b, 0x27, 0x8c, 0x50, 0x13, 0x89, 0x4c, 0x9c, 0x15, 0x5b, 0x0f, + 0xe4, 0xce, 0x26, 0xdf, 0x40, 0x9f, 0xc1, 0x4c, 0x13, 0xfa, 0xec, 0xaa, 0xc0, 0x31, 0x73, 0x4e, + 0x38, 0xb4, 0x36, 0x30, 0x00, 0x5a, 0xd3, 0x41, 0xdb, 0x48, 0xf1, 0x43, 0x98, 0xab, 0xfb, 0xd8, + 0xb1, 0xf7, 0x14, 0x16, 0x88, 0xb2, 0xa0, 0xe6, 0x7c, 0x2f, 0x7c, 0xe9, 0xc0, 0x0f, 0x6b, 0xb6, + 0xde, 0x01, 0x29, 0x0f, 0x61, 0x06, 0x47, 0xcc, 0x57, 0x56, 0xcb, 0x8a, 0x7b, 0x43, 0x48, 0xbe, + 0xa6, 0xcd, 0xb8, 0x8d, 0x88, 0xf9, 0xd2, 0x2e, 0xce, 0x6f, 0x15, 0x70, 0xea, 0xbb, 0xf8, 0x1c, + 0x26, 0x93, 0x21, 0x4d, 0xe2, 0xe3, 0x84, 0xc4, 0xc7, 0xdb, 0x69, 0x7c, 0xec, 0xab, 0xf8, 0x5a, + 0xb0, 0x98, 0x00, 0xad, 0x8d, 0x2a, 0x73, 0x8f, 0x5c, 0x76, 0x72, 0x7a, 0xd0, 0xd2, 0x48, 0xf8, + 0x5f, 0x04, 0xad, 0xdf, 0x40, 0x13, 0xb4, 0xd2, 0x16, 0x7f, 0xad, 0xa0, 0x75, 0x05, 0xf2, 0x58, + 0x59, 0xd3, 0x0a, 0x02, 0xc4, 0x4b, 0x15, 0x87, 0xa3, 0x5a, 0x93, 0x40, 0xa0, 0xda, 0x48, 0x17, + 0x54, 0x6b, 0x3a, 0x26, 0x50, 0x0d, 0x27, 0xbe, 0xd0, 0x3a, 0xe4, 0x5c, 0x2f, 0x88, 0x98, 0x88, + 0x4e, 0x7e, 0xfd, 0xb2, 0xfe, 0x44, 0xf1, 0x09, 0xcf, 0x6d, 0x4b, 0x92, 0x6a, 0x1a, 0xd4, 0xe8, + 0x59, 0x1b, 0xd4, 0xd8, 0x60, 0x0d, 0x6a, 0x17, 0x2e, 0xc6, 0xf2, 0x6c, 0x5e, 0x5e, 0x75, 0x9f, + 0x12, 0x21, 0xc8, 0x8f, 0x24, 0xa4, 0xe5, 0xd7, 0x2f, 0x76, 0xc8, 0xda, 0x56, 0xb7, 0x42, 0x6b, + 0x21, 0xe6, 0xdd, 0xf5, 0xb7, 0x38, 0xe7, 0xae, 0x64, 0x44, 0xdf, 0x87, 0x05, 0xa1, 0xa4, 0x53, + 0xe4, 0x44, 0x2f, 0x91, 0x73, 0x82, 0xb1, 0x4d, 0xde, 0x0e, 0xcc, 0xd6, 0x08, 0x0e, 0xd9, 0x1e, + 0xc1, 0xac, 0x29, 0x0a, 0x7a, 0x89, 0x9a, 0x69, 0xf2, 0xc4, 0x72, 0x12, 0xb8, 0x9f, 0x4f, 0xe3, + 0xfe, 0x73, 0x58, 0x4a, 0x9f, 0x84, 0xed, 0xef, 0xdb, 0xac, 0xe6, 0x52, 0x3b, 0x66, 0x98, 0xec, + 0x19, 0xd8, 0x62, 0xea, 0x64, 0x1e, 0xed, 0xef, 0xd6, 0x5c, 0xba, 0xa1, 0xe4, 0x57, 0x92, 0x1e, + 0x38, 0x84, 0x61, 0xb7, 0x4e, 0x05, 0xb6, 0xf5, 0xca, 0x94, 0x96, 0x13, 0xdb, 0x92, 0xab, 0x73, + 0x0c, 0x2b, 0x9c, 0x6e, 0x0c, 0x7b, 0x0b, 0xa6, 0x9b, 0x72, 0x64, 0xc7, 0x10, 0xf0, 0x38, 0x61, + 0x15, 0xe2, 0xe5, 0x6d, 0xb1, 0x8a, 0xde, 0x83, 0xd1, 0x1a, 0xc1, 0x0e, 0x09, 0x15, 0xfa, 0x5d, + 0xd2, 0x6a, 0x7a, 0x20, 0x48, 0x2c, 0x45, 0x9a, 0x85, 0x06, 0xb3, 0xe7, 0x82, 0x06, 0xaf, 0x16, + 0xc8, 0x74, 0x58, 0x33, 0x7f, 0x6a, 0xac, 0x29, 0xfd, 0x65, 0x04, 0x16, 0x36, 0x1c, 0x47, 0x77, + 0x79, 0x49, 0x35, 0x6f, 0xa3, 0xad, 0x79, 0xbf, 0xa2, 0x86, 0x78, 0x07, 0x26, 0x5a, 0x43, 0xdb, + 0x70, 0x3f, 0x43, 0xdb, 0x38, 0x8b, 0x67, 0xb4, 0x2b, 0x90, 0x6f, 0x76, 0x0b, 0x35, 0xab, 0x0f, + 0x5b, 0x10, 0x2f, 0x55, 0x9c, 0xf6, 0x76, 0xa2, 0x9a, 0x80, 0x2a, 0xd8, 0xdc, 0x00, 0xed, 0x44, + 0x8c, 0xf6, 0x71, 0xd9, 0xde, 0x81, 0x51, 0xea, 0x47, 0x61, 0x55, 0xb6, 0xc7, 0x42, 0x3b, 0x18, + 0x27, 0xe6, 0x58, 0x4c, 0x0f, 0x9f, 0x08, 0x4a, 0x4b, 0x71, 0x68, 0x50, 0x6e, 0x4c, 0x87, 0x72, + 0x81, 0x26, 0xa3, 0xc6, 0x7b, 0x3d, 0x46, 0xe8, 0x4f, 0xb5, 0xdc, 0x96, 0x60, 0xea, 0x69, 0xa0, + 0x2d, 0xcb, 0x8a, 0x9b, 0x30, 0xaf, 0x23, 0xd4, 0x8c, 0x22, 0xf3, 0xc9, 0x51, 0x64, 0x22, 0x39, + 0x66, 0x1c, 0xc3, 0x85, 0x0e, 0x1b, 0x14, 0xda, 0xea, 0x4a, 0xc4, 0x38, 0xaf, 0x12, 0x29, 0xfd, + 0x2b, 0x27, 0x72, 0x5a, 0x37, 0xdb, 0x7c, 0x1d, 0x39, 0xcd, 0x6f, 0x7e, 0xe2, 0xb8, 0xed, 0x96, + 0x6a, 0x89, 0xf4, 0x05, 0xb9, 0xbe, 0x1d, 0x1b, 0x90, 0xca, 0xfe, 0x91, 0x33, 0x65, 0x7f, 0x6e, + 0xb0, 0xec, 0x1f, 0x3d, 0x7b, 0xf6, 0x8f, 0x9d, 0x43, 0xf6, 0x8f, 0xeb, 0xb2, 0xdf, 0x03, 0x13, + 0x27, 0x8e, 0x72, 0xdb, 0xa5, 0x01, 0xcf, 0x0a, 0x7e, 0xef, 0x53, 0x88, 0xbd, 0xde, 0xa5, 0x0a, + 0x32, 0x38, 0xad, 0x4c, 0x99, 0xda, 0x6a, 0x83, 0x3e, 0xaa, 0x4d, 0x93, 0x6f, 0xaf, 0xb1, 0xda, + 0xbe, 0x1a, 0x06, 0x33, 0xcb, 0x59, 0xf4, 0x3d, 0x98, 0x6e, 0x0d, 0x10, 0xe2, 0xb6, 0xaa, 0xca, + 0x4d, 0x8f, 0xcb, 0xea, 0x5e, 0x26, 0x9e, 0x14, 0xac, 0xd6, 0x10, 0x28, 0xbe, 0x3b, 0x66, 0xba, + 0xa1, 0xc1, 0x66, 0xba, 0xc4, 0x94, 0x33, 0x3c, 0xe8, 0x94, 0x33, 0x72, 0xfe, 0x53, 0x4e, 0xee, + 0x7c, 0xa6, 0x9c, 0xd1, 0x73, 0x9b, 0x72, 0xc6, 0x74, 0x53, 0x8e, 0xea, 0xa5, 0xda, 0x9b, 0xcb, + 0xab, 0xed, 0xa5, 0x5f, 0x19, 0x30, 0x2f, 0x2e, 0x90, 0xb1, 0x17, 0x71, 0x27, 0xdd, 0x6a, 0xbf, + 0x25, 0xbe, 0xad, 0x75, 0x5e, 0xc7, 0xdb, 0xe7, 0xfd, 0xf0, 0x2c, 0xb3, 0x40, 0x7f, 0xd7, 0xc7, + 0xd2, 0x97, 0x06, 0xbc, 0xd1, 0x66, 0xa1, 0x8a, 0xea, 0x5d, 0x98, 0x14, 0xaf, 0x55, 0x76, 0x48, + 0x68, 0x54, 0x8f, 0x7d, 0xec, 0x9e, 0x27, 0x79, 0xc1, 0x61, 0x09, 0x06, 0x54, 0x81, 0x42, 0x2c, + 0xe0, 0xc7, 0xa4, 0xca, 0x88, 0xd3, 0xf5, 0xae, 0x2e, 0xef, 0xe8, 0x8a, 0xd2, 0x9a, 0x7a, 0x91, + 0xfc, 0x2c, 0xfd, 0xc3, 0x80, 0x65, 0x69, 0x98, 0x23, 0xe8, 0xb8, 0xbf, 0x5b, 0x7e, 0x23, 0xa8, + 0x13, 0x4e, 0xac, 0x42, 0xf9, 0xa8, 0xfd, 0x3c, 0x6e, 0x6a, 0x15, 0xf5, 0x92, 0xf3, 0x1a, 0xce, + 0xe6, 0x02, 0x8c, 0x09, 0x5e, 0x35, 0xa3, 0x4d, 0x58, 0xa3, 0xfc, 0xb3, 0xe2, 0x94, 0xae, 0xc1, + 0xd5, 0x2e, 0xe6, 0xc9, 0x83, 0x29, 0xfd, 0xd5, 0x80, 0xcb, 0x5b, 0x7c, 0xda, 0xae, 0x3f, 0x8a, + 0x18, 0x65, 0xd8, 0x73, 0x5c, 0xef, 0x80, 0xdf, 0xec, 0xfb, 0x82, 0xf8, 0xd4, 0x9b, 0xc3, 0x50, + 0xdb, 0x9b, 0xc3, 0x7d, 0x28, 0x34, 0x9d, 0x6a, 0xbd, 0x21, 0x17, 0x32, 0xca, 0x3a, 0xf6, 0x4c, + 0x96, 0x35, 0x4b, 0x7c, 0x9d, 0x05, 0xc7, 0x4b, 0x57, 0x60, 0x31, 0xc3, 0x3d, 0x15, 0x80, 0x9f, + 0xc0, 0x85, 0x6d, 0x42, 0xab, 0xa1, 0xbb, 0x47, 0x9a, 0xec, 0xca, 0xf5, 0x9d, 0xf6, 0x1c, 0x78, + 0x47, 0xab, 0x35, 0x83, 0xbd, 0xbf, 0xa3, 0x2f, 0xfd, 0xc7, 0x00, 0xb3, 0x53, 0x82, 0x2a, 0x9b, + 0x0f, 0x60, 0x4c, 0x86, 0x53, 0xfe, 0xee, 0x97, 0x5f, 0xbf, 0x92, 0xf9, 0x76, 0x44, 0x42, 0x81, + 0xc3, 0x31, 0x3d, 0xbf, 0xd8, 0xb4, 0xa2, 0x4f, 0x19, 0x66, 0x11, 0x55, 0x25, 0x73, 0xad, 0x6b, + 0xec, 0x9e, 0x08, 0x52, 0xab, 0xc0, 0x52, 0xdf, 0xe8, 0x99, 0xa6, 0x2d, 0x0e, 0x77, 0x09, 0x4a, + 0xdf, 0x1d, 0x91, 0xc2, 0xa2, 0x38, 0xe8, 0x76, 0x7a, 0x1a, 0x9f, 0xc2, 0x02, 0x8c, 0xaa, 0x5e, + 0x2e, 0xb3, 0x4f, 0x7d, 0xa5, 0xb3, 0x62, 0x68, 0xb0, 0xac, 0xf8, 0xc5, 0x10, 0x2c, 0x65, 0x69, + 0x55, 0xa1, 0x7f, 0x01, 0x8b, 0xad, 0xa7, 0xa2, 0x66, 0x20, 0x13, 0xbf, 0x26, 0xca, 0x03, 0x29, + 0xf7, 0xe7, 0xfd, 0x43, 0xc2, 0xb0, 0x83, 0x19, 0xb6, 0x8a, 0xc9, 0x39, 0x29, 0xad, 0x9a, 0xab, + 0x6c, 0xbe, 0xe4, 0x6b, 0x55, 0x0e, 0x9d, 0x4e, 0xa5, 0x93, 0xb8, 0x33, 0xa4, 0x55, 0x96, 0x6e, + 0xc2, 0xa5, 0xfb, 0xa4, 0x19, 0x06, 0xba, 0x79, 0x22, 0x01, 0xb2, 0x47, 0xec, 0x4b, 0x7f, 0x18, + 0x81, 0xcb, 0x7a, 0x3e, 0x15, 0xbd, 0x9f, 0x19, 0xb0, 0xa0, 0xf1, 0xa5, 0x81, 0x03, 0x15, 0xb7, + 0x47, 0xd9, 0x60, 0xda, 0x4d, 0x70, 0x79, 0xbb, 0xcd, 0x97, 0x87, 0x38, 0x90, 0x53, 0xe0, 0x9c, + 0xd3, 0xb9, 0x23, 0xcc, 0xd0, 0x9c, 0x22, 0x37, 0x63, 0xe8, 0x4c, 0x66, 0x6c, 0xb4, 0x9d, 0x62, + 0xcb, 0x0c, 0xdc, 0xb9, 0x53, 0xfc, 0x82, 0x97, 0xb8, 0xde, 0x6e, 0xcd, 0x50, 0xfa, 0x20, 0xfd, + 0x1a, 0xdd, 0x65, 0x1a, 0xcf, 0xea, 0x1b, 0xc9, 0x5f, 0x89, 0xbf, 0x48, 0xcf, 0xb1, 0xaf, 0x53, + 0x77, 0xe9, 0x77, 0x43, 0xf0, 0xe6, 0xa7, 0x81, 0x83, 0x19, 0xc9, 0x6a, 0x07, 0xfd, 0x80, 0xcc, + 0x19, 0x0a, 0xfd, 0xfc, 0x30, 0x48, 0xd7, 0xff, 0x46, 0xce, 0xa3, 0xff, 0xbd, 0x05, 0xd7, 0x7b, + 0x84, 0x48, 0x01, 0xd5, 0xef, 0x87, 0xe0, 0xba, 0x45, 0xf6, 0x43, 0x42, 0x6b, 0xff, 0x8f, 0x66, + 0x56, 0x34, 0x57, 0xe0, 0x46, 0xaf, 0x18, 0xc9, 0x70, 0xae, 0xff, 0x7b, 0x12, 0xf2, 0x0f, 0x55, + 0x3e, 0x6f, 0x3c, 0xae, 0xa0, 0x9f, 0x1a, 0x30, 0xa7, 0xf9, 0x55, 0x0e, 0xbd, 0x3f, 0xe0, 0x8f, + 0x78, 0xe2, 0x08, 0x8a, 0x37, 0x4f, 0xf5, 0xd3, 0x5f, 0xd2, 0x88, 0x64, 0xd1, 0xf6, 0x61, 0x84, + 0xe6, 0xb6, 0xdc, 0x87, 0x11, 0xda, 0x1b, 0xd0, 0x11, 0x4c, 0xb7, 0x3d, 0x34, 0xa1, 0x77, 0x07, + 0x7d, 0x17, 0x2b, 0xae, 0x0d, 0xc0, 0x91, 0xd2, 0x9b, 0xf2, 0xfb, 0xdd, 0x41, 0x5f, 0x08, 0x7a, + 0xe8, 0xd5, 0xfa, 0x1b, 0xc0, 0x54, 0xea, 0xd2, 0x82, 0xca, 0xd9, 0x32, 0x74, 0xf7, 0xaf, 0xe2, + 0x6a, 0xdf, 0xf4, 0x4a, 0xe3, 0xaf, 0x0d, 0xb8, 0x98, 0x39, 0x9a, 0xa3, 0x3b, 0xd9, 0xe2, 0x7a, + 0x5d, 0x37, 0x8a, 0x1f, 0x9e, 0x8a, 0x57, 0x99, 0xf5, 0x4b, 0x03, 0xde, 0xd0, 0x0e, 0xcb, 0xe8, + 0x56, 0xb6, 0xd8, 0x6e, 0x97, 0x87, 0xe2, 0xb7, 0x07, 0xe6, 0x53, 0xa6, 0x9c, 0xc0, 0x4c, 0x3b, + 0xc0, 0xa0, 0xb5, 0x41, 0xc0, 0x48, 0xea, 0x3f, 0x05, 0x7e, 0xa1, 0x5f, 0x19, 0xb0, 0xa0, 0x9f, + 0x0d, 0x51, 0x17, 0x77, 0xba, 0xce, 0xb0, 0xc5, 0xdb, 0x83, 0x33, 0x2a, 0x6b, 0x7e, 0x6e, 0xc0, + 0xbc, 0x6e, 0x12, 0x41, 0x37, 0x07, 0x9d, 0x5c, 0xa4, 0x25, 0xb7, 0x4e, 0x37, 0xf0, 0xa0, 0xdf, + 0x1a, 0xb0, 0xd8, 0x15, 0xa7, 0xd0, 0x47, 0xd9, 0x92, 0xfb, 0x99, 0x01, 0x8a, 0x77, 0x4f, 0xcd, + 0xaf, 0x4c, 0xfc, 0xd2, 0x80, 0xa5, 0xee, 0xcd, 0x1f, 0xdd, 0xed, 0x56, 0x1e, 0x7d, 0x40, 0x6b, + 0xf1, 0xbb, 0xa7, 0x17, 0x20, 0xad, 0xdc, 0xbc, 0xff, 0xa7, 0x97, 0x4b, 0xc6, 0x9f, 0x5f, 0x2e, + 0x19, 0x7f, 0x7b, 0xb9, 0x64, 0xfc, 0xe0, 0x83, 0x03, 0x97, 0xd5, 0xa2, 0xbd, 0x72, 0xd5, 0x6f, + 0xac, 0xa6, 0xfe, 0x51, 0xb4, 0x7c, 0x40, 0x3c, 0xf9, 0x9f, 0xb5, 0xc9, 0x7f, 0xee, 0xfd, 0x30, + 0xfe, 0xfb, 0x68, 0x6d, 0x6f, 0x54, 0xec, 0xbe, 0xf7, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, + 0xff, 0x4c, 0xcb, 0x0a, 0x2c, 0x00, 0x00, +} + +func (m *TaskListPartition) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TaskListPartition) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TaskListPartition) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.IsolationGroups) > 0 { + for iNdEx := len(m.IsolationGroups) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.IsolationGroups[iNdEx]) + copy(dAtA[i:], m.IsolationGroups[iNdEx]) + i = encodeVarintService(dAtA, i, uint64(len(m.IsolationGroups[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil } func (m *TaskListPartitionConfig) Marshal() (dAtA []byte, err error) { @@ -2252,6 +2362,54 @@ func (m *TaskListPartitionConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.WritePartitions) > 0 { + for k := range m.WritePartitions { + v := m.WritePartitions[k] + baseI := i + if v != nil { + { + size, err := v.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintService(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i = encodeVarintService(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = encodeVarintService(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x2a + } + } + if len(m.ReadPartitions) > 0 { + for k := range m.ReadPartitions { + v := m.ReadPartitions[k] + baseI := i + if v != nil { + { + size, err := v.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintService(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i = encodeVarintService(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = encodeVarintService(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x22 + } + } if m.NumWritePartitions != 0 { i = encodeVarintService(dAtA, i, uint64(m.NumWritePartitions)) i-- @@ -4151,6 +4309,24 @@ func encodeVarintService(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *TaskListPartition) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.IsolationGroups) > 0 { + for _, s := range m.IsolationGroups { + l = len(s) + n += 1 + l + sovService(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *TaskListPartitionConfig) Size() (n int) { if m == nil { return 0 @@ -4166,6 +4342,32 @@ func (m *TaskListPartitionConfig) Size() (n int) { if m.NumWritePartitions != 0 { n += 1 + sovService(uint64(m.NumWritePartitions)) } + if len(m.ReadPartitions) > 0 { + for k, v := range m.ReadPartitions { + _ = k + _ = v + l = 0 + if v != nil { + l = v.Size() + l += 1 + sovService(uint64(l)) + } + mapEntrySize := 1 + sovService(uint64(k)) + l + n += mapEntrySize + 1 + sovService(uint64(mapEntrySize)) + } + } + if len(m.WritePartitions) > 0 { + for k, v := range m.WritePartitions { + _ = k + _ = v + l = 0 + if v != nil { + l = v.Size() + l += 1 + sovService(uint64(l)) + } + mapEntrySize := 1 + sovService(uint64(k)) + l + n += mapEntrySize + 1 + sovService(uint64(mapEntrySize)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -4965,6 +5167,89 @@ func sovService(x uint64) (n int) { func sozService(x uint64) (n int) { return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *TaskListPartition) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TaskListPartition: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TaskListPartition: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IsolationGroups", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthService + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthService + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IsolationGroups = append(m.IsolationGroups, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipService(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthService + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *TaskListPartitionConfig) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -5051,6 +5336,236 @@ func (m *TaskListPartitionConfig) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadPartitions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthService + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthService + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ReadPartitions == nil { + m.ReadPartitions = make(map[int32]*TaskListPartition) + } + var mapkey int32 + var mapvalue *TaskListPartition + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthService + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return ErrInvalidLengthService + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &TaskListPartition{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skipService(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthService + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.ReadPartitions[mapkey] = mapvalue + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WritePartitions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthService + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthService + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.WritePartitions == nil { + m.WritePartitions = make(map[int32]*TaskListPartition) + } + var mapkey int32 + var mapvalue *TaskListPartition + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthService + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return ErrInvalidLengthService + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &TaskListPartition{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skipService(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthService + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.WritePartitions[mapkey] = mapvalue + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipService(dAtA[iNdEx:]) diff --git a/.gen/proto/matching/v1/service.pb.yarpc.go b/.gen/proto/matching/v1/service.pb.yarpc.go index 6809df3ffde..1bbd7238cd2 100644 --- a/.gen/proto/matching/v1/service.pb.yarpc.go +++ b/.gen/proto/matching/v1/service.pb.yarpc.go @@ -805,157 +805,163 @@ var ( var yarpcFileDescriptorClosure826e827d3aabf7fc = [][]byte{ // uber/cadence/matching/v1/service.proto []byte{ - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x5b, 0x73, 0x1b, 0x49, - 0x15, 0xae, 0xf1, 0xdd, 0x47, 0xb6, 0x6c, 0xb7, 0xbd, 0xce, 0x44, 0x89, 0x13, 0x47, 0xd9, 0x64, - 0x0d, 0x2c, 0x72, 0xec, 0xdd, 0x84, 0x6c, 0x52, 0x10, 0x7c, 0xc9, 0x45, 0xd4, 0x86, 0x64, 0x27, - 0xde, 0xa4, 0x0a, 0xb6, 0x32, 0xb4, 0x34, 0x6d, 0x6b, 0xb0, 0x34, 0x33, 0x99, 0xee, 0x91, 0x57, - 0x3c, 0xf0, 0x40, 0x01, 0x45, 0x15, 0xaf, 0xec, 0x3b, 0xb0, 0xfc, 0x0e, 0x7e, 0x07, 0x55, 0x5b, - 0x3c, 0xf2, 0x03, 0xa0, 0x8a, 0x47, 0xaa, 0xa8, 0xbe, 0x8c, 0x34, 0x23, 0xf5, 0xe8, 0x62, 0x3b, - 0xbb, 0x3c, 0xf0, 0xe6, 0xe9, 0x3e, 0xb7, 0x3e, 0x7d, 0xce, 0xf9, 0xce, 0x69, 0x19, 0x6e, 0x46, - 0x15, 0x12, 0x6e, 0x56, 0xb1, 0x43, 0xbc, 0x2a, 0xd9, 0x6c, 0x60, 0x56, 0xad, 0xb9, 0xde, 0xd1, - 0x66, 0x73, 0x6b, 0x93, 0x92, 0xb0, 0xe9, 0x56, 0x49, 0x29, 0x08, 0x7d, 0xe6, 0x23, 0x93, 0xd3, - 0x95, 0x14, 0x5d, 0x29, 0xa6, 0x2b, 0x35, 0xb7, 0x0a, 0x57, 0x8e, 0x7c, 0xff, 0xa8, 0x4e, 0x36, - 0x05, 0x5d, 0x25, 0x3a, 0xdc, 0x74, 0xa2, 0x10, 0x33, 0xd7, 0xf7, 0x24, 0x67, 0xe1, 0x6a, 0xf7, - 0x3e, 0x73, 0x1b, 0x84, 0x32, 0xdc, 0x08, 0x14, 0x41, 0x8f, 0x80, 0x93, 0x10, 0x07, 0x01, 0x09, - 0xa9, 0xda, 0x5f, 0x4f, 0x99, 0x88, 0x03, 0x97, 0x5b, 0x57, 0xf5, 0x1b, 0x8d, 0x8e, 0x0a, 0x1d, - 0xc5, 0x9b, 0x88, 0x84, 0x2d, 0x45, 0x50, 0xd4, 0x11, 0x30, 0x4c, 0x8f, 0xeb, 0x2e, 0x65, 0x8a, - 0x66, 0x43, 0x47, 0xa3, 0x9c, 0x60, 0x9f, 0xf8, 0xe1, 0x31, 0x09, 0x15, 0xe5, 0xb7, 0x07, 0x51, - 0x1e, 0xd6, 0xfd, 0x13, 0x45, 0x7b, 0x4d, 0x47, 0x5b, 0x73, 0x29, 0xf3, 0xdb, 0xc6, 0xbd, 0x9b, - 0x22, 0xa1, 0x35, 0x1c, 0x12, 0xa7, 0x97, 0xea, 0x46, 0x06, 0x55, 0xfa, 0x14, 0xc5, 0x2f, 0x0c, - 0xb8, 0x70, 0x80, 0xe9, 0xf1, 0xc7, 0x2e, 0x65, 0xcf, 0x71, 0xc8, 0x5c, 0x7e, 0x13, 0x7b, 0xbe, - 0x77, 0xe8, 0x1e, 0x21, 0x13, 0xa6, 0x9b, 0x24, 0xa4, 0xae, 0xef, 0x99, 0xc6, 0xba, 0xb1, 0x31, - 0x6e, 0xc5, 0x9f, 0xa8, 0x04, 0xcb, 0x5e, 0xd4, 0xb0, 0x43, 0x82, 0x1d, 0x3b, 0x88, 0xb9, 0xa8, - 0x39, 0xb6, 0x6e, 0x6c, 0x4c, 0x5a, 0x4b, 0x5e, 0xd4, 0xb0, 0x08, 0x76, 0xda, 0xe2, 0x28, 0xba, - 0x05, 0x2b, 0x9c, 0xfe, 0x24, 0x74, 0x19, 0x49, 0x32, 0x8c, 0x0b, 0x06, 0xe4, 0x45, 0x8d, 0x57, - 0x7c, 0xab, 0xc3, 0x51, 0xfc, 0x19, 0x2c, 0x7d, 0xec, 0x63, 0x67, 0x17, 0xd7, 0xb1, 0x57, 0x25, - 0xe1, 0x13, 0xd7, 0x63, 0x14, 0x5d, 0x87, 0xf9, 0x0a, 0xae, 0x1e, 0xd7, 0xfd, 0x23, 0xbb, 0xea, - 0x47, 0x1e, 0x53, 0x66, 0xcd, 0xa9, 0xc5, 0x3d, 0xbe, 0x86, 0x6e, 0xc2, 0x42, 0x88, 0xb9, 0x1a, - 0x12, 0xda, 0x94, 0x54, 0x7d, 0xcf, 0x11, 0x76, 0x19, 0xd6, 0x3c, 0x5f, 0x7e, 0x4e, 0xc2, 0x17, - 0x62, 0xb1, 0xf8, 0x4f, 0x03, 0x0a, 0xcf, 0xfd, 0x7a, 0xfd, 0x91, 0x1f, 0xee, 0x93, 0xaa, 0xcb, - 0xcf, 0xc5, 0x1d, 0x61, 0x91, 0x37, 0x11, 0xa1, 0x0c, 0x95, 0x61, 0x3a, 0x94, 0x7f, 0x0a, 0x2d, - 0xb9, 0xed, 0xcd, 0x52, 0x2a, 0xa4, 0x71, 0xe0, 0x96, 0x9a, 0x5b, 0xa5, 0x6c, 0x09, 0x56, 0xcc, - 0x8f, 0x2e, 0xc1, 0xac, 0xe3, 0x37, 0xb0, 0xeb, 0xd9, 0xae, 0xb4, 0x65, 0xd6, 0x9a, 0x91, 0x0b, - 0x65, 0x87, 0x6f, 0x06, 0x7e, 0xbd, 0x4e, 0x42, 0xbe, 0x39, 0x2e, 0x37, 0xe5, 0x42, 0xd9, 0x41, - 0x37, 0x20, 0x7f, 0xe8, 0x87, 0x27, 0x38, 0x74, 0x88, 0x63, 0x1f, 0x86, 0x7e, 0xc3, 0x9c, 0x10, - 0x14, 0xf3, 0xed, 0xd5, 0x47, 0xa1, 0xdf, 0x40, 0xef, 0xc1, 0x82, 0x4b, 0xfd, 0xba, 0xc8, 0x22, - 0xfb, 0x28, 0xf4, 0xa3, 0xc0, 0x9c, 0x14, 0x74, 0xf9, 0xf6, 0xf2, 0x63, 0xbe, 0x5a, 0xfc, 0x6b, - 0x0e, 0x2e, 0x69, 0x2d, 0xa6, 0x81, 0xef, 0x51, 0x82, 0xd6, 0x00, 0x78, 0x7c, 0xd8, 0xcc, 0x3f, - 0x26, 0xf2, 0xd2, 0xe7, 0xac, 0x59, 0xbe, 0x72, 0xc0, 0x17, 0xd0, 0xa7, 0x80, 0xe2, 0x70, 0xb5, - 0xc9, 0xe7, 0xa4, 0x1a, 0x71, 0xc9, 0xe2, 0x44, 0xb9, 0xed, 0x9b, 0x5a, 0xf7, 0xbc, 0x52, 0xe4, - 0x0f, 0x63, 0x6a, 0x6b, 0xe9, 0xa4, 0x7b, 0x09, 0x3d, 0x82, 0xf9, 0xb6, 0x58, 0xd6, 0x0a, 0x88, - 0x70, 0x43, 0x6e, 0xfb, 0x5a, 0x5f, 0x89, 0x07, 0xad, 0x80, 0x58, 0x73, 0x27, 0x89, 0x2f, 0xf4, - 0x12, 0x2e, 0x06, 0x21, 0x69, 0xba, 0x7e, 0x44, 0x6d, 0xca, 0x70, 0xc8, 0x88, 0x63, 0x93, 0x26, - 0xf1, 0x18, 0x77, 0xed, 0x84, 0x90, 0x79, 0xa9, 0x24, 0x8b, 0x47, 0x29, 0x2e, 0x1e, 0xa5, 0xb2, - 0xc7, 0xee, 0x7c, 0xf8, 0x12, 0xd7, 0x23, 0x62, 0xad, 0xc6, 0xdc, 0x2f, 0x24, 0xf3, 0x43, 0xce, - 0x5b, 0x76, 0xd0, 0x06, 0x2c, 0xf6, 0x88, 0x9b, 0x14, 0x91, 0x97, 0xa7, 0x69, 0x4a, 0x13, 0xa6, - 0x31, 0x63, 0xa4, 0x11, 0x30, 0x73, 0x4a, 0x84, 0x76, 0xfc, 0x89, 0x8a, 0x30, 0xef, 0x91, 0xcf, - 0x59, 0x47, 0xc0, 0xb4, 0x10, 0x90, 0xe3, 0x8b, 0x31, 0xf7, 0xfb, 0x80, 0x52, 0xe1, 0x6d, 0xd7, - 0x5c, 0x8f, 0x99, 0x33, 0x82, 0x70, 0x31, 0x19, 0xe3, 0x3c, 0x1b, 0xd0, 0x5d, 0x30, 0x29, 0x73, - 0xab, 0xc7, 0xad, 0xce, 0x55, 0xd8, 0xc4, 0xc3, 0x95, 0x3a, 0x71, 0xcc, 0xd9, 0x75, 0x63, 0x63, - 0xc6, 0x5a, 0x95, 0xfb, 0x6d, 0x47, 0x3f, 0x94, 0xbb, 0xe8, 0x2e, 0x4c, 0x8a, 0x62, 0x67, 0x82, - 0xf0, 0x49, 0xb1, 0xaf, 0x9f, 0x3f, 0xe1, 0x94, 0x96, 0x64, 0x40, 0x16, 0xcc, 0x3b, 0x2a, 0x6e, - 0x6c, 0xd7, 0x3b, 0xf4, 0xcd, 0x9c, 0x90, 0xf0, 0xdd, 0xb4, 0x04, 0x59, 0x6c, 0xb8, 0x90, 0x83, - 0x10, 0x7b, 0xd4, 0x25, 0x1e, 0x8b, 0xa3, 0xad, 0xec, 0x1d, 0xfa, 0xd6, 0x9c, 0x93, 0xf8, 0x42, - 0xaf, 0xe1, 0x72, 0x6f, 0x50, 0xd9, 0x22, 0x0c, 0x79, 0x9d, 0x32, 0xe7, 0x84, 0x8a, 0x35, 0xad, - 0x91, 0x71, 0xe5, 0xb2, 0x2e, 0xf6, 0x44, 0x55, 0xbc, 0xc5, 0x6b, 0x95, 0x74, 0x3a, 0xaf, 0x8e, - 0xc4, 0x8e, 0x2b, 0xda, 0xbc, 0xac, 0x55, 0x62, 0xeb, 0x05, 0xdf, 0x79, 0xa9, 0x6a, 0xdb, 0x35, - 0x98, 0xab, 0x84, 0xd8, 0xab, 0xd6, 0x54, 0x16, 0xe4, 0x45, 0x16, 0xe4, 0xe4, 0x9a, 0xcc, 0x83, - 0x1d, 0xc8, 0xd3, 0x6a, 0x8d, 0x38, 0x51, 0x9d, 0x38, 0x36, 0x87, 0x27, 0x73, 0x41, 0x18, 0x59, - 0xe8, 0x89, 0xae, 0x83, 0x18, 0xbb, 0xac, 0xf9, 0x36, 0x07, 0x5f, 0x43, 0xdf, 0x87, 0xb9, 0x38, - 0xa6, 0x84, 0x80, 0xc5, 0x81, 0x02, 0x72, 0x8a, 0x5e, 0xb0, 0x7f, 0x06, 0xd3, 0xfc, 0x46, 0x5c, - 0x42, 0xcd, 0xa5, 0xf5, 0xf1, 0x8d, 0xdc, 0xf6, 0x6e, 0x29, 0x0b, 0x70, 0x4b, 0x7d, 0x12, 0xbe, - 0xf4, 0x89, 0x14, 0xf2, 0xd0, 0x63, 0x61, 0xcb, 0x8a, 0x45, 0x72, 0x97, 0x31, 0x9f, 0xe1, 0xba, - 0xad, 0x20, 0xc5, 0xae, 0xb4, 0x18, 0xa1, 0x26, 0x12, 0x91, 0xb8, 0x24, 0xb6, 0x9e, 0xc8, 0x9d, - 0x5d, 0xbe, 0x81, 0x3e, 0x83, 0xc5, 0x76, 0x51, 0xb7, 0xab, 0x02, 0x3c, 0xcc, 0x65, 0x71, 0xa0, - 0xad, 0x6c, 0xb3, 0x32, 0x50, 0xc7, 0x5a, 0x08, 0xba, 0x60, 0xe8, 0xa7, 0xb0, 0x5c, 0xf7, 0xb1, - 0x63, 0x57, 0x14, 0x16, 0x88, 0xb4, 0xa0, 0xe6, 0x8a, 0x50, 0xf0, 0x9d, 0x6c, 0x05, 0x3d, 0xf8, - 0x61, 0x2d, 0xd5, 0x7b, 0x20, 0xe5, 0x29, 0x2c, 0xe2, 0x88, 0xf9, 0xca, 0x6a, 0x99, 0x71, 0xef, - 0x08, 0xc9, 0xd7, 0xb5, 0x11, 0xb7, 0x13, 0x31, 0x5f, 0xda, 0xc5, 0xf9, 0xad, 0x3c, 0x4e, 0x7d, - 0x17, 0x5e, 0xc3, 0x5c, 0xd2, 0xa5, 0x68, 0x11, 0xc6, 0x8f, 0x49, 0x4b, 0x54, 0xd2, 0x59, 0x8b, - 0xff, 0xc9, 0x93, 0xaf, 0xc9, 0xab, 0x8d, 0x2a, 0x9b, 0x43, 0x25, 0x9f, 0x60, 0xb8, 0x37, 0x76, - 0xd7, 0x48, 0x82, 0xd6, 0x4e, 0x95, 0xb9, 0x4d, 0x97, 0xb5, 0x4e, 0x0f, 0x5a, 0x1a, 0x09, 0xff, - 0x8b, 0xa0, 0xf5, 0x05, 0xb4, 0x41, 0x2b, 0x6d, 0xf1, 0x37, 0x0a, 0x5a, 0x57, 0x21, 0x87, 0x95, - 0x35, 0x1d, 0x27, 0x40, 0xbc, 0x54, 0x76, 0x38, 0xaa, 0xb5, 0x09, 0x04, 0xaa, 0x4d, 0xf4, 0x41, - 0xb5, 0xf6, 0xc1, 0x04, 0xaa, 0xe1, 0xc4, 0x17, 0xda, 0x86, 0x49, 0xd7, 0x0b, 0x22, 0x26, 0xbc, - 0x93, 0xdb, 0xbe, 0xac, 0xbf, 0x51, 0xdc, 0xe2, 0xb1, 0x6d, 0x49, 0x52, 0x4d, 0x81, 0x9a, 0x3a, - 0x6b, 0x81, 0x9a, 0x1e, 0xad, 0x40, 0x1d, 0xc0, 0xc5, 0x58, 0x9e, 0xcd, 0xd3, 0xab, 0xee, 0x53, - 0x22, 0x04, 0xf9, 0x91, 0x84, 0xb4, 0xdc, 0xf6, 0xc5, 0x1e, 0x59, 0xfb, 0x6a, 0x12, 0xb0, 0x56, - 0x63, 0xde, 0x03, 0x7f, 0x8f, 0x73, 0x1e, 0x48, 0x46, 0xf4, 0x63, 0x58, 0x15, 0x4a, 0x7a, 0x45, - 0xce, 0x0e, 0x12, 0xb9, 0x2c, 0x18, 0xbb, 0xe4, 0x3d, 0x82, 0xa5, 0x1a, 0xc1, 0x21, 0xab, 0x10, - 0xcc, 0xda, 0xa2, 0x60, 0x90, 0xa8, 0xc5, 0x36, 0x4f, 0x2c, 0x27, 0x81, 0xfb, 0xb9, 0x34, 0xee, - 0xbf, 0x86, 0x2b, 0xe9, 0x9b, 0xb0, 0xfd, 0x43, 0x9b, 0xd5, 0x5c, 0x6a, 0xc7, 0x0c, 0x73, 0x03, - 0x1d, 0x5b, 0x48, 0xdd, 0xcc, 0xb3, 0xc3, 0x83, 0x9a, 0x4b, 0x77, 0x94, 0xfc, 0x72, 0xf2, 0x04, - 0x0e, 0x61, 0xd8, 0xad, 0x53, 0x81, 0x6d, 0x83, 0x22, 0xa5, 0x73, 0x88, 0x7d, 0xc9, 0xd5, 0xdb, - 0x86, 0xe5, 0x4f, 0xd7, 0x86, 0xbd, 0x07, 0x0b, 0x6d, 0x39, 0xb2, 0x62, 0x08, 0x78, 0x9c, 0xb5, - 0xf2, 0xf1, 0xf2, 0xbe, 0x58, 0x45, 0x1f, 0xc0, 0x54, 0x8d, 0x60, 0x87, 0x84, 0x0a, 0xfd, 0x2e, - 0x69, 0x35, 0x3d, 0x11, 0x24, 0x96, 0x22, 0xcd, 0x42, 0x83, 0xa5, 0x73, 0x41, 0x83, 0xb7, 0x0b, - 0x64, 0x3a, 0xac, 0x59, 0x39, 0x35, 0xd6, 0x14, 0xff, 0x36, 0x01, 0xab, 0x3b, 0x8e, 0xa3, 0x1b, - 0x5e, 0x52, 0xc5, 0xdb, 0xe8, 0x2a, 0xde, 0x6f, 0xa9, 0x20, 0xde, 0x83, 0xd9, 0x4e, 0xd3, 0x36, - 0x3e, 0x4c, 0xd3, 0x36, 0xc3, 0xe2, 0x1e, 0xed, 0x2a, 0xe4, 0xda, 0xd5, 0x42, 0xf5, 0xea, 0xe3, - 0x16, 0xc4, 0x4b, 0x65, 0xa7, 0xbb, 0x9c, 0xa8, 0x22, 0xa0, 0x12, 0x76, 0x72, 0x84, 0x72, 0x22, - 0x5a, 0xfb, 0x38, 0x6d, 0xef, 0xc1, 0x14, 0xf5, 0xa3, 0xb0, 0x2a, 0xcb, 0x63, 0xbe, 0x1b, 0x8c, - 0x13, 0x7d, 0x2c, 0xa6, 0xc7, 0x2f, 0x04, 0xa5, 0xa5, 0x38, 0x34, 0x28, 0x37, 0xad, 0x43, 0xb9, - 0x40, 0x13, 0x51, 0x33, 0xa2, 0x63, 0x7b, 0x98, 0x1d, 0x51, 0xfa, 0x5b, 0x2d, 0x75, 0x05, 0x98, - 0x6c, 0xda, 0xba, 0xa3, 0xac, 0xb0, 0x0b, 0x2b, 0x3a, 0x42, 0x4d, 0x2b, 0xb2, 0x92, 0x6c, 0x45, - 0x66, 0x93, 0x6d, 0xc6, 0x09, 0x5c, 0xe8, 0xb1, 0x41, 0xa1, 0xad, 0x2e, 0x45, 0x8c, 0xf3, 0x4a, - 0x91, 0xe2, 0xbf, 0x26, 0x45, 0x4c, 0xeb, 0x7a, 0x9b, 0x6f, 0x22, 0xa6, 0xf9, 0xe4, 0x27, 0xae, - 0xdb, 0xee, 0xa8, 0x96, 0x48, 0x9f, 0x97, 0xeb, 0xfb, 0xb1, 0x01, 0xa9, 0xe8, 0x9f, 0x38, 0x53, - 0xf4, 0x4f, 0x8e, 0x16, 0xfd, 0x53, 0x67, 0x8f, 0xfe, 0xe9, 0x73, 0x88, 0xfe, 0x19, 0x5d, 0xf4, - 0x7b, 0x60, 0xe2, 0xc4, 0x55, 0xee, 0xbb, 0x34, 0xe0, 0x51, 0xc1, 0xe7, 0x3e, 0x85, 0xd8, 0xdb, - 0x7d, 0xb2, 0x20, 0x83, 0xd3, 0xca, 0x94, 0xa9, 0xcd, 0x36, 0x18, 0x22, 0xdb, 0x34, 0xf1, 0xf6, - 0x35, 0x66, 0xdb, 0x57, 0xe3, 0x60, 0x66, 0x1d, 0x16, 0xfd, 0x08, 0x16, 0x3a, 0x0d, 0x84, 0x98, - 0x56, 0x55, 0xba, 0xe9, 0x71, 0x59, 0xcd, 0x65, 0xe2, 0x49, 0xc1, 0xea, 0x34, 0x81, 0xe2, 0xbb, - 0xa7, 0xa7, 0x1b, 0x1b, 0xad, 0xa7, 0x4b, 0x74, 0x39, 0xe3, 0xa3, 0x76, 0x39, 0x13, 0xe7, 0xdf, - 0xe5, 0x4c, 0x9e, 0x4f, 0x97, 0x33, 0x75, 0x6e, 0x5d, 0xce, 0xb4, 0xae, 0xcb, 0x51, 0xb5, 0x54, - 0x3b, 0xb9, 0xbc, 0xdd, 0x5a, 0xfa, 0x95, 0x01, 0x2b, 0x62, 0x80, 0x8c, 0x4f, 0x11, 0x57, 0xd2, - 0xbd, 0xee, 0x29, 0xf1, 0x5b, 0xda, 0xc3, 0xeb, 0x78, 0x87, 0x9c, 0x0f, 0xcf, 0xd2, 0x0b, 0x0c, - 0x37, 0x3e, 0x16, 0xbf, 0x34, 0xe0, 0x9d, 0x2e, 0x0b, 0x95, 0x57, 0x1f, 0xc0, 0x9c, 0x78, 0xad, - 0xb2, 0x43, 0x42, 0xa3, 0x7a, 0x7c, 0xc6, 0xfe, 0x71, 0x92, 0x13, 0x1c, 0x96, 0x60, 0x40, 0x65, - 0xc8, 0xc7, 0x02, 0x7e, 0x4e, 0xaa, 0x8c, 0x38, 0x7d, 0x67, 0x75, 0x39, 0xa3, 0x2b, 0x4a, 0x6b, - 0xfe, 0x4d, 0xf2, 0xb3, 0xf8, 0x0f, 0x03, 0xd6, 0xa5, 0x61, 0x8e, 0xa0, 0xe3, 0xe7, 0xdd, 0xf3, - 0x1b, 0x41, 0x9d, 0x70, 0x62, 0xe5, 0xca, 0x67, 0xdd, 0xf7, 0x71, 0x5b, 0xab, 0x68, 0x90, 0x9c, - 0xaf, 0xe1, 0x6e, 0x2e, 0xc0, 0xb4, 0xe0, 0x55, 0x3d, 0xda, 0xac, 0x35, 0xc5, 0x3f, 0xcb, 0x4e, - 0xf1, 0x3a, 0x5c, 0xeb, 0x63, 0x9e, 0xbc, 0x98, 0xe2, 0xdf, 0x0d, 0xb8, 0xbc, 0xc7, 0xbb, 0xed, - 0xfa, 0xb3, 0x88, 0x51, 0x86, 0x3d, 0xc7, 0xf5, 0x8e, 0xf8, 0x64, 0x3f, 0x14, 0xc4, 0xa7, 0xde, - 0x1c, 0xc6, 0xba, 0xde, 0x1c, 0x1e, 0x43, 0xbe, 0x7d, 0xa8, 0xce, 0x1b, 0x72, 0x3e, 0x23, 0xad, - 0xe3, 0x93, 0xc9, 0xb4, 0x66, 0x89, 0xaf, 0xb3, 0xe0, 0x78, 0xf1, 0x2a, 0xac, 0x65, 0x1c, 0x4f, - 0x39, 0xe0, 0x97, 0x70, 0x61, 0x9f, 0xd0, 0x6a, 0xe8, 0x56, 0x48, 0x9b, 0x5d, 0x1d, 0xfd, 0x51, - 0x77, 0x0c, 0xbc, 0xaf, 0xd5, 0x9a, 0xc1, 0x3e, 0xdc, 0xd5, 0x17, 0xff, 0x63, 0x80, 0xd9, 0x2b, - 0x41, 0xa5, 0xcd, 0x47, 0x30, 0x2d, 0xdd, 0x49, 0x4d, 0x43, 0x40, 0xe6, 0xd5, 0xcc, 0xb7, 0x23, - 0x12, 0x0a, 0x1c, 0x8e, 0xe9, 0xf9, 0x60, 0xd3, 0xf1, 0x3e, 0x65, 0x98, 0x45, 0x54, 0xa5, 0xcc, - 0xf5, 0xbe, 0xbe, 0x7b, 0x21, 0x48, 0xad, 0x3c, 0x4b, 0x7d, 0xa3, 0x57, 0x9a, 0xb2, 0x38, 0xde, - 0xc7, 0x29, 0x43, 0x57, 0x44, 0x0a, 0x6b, 0xe2, 0xa2, 0xbb, 0xe9, 0x69, 0x7c, 0x0b, 0xab, 0x30, - 0xa5, 0x6a, 0xb9, 0x8c, 0x3e, 0xf5, 0x95, 0x8e, 0x8a, 0xb1, 0xd1, 0xa2, 0xe2, 0xb7, 0x63, 0x70, - 0x25, 0x4b, 0xab, 0x72, 0xfd, 0x1b, 0x58, 0xeb, 0x3c, 0x15, 0xb5, 0x1d, 0x99, 0xf8, 0x9d, 0x4c, - 0x5e, 0x48, 0x69, 0xb8, 0xd3, 0x3f, 0x25, 0x0c, 0x3b, 0x98, 0x61, 0xab, 0x90, 0xec, 0x93, 0xd2, - 0xaa, 0xb9, 0xca, 0xf6, 0x4b, 0xbe, 0x56, 0xe5, 0xd8, 0xe9, 0x54, 0x3a, 0x89, 0x99, 0x21, 0xad, - 0xb2, 0x78, 0x1b, 0x2e, 0x3d, 0x26, 0x6d, 0x37, 0xd0, 0xdd, 0x96, 0x04, 0xc8, 0x01, 0xbe, 0x2f, - 0xfe, 0x65, 0x02, 0x2e, 0xeb, 0xf9, 0x94, 0xf7, 0x7e, 0x6d, 0xc0, 0xaa, 0xe6, 0x2c, 0x0d, 0x1c, - 0x28, 0xbf, 0x3d, 0xcb, 0x06, 0xd3, 0x7e, 0x82, 0x4b, 0xfb, 0x5d, 0x67, 0x79, 0x8a, 0x03, 0xd9, - 0x05, 0x2e, 0x3b, 0xbd, 0x3b, 0xc2, 0x0c, 0xcd, 0x2d, 0x72, 0x33, 0xc6, 0xce, 0x64, 0xc6, 0x4e, - 0xd7, 0x2d, 0x76, 0xcc, 0xc0, 0xbd, 0x3b, 0x85, 0x5f, 0xf0, 0x14, 0xd7, 0xdb, 0xad, 0x69, 0x4a, - 0x9f, 0xa4, 0x5f, 0xa3, 0xfb, 0x74, 0xe3, 0x59, 0x75, 0x23, 0xd1, 0xc8, 0x72, 0xdd, 0x59, 0xc6, - 0xbe, 0x6d, 0xdd, 0xc5, 0x3f, 0x8d, 0xc1, 0xbb, 0x9f, 0x06, 0x0e, 0x66, 0x24, 0xab, 0x1c, 0x0c, - 0x03, 0x32, 0x67, 0x48, 0xf4, 0xf3, 0xc3, 0x20, 0x5d, 0xfd, 0x9b, 0x38, 0x8f, 0xfa, 0xf7, 0x1e, - 0xdc, 0x18, 0xe0, 0x22, 0x05, 0x54, 0x7f, 0x1e, 0x83, 0x1b, 0x16, 0x39, 0x0c, 0x09, 0xad, 0xfd, - 0xdf, 0x9b, 0x59, 0xde, 0xdc, 0x80, 0x9b, 0x83, 0x7c, 0x24, 0xdd, 0xb9, 0xfd, 0xef, 0x39, 0xc8, - 0x3d, 0x55, 0xf1, 0xbc, 0xf3, 0xbc, 0x8c, 0x7e, 0x65, 0xc0, 0xb2, 0xe6, 0x57, 0x39, 0xf4, 0xe1, - 0x88, 0x3f, 0xe2, 0x89, 0x2b, 0x28, 0xdc, 0x3e, 0xd5, 0x4f, 0x7f, 0x49, 0x23, 0x92, 0x49, 0x3b, - 0x84, 0x11, 0x9a, 0x69, 0x79, 0x08, 0x23, 0xb4, 0x13, 0x50, 0x13, 0x16, 0xba, 0x1e, 0x9a, 0xd0, - 0xad, 0x51, 0xdf, 0xc5, 0x0a, 0x5b, 0x23, 0x70, 0xa4, 0xf4, 0xa6, 0xce, 0x7d, 0x6b, 0xd4, 0x17, - 0x82, 0x01, 0x7a, 0xb5, 0xe7, 0x0d, 0x60, 0x3e, 0x35, 0xb4, 0xa0, 0x52, 0xb6, 0x0c, 0xdd, 0xfc, - 0x55, 0xd8, 0x1c, 0x9a, 0x5e, 0x69, 0xfc, 0x83, 0x01, 0x17, 0x33, 0x5b, 0x73, 0x74, 0x2f, 0x5b, - 0xdc, 0xa0, 0x71, 0xa3, 0x70, 0xff, 0x54, 0xbc, 0xca, 0xac, 0xdf, 0x19, 0xf0, 0x8e, 0xb6, 0x59, - 0x46, 0x77, 0xb2, 0xc5, 0xf6, 0x1b, 0x1e, 0x0a, 0xdf, 0x1b, 0x99, 0x4f, 0x99, 0xd2, 0x82, 0xc5, - 0x6e, 0x80, 0x41, 0x5b, 0xa3, 0x80, 0x91, 0xd4, 0x7f, 0x0a, 0xfc, 0x42, 0xbf, 0x37, 0x60, 0x55, - 0xdf, 0x1b, 0xa2, 0x3e, 0xc7, 0xe9, 0xdb, 0xc3, 0x16, 0xee, 0x8e, 0xce, 0xa8, 0xac, 0xf9, 0x8d, - 0x01, 0x2b, 0xba, 0x4e, 0x04, 0xdd, 0x1e, 0xb5, 0x73, 0x91, 0x96, 0xdc, 0x39, 0x5d, 0xc3, 0x83, - 0xfe, 0x68, 0xc0, 0x5a, 0x5f, 0x9c, 0x42, 0x3f, 0xc8, 0x96, 0x3c, 0x4c, 0x0f, 0x50, 0x78, 0x70, - 0x6a, 0x7e, 0x65, 0xe2, 0x97, 0x06, 0x5c, 0xe9, 0x5f, 0xfc, 0xd1, 0x83, 0x7e, 0xe9, 0x31, 0x04, - 0xb4, 0x16, 0x7e, 0x78, 0x7a, 0x01, 0xd2, 0xca, 0xdd, 0xfb, 0x3f, 0xf9, 0xe8, 0xc8, 0x65, 0xb5, - 0xa8, 0x52, 0xaa, 0xfa, 0x8d, 0xcd, 0xd4, 0x3f, 0x04, 0x96, 0x8e, 0x88, 0x27, 0xff, 0x83, 0x32, - 0xf9, 0x4f, 0x9c, 0xf7, 0xe3, 0xbf, 0x9b, 0x5b, 0x95, 0x29, 0xb1, 0xfb, 0xc1, 0x7f, 0x03, 0x00, - 0x00, 0xff, 0xff, 0x51, 0x65, 0xff, 0xaf, 0xf2, 0x29, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x5b, 0x6f, 0x1b, 0xc7, + 0xf5, 0xc7, 0x4a, 0xa2, 0x2e, 0x87, 0x12, 0x25, 0x8d, 0x14, 0x79, 0x4d, 0x5b, 0xb6, 0x4c, 0xc7, + 0x8e, 0xf2, 0xff, 0xa7, 0x54, 0xa4, 0xd8, 0xae, 0x63, 0xa3, 0x71, 0x75, 0xb1, 0x6c, 0x16, 0x71, + 0xed, 0xac, 0x15, 0x1b, 0x68, 0x03, 0x6f, 0x47, 0xdc, 0x91, 0xb8, 0x15, 0xb9, 0xbb, 0xde, 0x99, + 0x95, 0xc2, 0x3c, 0xf4, 0xa1, 0x68, 0x8b, 0x02, 0x7d, 0x6d, 0xdf, 0xdb, 0xa6, 0x9f, 0xa3, 0x9f, + 0xa3, 0x40, 0xd0, 0x87, 0x3e, 0xf4, 0x03, 0xb4, 0x40, 0x1f, 0x0b, 0x14, 0x73, 0x59, 0x72, 0x97, + 0x9c, 0xe5, 0x45, 0x92, 0x9d, 0x3e, 0xf4, 0x4d, 0x3b, 0x73, 0xee, 0x73, 0xce, 0xf9, 0x9d, 0x19, + 0x0a, 0x6e, 0x46, 0xfb, 0x24, 0x5c, 0xab, 0x62, 0x87, 0x78, 0x55, 0xb2, 0xd6, 0xc0, 0xac, 0x5a, + 0x73, 0xbd, 0xc3, 0xb5, 0xe3, 0xf5, 0x35, 0x4a, 0xc2, 0x63, 0xb7, 0x4a, 0xca, 0x41, 0xe8, 0x33, + 0x1f, 0x99, 0x9c, 0xae, 0xac, 0xe8, 0xca, 0x31, 0x5d, 0xf9, 0x78, 0xbd, 0x78, 0xe5, 0xd0, 0xf7, + 0x0f, 0xeb, 0x64, 0x4d, 0xd0, 0xed, 0x47, 0x07, 0x6b, 0x4e, 0x14, 0x62, 0xe6, 0xfa, 0x9e, 0xe4, + 0x2c, 0x5e, 0xed, 0xdc, 0x67, 0x6e, 0x83, 0x50, 0x86, 0x1b, 0x81, 0x22, 0xe8, 0x12, 0x70, 0x12, + 0xe2, 0x20, 0x20, 0x21, 0x55, 0xfb, 0x2b, 0x29, 0x13, 0x71, 0xe0, 0x72, 0xeb, 0xaa, 0x7e, 0xa3, + 0xd1, 0x56, 0xa1, 0xa3, 0x78, 0x1d, 0x91, 0xb0, 0xa9, 0x08, 0x4a, 0x3a, 0x02, 0x86, 0xe9, 0x51, + 0xdd, 0xa5, 0x4c, 0xd1, 0xac, 0xea, 0x68, 0x54, 0x10, 0xec, 0x13, 0x3f, 0x3c, 0x22, 0xa1, 0xa2, + 0xfc, 0xbf, 0x7e, 0x94, 0x07, 0x75, 0xff, 0x44, 0xd1, 0x5e, 0xd3, 0xd1, 0xd6, 0x5c, 0xca, 0xfc, + 0x96, 0x71, 0xef, 0xa6, 0x48, 0x68, 0x0d, 0x87, 0xc4, 0xe9, 0xa6, 0xba, 0x91, 0x41, 0x95, 0xf6, + 0xa2, 0xf4, 0x09, 0xcc, 0xef, 0x61, 0x7a, 0xf4, 0xa9, 0x4b, 0xd9, 0x33, 0x1c, 0x32, 0x97, 0x1f, + 0x04, 0x7a, 0x1f, 0xe6, 0x5c, 0xea, 0xd7, 0xc5, 0xa9, 0xd8, 0x87, 0xa1, 0x1f, 0x05, 0xd4, 0x34, + 0x56, 0x46, 0x57, 0xa7, 0xac, 0xd9, 0xd6, 0xfa, 0x23, 0xb1, 0x5c, 0xfa, 0xdb, 0x18, 0x5c, 0xe8, + 0x12, 0xb0, 0xed, 0x7b, 0x07, 0xee, 0x21, 0x32, 0x61, 0xe2, 0x98, 0x84, 0xd4, 0xf5, 0x3d, 0xd3, + 0x58, 0x31, 0x56, 0x47, 0xad, 0xf8, 0x13, 0x6d, 0xc0, 0x82, 0x17, 0x35, 0xec, 0x90, 0x60, 0xc7, + 0x0e, 0x62, 0x2e, 0x6a, 0x8e, 0xac, 0x18, 0xab, 0xb9, 0xad, 0x11, 0xd3, 0xb0, 0xe6, 0xbd, 0xa8, + 0x61, 0x11, 0xec, 0xb4, 0x44, 0x52, 0x74, 0x0b, 0x16, 0x39, 0xcf, 0x49, 0xe8, 0x32, 0x92, 0x64, + 0x1a, 0x6d, 0x31, 0x21, 0x2f, 0x6a, 0xbc, 0xe4, 0xdb, 0x09, 0x2e, 0x0f, 0x66, 0x3b, 0xb5, 0x8c, + 0xad, 0x8c, 0xae, 0xe6, 0x37, 0x1e, 0x96, 0xb3, 0x32, 0xb4, 0x9c, 0xe1, 0x4f, 0x39, 0x6d, 0xd0, + 0x43, 0x8f, 0x85, 0x4d, 0xab, 0x10, 0xa6, 0xad, 0x7c, 0x0d, 0x73, 0x5d, 0x16, 0xe6, 0x84, 0xc2, + 0xdd, 0xe1, 0x15, 0x76, 0x38, 0x23, 0x35, 0xce, 0x9e, 0xa4, 0x57, 0x8b, 0x1e, 0x2c, 0x68, 0x2c, + 0x43, 0x73, 0x30, 0x7a, 0x44, 0x9a, 0x22, 0xf2, 0x39, 0x8b, 0xff, 0x89, 0x36, 0x21, 0x77, 0x8c, + 0xeb, 0x11, 0x11, 0x71, 0xce, 0x6f, 0xfc, 0xff, 0x10, 0x06, 0x59, 0x92, 0xf3, 0xde, 0xc8, 0x5d, + 0xa3, 0xe8, 0xc3, 0xa2, 0xce, 0xb0, 0x37, 0xa6, 0xb0, 0xf4, 0x13, 0x98, 0xff, 0xd4, 0xc7, 0xce, + 0x16, 0xae, 0x63, 0xaf, 0x4a, 0xc2, 0xc7, 0xae, 0xc7, 0x28, 0xba, 0x0e, 0x33, 0xfb, 0xb8, 0x7a, + 0x54, 0xf7, 0x0f, 0xed, 0xaa, 0x1f, 0x79, 0x4c, 0xa5, 0xd8, 0xb4, 0x5a, 0xdc, 0xe6, 0x6b, 0xe8, + 0x26, 0xcc, 0x86, 0x98, 0x1f, 0x06, 0x09, 0x6d, 0x4a, 0xaa, 0xbe, 0xe7, 0x08, 0x53, 0x0c, 0x6b, + 0x86, 0x2f, 0x3f, 0x23, 0xe1, 0x73, 0xb1, 0x58, 0xfa, 0x87, 0x01, 0xc5, 0x67, 0x7e, 0xbd, 0xbe, + 0xeb, 0x87, 0x3b, 0xa4, 0xea, 0xf2, 0x1c, 0xe5, 0x16, 0x59, 0xe4, 0x75, 0x44, 0x28, 0x43, 0x15, + 0x98, 0x08, 0xe5, 0x9f, 0x42, 0x4b, 0x7e, 0x63, 0x2d, 0xed, 0x09, 0x0e, 0x5c, 0xee, 0x44, 0xb6, + 0x04, 0x2b, 0xe6, 0x47, 0x97, 0x60, 0xca, 0xf1, 0x1b, 0xd8, 0xf5, 0x6c, 0x57, 0xda, 0x32, 0x65, + 0x4d, 0xca, 0x85, 0x8a, 0xc3, 0x37, 0x03, 0xbf, 0x5e, 0x27, 0x21, 0xdf, 0x1c, 0x95, 0x9b, 0x72, + 0xa1, 0xe2, 0xa0, 0x1b, 0x50, 0x38, 0xf0, 0xc3, 0x13, 0x1c, 0x3a, 0xc4, 0xb1, 0x0f, 0x42, 0xbf, + 0x61, 0x8e, 0x09, 0x8a, 0x99, 0xd6, 0xea, 0x6e, 0xe8, 0x37, 0xd0, 0x7b, 0x30, 0xdb, 0x51, 0xbb, + 0x66, 0x4e, 0xd0, 0x15, 0xd2, 0xa5, 0x5b, 0xfa, 0x73, 0x1e, 0x2e, 0x69, 0x2d, 0xa6, 0x81, 0xef, + 0x51, 0x82, 0x96, 0x01, 0x78, 0xaf, 0xb0, 0x99, 0x7f, 0x44, 0x64, 0x01, 0x4f, 0x5b, 0x53, 0x7c, + 0x65, 0x8f, 0x2f, 0xa0, 0xcf, 0x01, 0xc5, 0xad, 0xcb, 0x26, 0x5f, 0x92, 0x6a, 0xc4, 0x25, 0xab, + 0x83, 0xbe, 0xa9, 0x0d, 0xcf, 0x4b, 0x45, 0xfe, 0x30, 0xa6, 0xb6, 0xe6, 0x4f, 0x3a, 0x97, 0xd0, + 0x2e, 0xcc, 0xb4, 0xc4, 0xb2, 0x66, 0x40, 0x44, 0x18, 0xf2, 0x1b, 0xd7, 0x7a, 0x4a, 0xdc, 0x6b, + 0x06, 0xc4, 0x9a, 0x3e, 0x49, 0x7c, 0xa1, 0x17, 0x70, 0x31, 0x08, 0xc9, 0xb1, 0xeb, 0x47, 0xd4, + 0xa6, 0x0c, 0x87, 0x8c, 0x38, 0x36, 0x39, 0x26, 0x1e, 0xe3, 0xa1, 0x1d, 0x13, 0x32, 0x2f, 0x95, + 0x25, 0x90, 0x94, 0x63, 0x20, 0x29, 0x57, 0x3c, 0x76, 0xe7, 0xd6, 0x0b, 0x9e, 0x77, 0xd6, 0x52, + 0xcc, 0xfd, 0x5c, 0x32, 0x3f, 0xe4, 0xbc, 0x15, 0x07, 0xad, 0xc2, 0x5c, 0x97, 0xb8, 0x9c, 0xc8, + 0xbc, 0x02, 0x4d, 0x53, 0x9a, 0x30, 0x81, 0x19, 0x23, 0x8d, 0x80, 0x99, 0xe3, 0xa2, 0x24, 0xe2, + 0x4f, 0x54, 0x82, 0x19, 0x8f, 0x7c, 0xc9, 0xda, 0x02, 0x26, 0x84, 0x80, 0x3c, 0x5f, 0x8c, 0xb9, + 0x3f, 0x00, 0x94, 0x4a, 0x6f, 0xbb, 0xe6, 0x7a, 0xcc, 0x9c, 0x14, 0x84, 0x73, 0xc9, 0x1c, 0xe7, + 0xd5, 0x80, 0xee, 0x82, 0x49, 0x99, 0x5b, 0x3d, 0x6a, 0xb6, 0x8f, 0xc2, 0x26, 0x1e, 0xde, 0xaf, + 0x13, 0xc7, 0x9c, 0x5a, 0x31, 0x56, 0x27, 0xad, 0x25, 0xb9, 0xdf, 0x0a, 0xf4, 0x43, 0xb9, 0x8b, + 0xee, 0x42, 0x4e, 0x00, 0x9f, 0x09, 0x22, 0x26, 0xa5, 0x9e, 0x71, 0xfe, 0x8c, 0x53, 0x5a, 0x92, + 0x01, 0x59, 0x30, 0xe3, 0xa8, 0xbc, 0xb1, 0x5d, 0xef, 0xc0, 0x37, 0xf3, 0x42, 0xc2, 0x77, 0xd2, + 0x12, 0x24, 0xf0, 0x88, 0x12, 0x0f, 0xb1, 0x47, 0x5d, 0xe2, 0xb1, 0x38, 0xdb, 0x2a, 0xde, 0x81, + 0x6f, 0x4d, 0x3b, 0x89, 0x2f, 0xf4, 0x0a, 0x2e, 0x77, 0x27, 0x95, 0x2d, 0xd2, 0x90, 0x63, 0x96, + 0x39, 0x2d, 0x54, 0x2c, 0x6b, 0x8d, 0x8c, 0x5b, 0x88, 0x75, 0xb1, 0x2b, 0xab, 0xe2, 0x2d, 0x54, + 0x86, 0x05, 0x19, 0x74, 0x8e, 0x94, 0xc4, 0x8e, 0xd1, 0x69, 0x46, 0x9c, 0xcf, 0xbc, 0xd8, 0x7a, + 0xce, 0x77, 0x5e, 0x28, 0x9c, 0xba, 0x06, 0xd3, 0xfb, 0x21, 0xf6, 0xaa, 0x35, 0x55, 0x05, 0x05, + 0x51, 0x05, 0x79, 0xb9, 0x26, 0xeb, 0x60, 0x13, 0x0a, 0xb4, 0x5a, 0x23, 0x4e, 0x54, 0x27, 0x8e, + 0xcd, 0x47, 0x15, 0x73, 0x56, 0x18, 0x59, 0xec, 0xca, 0xae, 0xbd, 0x78, 0x8e, 0xb1, 0x66, 0x5a, + 0x1c, 0x7c, 0x0d, 0x7d, 0x0f, 0xa6, 0xe3, 0x9c, 0x12, 0x02, 0xe6, 0xfa, 0x0a, 0xc8, 0x2b, 0x7a, + 0xc1, 0xfe, 0x05, 0x4c, 0xf0, 0x13, 0x71, 0x09, 0x35, 0xe7, 0x05, 0xd2, 0x6c, 0x65, 0xf7, 0xd9, + 0x1e, 0x05, 0x5f, 0xfe, 0x4c, 0x0a, 0x91, 0x28, 0x13, 0x8b, 0xe4, 0x21, 0x63, 0x3e, 0xc3, 0x75, + 0x5b, 0x8d, 0x17, 0xf6, 0x7e, 0x93, 0x11, 0x6a, 0x22, 0x91, 0x89, 0xf3, 0x62, 0xeb, 0xb1, 0xdc, + 0xd9, 0xe2, 0x1b, 0xe8, 0x0b, 0x98, 0x6b, 0x41, 0x9f, 0x5d, 0x15, 0x38, 0x66, 0x2e, 0x08, 0x87, + 0xd6, 0x87, 0x06, 0x40, 0x6b, 0x36, 0xe8, 0x18, 0x29, 0x7e, 0x0c, 0x0b, 0x75, 0x1f, 0x3b, 0xf6, + 0xbe, 0xc2, 0x02, 0x51, 0x16, 0xd4, 0x5c, 0xec, 0x87, 0x2f, 0x5d, 0xf8, 0x61, 0xcd, 0xd7, 0xbb, + 0x20, 0xe5, 0x09, 0xcc, 0xe1, 0x88, 0xf9, 0xca, 0x6a, 0x59, 0x71, 0xef, 0x08, 0xc9, 0xd7, 0xb5, + 0x19, 0xb7, 0x19, 0x31, 0x5f, 0xda, 0xc5, 0xf9, 0xad, 0x02, 0x4e, 0x7d, 0x17, 0x5f, 0xc1, 0x74, + 0x32, 0xa4, 0x49, 0x7c, 0x9c, 0x92, 0xf8, 0x78, 0x37, 0x8d, 0x8f, 0x03, 0x15, 0x5f, 0x1b, 0x16, + 0x13, 0xa0, 0xb5, 0x59, 0x65, 0xee, 0xb1, 0xcb, 0x9a, 0xa7, 0x07, 0x2d, 0x8d, 0x84, 0xff, 0x46, + 0xd0, 0xfa, 0x1d, 0xb4, 0x40, 0x2b, 0x6d, 0xf1, 0xb7, 0x0a, 0x5a, 0x57, 0x21, 0x8f, 0x95, 0x35, + 0xed, 0x20, 0x40, 0xbc, 0x54, 0x71, 0x38, 0xaa, 0xb5, 0x08, 0x04, 0xaa, 0x8d, 0xf5, 0x40, 0xb5, + 0x96, 0x63, 0x02, 0xd5, 0x70, 0xe2, 0x0b, 0x6d, 0x40, 0xce, 0xf5, 0x82, 0x88, 0x89, 0xe8, 0xe4, + 0x37, 0x2e, 0xeb, 0x4f, 0x14, 0x37, 0x79, 0x6e, 0x5b, 0x92, 0x54, 0xd3, 0xa0, 0xc6, 0xcf, 0xda, + 0xa0, 0x26, 0x86, 0x6b, 0x50, 0x7b, 0x70, 0x31, 0x96, 0x67, 0xf3, 0xf2, 0xaa, 0xfb, 0x94, 0x08, + 0x41, 0x7e, 0x24, 0x21, 0x2d, 0xbf, 0x71, 0xb1, 0x4b, 0xd6, 0x8e, 0xba, 0x15, 0x5a, 0x4b, 0x31, + 0xef, 0x9e, 0xbf, 0xcd, 0x39, 0xf7, 0x24, 0x23, 0xfa, 0x21, 0x2c, 0x09, 0x25, 0xdd, 0x22, 0xa7, + 0xfa, 0x89, 0x5c, 0x10, 0x8c, 0x1d, 0xf2, 0x76, 0x61, 0xbe, 0x46, 0x70, 0xc8, 0xf6, 0x09, 0x66, + 0x2d, 0x51, 0xd0, 0x4f, 0xd4, 0x5c, 0x8b, 0x27, 0x96, 0x93, 0xc0, 0xfd, 0x7c, 0x1a, 0xf7, 0x5f, + 0xc1, 0x95, 0xf4, 0x49, 0xd8, 0xfe, 0x81, 0xcd, 0x6a, 0x2e, 0xb5, 0x63, 0x86, 0xe9, 0xbe, 0x81, + 0x2d, 0xa6, 0x4e, 0xe6, 0xe9, 0xc1, 0x5e, 0xcd, 0xa5, 0x9b, 0x4a, 0x7e, 0x25, 0xe9, 0x81, 0x43, + 0x18, 0x76, 0xeb, 0x54, 0x60, 0x5b, 0xbf, 0x4c, 0x69, 0x3b, 0xb1, 0x23, 0xb9, 0xba, 0xc7, 0xb0, + 0xc2, 0xe9, 0xc6, 0xb0, 0xf7, 0x60, 0xb6, 0x25, 0x47, 0x76, 0x0c, 0x01, 0x8f, 0x53, 0x56, 0x21, + 0x5e, 0xde, 0x11, 0xab, 0xe8, 0x23, 0x18, 0xaf, 0x11, 0xec, 0x90, 0x50, 0xa1, 0xdf, 0x25, 0xad, + 0xa6, 0xc7, 0x82, 0xc4, 0x52, 0xa4, 0x59, 0x68, 0x30, 0x7f, 0x2e, 0x68, 0xf0, 0x66, 0x81, 0x4c, + 0x87, 0x35, 0x8b, 0xa7, 0xc6, 0x9a, 0xd2, 0x5f, 0xc6, 0x60, 0x69, 0xd3, 0x71, 0x74, 0x97, 0x97, + 0x54, 0xf3, 0x36, 0x3a, 0x9a, 0xf7, 0x1b, 0x6a, 0x88, 0xf7, 0x60, 0xaa, 0x3d, 0xb4, 0x8d, 0x0e, + 0x32, 0xb4, 0x4d, 0xb2, 0x78, 0x46, 0xbb, 0x0a, 0xf9, 0x56, 0xb7, 0x50, 0xb3, 0xfa, 0xa8, 0x05, + 0xf1, 0x52, 0xc5, 0xe9, 0x6c, 0x27, 0xaa, 0x09, 0xa8, 0x82, 0xcd, 0x0d, 0xd1, 0x4e, 0xc4, 0x68, + 0x1f, 0x97, 0xed, 0x3d, 0x18, 0xa7, 0x7e, 0x14, 0x56, 0x65, 0x7b, 0x2c, 0x74, 0x82, 0x71, 0x62, + 0x8e, 0xc5, 0xf4, 0xe8, 0xb9, 0xa0, 0xb4, 0x14, 0x87, 0x06, 0xe5, 0x26, 0x74, 0x28, 0x17, 0x68, + 0x32, 0x6a, 0xb2, 0xdf, 0x63, 0x84, 0xfe, 0x54, 0xcb, 0x1d, 0x09, 0xa6, 0x9e, 0x06, 0x3a, 0xb2, + 0xac, 0xb8, 0x05, 0x8b, 0x3a, 0x42, 0xcd, 0x28, 0xb2, 0x98, 0x1c, 0x45, 0xa6, 0x92, 0x63, 0xc6, + 0x09, 0x5c, 0xe8, 0xb2, 0x41, 0xa1, 0xad, 0xae, 0x44, 0x8c, 0xf3, 0x2a, 0x91, 0xd2, 0x3f, 0x73, + 0x22, 0xa7, 0x75, 0xb3, 0xcd, 0xb7, 0x91, 0xd3, 0xfc, 0xe6, 0x27, 0x8e, 0xdb, 0x6e, 0xab, 0x96, + 0x48, 0x5f, 0x90, 0xeb, 0x3b, 0xb1, 0x01, 0xa9, 0xec, 0x1f, 0x3b, 0x53, 0xf6, 0xe7, 0x86, 0xcb, + 0xfe, 0xf1, 0xb3, 0x67, 0xff, 0xc4, 0x39, 0x64, 0xff, 0xa4, 0x2e, 0xfb, 0x3d, 0x30, 0x71, 0xe2, + 0x28, 0x77, 0x5c, 0x1a, 0xf0, 0xac, 0xe0, 0xf7, 0x3e, 0x85, 0xd8, 0x1b, 0x3d, 0xaa, 0x20, 0x83, + 0xd3, 0xca, 0x94, 0xa9, 0xad, 0x36, 0x18, 0xa0, 0xda, 0x34, 0xf9, 0xf6, 0x16, 0xab, 0xed, 0x9b, + 0x51, 0x30, 0xb3, 0x9c, 0x45, 0x3f, 0x80, 0xd9, 0xf6, 0x00, 0x21, 0x6e, 0xab, 0xaa, 0xdc, 0xf4, + 0xb8, 0xac, 0xee, 0x65, 0xe2, 0x49, 0xc1, 0x6a, 0x0f, 0x81, 0xe2, 0xbb, 0x6b, 0xa6, 0x1b, 0x19, + 0x6e, 0xa6, 0x4b, 0x4c, 0x39, 0xa3, 0xc3, 0x4e, 0x39, 0x63, 0xe7, 0x3f, 0xe5, 0xe4, 0xce, 0x67, + 0xca, 0x19, 0x3f, 0xb7, 0x29, 0x67, 0x42, 0x37, 0xe5, 0xa8, 0x5e, 0xaa, 0xbd, 0xb9, 0xbc, 0xd9, + 0x5e, 0xfa, 0x8d, 0x01, 0x8b, 0xe2, 0x02, 0x19, 0x7b, 0x11, 0x77, 0xd2, 0xed, 0xce, 0x5b, 0xe2, + 0xfb, 0x5a, 0xe7, 0x75, 0xbc, 0x03, 0xde, 0x0f, 0xcf, 0x32, 0x0b, 0x0c, 0x76, 0x7d, 0x2c, 0x7d, + 0x6d, 0xc0, 0x3b, 0x1d, 0x16, 0xaa, 0xa8, 0x3e, 0x80, 0x69, 0xf1, 0x5a, 0x65, 0x87, 0x84, 0x46, + 0xf5, 0xd8, 0xc7, 0xde, 0x79, 0x92, 0x17, 0x1c, 0x96, 0x60, 0x40, 0x15, 0x28, 0xc4, 0x02, 0x7e, + 0x4a, 0xaa, 0x8c, 0x38, 0x3d, 0xef, 0xea, 0xf2, 0x8e, 0xae, 0x28, 0xad, 0x99, 0xd7, 0xc9, 0xcf, + 0xd2, 0xdf, 0x0d, 0x58, 0x91, 0x86, 0x39, 0x82, 0x8e, 0xfb, 0xbb, 0xed, 0x37, 0x82, 0x3a, 0xe1, + 0xc4, 0x2a, 0x94, 0x4f, 0x3b, 0xcf, 0xe3, 0xb6, 0x56, 0x51, 0x3f, 0x39, 0x6f, 0xe1, 0x6c, 0x2e, + 0xc0, 0x84, 0xe0, 0x55, 0x33, 0xda, 0x94, 0x35, 0xce, 0x3f, 0x2b, 0x4e, 0xe9, 0x3a, 0x5c, 0xeb, + 0x61, 0x9e, 0x3c, 0x98, 0xd2, 0x5f, 0x0d, 0xb8, 0xbc, 0xcd, 0xa7, 0xed, 0xfa, 0xd3, 0x88, 0x51, + 0x86, 0x3d, 0xc7, 0xf5, 0x0e, 0xf9, 0xcd, 0x7e, 0x20, 0x88, 0x4f, 0xbd, 0x39, 0x8c, 0x74, 0xbc, + 0x39, 0x3c, 0x82, 0x42, 0xcb, 0xa9, 0xf6, 0x1b, 0x72, 0x21, 0xa3, 0xac, 0x63, 0xcf, 0x64, 0x59, + 0xb3, 0xc4, 0xd7, 0x59, 0x70, 0xbc, 0x74, 0x15, 0x96, 0x33, 0xdc, 0x53, 0x01, 0xf8, 0x19, 0x5c, + 0xd8, 0x21, 0xb4, 0x1a, 0xba, 0xfb, 0xa4, 0xc5, 0xae, 0x5c, 0xdf, 0xed, 0xcc, 0x81, 0x0f, 0xb4, + 0x5a, 0x33, 0xd8, 0x07, 0x3b, 0xfa, 0xd2, 0xbf, 0x0d, 0x30, 0xbb, 0x25, 0xa8, 0xb2, 0xf9, 0x18, + 0x26, 0x64, 0x38, 0xe5, 0xef, 0x7e, 0xf9, 0x8d, 0xab, 0x99, 0x6f, 0x47, 0x24, 0x14, 0x38, 0x1c, + 0xd3, 0xf3, 0x8b, 0x4d, 0x3b, 0xfa, 0x94, 0x61, 0x16, 0x51, 0x55, 0x32, 0xd7, 0x7b, 0xc6, 0xee, + 0xb9, 0x20, 0xb5, 0x0a, 0x2c, 0xf5, 0x8d, 0x5e, 0x6a, 0xda, 0xe2, 0x68, 0x8f, 0xa0, 0x0c, 0xdc, + 0x11, 0x29, 0x2c, 0x8b, 0x83, 0xee, 0xa4, 0xa7, 0xf1, 0x29, 0x2c, 0xc1, 0xb8, 0xea, 0xe5, 0x32, + 0xfb, 0xd4, 0x57, 0x3a, 0x2b, 0x46, 0x86, 0xcb, 0x8a, 0x5f, 0x8d, 0xc0, 0x95, 0x2c, 0xad, 0x2a, + 0xf4, 0xaf, 0x61, 0xb9, 0xfd, 0x54, 0xd4, 0x0a, 0x64, 0xe2, 0xd7, 0x44, 0x79, 0x20, 0xe5, 0xc1, + 0xbc, 0x7f, 0x42, 0x18, 0x76, 0x30, 0xc3, 0x56, 0x31, 0x39, 0x27, 0xa5, 0x55, 0x73, 0x95, 0xad, + 0x97, 0x7c, 0xad, 0xca, 0x91, 0xd3, 0xa9, 0x74, 0x12, 0x77, 0x86, 0xb4, 0xca, 0xd2, 0x6d, 0xb8, + 0xf4, 0x88, 0xb4, 0xc2, 0x40, 0xb7, 0x9a, 0x12, 0x20, 0xfb, 0xc4, 0xbe, 0xf4, 0xa7, 0x31, 0xb8, + 0xac, 0xe7, 0x53, 0xd1, 0xfb, 0x85, 0x01, 0x4b, 0x1a, 0x5f, 0x1a, 0x38, 0x50, 0x71, 0x7b, 0x9a, + 0x0d, 0xa6, 0xbd, 0x04, 0x97, 0x77, 0x3a, 0x7c, 0x79, 0x82, 0x03, 0x39, 0x05, 0x2e, 0x38, 0xdd, + 0x3b, 0xc2, 0x0c, 0xcd, 0x29, 0x72, 0x33, 0x46, 0xce, 0x64, 0xc6, 0x66, 0xc7, 0x29, 0xb6, 0xcd, + 0xc0, 0xdd, 0x3b, 0xc5, 0xaf, 0x78, 0x89, 0xeb, 0xed, 0xd6, 0x0c, 0xa5, 0x8f, 0xd3, 0xaf, 0xd1, + 0x3d, 0xa6, 0xf1, 0xac, 0xbe, 0x91, 0xfc, 0x95, 0xf8, 0xab, 0xf4, 0x1c, 0xfb, 0x36, 0x75, 0x97, + 0xfe, 0x30, 0x02, 0xef, 0x7e, 0x1e, 0x38, 0x98, 0x91, 0xac, 0x76, 0x30, 0x08, 0xc8, 0x9c, 0xa1, + 0xd0, 0xcf, 0x0f, 0x83, 0x74, 0xfd, 0x6f, 0xec, 0x3c, 0xfa, 0xdf, 0x7b, 0x70, 0xa3, 0x4f, 0x88, + 0x14, 0x50, 0xfd, 0x71, 0x04, 0x6e, 0x58, 0xe4, 0x20, 0x24, 0xb4, 0xf6, 0xbf, 0x68, 0x66, 0x45, + 0x73, 0x15, 0x6e, 0xf6, 0x8b, 0x91, 0x0c, 0xe7, 0xc6, 0xbf, 0xa6, 0x21, 0xff, 0x44, 0xe5, 0xf3, + 0xe6, 0xb3, 0x0a, 0xfa, 0xb9, 0x01, 0x0b, 0x9a, 0x5f, 0xe5, 0xd0, 0xad, 0x21, 0x7f, 0xc4, 0x13, + 0x47, 0x50, 0xbc, 0x7d, 0xaa, 0x9f, 0xfe, 0x92, 0x46, 0x24, 0x8b, 0x76, 0x00, 0x23, 0x34, 0xb7, + 0xe5, 0x01, 0x8c, 0xd0, 0xde, 0x80, 0x8e, 0x61, 0xb6, 0xe3, 0xa1, 0x09, 0x7d, 0x38, 0xec, 0xbb, + 0x58, 0x71, 0x7d, 0x08, 0x8e, 0x94, 0xde, 0x94, 0xdf, 0x1f, 0x0e, 0xfb, 0x42, 0xd0, 0x47, 0xaf, + 0xd6, 0xdf, 0x00, 0x66, 0x52, 0x97, 0x16, 0x54, 0xce, 0x96, 0xa1, 0xbb, 0x7f, 0x15, 0xd7, 0x06, + 0xa6, 0x57, 0x1a, 0x7f, 0x6b, 0xc0, 0xc5, 0xcc, 0xd1, 0x1c, 0xdd, 0xcb, 0x16, 0xd7, 0xef, 0xba, + 0x51, 0xbc, 0x7f, 0x2a, 0x5e, 0x65, 0xd6, 0xaf, 0x0d, 0x78, 0x47, 0x3b, 0x2c, 0xa3, 0x3b, 0xd9, + 0x62, 0x7b, 0x5d, 0x1e, 0x8a, 0xdf, 0x1d, 0x9a, 0x4f, 0x99, 0xd2, 0x84, 0xb9, 0x4e, 0x80, 0x41, + 0xeb, 0xc3, 0x80, 0x91, 0xd4, 0x7f, 0x0a, 0xfc, 0x42, 0xbf, 0x31, 0x60, 0x49, 0x3f, 0x1b, 0xa2, + 0x1e, 0xee, 0xf4, 0x9c, 0x61, 0x8b, 0x77, 0x87, 0x67, 0x54, 0xd6, 0xfc, 0xd2, 0x80, 0x45, 0xdd, + 0x24, 0x82, 0x6e, 0x0f, 0x3b, 0xb9, 0x48, 0x4b, 0xee, 0x9c, 0x6e, 0xe0, 0x41, 0xbf, 0x37, 0x60, + 0xb9, 0x27, 0x4e, 0xa1, 0x4f, 0xb2, 0x25, 0x0f, 0x32, 0x03, 0x14, 0x1f, 0x9c, 0x9a, 0x5f, 0x99, + 0xf8, 0xb5, 0x01, 0x57, 0x7a, 0x37, 0x7f, 0xf4, 0xa0, 0x57, 0x79, 0x0c, 0x00, 0xad, 0xc5, 0xef, + 0x9f, 0x5e, 0x80, 0xb4, 0x72, 0xeb, 0xfe, 0x8f, 0x3e, 0x3e, 0x74, 0x59, 0x2d, 0xda, 0x2f, 0x57, + 0xfd, 0xc6, 0x5a, 0xea, 0x9f, 0x43, 0xcb, 0x87, 0xc4, 0x93, 0xff, 0x4d, 0x9b, 0xfc, 0x87, 0xde, + 0xfb, 0xf1, 0xdf, 0xc7, 0xeb, 0xfb, 0xe3, 0x62, 0xf7, 0xa3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, + 0x3d, 0x55, 0x76, 0xc1, 0xfe, 0x2b, 0x00, 0x00, }, // google/protobuf/duration.proto []byte{ diff --git a/Dockerfile b/Dockerfile index b0e16fd892f..216078d066b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -92,6 +92,7 @@ RUN apk add --update --no-cache ca-certificates py3-pip mysql-client RUN pip3 install cqlsh && cqlsh --version COPY docker/start.sh /start.sh +COPY docker/domain /etc/cadence/domain CMD /start.sh diff --git a/client/matching/client_test.go b/client/matching/client_test.go index 77fb8cd237c..34f3e555809 100644 --- a/client/matching/client_test.go +++ b/client/matching/client_test.go @@ -604,9 +604,20 @@ func testMatchingUpdateTaskListPartitionConfigRequest() *types.MatchingUpdateTas DomainUUID: _testDomainUUID, TaskList: &types.TaskList{Name: _testTaskList}, PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + 2: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, }, } } @@ -616,9 +627,20 @@ func testMatchingRefreshTaskListPartitionConfigRequest() *types.MatchingRefreshT DomainUUID: _testDomainUUID, TaskList: &types.TaskList{Name: _testTaskList}, PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + 2: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, }, } } diff --git a/client/matching/partition_config_provider.go b/client/matching/partition_config_provider.go index 2e8990d873e..06b48758f95 100644 --- a/client/matching/partition_config_provider.go +++ b/client/matching/partition_config_provider.go @@ -112,8 +112,8 @@ func (p *partitionConfigProviderImpl) GetNumberOfReadPartitions(domainID string, } c.RLock() v := c.Version - w := c.NumWritePartitions - r := c.NumReadPartitions + w := len(c.WritePartitions) + r := len(c.ReadPartitions) c.RUnlock() scope := p.metricsClient.Scope(metrics.PartitionConfigProviderScope, metrics.DomainTag(domainName), metrics.TaskListRootPartitionTag(taskList.GetName()), getTaskListTypeTag(taskListType)) scope.UpdateGauge(metrics.TaskListPartitionConfigNumReadGauge, float64(r)) @@ -142,8 +142,8 @@ func (p *partitionConfigProviderImpl) GetNumberOfWritePartitions(domainID string } c.RLock() v := c.Version - w := c.NumWritePartitions - r := c.NumReadPartitions + w := len(c.WritePartitions) + r := len(c.ReadPartitions) c.RUnlock() scope := p.metricsClient.Scope(metrics.PartitionConfigProviderScope, metrics.DomainTag(domainName), metrics.TaskListRootPartitionTag(taskList.GetName()), getTaskListTypeTag(taskListType)) scope.UpdateGauge(metrics.TaskListPartitionConfigNumReadGauge, float64(r)) @@ -180,7 +180,9 @@ func (p *partitionConfigProviderImpl) UpdatePartitionConfig(domainID string, tas } updated := c.updateConfig(*config) if updated { - p.logger.Info("tasklist partition config updated", tag.WorkflowDomainID(domainID), tag.WorkflowTaskListName(taskList.Name), tag.WorkflowTaskListType(taskListType), tag.Dynamic("read-partition", config.NumReadPartitions), tag.Dynamic("write-partition", config.NumWritePartitions), tag.Dynamic("config-version", config.Version)) + w := len(c.WritePartitions) + r := len(c.ReadPartitions) + p.logger.Info("tasklist partition config updated", tag.WorkflowDomainID(domainID), tag.WorkflowTaskListName(taskList.Name), tag.WorkflowTaskListType(taskListType), tag.Dynamic("read-partition", r), tag.Dynamic("write-partition", w), tag.Dynamic("config-version", config.Version)) } } diff --git a/client/matching/partition_config_provider_test.go b/client/matching/partition_config_provider_test.go index b13b9ddb297..cbe90f05d56 100644 --- a/client/matching/partition_config_provider_test.go +++ b/client/matching/partition_config_provider_test.go @@ -136,7 +136,7 @@ func TestGetNumberOfReadPartitions(t *testing.T) { if tc.enableReadFromCache && tc.taskListKind == types.TaskListKindNormal { if tc.cachedConfigExists { mockCache.EXPECT().Get(gomock.Any()).Return(&syncedTaskListPartitionConfig{ - TaskListPartitionConfig: types.TaskListPartitionConfig{NumReadPartitions: 4}, + TaskListPartitionConfig: types.TaskListPartitionConfig{ReadPartitions: partitions(4)}, }).Times(1) } else { mockCache.EXPECT().Get(gomock.Any()).Return(nil).Times(1) @@ -145,10 +145,10 @@ func TestGetNumberOfReadPartitions(t *testing.T) { kind := tc.taskListKind taskList := types.TaskList{Name: "test-task-list", Kind: &kind} - partitions := partitionProvider.GetNumberOfReadPartitions("test-domain-id", taskList, 0) + p := partitionProvider.GetNumberOfReadPartitions("test-domain-id", taskList, 0) // Validate result - assert.Equal(t, tc.expectedPartitions, partitions) + assert.Equal(t, tc.expectedPartitions, p) }) } } @@ -196,7 +196,7 @@ func TestGetNumberOfWritePartitions(t *testing.T) { if tc.enableReadFromCache && tc.taskListKind == types.TaskListKindNormal { if tc.cachedConfigExists { mockCache.EXPECT().Get(gomock.Any()).Return(&syncedTaskListPartitionConfig{ - TaskListPartitionConfig: types.TaskListPartitionConfig{NumReadPartitions: 2, NumWritePartitions: 5}, + TaskListPartitionConfig: types.TaskListPartitionConfig{ReadPartitions: partitions(2), WritePartitions: partitions(5)}, }).Times(1) } else { mockCache.EXPECT().Get(gomock.Any()).Return(nil).Times(1) @@ -204,10 +204,10 @@ func TestGetNumberOfWritePartitions(t *testing.T) { } kind := tc.taskListKind taskList := types.TaskList{Name: "test-task-list", Kind: &kind} - partitions := partitionProvider.GetNumberOfWritePartitions("test-domain-id", taskList, 0) + p := partitionProvider.GetNumberOfWritePartitions("test-domain-id", taskList, 0) // Validate result - assert.Equal(t, tc.expectedPartitions, partitions) + assert.Equal(t, tc.expectedPartitions, p) }) } } @@ -253,3 +253,11 @@ func TestUpdatePartitionConfig(t *testing.T) { }) } } + +func partitions(num int) map[int]*types.TaskListPartition { + result := make(map[int]*types.TaskListPartition, num) + for i := 0; i < num; i++ { + result[i] = &types.TaskListPartition{} + } + return result +} diff --git a/common/clock/sustain.go b/common/clock/sustain.go new file mode 100644 index 00000000000..09bc41a888b --- /dev/null +++ b/common/clock/sustain.go @@ -0,0 +1,58 @@ +// The MIT License (MIT) + +// Copyright (c) 2017-2020 Uber Technologies Inc. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package clock + +import "time" + +type Sustain struct { + started time.Time + source TimeSource + duration func() time.Duration +} + +func NewSustain(source TimeSource, duration func() time.Duration) Sustain { + return Sustain{ + source: source, + duration: duration, + } +} + +func (s *Sustain) Check(value bool) bool { + if value { + now := s.source.Now() + if s.started.IsZero() { + s.started = now + } + if now.Sub(s.started) >= s.duration() { + s.Reset() + return true + } + } else { + s.Reset() + } + return false +} + +func (s *Sustain) Reset() { + s.started = time.Time{} +} diff --git a/common/clock/sustain_test.go b/common/clock/sustain_test.go new file mode 100644 index 00000000000..ec7d25e46b1 --- /dev/null +++ b/common/clock/sustain_test.go @@ -0,0 +1,135 @@ +// The MIT License (MIT) + +// Copyright (c) 2017-2020 Uber Technologies Inc. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package clock + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type check struct { + seconds int + value bool +} + +func TestSustain(t *testing.T) { + cases := []struct { + name string + duration time.Duration + calls []check + expected []bool + }{ + { + name: "simple case", + duration: time.Second * 10, + calls: []check{ + {0, true}, + {10, true}, + }, + expected: []bool{ + false, + true, + }, + }, + { + name: "intermediate successes", + duration: 10 * time.Second, + calls: []check{ + {0, true}, + {2, true}, + {2, true}, + {2, true}, + {2, true}, + {2, true}, + }, + expected: []bool{ + false, + false, + false, + false, + false, + true, + }, + }, + { + name: "resets after success", + duration: time.Second * 10, + calls: []check{ + {0, true}, + {10, true}, + {0, true}, + }, + expected: []bool{ + false, + true, + false, + }, + }, + { + name: "resets after false", + duration: time.Second * 10, + calls: []check{ + {0, true}, + {1, false}, + {1, true}, + {9, true}, + {1, true}, + }, + expected: []bool{ + false, + false, + false, + false, + true, + }, + }, + { + name: "duration = 0", + duration: 0, + calls: []check{ + {0, true}, + }, + expected: []bool{ + true, + }, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + clock := NewMockedTimeSource() + sus := NewSustain(clock, func() time.Duration { + return tc.duration + }) + require.Equal(t, len(tc.calls), len(tc.expected)) + for i, c := range tc.calls { + expected := tc.expected[i] + clock.Advance(time.Duration(c.seconds) * time.Second) + actual := sus.Check(c.value) + assert.Equal(t, expected, actual, "check %d", i) + } + }) + } +} diff --git a/common/log/tag/tags.go b/common/log/tag/tags.go index 42f78eb8525..7cb02c0f833 100644 --- a/common/log/tag/tags.go +++ b/common/log/tag/tags.go @@ -1034,20 +1034,20 @@ func CurrentQPS(qps float64) Tag { return newFloat64Tag("current-qps", qps) } -func NumReadPartitions(n int32) Tag { - return newInt32("num-read-partitions", n) +func NumReadPartitions(n int) Tag { + return newInt("num-read-partitions", n) } -func NumWritePartitions(n int32) Tag { - return newInt32("num-write-partitions", n) +func NumWritePartitions(n int) Tag { + return newInt("num-write-partitions", n) } -func CurrentNumReadPartitions(n int32) Tag { - return newInt32("current-num-read-partitions", n) +func CurrentNumReadPartitions(n int) Tag { + return newInt("current-num-read-partitions", n) } -func CurrentNumWritePartitions(n int32) Tag { - return newInt32("current-num-write-partitions", n) +func CurrentNumWritePartitions(n int) Tag { + return newInt("current-num-write-partitions", n) } func PartitionUpscaleThreshold(qps float64) Tag { diff --git a/common/persistence/data_manager_interfaces.go b/common/persistence/data_manager_interfaces.go index ba7b586c3de..382992573e0 100644 --- a/common/persistence/data_manager_interfaces.go +++ b/common/persistence/data_manager_interfaces.go @@ -459,11 +459,15 @@ type ( AdaptivePartitionConfig *TaskListPartitionConfig } + TaskListPartition struct { + IsolationGroups []string + } + // TaskListPartitionConfig represents the configuration for task list partitions. TaskListPartitionConfig struct { - Version int64 - NumReadPartitions int - NumWritePartitions int + Version int64 + ReadPartitions map[int]*TaskListPartition + WritePartitions map[int]*TaskListPartition } // TaskInfo describes either activity or decision task @@ -2059,9 +2063,31 @@ func (p *TaskListPartitionConfig) ToInternalType() *types.TaskListPartitionConfi if p == nil { return nil } + var readPartitions map[int]*types.TaskListPartition + if p.ReadPartitions != nil { + readPartitions = make(map[int]*types.TaskListPartition, len(p.ReadPartitions)) + for id, par := range p.ReadPartitions { + readPartitions[id] = par.ToInternalType() + } + } + var writePartitions map[int]*types.TaskListPartition + if p.WritePartitions != nil { + writePartitions = make(map[int]*types.TaskListPartition, len(p.WritePartitions)) + for id, par := range p.WritePartitions { + writePartitions[id] = par.ToInternalType() + } + } + return &types.TaskListPartitionConfig{ - Version: p.Version, - NumReadPartitions: int32(p.NumReadPartitions), - NumWritePartitions: int32(p.NumWritePartitions), + Version: p.Version, + ReadPartitions: readPartitions, + WritePartitions: writePartitions, + } +} + +func (p *TaskListPartition) ToInternalType() *types.TaskListPartition { + if p == nil { + return nil } + return &types.TaskListPartition{IsolationGroups: p.IsolationGroups} } diff --git a/common/persistence/data_manager_interfaces_test.go b/common/persistence/data_manager_interfaces_test.go index 980bc1b8c5e..edba0c0e66f 100644 --- a/common/persistence/data_manager_interfaces_test.go +++ b/common/persistence/data_manager_interfaces_test.go @@ -529,14 +529,36 @@ func TestTaskListPartitionConfigToInternalType(t *testing.T) { { name: "normal case", input: &TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: map[int]*TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + 1: {}, + }, + WritePartitions: map[int]*TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + 1: {}, + 2: {}, + }, }, expect: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + 1: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + 1: {}, + 2: {}, + }, }, }, } diff --git a/common/persistence/nosql/nosql_task_store_test.go b/common/persistence/nosql/nosql_task_store_test.go index 51628c30f9e..e67a8179829 100644 --- a/common/persistence/nosql/nosql_task_store_test.go +++ b/common/persistence/nosql/nosql_task_store_test.go @@ -741,9 +741,20 @@ func getExpectedTaskListRowWithPartitionConfig() *nosqlplugin.TaskListRow { AckLevel: initialAckLevel, LastUpdatedTime: time.Now(), AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: {}, + 2: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, }, } } @@ -767,9 +778,20 @@ func getExpectedTaskListInfo() *persistence.TaskListInfo { Kind: int(types.TaskListKindNormal), LastUpdated: time.Now(), AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: {}, + 2: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, }, } } diff --git a/common/persistence/nosql/nosqlplugin/cassandra/tasks.go b/common/persistence/nosql/nosqlplugin/cassandra/tasks.go index 0f7b1ebfe0b..6de9f0b80d7 100644 --- a/common/persistence/nosql/nosqlplugin/cassandra/tasks.go +++ b/common/persistence/nosql/nosqlplugin/cassandra/tasks.go @@ -89,10 +89,56 @@ func toTaskListPartitionConfig(v interface{}) *persistence.TaskListPartitionConf version := partition["version"].(int64) numRead := partition["num_read_partitions"].(int) numWrite := partition["num_write_partitions"].(int) + readPartitions := toTaskListPartitions(partition["read_partitions"]) + writePartitions := toTaskListPartitions(partition["write_partitions"]) + // If they're out of sync, go with the value of num_*_partitions. This is necessary only while support for + // read_partitions and write_partitions rolls out + if numRead != len(readPartitions) { + readPartitions = createDefaultPartitions(numRead) + } + if numWrite != len(writePartitions) { + writePartitions = createDefaultPartitions(numWrite) + } return &persistence.TaskListPartitionConfig{ - Version: version, - NumReadPartitions: numRead, - NumWritePartitions: numWrite, + Version: version, + ReadPartitions: readPartitions, + WritePartitions: writePartitions, + } +} + +func createDefaultPartitions(num int) map[int]*persistence.TaskListPartition { + partitions := make(map[int]*persistence.TaskListPartition, num) + for i := 0; i < num; i++ { + partitions[i] = &persistence.TaskListPartition{} + } + return partitions +} + +func toTaskListPartitions(values any) map[int]*persistence.TaskListPartition { + if values == nil { + return nil + } + partitions, ok := values.(map[int]map[string]any) + if !ok || len(partitions) == 0 { + return nil + } + result := make(map[int]*persistence.TaskListPartition, len(partitions)) + for id, p := range partitions { + partition := toTaskListPartition(p) + if partition != nil { + result[id] = partition + } + } + return result +} + +func toTaskListPartition(partition map[string]any) *persistence.TaskListPartition { + if len(partition) == 0 { + return nil + } + isolationGroups := partition["isolation_groups"].([]string) + return &persistence.TaskListPartition{ + IsolationGroups: isolationGroups, } } @@ -102,8 +148,30 @@ func fromTaskListPartitionConfig(config *persistence.TaskListPartitionConfig) ma } return map[string]interface{}{ "version": config.Version, - "num_read_partitions": config.NumReadPartitions, - "num_write_partitions": config.NumWritePartitions, + "num_read_partitions": len(config.ReadPartitions), + "num_write_partitions": len(config.WritePartitions), + "read_partitions": fromTaskListPartitions(config.ReadPartitions), + "write_partitions": fromTaskListPartitions(config.WritePartitions), + } +} + +func fromTaskListPartitions(partitions map[int]*persistence.TaskListPartition) map[int]any { + if len(partitions) == 0 { + return nil + } + result := make(map[int]any, len(partitions)) + for id, partition := range partitions { + result[id] = fromTaskListPartition(partition) + } + return result +} + +func fromTaskListPartition(partition *persistence.TaskListPartition) any { + if partition == nil { + return nil + } + return map[string]any{ + "isolation_groups": partition.IsolationGroups, } } diff --git a/common/persistence/nosql/nosqlplugin/cassandra/tasks_test.go b/common/persistence/nosql/nosqlplugin/cassandra/tasks_test.go index 256f2b24e89..948da6f1aee 100644 --- a/common/persistence/nosql/nosqlplugin/cassandra/tasks_test.go +++ b/common/persistence/nosql/nosqlplugin/cassandra/tasks_test.go @@ -93,9 +93,64 @@ func TestSelectTaskList(t *testing.T) { RangeID: 25, LastUpdatedTime: now, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 0, - NumReadPartitions: 1, - NumWritePartitions: 1, + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"bar"}, + }, + }, + }, + }, + wantQueries: []string{ + `SELECT range_id, task_list FROM tasks WHERE domain_id = domain1 and task_list_name = tasklist1 and task_list_type = 1 and type = 1 and task_id = -12345`, + }, + }, + { + name: "success - partition numbers only", + filter: &nosqlplugin.TaskListFilter{ + DomainID: "domain1", + TaskListName: "tasklist1", + TaskListType: 1, + }, + queryMockFn: func(query *gocql.MockQuery) { + query.EXPECT().WithContext(gomock.Any()).Return(query).Times(1) + query.EXPECT().Scan(gomock.Any()).DoAndReturn(func(args ...interface{}) error { + rangeID := args[0].(*int64) + *rangeID = 25 + tlDB := args[1].(*map[string]interface{}) + *tlDB = make(map[string]interface{}) + (*tlDB)["ack_level"] = int64(1000) + (*tlDB)["kind"] = 2 + (*tlDB)["last_updated"] = now + (*tlDB)["adaptive_partition_config"] = map[string]interface{}{ + "version": int64(0), + "num_read_partitions": int(1), + "num_write_partitions": int(1), + } + return nil + }).Times(1) + }, + wantRow: &nosqlplugin.TaskListRow{ + DomainID: "domain1", + TaskListName: "tasklist1", + TaskListType: 1, + TaskListKind: 2, + AckLevel: 1000, + RangeID: 25, + LastUpdatedTime: now, + AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, }, }, wantQueries: []string{ @@ -203,9 +258,13 @@ func TestInsertTaskList(t *testing.T) { RangeID: 25, LastUpdatedTime: ts, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 1, - NumWritePartitions: 1, + Version: 1, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, }, }, queryMockFn: func(query *gocql.MockQuery) { @@ -218,7 +277,7 @@ func TestInsertTaskList(t *testing.T) { `INSERT INTO tasks (domain_id, task_list_name, task_list_type, type, task_id, range_id, task_list, created_time ) ` + `VALUES (domain1, tasklist1, 1, 1, -12345, 1, ` + `{domain_id: domain1, name: tasklist1, type: 1, ack_level: 0, kind: 2, last_updated: 2024-04-01T22:08:41Z, ` + - `adaptive_partition_config: map[num_read_partitions:1 num_write_partitions:1 version:1] }` + + `adaptive_partition_config: map[num_read_partitions:1 num_write_partitions:1 read_partitions:map[0:map[isolation_groups:[]]] version:1 write_partitions:map[0:map[isolation_groups:[]]]] }` + `, 2025-01-06T15:00:00Z) IF NOT EXISTS`, }, }, diff --git a/common/persistence/persistence-tests/matchingPersistenceTest.go b/common/persistence/persistence-tests/matchingPersistenceTest.go index 2689706581f..4c92390ea8e 100644 --- a/common/persistence/persistence-tests/matchingPersistenceTest.go +++ b/common/persistence/persistence-tests/matchingPersistenceTest.go @@ -375,6 +375,16 @@ func (s *MatchingPersistenceSuite) TestLeaseAndUpdateTaskList() { _, ok := err.(*p.ConditionFailedError) s.True(ok) + readPartitions := map[int]*p.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"foo"}, + }, + } + writePartitions := map[int]*p.TaskListPartition{ + 0: {IsolationGroups: []string{"bar"}}, + } + taskListInfo := &p.TaskListInfo{ DomainID: domainID, Name: taskList, @@ -383,9 +393,9 @@ func (s *MatchingPersistenceSuite) TestLeaseAndUpdateTaskList() { AckLevel: 0, Kind: p.TaskListKindNormal, AdaptivePartitionConfig: &p.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: readPartitions, + WritePartitions: writePartitions, }, } _, err = s.TaskMgr.UpdateTaskList(ctx, &p.UpdateTaskListRequest{ @@ -407,8 +417,8 @@ func (s *MatchingPersistenceSuite) TestLeaseAndUpdateTaskList() { s.EqualValues(p.TaskListKindNormal, tli.Kind) s.NotNil(tli.AdaptivePartitionConfig) s.EqualValues(1, tli.AdaptivePartitionConfig.Version) - s.EqualValues(2, tli.AdaptivePartitionConfig.NumReadPartitions) - s.EqualValues(2, tli.AdaptivePartitionConfig.NumWritePartitions) + s.Equal(readPartitions, tli.AdaptivePartitionConfig.ReadPartitions) + s.EqualValues(writePartitions, tli.AdaptivePartitionConfig.WritePartitions) taskListInfo.RangeID = 3 _, err = s.TaskMgr.UpdateTaskList(ctx, &p.UpdateTaskListRequest{ diff --git a/common/persistence/serialization/interfaces.go b/common/persistence/serialization/interfaces.go index 9a17cc29b91..b2cf7ba5db6 100644 --- a/common/persistence/serialization/interfaces.go +++ b/common/persistence/serialization/interfaces.go @@ -261,10 +261,16 @@ type ( PartitionConfig map[string]string } + TaskListPartition struct { + IsolationGroups []string + } + TaskListPartitionConfig struct { Version int64 NumReadPartitions int32 NumWritePartitions int32 + ReadPartitions map[int32]*TaskListPartition + WritePartitions map[int32]*TaskListPartition } // TaskListInfo blob in a serialization agnostic format TaskListInfo struct { diff --git a/common/persistence/serialization/thrift_mapper.go b/common/persistence/serialization/thrift_mapper.go index 2e30a9eb206..639ed84ea7d 100644 --- a/common/persistence/serialization/thrift_mapper.go +++ b/common/persistence/serialization/thrift_mapper.go @@ -562,11 +562,35 @@ func taskListPartitionConfigToThrift(info *TaskListPartitionConfig) *sqlblobs.Ta } return &sqlblobs.TaskListPartitionConfig{ Version: &info.Version, - NumReadPartitions: &info.NumReadPartitions, - NumWritePartitions: &info.NumWritePartitions, + NumReadPartitions: common.Int32Ptr(info.NumReadPartitions), + NumWritePartitions: common.Int32Ptr(info.NumWritePartitions), + ReadPartitions: taskListPartitionMapToThrift(info.ReadPartitions), + WritePartitions: taskListPartitionMapToThrift(info.WritePartitions), } } +func taskListPartitionMapToThrift(m map[int32]*TaskListPartition) map[int32]*sqlblobs.TaskListPartition { + if m == nil { + return nil + } + result := make(map[int32]*sqlblobs.TaskListPartition) + for id, p := range m { + result[id] = &sqlblobs.TaskListPartition{IsolationGroups: p.IsolationGroups} + } + return result +} + +func taskListPartitionMapFromThrift(m map[int32]*sqlblobs.TaskListPartition) map[int32]*TaskListPartition { + if m == nil { + return nil + } + result := make(map[int32]*TaskListPartition) + for id, p := range m { + result[id] = &TaskListPartition{IsolationGroups: p.IsolationGroups} + } + return result +} + func taskListParititionConfigFromThrift(info *sqlblobs.TaskListPartitionConfig) *TaskListPartitionConfig { if info == nil { return nil @@ -575,6 +599,8 @@ func taskListParititionConfigFromThrift(info *sqlblobs.TaskListPartitionConfig) Version: info.GetVersion(), NumReadPartitions: info.GetNumReadPartitions(), NumWritePartitions: info.GetNumWritePartitions(), + ReadPartitions: taskListPartitionMapFromThrift(info.ReadPartitions), + WritePartitions: taskListPartitionMapFromThrift(info.WritePartitions), } } diff --git a/common/persistence/serialization/thrift_mapper_test.go b/common/persistence/serialization/thrift_mapper_test.go index 9c4beaa85ff..fe4dbd00661 100644 --- a/common/persistence/serialization/thrift_mapper_test.go +++ b/common/persistence/serialization/thrift_mapper_test.go @@ -467,25 +467,47 @@ func TestTaskInfo(t *testing.T) { } func TestTaskListInfo(t *testing.T) { - expected := &TaskListInfo{ - Kind: int16(rand.Intn(1000)), - AckLevel: int64(rand.Intn(1000)), - ExpiryTimestamp: time.Now(), - LastUpdated: time.Now(), - AdaptivePartitionConfig: &TaskListPartitionConfig{ - Version: 0, - NumReadPartitions: 1, - NumWritePartitions: 2, + cases := []*TaskListInfo{ + nil, + { + Kind: 0, + AckLevel: 1, + ExpiryTimestamp: time.UnixMicro(2), + LastUpdated: time.UnixMicro(3), + AdaptivePartitionConfig: &TaskListPartitionConfig{ + Version: 4, + NumReadPartitions: 1, + ReadPartitions: map[int32]*TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + }, + NumWritePartitions: 2, + WritePartitions: map[int32]*TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, + }, + }, + { + Kind: 0, + AckLevel: 1, + ExpiryTimestamp: time.UnixMicro(2), + LastUpdated: time.UnixMicro(3), + AdaptivePartitionConfig: &TaskListPartitionConfig{ + Version: 4, + NumReadPartitions: 10, + NumWritePartitions: 2, + }, }, } - actual := taskListInfoFromThrift(taskListInfoToThrift(expected)) - assert.Equal(t, expected.Kind, actual.Kind) - assert.Equal(t, expected.AckLevel, actual.AckLevel) - assert.Equal(t, expected.LastUpdated.Sub(actual.LastUpdated), time.Duration(0)) - assert.Equal(t, expected.ExpiryTimestamp.Sub(actual.ExpiryTimestamp), time.Duration(0)) - assert.Equal(t, expected.AdaptivePartitionConfig, actual.AdaptivePartitionConfig) - assert.Nil(t, taskListInfoFromThrift(nil)) - assert.Nil(t, taskListInfoToThrift(nil)) + for i, info := range cases { + assert.Equal(t, info, taskListInfoFromThrift(taskListInfoToThrift(info)), "case %d", i) + } } func TestTransferTaskInfo(t *testing.T) { diff --git a/common/persistence/sql/sql_task_store.go b/common/persistence/sql/sql_task_store.go index 28ec134e5ad..ed9b254aba8 100644 --- a/common/persistence/sql/sql_task_store.go +++ b/common/persistence/sql/sql_task_store.go @@ -189,14 +189,6 @@ func (m *sqlTaskStore) LeaseTaskList( if rowsAffected == 0 { return fmt.Errorf("%v rows affected instead of 1", rowsAffected) } - var c *persistence.TaskListPartitionConfig - if tlInfo.AdaptivePartitionConfig != nil { - c = &persistence.TaskListPartitionConfig{ - Version: tlInfo.AdaptivePartitionConfig.Version, - NumReadPartitions: int(tlInfo.AdaptivePartitionConfig.NumReadPartitions), - NumWritePartitions: int(tlInfo.AdaptivePartitionConfig.NumWritePartitions), - } - } resp = &persistence.LeaseTaskListResponse{TaskListInfo: &persistence.TaskListInfo{ DomainID: request.DomainID, Name: request.TaskList, @@ -205,7 +197,7 @@ func (m *sqlTaskStore) LeaseTaskList( AckLevel: ackLevel, Kind: request.TaskListKind, LastUpdated: now, - AdaptivePartitionConfig: c, + AdaptivePartitionConfig: fromSerializationTaskListPartitionConfig(tlInfo.AdaptivePartitionConfig), }} return nil }) @@ -232,14 +224,6 @@ func (m *sqlTaskStore) GetTaskList( if err != nil { return nil, err } - var c *persistence.TaskListPartitionConfig - if tlInfo.AdaptivePartitionConfig != nil { - c = &persistence.TaskListPartitionConfig{ - Version: tlInfo.AdaptivePartitionConfig.Version, - NumReadPartitions: int(tlInfo.AdaptivePartitionConfig.NumReadPartitions), - NumWritePartitions: int(tlInfo.AdaptivePartitionConfig.NumWritePartitions), - } - } return &persistence.GetTaskListResponse{ TaskListInfo: &persistence.TaskListInfo{ DomainID: request.DomainID, @@ -250,7 +234,7 @@ func (m *sqlTaskStore) GetTaskList( Kind: int(tlInfo.Kind), Expiry: tlInfo.ExpiryTimestamp, LastUpdated: tlInfo.LastUpdated, - AdaptivePartitionConfig: c, + AdaptivePartitionConfig: fromSerializationTaskListPartitionConfig(tlInfo.AdaptivePartitionConfig), }, }, nil } @@ -261,20 +245,12 @@ func (m *sqlTaskStore) UpdateTaskList( ) (*persistence.UpdateTaskListResponse, error) { dbShardID := sqlplugin.GetDBShardIDFromDomainIDAndTasklist(request.TaskListInfo.DomainID, request.TaskListInfo.Name, m.db.GetTotalNumDBShards()) domainID := serialization.MustParseUUID(request.TaskListInfo.DomainID) - var c *serialization.TaskListPartitionConfig - if request.TaskListInfo.AdaptivePartitionConfig != nil { - c = &serialization.TaskListPartitionConfig{ - Version: request.TaskListInfo.AdaptivePartitionConfig.Version, - NumReadPartitions: int32(request.TaskListInfo.AdaptivePartitionConfig.NumReadPartitions), - NumWritePartitions: int32(request.TaskListInfo.AdaptivePartitionConfig.NumWritePartitions), - } - } tlInfo := &serialization.TaskListInfo{ AckLevel: request.TaskListInfo.AckLevel, Kind: int16(request.TaskListInfo.Kind), ExpiryTimestamp: time.Unix(0, 0), LastUpdated: time.Now(), - AdaptivePartitionConfig: c, + AdaptivePartitionConfig: toSerializationTaskListPartitionConfig(request.TaskListInfo.AdaptivePartitionConfig), } if request.TaskListInfo.Kind == persistence.TaskListKindSticky { tlInfo.ExpiryTimestamp = stickyTaskListExpiry() @@ -654,3 +630,69 @@ func lockTaskList(ctx context.Context, tx sqlplugin.Tx, shardID int, domainID se func stickyTaskListExpiry() time.Time { return time.Now().Add(stickyTasksListsTTL) } + +func toSerializationTaskListPartitionConfig(c *persistence.TaskListPartitionConfig) *serialization.TaskListPartitionConfig { + if c == nil { + return nil + } + return &serialization.TaskListPartitionConfig{ + Version: c.Version, + NumReadPartitions: int32(len(c.ReadPartitions)), + NumWritePartitions: int32(len(c.WritePartitions)), + ReadPartitions: toSerializationTaskListPartitionMap(c.ReadPartitions), + WritePartitions: toSerializationTaskListPartitionMap(c.WritePartitions), + } +} + +func toSerializationTaskListPartitionMap(m map[int]*persistence.TaskListPartition) map[int32]*serialization.TaskListPartition { + if m == nil { + return nil + } + result := make(map[int32]*serialization.TaskListPartition, len(m)) + for id, p := range m { + result[int32(id)] = &serialization.TaskListPartition{IsolationGroups: p.IsolationGroups} + } + return result +} + +func fromSerializationTaskListPartitionConfig(c *serialization.TaskListPartitionConfig) *persistence.TaskListPartitionConfig { + if c == nil { + return nil + } + var read map[int]*persistence.TaskListPartition + if int32(len(c.ReadPartitions)) == c.NumReadPartitions { + read = fromSerializationTaskListPartitionMap(c.ReadPartitions) + } else { + read = createDefaultPartitions(c.NumReadPartitions) + } + var write map[int]*persistence.TaskListPartition + if int32(len(c.WritePartitions)) == c.NumWritePartitions { + write = fromSerializationTaskListPartitionMap(c.WritePartitions) + } else { + write = createDefaultPartitions(c.NumWritePartitions) + } + return &persistence.TaskListPartitionConfig{ + Version: c.Version, + ReadPartitions: read, + WritePartitions: write, + } +} + +func createDefaultPartitions(len int32) map[int]*persistence.TaskListPartition { + partitions := make(map[int]*persistence.TaskListPartition, len) + for i := 0; i < int(len); i++ { + partitions[i] = &persistence.TaskListPartition{} + } + return partitions +} + +func fromSerializationTaskListPartitionMap(m map[int32]*serialization.TaskListPartition) map[int]*persistence.TaskListPartition { + if m == nil { + return nil + } + result := make(map[int]*persistence.TaskListPartition, len(m)) + for id, p := range m { + result[int(id)] = &persistence.TaskListPartition{IsolationGroups: p.IsolationGroups} + } + return result +} diff --git a/common/persistence/sql/sql_task_store_test.go b/common/persistence/sql/sql_task_store_test.go index a592e61bc9d..a3ba1844798 100644 --- a/common/persistence/sql/sql_task_store_test.go +++ b/common/persistence/sql/sql_task_store_test.go @@ -24,7 +24,9 @@ package sql import ( "context" "database/sql" + "encoding/base64" "errors" + "fmt" "math" "testing" "time" @@ -245,7 +247,9 @@ func TestLeaseTaskList(t *testing.T) { AdaptivePartitionConfig: &serialization.TaskListPartitionConfig{ Version: 0, NumReadPartitions: 1, + ReadPartitions: map[int32]*serialization.TaskListPartition{0: {}}, NumWritePartitions: 1, + WritePartitions: map[int32]*serialization.TaskListPartition{0: {}}, }, }, nil) mockDB.EXPECT().BeginTx(gomock.Any(), 0).Return(mockTx, nil) @@ -283,9 +287,13 @@ func TestLeaseTaskList(t *testing.T) { AckLevel: 0, Kind: persistence.TaskListKindNormal, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 0, - NumReadPartitions: 1, - NumWritePartitions: 1, + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + }, }, }, }, @@ -570,6 +578,16 @@ func TestGetTaskList(t *testing.T) { Version: 0, NumReadPartitions: 1, NumWritePartitions: 1, + ReadPartitions: map[int32]*serialization.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int32]*serialization.TaskListPartition{ + 0: { + IsolationGroups: []string{"bar"}, + }, + }, }, }, nil) }, @@ -584,9 +602,79 @@ func TestGetTaskList(t *testing.T) { Expiry: time.Unix(1, 4), LastUpdated: time.Unix(10, 0), AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"bar"}, + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "Partition counts instead of data", + req: &persistence.GetTaskListRequest{ + DomainID: "c9488dc7-20b2-44c3-b2e4-bfea5af62ac0", + TaskList: "tl", + TaskType: 1, + }, + mockSetup: func(mockDB *sqlplugin.MockDB, mockParser *serialization.MockParser) { + mockDB.EXPECT().GetTotalNumDBShards().Return(1) + mockDB.EXPECT().SelectFromTaskLists(gomock.Any(), gomock.Any()).DoAndReturn(func(_ context.Context, filter *sqlplugin.TaskListsFilter) ([]sqlplugin.TaskListsRow, error) { + assert.Equal(t, serialization.MustParseUUID("c9488dc7-20b2-44c3-b2e4-bfea5af62ac0"), *filter.DomainID) + assert.Equal(t, "tl", *filter.Name) + assert.Equal(t, int64(1), *filter.TaskType) + return []sqlplugin.TaskListsRow{ + { + ShardID: 11, + DomainID: serialization.MustParseUUID("c9488dc7-20b2-44c3-b2e4-bfea5af62ac0"), + Name: "tl", + TaskType: 1, + RangeID: 123, + Data: []byte(`tl`), + DataEncoding: "tl", + }, + }, nil + }) + mockParser.EXPECT().TaskListInfoFromBlob([]byte(`tl`), "tl").Return(&serialization.TaskListInfo{ + Kind: 1, + AckLevel: 2, + ExpiryTimestamp: time.Unix(1, 4), + LastUpdated: time.Unix(10, 0), + AdaptivePartitionConfig: &serialization.TaskListPartitionConfig{ Version: 0, - NumReadPartitions: 1, - NumWritePartitions: 1, + NumReadPartitions: 2, + NumWritePartitions: 2, + }, + }, nil) + }, + want: &persistence.GetTaskListResponse{ + TaskListInfo: &persistence.TaskListInfo{ + DomainID: "c9488dc7-20b2-44c3-b2e4-bfea5af62ac0", + Name: "tl", + TaskType: 1, + RangeID: 123, + Kind: 1, + AckLevel: 2, + Expiry: time.Unix(1, 4), + LastUpdated: time.Unix(10, 0), + AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: {}, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: {}, + 1: {}, + }, }, }, }, @@ -695,9 +783,17 @@ func TestUpdateTaskList(t *testing.T) { AckLevel: 0, Kind: persistence.TaskListKindNormal, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 0, - NumReadPartitions: 1, - NumWritePartitions: 1, + Version: 0, + ReadPartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*persistence.TaskListPartition{ + 0: { + IsolationGroups: []string{"bar"}, + }, + }, }, }, }, @@ -709,6 +805,8 @@ func TestUpdateTaskList(t *testing.T) { assert.Equal(t, int64(0), info.AdaptivePartitionConfig.Version) assert.Equal(t, int32(1), info.AdaptivePartitionConfig.NumReadPartitions) assert.Equal(t, int32(1), info.AdaptivePartitionConfig.NumWritePartitions) + assert.Equal(t, "foo", info.AdaptivePartitionConfig.ReadPartitions[0].IsolationGroups[0]) + assert.Equal(t, "bar", info.AdaptivePartitionConfig.WritePartitions[0].IsolationGroups[0]) return persistence.DataBlob{ Data: []byte(`tl`), Encoding: common.EncodingType("tl"), @@ -1493,3 +1591,16 @@ func TestCompleteTaskLessThan(t *testing.T) { }) } } + +func TestHelp(t *testing.T) { + shard := sqlplugin.GetDBShardIDFromDomainIDAndTasklist("c4b5cb22-c213-4812-bb4a-fc1ade5405ef", "pgtasklist", 16384) + println("shard: ", shard) + // BgAKAAAKAAwAAAAABQ+kWAoADgAAAAAAAAAACgAQGB6uFsU9cvEMABIKAAoAAAAAAAAAAQgADAAAAAAIAA4AAAAAAAA= + parser, err := serialization.NewParser(common.EncodingTypeThriftRW, common.EncodingTypeThriftRW) + require.NoError(t, err) + data, err := base64.StdEncoding.DecodeString("BgAKAAAKAAwAAAAABGGFYAoADgAAAAAAAAAACgAQGB6uGPaVqOUMABIKAAoAAAAAAAAAAQgADAAAAAIIAA4AAAACAAA=") + require.NoError(t, err) + info, err := parser.TaskListInfoFromBlob(data, "thriftrw") + require.NoError(t, err) + fmt.Printf("info: %v", info) +} diff --git a/common/types/mapper/proto/api.go b/common/types/mapper/proto/api.go index babecda8127..c95c66e1799 100644 --- a/common/types/mapper/proto/api.go +++ b/common/types/mapper/proto/api.go @@ -6124,8 +6124,10 @@ func FromAPITaskListPartitionConfig(t *types.TaskListPartitionConfig) *apiv1.Tas } return &apiv1.TaskListPartitionConfig{ Version: t.Version, - NumReadPartitions: t.NumReadPartitions, - NumWritePartitions: t.NumWritePartitions, + NumReadPartitions: int32(len(t.ReadPartitions)), + NumWritePartitions: int32(len(t.WritePartitions)), + ReadPartitions: FromAPITaskListPartitionsMap(t.ReadPartitions), + WritePartitions: FromAPITaskListPartitionsMap(t.WritePartitions), } } @@ -6134,10 +6136,56 @@ func ToAPITaskListPartitionConfig(t *apiv1.TaskListPartitionConfig) *types.TaskL return nil } return &types.TaskListPartitionConfig{ - Version: t.Version, - NumReadPartitions: t.NumReadPartitions, - NumWritePartitions: t.NumWritePartitions, + Version: t.Version, + ReadPartitions: ToAPITaskListPartitionsMap(t.NumReadPartitions, t.ReadPartitions), + WritePartitions: ToAPITaskListPartitionsMap(t.NumWritePartitions, t.WritePartitions), + } +} + +func FromAPITaskListPartition(t *types.TaskListPartition) *apiv1.TaskListPartition { + if t == nil { + return nil + } + return &apiv1.TaskListPartition{ + IsolationGroups: t.IsolationGroups, + } +} + +func ToAPITaskListPartition(t *apiv1.TaskListPartition) *types.TaskListPartition { + if t == nil { + return nil + } + return &types.TaskListPartition{ + IsolationGroups: t.IsolationGroups, + } +} + +func FromAPITaskListPartitionsMap(m map[int]*types.TaskListPartition) map[int32]*apiv1.TaskListPartition { + if m == nil { + return nil + } + result := make(map[int32]*apiv1.TaskListPartition, len(m)) + for id, p := range m { + result[int32(id)] = FromAPITaskListPartition(p) + } + return result +} + +func ToAPITaskListPartitionsMap(numPartitions int32, m map[int32]*apiv1.TaskListPartition) map[int]*types.TaskListPartition { + if m == nil && numPartitions == 0 { + return nil + } + result := make(map[int]*types.TaskListPartition, len(m)) + if numPartitions != int32(len(m)) { + for i := int32(0); i < numPartitions; i++ { + result[int(i)] = &types.TaskListPartition{} + } + } else { + for id, p := range m { + result[int(id)] = ToAPITaskListPartition(p) + } } + return result } func FromAutoConfigHint(t *types.AutoConfigHint) *apiv1.AutoConfigHint { diff --git a/common/types/mapper/proto/api_test.go b/common/types/mapper/proto/api_test.go index 300b4dd5307..176772c69d0 100644 --- a/common/types/mapper/proto/api_test.go +++ b/common/types/mapper/proto/api_test.go @@ -1089,3 +1089,90 @@ func TestAPITaskListPartitionConfig(t *testing.T) { assert.Equal(t, item, ToAPITaskListPartitionConfig(FromAPITaskListPartitionConfig(item))) } } + +func TestToAPITaskListPartitionConfig(t *testing.T) { + cases := []struct { + name string + config *apiv1.TaskListPartitionConfig + expected *types.TaskListPartitionConfig + }{ + { + name: "happy path", + config: &apiv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 2, + ReadPartitions: map[int32]*apiv1.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int32]*apiv1.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + }, + { + name: "numbers only", + config: &apiv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 2, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + }, + }, + { + name: "number mismatch", + config: &apiv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 1, + ReadPartitions: map[int32]*apiv1.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int32]*apiv1.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + }, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + actual := ToAPITaskListPartitionConfig(tc.config) + assert.Equal(t, tc.expected, actual) + }) + } +} diff --git a/common/types/mapper/proto/matching.go b/common/types/mapper/proto/matching.go index f1dea30192a..1d1a925397c 100644 --- a/common/types/mapper/proto/matching.go +++ b/common/types/mapper/proto/matching.go @@ -368,8 +368,10 @@ func FromTaskListPartitionConfig(t *types.TaskListPartitionConfig) *matchingv1.T } return &matchingv1.TaskListPartitionConfig{ Version: t.Version, - NumReadPartitions: t.NumReadPartitions, - NumWritePartitions: t.NumWritePartitions, + NumReadPartitions: int32(len(t.ReadPartitions)), + NumWritePartitions: int32(len(t.WritePartitions)), + ReadPartitions: FromMatchingTaskListPartitionsMap(t.ReadPartitions), + WritePartitions: FromMatchingTaskListPartitionsMap(t.WritePartitions), } } @@ -378,10 +380,56 @@ func ToTaskListPartitionConfig(t *matchingv1.TaskListPartitionConfig) *types.Tas return nil } return &types.TaskListPartitionConfig{ - Version: t.Version, - NumReadPartitions: t.NumReadPartitions, - NumWritePartitions: t.NumWritePartitions, + Version: t.Version, + ReadPartitions: ToMatchingTaskListPartitionsMap(t.NumReadPartitions, t.ReadPartitions), + WritePartitions: ToMatchingTaskListPartitionsMap(t.NumWritePartitions, t.WritePartitions), + } +} + +func FromMatchingTaskListPartition(t *types.TaskListPartition) *matchingv1.TaskListPartition { + if t == nil { + return nil + } + return &matchingv1.TaskListPartition{ + IsolationGroups: t.IsolationGroups, + } +} + +func ToMatchingTaskListPartition(t *matchingv1.TaskListPartition) *types.TaskListPartition { + if t == nil { + return nil + } + return &types.TaskListPartition{ + IsolationGroups: t.IsolationGroups, + } +} + +func FromMatchingTaskListPartitionsMap(m map[int]*types.TaskListPartition) map[int32]*matchingv1.TaskListPartition { + if m == nil { + return nil + } + result := make(map[int32]*matchingv1.TaskListPartition, len(m)) + for id, p := range m { + result[int32(id)] = FromMatchingTaskListPartition(p) + } + return result +} + +func ToMatchingTaskListPartitionsMap(numPartitions int32, m map[int32]*matchingv1.TaskListPartition) map[int]*types.TaskListPartition { + if m == nil && numPartitions == 0 { + return nil + } + result := make(map[int]*types.TaskListPartition, len(m)) + if numPartitions != int32(len(m)) { + for i := int32(0); i < numPartitions; i++ { + result[int(i)] = &types.TaskListPartition{} + } + } else { + for id, p := range m { + result[int(id)] = ToMatchingTaskListPartition(p) + } } + return result } func FromMatchingPollForActivityTaskResponse(t *types.MatchingPollForActivityTaskResponse) *matchingv1.PollForActivityTaskResponse { diff --git a/common/types/mapper/proto/matching_test.go b/common/types/mapper/proto/matching_test.go index 63bb9fcc155..be97d5012dd 100644 --- a/common/types/mapper/proto/matching_test.go +++ b/common/types/mapper/proto/matching_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/assert" + matchingv1 "github.com/uber/cadence/.gen/proto/matching/v1" "github.com/uber/cadence/common/types" "github.com/uber/cadence/common/types/testdata" ) @@ -172,3 +173,90 @@ func TestMatchingRefreshTaskListPartitionConfigResponse(t *testing.T) { assert.Equal(t, item, ToMatchingRefreshTaskListPartitionConfigResponse(FromMatchingRefreshTaskListPartitionConfigResponse(item))) } } + +func TestToMatchingTaskListPartitionConfig(t *testing.T) { + cases := []struct { + name string + config *matchingv1.TaskListPartitionConfig + expected *types.TaskListPartitionConfig + }{ + { + name: "happy path", + config: &matchingv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 2, + ReadPartitions: map[int32]*matchingv1.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int32]*matchingv1.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + }, + { + name: "numbers only", + config: &matchingv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 2, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + }, + }, + { + name: "number mismatch", + config: &matchingv1.TaskListPartitionConfig{ + Version: 1, + NumReadPartitions: 2, + NumWritePartitions: 1, + ReadPartitions: map[int32]*matchingv1.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int32]*matchingv1.TaskListPartition{ + 0: {IsolationGroups: []string{"baz"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + }, + expected: &types.TaskListPartitionConfig{ + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {IsolationGroups: []string{"foo"}}, + 1: {IsolationGroups: []string{"bar"}}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + }, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + actual := ToTaskListPartitionConfig(tc.config) + assert.Equal(t, tc.expected, actual) + }) + } +} diff --git a/common/types/matching.go b/common/types/matching.go index 74dc3fdc0d7..4fcfd4dcf27 100644 --- a/common/types/matching.go +++ b/common/types/matching.go @@ -418,10 +418,14 @@ func (v *MatchingPollForDecisionTaskRequest) GetIsolationGroup() (o string) { return } +type TaskListPartition struct { + IsolationGroups []string +} + type TaskListPartitionConfig struct { - Version int64 - NumReadPartitions int32 - NumWritePartitions int32 + Version int64 + ReadPartitions map[int]*TaskListPartition + WritePartitions map[int]*TaskListPartition } // MatchingPollForDecisionTaskResponse is an internal type (TBD...) diff --git a/common/types/shared.go b/common/types/shared.go index becf850df91..5b49fc02721 100644 --- a/common/types/shared.go +++ b/common/types/shared.go @@ -1690,9 +1690,9 @@ func (v *DescribeTaskListRequest) GetIncludeTaskListStatus() (o bool) { // DescribeTaskListResponse is an internal type (TBD...) type DescribeTaskListResponse struct { - Pollers []*PollerInfo `json:"pollers,omitempty"` - TaskListStatus *TaskListStatus `json:"taskListStatus,omitempty"` - PartitionConfig *TaskListPartitionConfig + Pollers []*PollerInfo `json:"pollers,omitempty"` + TaskListStatus *TaskListStatus `json:"taskListStatus,omitempty"` + PartitionConfig *TaskListPartitionConfig `json:"partitionConfig,omitempty"` } // GetPollers is an internal getter (TBD...) diff --git a/common/types/testdata/service_matching.go b/common/types/testdata/service_matching.go index 28185050274..2108ad3a062 100644 --- a/common/types/testdata/service_matching.go +++ b/common/types/testdata/service_matching.go @@ -32,9 +32,20 @@ const ( var ( TaskListPartitionConfig = types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + 2: { + IsolationGroups: []string{"foo"}, + }, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: { + IsolationGroups: []string{"bar"}, + }, + }, } LoadBalancerHints = types.LoadBalancerHints{ BacklogCount: 1000, diff --git a/docker/domain/cassandra.cql b/docker/domain/cassandra.cql new file mode 100644 index 00000000000..83b44ce59a5 --- /dev/null +++ b/docker/domain/cassandra.cql @@ -0,0 +1,55 @@ +-- Insert into domains table +INSERT INTO domains ( + id, + domain +) VALUES ( + 123e4567-e89b-12d3-a456-426614174000, -- Replace with your UUID + { + id: 123e4567-e89b-12d3-a456-426614174000, -- Replace with your UUID + name: 'default', + status: 0, -- Registered + description: 'This is an example domain.', + data: {'key1': 'value1', 'key2': 'value2'}, + owner_email: 'owner@example.com' + } +) IF NOT EXISTS; + +-- Insert into domains_by_name_v2 table +INSERT INTO domains_by_name_v2 ( + domains_partition, + name, + domain, + config, + replication_config, + is_global_domain, + config_version, + failover_version, + failover_notification_version, + notification_version +) VALUES ( + 0, + 'default', + { + id: 123e4567-e89b-12d3-a456-426614174000, -- Replace with your UUID + name: 'default', + status: 0, -- Registered + description: 'This is an example domain.', + data: {'key1': 'value1', 'key2': 'value2'}, + owner_email: 'owner@example.com' + }, + { + retention: 7, + emit_metric: True, + history_archival_status: 0, -- Default to disabled + visibility_archival_status: 0 -- Default to disabled + }, + { + active_cluster_name: 'cluster0', + clusters: [{cluster_name: 'cluster0'}] + }, + True, -- is_global_domain + 1, -- config_version + 0, -- failover_version + 0, -- failover_notification_version + 0 -- notification_version +) IF NOT EXISTS; diff --git a/docker/domain/mysql.sql b/docker/domain/mysql.sql new file mode 100644 index 00000000000..2613c6eda12 --- /dev/null +++ b/docker/domain/mysql.sql @@ -0,0 +1,25 @@ +-- Insert into domains table +INSERT INTO domains ( + shard_id, + id, + name, + data, + data_encoding, + is_global +) VALUES ( + 54321, -- Default shard_id + UNHEX(REPLACE(UUID(), '-', '')), -- Generate a 16-byte UUID + 'default', -- Domain name + '{"key1":"value1","key2":"value2"}', -- Example data as JSON + 'json', -- Encoding type + 1 -- Set to 1 for a global domain +) ON DUPLICATE KEY UPDATE + name = VALUES(name); + +-- Insert into domain_metadata table +INSERT INTO domain_metadata ( + notification_version +) VALUES ( + 1 +) ON DUPLICATE KEY UPDATE + notification_version = VALUES(notification_version); \ No newline at end of file diff --git a/docker/domain/postgres.sql b/docker/domain/postgres.sql new file mode 100644 index 00000000000..073da21a445 --- /dev/null +++ b/docker/domain/postgres.sql @@ -0,0 +1,32 @@ +-- Insert into domains table +INSERT INTO domains ( + shard_id, + id, + name, + data, + data_encoding, + is_global +) VALUES ( + 54321, -- Default shard_id + gen_random_uuid(), -- Generate a UUID for the domain ID + 'default', -- Domain name + '{"key1":"value1","key2":"value2"}', -- Example JSON data + 'json', -- Encoding type + TRUE -- Set to TRUE for a global domain +) ON CONFLICT (shard_id, id) DO UPDATE +SET + name = EXCLUDED.name, + data = EXCLUDED.data, + data_encoding = EXCLUDED.data_encoding, + is_global = EXCLUDED.is_global; + +-- Insert into domain_metadata table +INSERT INTO domain_metadata ( + id, + notification_version +) VALUES ( + 1, -- Default ID + 1 -- Notification version +) ON CONFLICT (id) DO UPDATE +SET + notification_version = EXCLUDED.notification_version; \ No newline at end of file diff --git a/docker/start.sh b/docker/start.sh index d92567a00a3..8213cbf8737 100755 --- a/docker/start.sh +++ b/docker/start.sh @@ -32,6 +32,8 @@ setup_cassandra_schema() { cadence-cassandra-tool --ep $CASSANDRA_SEEDS create -k $VISIBILITY_KEYSPACE --rf $RF cadence-cassandra-tool --ep $CASSANDRA_SEEDS -k $VISIBILITY_KEYSPACE setup-schema -v 0.0 cadence-cassandra-tool --ep $CASSANDRA_SEEDS -k $VISIBILITY_KEYSPACE update-schema -d $VISIBILITY_SCHEMA_DIR + echo "Registering domain for Cassandra..." + cqlsh $CASSANDRA_SEEDS -k $KEYSPACE -f /etc/cadence/domain/cassandra.cql } setup_mysql_schema() { @@ -46,6 +48,8 @@ setup_mysql_schema() { cadence-sql-tool --ep $MYSQL_SEEDS -u $MYSQL_USER --pw $MYSQL_PWD $CONNECT_ATTR create --db $VISIBILITY_DBNAME cadence-sql-tool --ep $MYSQL_SEEDS -u $MYSQL_USER --pw $MYSQL_PWD --db $VISIBILITY_DBNAME $CONNECT_ATTR setup-schema -v 0.0 cadence-sql-tool --ep $MYSQL_SEEDS -u $MYSQL_USER --pw $MYSQL_PWD --db $VISIBILITY_DBNAME $CONNECT_ATTR update-schema -d $VISIBILITY_SCHEMA_DIR + echo "Registering domain for MySQL..." + mysql -h $MYSQL_HOST -u $MYSQL_USER -p $MYSQL_PASSWORD $MYSQL_DATABASE < /etc/cadence/domain/mysql.sql } setup_postgres_schema() { @@ -57,6 +61,8 @@ setup_postgres_schema() { cadence-sql-tool --plugin postgres --ep $POSTGRES_SEEDS -u $POSTGRES_USER --pw "$POSTGRES_PWD" -p $DB_PORT create --db $VISIBILITY_DBNAME cadence-sql-tool --plugin postgres --ep $POSTGRES_SEEDS -u $POSTGRES_USER --pw "$POSTGRES_PWD" -p $DB_PORT --db $VISIBILITY_DBNAME setup-schema -v 0.0 cadence-sql-tool --plugin postgres --ep $POSTGRES_SEEDS -u $POSTGRES_USER --pw "$POSTGRES_PWD" -p $DB_PORT --db $VISIBILITY_DBNAME update-schema -d $VISIBILITY_SCHEMA_DIR + echo "Registering domain for PostgreSQL..." + PGPASSWORD=$POSTGRES_PASSWORD psql -h $POSTGRES_HOST -U $POSTGRES_USER -d $POSTGRES_DATABASE -f /etc/cadence/domain/postgres.sql } diff --git a/proto/internal/uber/cadence/matching/v1/service.proto b/proto/internal/uber/cadence/matching/v1/service.proto index 0ec65534986..4d116beea54 100644 --- a/proto/internal/uber/cadence/matching/v1/service.proto +++ b/proto/internal/uber/cadence/matching/v1/service.proto @@ -97,10 +97,16 @@ service MatchingAPI { rpc RefreshTaskListPartitionConfig(RefreshTaskListPartitionConfigRequest) returns (RefreshTaskListPartitionConfigResponse); } +message TaskListPartition { + repeated string isolation_groups = 1; +} + message TaskListPartitionConfig { int64 version = 1; - int32 num_read_partitions = 2; - int32 num_write_partitions = 3; + int32 num_read_partitions = 2 [deprecated = true]; + int32 num_write_partitions = 3 [deprecated = true]; + map read_partitions = 4; + map write_partitions = 5; } message LoadBalancerHints { diff --git a/service/frontend/admin/handler.go b/service/frontend/admin/handler.go index d81c194cfd7..6122e96d517 100644 --- a/service/frontend/admin/handler.go +++ b/service/frontend/admin/handler.go @@ -1803,10 +1803,10 @@ func (adh *adminHandlerImpl) UpdateTaskListPartitionConfig(ctx context.Context, if request.PartitionConfig == nil { return nil, adh.error(&types.BadRequestError{Message: "Task list partition config is not set in the request."}, scope) } - if request.PartitionConfig.NumWritePartitions > request.PartitionConfig.NumReadPartitions { + if len(request.PartitionConfig.WritePartitions) > len(request.PartitionConfig.ReadPartitions) { return nil, adh.error(&types.BadRequestError{Message: "The number of write partitions cannot be larger than the number of read partitions."}, scope) } - if request.PartitionConfig.NumWritePartitions <= 0 { + if len(request.PartitionConfig.WritePartitions) <= 0 { return nil, adh.error(&types.BadRequestError{Message: "The number of partitions must be larger than 0."}, scope) } _, err = adh.GetMatchingClient().UpdateTaskListPartitionConfig(ctx, &types.MatchingUpdateTaskListPartitionConfigRequest{ diff --git a/service/frontend/admin/handler_test.go b/service/frontend/admin/handler_test.go index a11261513d6..96d5646b021 100644 --- a/service/frontend/admin/handler_test.go +++ b/service/frontend/admin/handler_test.go @@ -2731,8 +2731,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { kind := types.TaskListKindNormal taskListType := types.TaskListTypeActivity partitionConfig := &types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, } testCases := []struct { @@ -2840,8 +2845,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: &taskListType, PartitionConfig: &types.TaskListPartitionConfig{ - NumReadPartitions: 1, - NumWritePartitions: 2, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, }, }, setupMocks: func(mockMatchingClient *matching.MockClient, mockDomainCache *cache.MockDomainCache) { @@ -2860,8 +2870,11 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: &taskListType, PartitionConfig: &types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 0, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + 1: {}, + }, + WritePartitions: nil, }, }, setupMocks: func(mockMatchingClient *matching.MockClient, mockDomainCache *cache.MockDomainCache) { diff --git a/service/matching/handler/engine.go b/service/matching/handler/engine.go index 910ac7e8843..c8dfc7da59b 100644 --- a/service/matching/handler/engine.go +++ b/service/matching/handler/engine.go @@ -1062,12 +1062,6 @@ func (e *matchingEngineImpl) UpdateTaskListPartitionConfig( if request.PartitionConfig == nil { return nil, &types.BadRequestError{Message: "Task list partition config is not set in the request."} } - if request.PartitionConfig.NumWritePartitions > request.PartitionConfig.NumReadPartitions { - return nil, &types.BadRequestError{Message: "The number of write partitions cannot be larger than the number of read partitions."} - } - if request.PartitionConfig.NumWritePartitions <= 0 { - return nil, &types.BadRequestError{Message: "The number of partitions must be larger than 0."} - } taskListID, err := tasklist.NewIdentifier(domainID, taskListName, taskListType) if err != nil { return nil, err @@ -1100,12 +1094,6 @@ func (e *matchingEngineImpl) RefreshTaskListPartitionConfig( if taskListKind != types.TaskListKindNormal { return nil, &types.BadRequestError{Message: "Only normal tasklist's partition config can be updated."} } - if request.PartitionConfig != nil && request.PartitionConfig.NumWritePartitions > request.PartitionConfig.NumReadPartitions { - return nil, &types.BadRequestError{Message: "The number of write partitions cannot be larger than the number of read partitions."} - } - if request.PartitionConfig != nil && request.PartitionConfig.NumWritePartitions <= 0 { - return nil, &types.BadRequestError{Message: "The number of partitions must be larger than 0."} - } taskListID, err := tasklist.NewIdentifier(domainID, taskListName, taskListType) if err != nil { return nil, err diff --git a/service/matching/handler/engine_test.go b/service/matching/handler/engine_test.go index bf5657eb5b3..a3382b5ab58 100644 --- a/service/matching/handler/engine_test.go +++ b/service/matching/handler/engine_test.go @@ -745,9 +745,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -755,9 +759,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, mockSetup: func(mockManager *tasklist.MockManager) { mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }).Return(nil) }, expectError: false, @@ -771,9 +779,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -781,9 +793,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, mockSetup: func(mockManager *tasklist.MockManager) { mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }).Return(errors.New("tasklist manager error")) }, expectError: true, @@ -798,9 +814,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -820,9 +840,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -833,50 +857,6 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { expectError: true, expectedError: "invalid partitioned task list name /__cadence_sys/test-tasklist", }, - { - name: "invalid partition config", - req: &types.MatchingUpdateTaskListPartitionConfigRequest{ - DomainUUID: "test-domain-id", - TaskList: &types.TaskList{ - Name: "test-tasklist", - }, - TaskListType: types.TaskListTypeActivity.Ptr(), - PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 3, - }, - }, - hCtx: &handlerContext{ - Context: context.Background(), - }, - mockSetup: func(mockManager *tasklist.MockManager) { - }, - expectError: true, - expectedError: "The number of write partitions cannot be larger than the number of read partitions.", - }, - { - name: "invalid partition config - 2", - req: &types.MatchingUpdateTaskListPartitionConfigRequest{ - DomainUUID: "test-domain-id", - TaskList: &types.TaskList{ - Name: "test-tasklist", - }, - TaskListType: types.TaskListTypeActivity.Ptr(), - PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: -1, - }, - }, - hCtx: &handlerContext{ - Context: context.Background(), - }, - mockSetup: func(mockManager *tasklist.MockManager) { - }, - expectError: true, - expectedError: "The number of partitions must be larger than 0.", - }, { name: "nil partition config", req: &types.MatchingUpdateTaskListPartitionConfigRequest{ @@ -980,9 +960,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -990,9 +974,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, mockSetup: func(mockManager *tasklist.MockManager) { mockManager.EXPECT().RefreshTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }).Return(nil) }, expectError: false, @@ -1006,9 +994,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -1016,9 +1008,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, mockSetup: func(mockManager *tasklist.MockManager) { mockManager.EXPECT().RefreshTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }).Return(errors.New("tasklist manager error")) }, expectError: true, @@ -1033,9 +1029,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ @@ -1046,50 +1046,6 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { expectError: true, expectedError: "invalid partitioned task list name /__cadence_sys/test-tasklist", }, - { - name: "invalid partition config", - req: &types.MatchingRefreshTaskListPartitionConfigRequest{ - DomainUUID: "test-domain-id", - TaskList: &types.TaskList{ - Name: "test-tasklist", - }, - TaskListType: types.TaskListTypeActivity.Ptr(), - PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 3, - }, - }, - hCtx: &handlerContext{ - Context: context.Background(), - }, - mockSetup: func(mockManager *tasklist.MockManager) { - }, - expectError: true, - expectedError: "The number of write partitions cannot be larger than the number of read partitions.", - }, - { - name: "invalid partition config - 2", - req: &types.MatchingRefreshTaskListPartitionConfigRequest{ - DomainUUID: "test-domain-id", - TaskList: &types.TaskList{ - Name: "test-tasklist", - }, - TaskListType: types.TaskListTypeActivity.Ptr(), - PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: -1, - }, - }, - hCtx: &handlerContext{ - Context: context.Background(), - }, - mockSetup: func(mockManager *tasklist.MockManager) { - }, - expectError: true, - expectedError: "The number of partitions must be larger than 0.", - }, { name: "invalid tasklist kind", req: &types.MatchingRefreshTaskListPartitionConfigRequest{ @@ -1117,9 +1073,13 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }, TaskListType: types.TaskListTypeActivity.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, }, }, hCtx: &handlerContext{ diff --git a/service/matching/handler/handler_test.go b/service/matching/handler/handler_test.go index 73a684c926e..db8332b8479 100644 --- a/service/matching/handler/handler_test.go +++ b/service/matching/handler/handler_test.go @@ -170,17 +170,17 @@ func (s *handlerSuite) TestAddActivityTask() { s.mockLimiter.EXPECT().Allow().Return(true).Times(1) s.mockEngine.EXPECT().AddActivityTask(gomock.Any(), &request).Return(&types.AddActivityTaskResponse{ PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }, nil).Times(1) }, want: &types.AddActivityTaskResponse{ PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }, }, @@ -238,17 +238,17 @@ func (s *handlerSuite) TestAddDecisionTask() { s.mockLimiter.EXPECT().Allow().Return(true).Times(1) s.mockEngine.EXPECT().AddDecisionTask(gomock.Any(), &request).Return(&types.AddDecisionTaskResponse{ PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }, nil).Times(1) }, want: &types.AddDecisionTaskResponse{ PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }, }, @@ -894,3 +894,11 @@ func (s *handlerSuite) TestUpdateTaskListPartitionConfig() { }) } } + +func partitions(num int) map[int]*types.TaskListPartition { + result := make(map[int]*types.TaskListPartition, num) + for i := 0; i < num; i++ { + result[i] = &types.TaskListPartition{} + } + return result +} diff --git a/service/matching/tasklist/adaptive_scaler.go b/service/matching/tasklist/adaptive_scaler.go index fa323f1b2d9..46b46202fb5 100644 --- a/service/matching/tasklist/adaptive_scaler.go +++ b/service/matching/tasklist/adaptive_scaler.go @@ -27,7 +27,8 @@ import ( "math" "sync" "sync/atomic" - "time" + + "golang.org/x/sync/errgroup" "github.com/uber/cadence/client/matching" "github.com/uber/cadence/common" @@ -36,7 +37,6 @@ import ( "github.com/uber/cadence/common/log/tag" "github.com/uber/cadence/common/metrics" "github.com/uber/cadence/common/persistence" - "github.com/uber/cadence/common/stats" "github.com/uber/cadence/common/types" "github.com/uber/cadence/service/matching/config" "github.com/uber/cadence/service/matching/event" @@ -50,30 +50,38 @@ type ( adaptiveScalerImpl struct { taskListID *Identifier tlMgr Manager - qpsTracker stats.QPSTracker config *config.TaskListConfig timeSource clock.TimeSource logger log.Logger scope metrics.Scope matchingClient matching.Client - taskListType *types.TaskListType - status int32 - wg sync.WaitGroup - ctx context.Context - cancel func() - overLoad bool - overLoadStartTime time.Time - underLoad bool - underLoadStartTime time.Time - baseEvent event.E + taskListType *types.TaskListType + status int32 + wg sync.WaitGroup + ctx context.Context + cancel func() + overLoad clock.Sustain + underLoad clock.Sustain + baseEvent event.E + } + + aggregatePartitionMetrics struct { + totalQPS float64 + qpsByIsolationGroup map[string]float64 + byPartition map[int]*partitionMetrics + } + + partitionMetrics struct { + qps float64 + backlog int64 + readOnly bool } ) func NewAdaptiveScaler( taskListID *Identifier, tlMgr Manager, - qpsTracker stats.QPSTracker, config *config.TaskListConfig, timeSource clock.TimeSource, logger log.Logger, @@ -85,7 +93,6 @@ func NewAdaptiveScaler( return &adaptiveScalerImpl{ taskListID: taskListID, tlMgr: tlMgr, - qpsTracker: qpsTracker, config: config, timeSource: timeSource, logger: logger.WithTags(tag.ComponentTaskListAdaptiveScaler), @@ -94,8 +101,8 @@ func NewAdaptiveScaler( taskListType: getTaskListType(taskListID.GetType()), ctx: ctx, cancel: cancel, - overLoad: false, - underLoad: false, + overLoad: clock.NewSustain(timeSource, config.PartitionUpscaleSustainedDuration), + underLoad: clock.NewSustain(timeSource, config.PartitionDownscaleSustainedDuration), baseEvent: baseEvent, } } @@ -137,35 +144,45 @@ func (a *adaptiveScalerImpl) run() { if !a.config.EnableAdaptiveScaler() || !a.config.EnableGetNumberOfPartitionsFromCache() { return } - qps := a.qpsTracker.QPS() + partitionConfig := a.getPartitionConfig() + m, err := a.collectPartitionMetrics(partitionConfig) + // TODO: Handle this better. Maybe we should allow scaling up but not down if our data is incomplete? + if err != nil { + a.underLoad.Reset() + a.overLoad.Reset() + a.logger.Error("Failed to collect partition metrics", tag.Error(err)) + return + } // adjust the number of write partitions based on qps - numWritePartitions := a.adjustWritePartitions(qps, partitionConfig.NumWritePartitions) - // adjust the number of read partitions - numReadPartitions := a.adjustReadPartitions(partitionConfig.NumReadPartitions, numWritePartitions) + numWritePartitions := a.calculateWritePartitionCount(m.totalQPS, len(partitionConfig.WritePartitions)) + writePartitions, writeChanged := a.adjustWritePartitions(partitionConfig.WritePartitions, numWritePartitions) + // TODO: Rebalance isolation groups between partitions + // adjust the read partitions + readPartitions, readChanged := a.adjustReadPartitions(m, partitionConfig.ReadPartitions, writePartitions) e := a.baseEvent e.EventName = "AdaptiveScalerCalculationResult" e.Payload = map[string]any{ - "NumReadPartitions": numReadPartitions, - "NumWritePartitions": numWritePartitions, - "QPS": qps, + "NumReadPartitions": len(readPartitions), + "NumWritePartitions": len(writePartitions), + "QPS": m.totalQPS, } event.Log(e) - if numReadPartitions == partitionConfig.NumReadPartitions && numWritePartitions == partitionConfig.NumWritePartitions { + if !writeChanged && !readChanged { return } a.logger.Info("adaptive scaler is updating number of partitions", - tag.CurrentQPS(qps), - tag.NumReadPartitions(numReadPartitions), - tag.NumWritePartitions(numWritePartitions), + tag.CurrentQPS(m.totalQPS), + tag.NumReadPartitions(len(readPartitions)), + tag.NumWritePartitions(len(writePartitions)), tag.Dynamic("task-list-partition-config", partitionConfig), ) a.scope.IncCounter(metrics.CadenceRequests) - err := a.tlMgr.UpdateTaskListPartitionConfig(a.ctx, &types.TaskListPartitionConfig{ - NumReadPartitions: numReadPartitions, - NumWritePartitions: numWritePartitions, + err = a.tlMgr.UpdateTaskListPartitionConfig(a.ctx, &types.TaskListPartitionConfig{ + ReadPartitions: readPartitions, + WritePartitions: writePartitions, }) if err != nil { a.logger.Error("failed to update task list partition config", tag.Error(err)) @@ -177,91 +194,183 @@ func (a *adaptiveScalerImpl) getPartitionConfig() *types.TaskListPartitionConfig partitionConfig := a.tlMgr.TaskListPartitionConfig() if partitionConfig == nil { partitionConfig = &types.TaskListPartitionConfig{ - NumReadPartitions: 1, - NumWritePartitions: 1, + ReadPartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, + WritePartitions: map[int]*types.TaskListPartition{ + 0: {}, + }, } } return partitionConfig } -func (a *adaptiveScalerImpl) adjustWritePartitions(qps float64, numWritePartitions int32) int32 { - upscaleThreshold := float64(a.config.PartitionUpscaleRPS()) +func (a *adaptiveScalerImpl) calculateWritePartitionCount(qps float64, numWritePartitions int) int { + upscaleRps := float64(a.config.PartitionUpscaleRPS()) + partitions := float64(numWritePartitions) downscaleFactor := a.config.PartitionDownscaleFactor() - downscaleThreshold := float64(numWritePartitions-1) * upscaleThreshold * downscaleFactor / float64(numWritePartitions) + upscaleThreshold := partitions * upscaleRps + downscaleThreshold := (partitions - 1) * upscaleRps * downscaleFactor a.scope.UpdateGauge(metrics.EstimatedAddTaskQPSGauge, qps) a.scope.UpdateGauge(metrics.TaskListPartitionUpscaleThresholdGauge, upscaleThreshold) a.scope.UpdateGauge(metrics.TaskListPartitionDownscaleThresholdGauge, downscaleThreshold) result := numWritePartitions - if qps > upscaleThreshold { - if !a.overLoad { - a.overLoad = true - a.overLoadStartTime = a.timeSource.Now() - } else if a.timeSource.Now().Sub(a.overLoadStartTime) > a.config.PartitionUpscaleSustainedDuration() { - result = getNumberOfPartitions(numWritePartitions, qps, upscaleThreshold) - a.logger.Info("adjust write partitions", tag.CurrentQPS(qps), tag.PartitionUpscaleThreshold(upscaleThreshold), tag.PartitionDownscaleThreshold(downscaleThreshold), tag.PartitionDownscaleFactor(downscaleFactor), tag.CurrentNumWritePartitions(numWritePartitions), tag.NumWritePartitions(result)) - a.overLoad = false - } - } else { - a.overLoad = false - } - if qps < downscaleThreshold { - if !a.underLoad { - a.underLoad = true - a.underLoadStartTime = a.timeSource.Now() - } else if a.timeSource.Now().Sub(a.underLoadStartTime) > a.config.PartitionDownscaleSustainedDuration() { - result = getNumberOfPartitions(numWritePartitions, qps, upscaleThreshold) - a.logger.Info("adjust write partitions", tag.CurrentQPS(qps), tag.PartitionUpscaleThreshold(upscaleThreshold), tag.PartitionDownscaleThreshold(downscaleThreshold), tag.PartitionDownscaleFactor(downscaleFactor), tag.CurrentNumWritePartitions(numWritePartitions), tag.NumWritePartitions(result)) - a.underLoad = false - } - } else { - a.underLoad = false + if a.overLoad.Check(qps > upscaleThreshold) { + result = getNumberOfPartitions(qps, upscaleRps) + a.logger.Info("adjust write partitions", tag.CurrentQPS(qps), tag.PartitionUpscaleThreshold(upscaleThreshold), tag.PartitionDownscaleThreshold(downscaleThreshold), tag.PartitionDownscaleFactor(downscaleFactor), tag.CurrentNumWritePartitions(numWritePartitions), tag.NumWritePartitions(result)) + } + if a.underLoad.Check(qps < downscaleThreshold) { + result = getNumberOfPartitions(qps, upscaleRps) + a.logger.Info("adjust write partitions", tag.CurrentQPS(qps), tag.PartitionUpscaleThreshold(upscaleThreshold), tag.PartitionDownscaleThreshold(downscaleThreshold), tag.PartitionDownscaleFactor(downscaleFactor), tag.CurrentNumWritePartitions(numWritePartitions), tag.NumWritePartitions(result)) } return result } -func (a *adaptiveScalerImpl) adjustReadPartitions(numReadPartitions, numWritePartitions int32) int32 { - if numReadPartitions < numWritePartitions { - a.logger.Info("adjust read partitions", tag.NumReadPartitions(numWritePartitions), tag.NumWritePartitions(numWritePartitions)) - return numWritePartitions +func (a *adaptiveScalerImpl) adjustWritePartitions(writePartitions map[int]*types.TaskListPartition, targetWritePartitions int) (map[int]*types.TaskListPartition, bool) { + if len(writePartitions) == targetWritePartitions { + return writePartitions, false } + result := make(map[int]*types.TaskListPartition, targetWritePartitions) + + for i := 0; i < targetWritePartitions; i++ { + if p, ok := writePartitions[i]; ok { + result[i] = p + } else { + result[i] = &types.TaskListPartition{} + } + } + return result, true +} + +func (a *adaptiveScalerImpl) adjustReadPartitions(m *aggregatePartitionMetrics, oldReadPartitions map[int]*types.TaskListPartition, newWritePartitions map[int]*types.TaskListPartition) (map[int]*types.TaskListPartition, bool) { + result := make(map[int]*types.TaskListPartition, len(newWritePartitions)) changed := false - // check the backlog of the drained partitions - for i := numReadPartitions - 1; i >= numWritePartitions; i-- { - resp, err := a.matchingClient.DescribeTaskList(a.ctx, &types.MatchingDescribeTaskListRequest{ - DomainUUID: a.taskListID.GetDomainID(), - DescRequest: &types.DescribeTaskListRequest{ - TaskListType: a.taskListType, - TaskList: &types.TaskList{ - Name: a.taskListID.GetPartition(int(i)), - Kind: types.TaskListKindNormal.Ptr(), - }, - IncludeTaskListStatus: true, - }, - }) - if err != nil { - a.logger.Error("failed to get task list backlog", tag.Error(err)) - break + for id, p := range oldReadPartitions { + result[id] = p + } + for id, p := range newWritePartitions { + if _, ok := result[id]; !ok { + changed = true } - nw := int32(1) - if resp.PartitionConfig != nil { - nw = resp.PartitionConfig.NumWritePartitions + result[id] = p + } + + for i := len(result) - 1; i >= len(newWritePartitions); i-- { + p, ok := m.byPartition[i] + if !ok { + resp, err := a.describePartition(i) + if err != nil { + a.logger.Warn("failed to get partition metrics", tag.WorkflowTaskListName(a.taskListID.GetPartition(i)), tag.Error(err)) + break + } + p = toPartitionMetrics(i, resp) } - // in order to drain a partition, 2 conditions need to be met: - // 1. the backlog size is 0 - // 2. no task is being added to the partition, which is guaranteed to be true if the partition knows that the number of write partition is less or equal to its partition ID - if resp.TaskListStatus.GetBacklogCountHint() == 0 && nw <= i { - // if the partition is drained, we can downscale the number of read partitions - numReadPartitions = i + if p.readOnly && p.backlog == 0 { changed = true + delete(result, i) } else { break } } if changed { - a.logger.Info("adjust read partitions", tag.NumReadPartitions(numReadPartitions), tag.NumWritePartitions(numWritePartitions)) + a.logger.Info("adjust read partitions", tag.NumReadPartitions(len(result)), tag.NumWritePartitions(len(newWritePartitions))) + } + return result, changed +} + +func (a *adaptiveScalerImpl) collectPartitionMetrics(config *types.TaskListPartitionConfig) (*aggregatePartitionMetrics, error) { + if a.config.EnableTasklistIsolation() { + return a.fetchMetricsFromPartitions(config) + } + return a.assumeEvenQPS(config) +} + +func (a *adaptiveScalerImpl) assumeEvenQPS(config *types.TaskListPartitionConfig) (*aggregatePartitionMetrics, error) { + resp := a.tlMgr.DescribeTaskList(true) + + totalQPS := resp.TaskListStatus.NewTasksPerSecond * float64(len(config.WritePartitions)) + + return &aggregatePartitionMetrics{ + totalQPS: totalQPS, + }, nil +} + +func (a *adaptiveScalerImpl) fetchMetricsFromPartitions(config *types.TaskListPartitionConfig) (*aggregatePartitionMetrics, error) { + var mutex sync.Mutex + results := make(map[int]*types.DescribeTaskListResponse, len(config.ReadPartitions)) + g := &errgroup.Group{} + for p := range config.ReadPartitions { + partitionID := p + g.Go(func() (e error) { + defer func() { log.CapturePanic(recover(), a.logger, &e) }() + + result, e := a.describePartition(partitionID) + if e != nil { + a.logger.Warn("failed to get partition metrics", tag.WorkflowTaskListName(a.taskListID.GetPartition(partitionID)), tag.Error(e)) + } + if result != nil { + mutex.Lock() + defer mutex.Unlock() + results[partitionID] = result + } + return e + }) + } + err := g.Wait() + if err != nil { + return nil, err + } + + return toAggregateMetrics(results), err +} + +func (a *adaptiveScalerImpl) describePartition(partitionID int) (*types.DescribeTaskListResponse, error) { + if partitionID == 0 { + return a.tlMgr.DescribeTaskList(true), nil + } + return a.matchingClient.DescribeTaskList(a.ctx, &types.MatchingDescribeTaskListRequest{ + DomainUUID: a.taskListID.GetDomainID(), + DescRequest: &types.DescribeTaskListRequest{ + TaskListType: a.taskListType, + TaskList: &types.TaskList{ + Name: a.taskListID.GetPartition(partitionID), + Kind: types.TaskListKindNormal.Ptr(), + }, + IncludeTaskListStatus: true, + }, + }) +} + +func toAggregateMetrics(partitions map[int]*types.DescribeTaskListResponse) *aggregatePartitionMetrics { + total := 0.0 + byIsolationGroup := make(map[string]float64) + byPartition := make(map[int]*partitionMetrics, len(partitions)) + for id, p := range partitions { + for ig, groupMetrics := range p.TaskListStatus.IsolationGroupMetrics { + byIsolationGroup[ig] += groupMetrics.NewTasksPerSecond + } + total += p.TaskListStatus.NewTasksPerSecond + + byPartition[id] = toPartitionMetrics(id, p) + } + return &aggregatePartitionMetrics{ + totalQPS: total, + qpsByIsolationGroup: byIsolationGroup, + byPartition: byPartition, + } +} + +func toPartitionMetrics(id int, p *types.DescribeTaskListResponse) *partitionMetrics { + hasWritePartition := true + if p.PartitionConfig != nil { + _, hasWritePartition = p.PartitionConfig.WritePartitions[id] + } + return &partitionMetrics{ + qps: p.TaskListStatus.NewTasksPerSecond, + backlog: p.TaskListStatus.BacklogCountHint, + readOnly: !hasWritePartition, } - return numReadPartitions } func getTaskListType(taskListType int) *types.TaskListType { @@ -273,8 +382,8 @@ func getTaskListType(taskListType int) *types.TaskListType { return nil } -func getNumberOfPartitions(numPartitions int32, qps float64, threshold float64) int32 { - p := int32(math.Ceil(qps * float64(numPartitions) / threshold)) +func getNumberOfPartitions(qps float64, upscaleQPS float64) int { + p := int(math.Ceil(qps / upscaleQPS)) if p <= 0 { p = 1 } diff --git a/service/matching/tasklist/adaptive_scaler_test.go b/service/matching/tasklist/adaptive_scaler_test.go index 020cf22dd13..13ba24a1a41 100644 --- a/service/matching/tasklist/adaptive_scaler_test.go +++ b/service/matching/tasklist/adaptive_scaler_test.go @@ -23,6 +23,7 @@ package tasklist import ( + "context" "testing" "time" @@ -44,6 +45,7 @@ import ( ) type mockAdaptiveScalerDeps struct { + id *Identifier mockManager *MockManager mockQPSTracker *stats.MockQPSTracker mockTimeSource clock.MockedTimeSource @@ -64,17 +66,19 @@ func setupMocksForAdaptiveScaler(t *testing.T, taskListID *Identifier) (*adaptiv mockTimeSource := clock.NewMockedTimeSourceAt(time.Now()) mockMatchingClient := matching.NewMockClient(ctrl) dynamicClient := dynamicconfig.NewInMemoryClient() + cfg := newTaskListConfig(taskListID, config.NewConfig(dynamicconfig.NewCollection(dynamicClient, logger), "test-host", func() []string { return nil }), "test-domain") deps := &mockAdaptiveScalerDeps{ + id: taskListID, mockManager: mockManager, mockQPSTracker: mockQPSTracker, mockTimeSource: mockTimeSource, mockMatchingClient: mockMatchingClient, dynamicClient: dynamicClient, + config: cfg, } - cfg := newTaskListConfig(taskListID, config.NewConfig(dynamicconfig.NewCollection(dynamicClient, logger), "test-host", func() []string { return nil }), "test-domain") - scaler := NewAdaptiveScaler(taskListID, mockManager, mockQPSTracker, cfg, mockTimeSource, logger, scope, mockMatchingClient, event.E{}).(*adaptiveScalerImpl) + scaler := NewAdaptiveScaler(taskListID, mockManager, cfg, mockTimeSource, logger, scope, mockMatchingClient, event.E{}).(*adaptiveScalerImpl) return scaler, deps } @@ -100,7 +104,7 @@ func TestAdaptiveScalerRun(t *testing.T) { { name: "no op", mockSetup: func(deps *mockAdaptiveScalerDeps) { - deps.mockQPSTracker.EXPECT().QPS().Return(0.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 0)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) }, cycles: 1, @@ -108,7 +112,7 @@ func TestAdaptiveScalerRun(t *testing.T) { { name: "overload start", mockSetup: func(deps *mockAdaptiveScalerDeps) { - deps.mockQPSTracker.EXPECT().QPS().Return(300.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 300)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) }, cycles: 1, @@ -117,15 +121,15 @@ func TestAdaptiveScalerRun(t *testing.T) { name: "overload sustained", mockSetup: func(deps *mockAdaptiveScalerDeps) { // overload start - deps.mockQPSTracker.EXPECT().QPS().Return(300.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 300)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) // overload passing sustained period - deps.mockQPSTracker.EXPECT().QPS().Return(300.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 300)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 2, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }).Return(nil) }, cycles: 2, @@ -134,16 +138,17 @@ func TestAdaptiveScalerRun(t *testing.T) { name: "overload fluctuate", mockSetup: func(deps *mockAdaptiveScalerDeps) { // overload start - deps.mockQPSTracker.EXPECT().QPS().Return(300.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 300)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) // load back to normal - deps.mockQPSTracker.EXPECT().QPS().Return(100.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 100)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) // overload start - deps.mockQPSTracker.EXPECT().QPS().Return(300.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 300)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) // load back to normal - deps.mockQPSTracker.EXPECT().QPS().Return(100.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 100)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) }, cycles: 4, @@ -151,10 +156,10 @@ func TestAdaptiveScalerRun(t *testing.T) { { name: "underload start", mockSetup: func(deps *mockAdaptiveScalerDeps) { - deps.mockQPSTracker.EXPECT().QPS().Return(0.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(10, 0)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ - NumWritePartitions: 10, - NumReadPartitions: 10, + WritePartitions: partitions(10), + ReadPartitions: partitions(10), }) }, cycles: 1, @@ -162,83 +167,205 @@ func TestAdaptiveScalerRun(t *testing.T) { { name: "underload sustained", mockSetup: func(deps *mockAdaptiveScalerDeps) { - deps.mockQPSTracker.EXPECT().QPS().Return(0.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(10, 0)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ - NumWritePartitions: 10, - NumReadPartitions: 10, + WritePartitions: partitions(10), + ReadPartitions: partitions(10), }) - deps.mockQPSTracker.EXPECT().QPS().Return(0.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(10, 0)) + // Partition 9 will be checked if it is drained, but it won't have received the update yet + mockDescribeTaskList(deps, 9, withPartitionsAndQPS(10, 0)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ - NumWritePartitions: 10, - NumReadPartitions: 10, + WritePartitions: partitions(10), + ReadPartitions: partitions(10), }) - deps.mockMatchingClient.EXPECT().DescribeTaskList(gomock.Any(), &types.MatchingDescribeTaskListRequest{ - DomainUUID: "test-domain-id", - DescRequest: &types.DescribeTaskListRequest{ - TaskList: &types.TaskList{ - Name: "/__cadence_sys/test-task-list/9", - Kind: types.TaskListKindNormal.Ptr(), - }, - TaskListType: types.TaskListTypeDecision.Ptr(), - IncludeTaskListStatus: true, - }, - }).Return(&types.DescribeTaskListResponse{ - TaskListStatus: &types.TaskListStatus{ - BacklogCountHint: 0, - }, - }, nil) - deps.mockMatchingClient.EXPECT().DescribeTaskList(gomock.Any(), &types.MatchingDescribeTaskListRequest{ - DomainUUID: "test-domain-id", - DescRequest: &types.DescribeTaskListRequest{ - TaskList: &types.TaskList{ - Name: "/__cadence_sys/test-task-list/8", - Kind: types.TaskListKindNormal.Ptr(), - }, - TaskListType: types.TaskListTypeDecision.Ptr(), - IncludeTaskListStatus: true, - }, - }).Return(&types.DescribeTaskListResponse{ - TaskListStatus: &types.TaskListStatus{ - BacklogCountHint: 1, - }, - }, nil) deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - NumWritePartitions: 1, - NumReadPartitions: 9, + WritePartitions: partitions(1), + ReadPartitions: partitions(10), }).Return(nil) }, cycles: 2, }, + { + name: "underload sustained then drain", + mockSetup: func(deps *mockAdaptiveScalerDeps) { + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(10, 0)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(10), + ReadPartitions: partitions(10), + }) + + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(10, 0)) + // Partition 9 will be checked if it is drained, but it won't have received the update yet + mockDescribeTaskList(deps, 9, withPartitionsAndQPS(10, 0)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(10), + ReadPartitions: partitions(10), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + WritePartitions: partitions(1), + ReadPartitions: partitions(10), + }).Return(nil) + + mockDescribeTaskList(deps, 0, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 9, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 8, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 7, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 6, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 5, withPartitionsAndBacklog(10, 1, 0)) + mockDescribeTaskList(deps, 4, withPartitionsAndBacklog(10, 1, 1)) + + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(1), + ReadPartitions: partitions(10), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + WritePartitions: partitions(1), + ReadPartitions: partitions(5), + }).Return(nil) + }, + cycles: 3, + }, { name: "overload but no fluctuation", mockSetup: func(deps *mockAdaptiveScalerDeps) { // overload start - deps.mockQPSTracker.EXPECT().QPS().Return(210.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 210)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) // overload passing sustained period - deps.mockQPSTracker.EXPECT().QPS().Return(210.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(1, 210)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(nil) deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 2, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }).Return(nil) // not overload with 1 partition, but avoid fluctuation, so don't scale down - deps.mockQPSTracker.EXPECT().QPS().Return(190.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(2, 190)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 2, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }) - deps.mockQPSTracker.EXPECT().QPS().Return(190.0) + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(2, 190)) deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 2, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }) }, cycles: 4, }, + { + name: "isolation - aggregate metrics to scale up", + mockSetup: func(deps *mockAdaptiveScalerDeps) { + deps.config.EnableTasklistIsolation = func() bool { + return true + } + // overload start + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(2, 1)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(2, 400)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(2), + ReadPartitions: partitions(2), + }) + + // overload passing sustained period + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(2, 1)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(2, 400)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(2), + ReadPartitions: partitions(2), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + ReadPartitions: partitions(3), + WritePartitions: partitions(3), + }).Return(nil) + }, + cycles: 2, + }, + { + name: "isolation - aggregate metrics to scale down", + mockSetup: func(deps *mockAdaptiveScalerDeps) { + deps.config.EnableTasklistIsolation = func() bool { + return true + } + // underload start + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(3, 200)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(3, 49)) + mockDescribeTaskList(deps, 2, withPartitionsAndQPS(3, 50)) + + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(3), + ReadPartitions: partitions(3), + }) + + // underload passing sustained period + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(3, 200)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(3, 49)) + mockDescribeTaskList(deps, 2, withPartitionsAndQPS(3, 50)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(3), + ReadPartitions: partitions(3), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + ReadPartitions: partitions(3), + WritePartitions: partitions(2), + }).Return(nil) + + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(2, 200)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(2, 99)) + mockDescribeTaskList(deps, 2, withPartitionsAndBacklog(3, 2, 0)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(2), + ReadPartitions: partitions(3), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + ReadPartitions: partitions(2), + WritePartitions: partitions(2), + }).Return(nil) + }, + cycles: 3, + }, + { + name: "isolation - error calling DescribeTaskList results in no-op", + mockSetup: func(deps *mockAdaptiveScalerDeps) { + deps.config.EnableTasklistIsolation = func() bool { + return true + } + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(3, 0)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(3, 0)) + mockDescribeTaskListWithErr(deps, 2, context.DeadlineExceeded) + + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(3), + ReadPartitions: partitions(3), + }) + + // underload would normally pass sustain period, but the error resets it + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(3, 0)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(3, 0)) + mockDescribeTaskList(deps, 2, withPartitionsAndQPS(3, 0)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(3), + ReadPartitions: partitions(3), + }) + + // Now we can scale down + mockDescribeTaskList(deps, 0, withPartitionsAndQPS(3, 0)) + mockDescribeTaskList(deps, 1, withPartitionsAndQPS(3, 0)) + mockDescribeTaskList(deps, 2, withPartitionsAndQPS(3, 0)) + deps.mockManager.EXPECT().TaskListPartitionConfig().Return(&types.TaskListPartitionConfig{ + WritePartitions: partitions(3), + ReadPartitions: partitions(3), + }) + deps.mockManager.EXPECT().UpdateTaskListPartitionConfig(gomock.Any(), &types.TaskListPartitionConfig{ + ReadPartitions: partitions(3), + WritePartitions: partitions(1), + }).Return(nil) + }, + cycles: 3, + }, } for _, tc := range testCases { @@ -261,3 +388,57 @@ func TestAdaptiveScalerRun(t *testing.T) { }) } } + +func withPartitionsAndQPS(numPartitions int, qps float64) *types.DescribeTaskListResponse { + return &types.DescribeTaskListResponse{ + Pollers: nil, + TaskListStatus: &types.TaskListStatus{NewTasksPerSecond: qps}, + PartitionConfig: &types.TaskListPartitionConfig{ + ReadPartitions: partitions(numPartitions), + WritePartitions: partitions(numPartitions), + }, + } +} + +func withPartitionsAndBacklog(numRead, numWrite int, backlog int64) *types.DescribeTaskListResponse { + return &types.DescribeTaskListResponse{ + Pollers: nil, + TaskListStatus: &types.TaskListStatus{NewTasksPerSecond: 0, BacklogCountHint: backlog}, + PartitionConfig: &types.TaskListPartitionConfig{ + ReadPartitions: partitions(numRead), + WritePartitions: partitions(numWrite), + }, + } +} + +func mockDescribeTaskList(mocks *mockAdaptiveScalerDeps, partitionID int, resp *types.DescribeTaskListResponse) { + if partitionID == 0 { + mocks.mockManager.EXPECT().DescribeTaskList(true).Return(resp) + } else { + mocks.mockMatchingClient.EXPECT().DescribeTaskList(gomock.Any(), &types.MatchingDescribeTaskListRequest{ + DomainUUID: mocks.id.domainID, + DescRequest: &types.DescribeTaskListRequest{ + TaskList: &types.TaskList{ + Name: mocks.id.GetPartition(partitionID), + Kind: types.TaskListKindNormal.Ptr(), + }, + TaskListType: types.TaskListTypeDecision.Ptr(), + IncludeTaskListStatus: true, + }, + }).Return(resp, nil) + } +} + +func mockDescribeTaskListWithErr(mocks *mockAdaptiveScalerDeps, partitionID int, err error) { + mocks.mockMatchingClient.EXPECT().DescribeTaskList(gomock.Any(), &types.MatchingDescribeTaskListRequest{ + DomainUUID: mocks.id.domainID, + DescRequest: &types.DescribeTaskListRequest{ + TaskList: &types.TaskList{ + Name: mocks.id.GetPartition(partitionID), + Kind: types.TaskListKindNormal.Ptr(), + }, + TaskListType: types.TaskListTypeDecision.Ptr(), + IncludeTaskListStatus: true, + }, + }).Return(nil, err) +} diff --git a/service/matching/tasklist/task_completer.go b/service/matching/tasklist/task_completer.go index 2c2003a56ad..2887e0c3dfa 100644 --- a/service/matching/tasklist/task_completer.go +++ b/service/matching/tasklist/task_completer.go @@ -156,7 +156,7 @@ func (tc *taskCompleterImpl) CompleteTaskIfStarted(ctx context.Context, task *In if err != nil && !errors.Is(err, errDomainIsActive) && !errors.Is(err, errTaskNotStarted) { tc.scope.IncCounter(metrics.StandbyClusterTasksCompletionFailurePerTaskList) - tc.logger.Error("Error completing task on domain's standby cluster", tag.Error(err)) + tc.logger.Error("Error completing task on domain's standby cluster", tag.Error(err), tag.WorkflowID(task.Event.WorkflowID), tag.WorkflowRunID(task.Event.RunID), tag.MatchingTaskID(task.Event.TaskID)) } return err diff --git a/service/matching/tasklist/task_list_manager.go b/service/matching/tasklist/task_list_manager.go index 85e1de1c69e..e848bbb392a 100644 --- a/service/matching/tasklist/task_list_manager.go +++ b/service/matching/tasklist/task_list_manager.go @@ -225,7 +225,7 @@ func NewManager( if taskList.IsRoot() && *taskListKind == types.TaskListKindNormal { adaptiveScalerScope := common.NewPerTaskListScope(domainName, taskList.GetName(), *taskListKind, metricsClient, metrics.MatchingAdaptiveScalerScope). Tagged(getTaskListTypeTag(taskList.GetType())) - tlMgr.adaptiveScaler = NewAdaptiveScaler(taskList, tlMgr, tlMgr.qpsTracker, taskListConfig, timeSource, tlMgr.logger, adaptiveScalerScope, matchingClient, baseEvent) + tlMgr.adaptiveScaler = NewAdaptiveScaler(taskList, tlMgr, taskListConfig, timeSource, tlMgr.logger, adaptiveScalerScope, matchingClient, baseEvent) } var isolationGroups []string if tlMgr.isIsolationMatcherEnabled() { @@ -240,7 +240,7 @@ func NewManager( partitionConfig := tlMgr.TaskListPartitionConfig() r := 1 if partitionConfig != nil { - r = int(partitionConfig.NumReadPartitions) + r = len(partitionConfig.ReadPartitions) } return r } @@ -289,11 +289,12 @@ func (c *taskListManagerImpl) Start() error { c.partitionConfig = c.db.PartitionConfig().ToInternalType() c.logger.Info("get task list partition config from db", tag.Dynamic("root-partition", c.taskListID.GetRoot()), tag.Dynamic("task-list-partition-config", c.partitionConfig)) if c.partitionConfig != nil { + startConfig := c.partitionConfig // push update notification to all non-root partitions on start c.stopWG.Add(1) go func() { defer c.stopWG.Done() - c.notifyPartitionConfig(context.Background(), *c.partitionConfig, int(c.partitionConfig.NumReadPartitions)) + c.notifyPartitionConfig(context.Background(), nil, startConfig) }() } } @@ -354,8 +355,8 @@ func (c *taskListManagerImpl) TaskListPartitionConfig() *types.TaskListPartition config := *c.partitionConfig c.logger.Debug("current partition config", tag.Dynamic("root-partition", c.taskListID.GetRoot()), tag.Dynamic("config", config)) - scope.UpdateGauge(metrics.TaskListPartitionConfigNumReadGauge, float64(config.NumReadPartitions)) - scope.UpdateGauge(metrics.TaskListPartitionConfigNumWriteGauge, float64(config.NumWritePartitions)) + scope.UpdateGauge(metrics.TaskListPartitionConfigNumReadGauge, float64(len(config.ReadPartitions))) + scope.UpdateGauge(metrics.TaskListPartitionConfigNumWriteGauge, float64(len(config.WritePartitions))) scope.UpdateGauge(metrics.TaskListPartitionConfigVersionGauge, float64(config.Version)) return &config } @@ -407,59 +408,71 @@ func (c *taskListManagerImpl) RefreshTaskListPartitionConfig(ctx context.Context // Root tasklist manager will update the partition config in the database and notify all non-root partitions. func (c *taskListManagerImpl) UpdateTaskListPartitionConfig(ctx context.Context, config *types.TaskListPartitionConfig) error { c.startWG.Wait() - numberOfPartitionsToRefresh, currentConfig, err := c.updatePartitionConfig(ctx, config) + oldConfig, newConfig, err := c.updatePartitionConfig(ctx, config) if err != nil { return err } - // push update notification to all non-root partitions - c.notifyPartitionConfig(ctx, currentConfig, numberOfPartitionsToRefresh) + if newConfig != nil { + // push update notification to all non-root partitions + c.notifyPartitionConfig(ctx, oldConfig, newConfig) + } return nil } -func (c *taskListManagerImpl) updatePartitionConfig(ctx context.Context, config *types.TaskListPartitionConfig) (int, types.TaskListPartitionConfig, error) { +func (c *taskListManagerImpl) updatePartitionConfig(ctx context.Context, newConfig *types.TaskListPartitionConfig) (*types.TaskListPartitionConfig, *types.TaskListPartitionConfig, error) { + err := validatePartitionConfig(newConfig) + if err != nil { + return nil, nil, err + } var version int64 - numberOfPartitionsToRefresh := 1 c.partitionConfigLock.Lock() defer c.partitionConfigLock.Unlock() - if c.partitionConfig != nil { - numberOfPartitionsToRefresh = int(c.partitionConfig.NumReadPartitions) - if isTaskListPartitionConfigEqual(*c.partitionConfig, *config) { - return 0, types.TaskListPartitionConfig{}, nil + oldConfig := c.partitionConfig + if oldConfig != nil { + if isTaskListPartitionConfigEqual(*oldConfig, *newConfig) { + return nil, nil, nil } - version = c.partitionConfig.Version + version = oldConfig.Version } else { - if config.NumReadPartitions == 1 && config.NumWritePartitions == 1 { - return 0, types.TaskListPartitionConfig{}, nil + if len(newConfig.ReadPartitions) == 1 && len(newConfig.WritePartitions) == 1 { + return nil, nil, nil } } - err := c.throttleRetry.Do(ctx, func() error { - return c.db.UpdateTaskListPartitionConfig(&persistence.TaskListPartitionConfig{ - Version: version + 1, - NumReadPartitions: int(config.NumReadPartitions), - NumWritePartitions: int(config.NumWritePartitions), - }) + err = c.throttleRetry.Do(ctx, func() error { + return c.db.UpdateTaskListPartitionConfig(toPersistenceConfig(version+1, newConfig)) }) if err != nil { // We're not sure whether the update was persisted or not, // Stop the tasklist manager and let it be reloaded c.scope.IncCounter(metrics.TaskListPartitionUpdateFailedCounter) c.Stop() - return 0, types.TaskListPartitionConfig{}, err + return nil, nil, err } c.partitionConfig = c.db.PartitionConfig().ToInternalType() - currentConfig := *c.partitionConfig - numberOfPartitionsToRefresh = common.MaxInt(numberOfPartitionsToRefresh, int(currentConfig.NumReadPartitions)) - return numberOfPartitionsToRefresh, currentConfig, nil + return oldConfig, c.partitionConfig, nil } -func (c *taskListManagerImpl) notifyPartitionConfig(ctx context.Context, config types.TaskListPartitionConfig, count int) { +func (c *taskListManagerImpl) notifyPartitionConfig(ctx context.Context, oldConfig, newConfig *types.TaskListPartitionConfig) { taskListType := types.TaskListTypeDecision.Ptr() if c.taskListID.GetType() == persistence.TaskListTypeActivity { taskListType = types.TaskListTypeActivity.Ptr() } + toNotify := make(map[int]any) + if oldConfig != nil { + for id := range oldConfig.ReadPartitions { + if id != 0 { + toNotify[id] = true + } + } + } + for id := range newConfig.ReadPartitions { + if id != 0 { + toNotify[id] = true + } + } g := &errgroup.Group{} - for i := 1; i < count; i++ { - taskListName := c.taskListID.GetPartition(i) + for p := range toNotify { + taskListName := c.taskListID.GetPartition(p) g.Go(func() (e error) { defer func() { log.CapturePanic(recover(), c.logger, &e) }() @@ -467,7 +480,7 @@ func (c *taskListManagerImpl) notifyPartitionConfig(ctx context.Context, config DomainUUID: c.taskListID.GetDomainID(), TaskList: &types.TaskList{Name: taskListName, Kind: &c.taskListKind}, TaskListType: taskListType, - PartitionConfig: &config, + PartitionConfig: newConfig, }) if e != nil { c.logger.Error("failed to notify partition", tag.Error(e), tag.Dynamic("task-list-partition-name", taskListName)) @@ -493,12 +506,11 @@ func (c *taskListManagerImpl) AddTask(ctx context.Context, params AddTaskParams) } if c.config.EnableGetNumberOfPartitionsFromCache() { partitionConfig := c.TaskListPartitionConfig() - w := 1 if partitionConfig != nil { - w = int(partitionConfig.NumWritePartitions) - } - if w <= c.taskListID.Partition() { - return false, &types.InternalServiceError{Message: "Current partition is drained."} + _, ok := partitionConfig.WritePartitions[c.taskListID.Partition()] + if !ok { + return false, &types.InternalServiceError{Message: "Current partition is drained."} + } } } if params.ForwardedFrom == "" { @@ -973,6 +985,46 @@ func rangeIDToTaskIDBlock(rangeID, rangeSize int64) taskIDBlock { } } +func toPersistenceConfig(version int64, config *types.TaskListPartitionConfig) *persistence.TaskListPartitionConfig { + read := make(map[int]*persistence.TaskListPartition, len(config.ReadPartitions)) + write := make(map[int]*persistence.TaskListPartition, len(config.WritePartitions)) + for id, p := range config.ReadPartitions { + read[id] = &persistence.TaskListPartition{IsolationGroups: p.IsolationGroups} + } + for id, p := range config.WritePartitions { + write[id] = &persistence.TaskListPartition{IsolationGroups: p.IsolationGroups} + } + return &persistence.TaskListPartitionConfig{ + Version: version, + ReadPartitions: read, + WritePartitions: write, + } +} + +func validatePartitionConfig(config *types.TaskListPartitionConfig) error { + if len(config.ReadPartitions) < 1 { + return &types.BadRequestError{Message: "read partitions < 1"} + } + if len(config.WritePartitions) < 1 { + return &types.BadRequestError{Message: "write partitions < 1"} + } + if len(config.ReadPartitions) < len(config.WritePartitions) { + return &types.BadRequestError{Message: fmt.Sprintf("read partitions (%d) < write partitions (%d)", len(config.ReadPartitions), len(config.WritePartitions))} + } + if _, ok := config.ReadPartitions[0]; !ok { + return &types.BadRequestError{Message: "the root partition must always be in read partitions"} + } + if _, ok := config.WritePartitions[0]; !ok { + return &types.BadRequestError{Message: "the root partition must always be in write partitions"} + } + for id := range config.WritePartitions { + if _, ok := config.ReadPartitions[id]; !ok { + return &types.BadRequestError{Message: fmt.Sprintf("partition %d included in write but not read", id)} + } + } + return nil +} + func newTaskListConfig(id *Identifier, cfg *config.Config, domainName string) *config.TaskListConfig { taskListName := id.GetName() taskType := id.GetType() diff --git a/service/matching/tasklist/task_list_manager_test.go b/service/matching/tasklist/task_list_manager_test.go index f4afdb00aac..340c5febe9f 100644 --- a/service/matching/tasklist/task_list_manager_test.go +++ b/service/matching/tasklist/task_list_manager_test.go @@ -270,16 +270,16 @@ func TestDescribeTaskList(t *testing.T) { name: "no status, with config", allowance: func(_ *gomock.Controller, impl *taskListManagerImpl) { err := impl.RefreshTaskListPartitionConfig(context.Background(), &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(2), }) require.NoError(t, err) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(2), }, }, { @@ -1215,42 +1215,42 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { { name: "success - refresh from request", req: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, setupMocks: func(m *mockDeps) {}, expectedConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, }, { name: "success - ignore older version", req: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, originalConfig: &types.TaskListPartitionConfig{ - Version: 3, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 3, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, setupMocks: func(m *mockDeps) {}, expectedConfig: &types.TaskListPartitionConfig{ - Version: 3, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 3, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }, { name: "success - refresh from database", originalConfig: &types.TaskListPartitionConfig{ - Version: 3, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 3, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, setupMocks: func(deps *mockDeps) { deps.mockTaskManager.EXPECT().GetTaskList(gomock.Any(), &persistence.GetTaskListRequest{ @@ -1261,25 +1261,25 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }).Return(&persistence.GetTaskListResponse{ TaskListInfo: &persistence.TaskListInfo{ AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 4, - NumReadPartitions: 10, - NumWritePartitions: 10, + Version: 4, + ReadPartitions: persistencePartitions(10), + WritePartitions: persistencePartitions(10), }, }, }, nil) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 4, - NumReadPartitions: 10, - NumWritePartitions: 10, + Version: 4, + ReadPartitions: partitions(10), + WritePartitions: partitions(10), }, }, { name: "failed to refresh from database", originalConfig: &types.TaskListPartitionConfig{ - Version: 3, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 3, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, setupMocks: func(deps *mockDeps) { deps.mockTaskManager.EXPECT().GetTaskList(gomock.Any(), &persistence.GetTaskListRequest{ @@ -1290,9 +1290,9 @@ func TestRefreshTaskListPartitionConfig(t *testing.T) { }).Return(nil, errors.New("some error")) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 3, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 3, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, expectError: true, expectedError: "some error", @@ -1333,26 +1333,26 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { { name: "success - no op", req: &types.TaskListPartitionConfig{ - NumReadPartitions: 3, - NumWritePartitions: 3, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, originalConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, setupMocks: func(m *mockDeps) {}, expectedConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, }, { name: "success - no op, nil pointer", req: &types.TaskListPartitionConfig{ - NumReadPartitions: 1, - NumWritePartitions: 1, + ReadPartitions: partitions(1), + WritePartitions: partitions(1), }, originalConfig: nil, setupMocks: func(m *mockDeps) {}, @@ -1361,13 +1361,13 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { { name: "success - update", req: &types.TaskListPartitionConfig{ - NumReadPartitions: 3, - NumWritePartitions: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, originalConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, setupMocks: func(deps *mockDeps) { deps.mockTaskManager.EXPECT().UpdateTaskList(gomock.Any(), &persistence.UpdateTaskListRequest{ @@ -1379,9 +1379,9 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { RangeID: 0, Kind: persistence.TaskListKindNormal, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: persistencePartitions(3), + WritePartitions: persistencePartitions(1), }, }, }).Return(&persistence.UpdateTaskListResponse{}, nil) @@ -1390,9 +1390,9 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { TaskList: &types.TaskList{Name: "/__cadence_sys/tl/1", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }).Return(&types.MatchingRefreshTaskListPartitionConfigResponse{}, nil) deps.mockMatchingClient.EXPECT().RefreshTaskListPartitionConfig(gomock.Any(), &types.MatchingRefreshTaskListPartitionConfigRequest{ @@ -1400,28 +1400,28 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { TaskList: &types.TaskList{Name: "/__cadence_sys/tl/2", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }).Return(&types.MatchingRefreshTaskListPartitionConfigResponse{}, nil) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }, { name: "success - push failures are ignored", req: &types.TaskListPartitionConfig{ - NumReadPartitions: 3, - NumWritePartitions: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, originalConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, setupMocks: func(deps *mockDeps) { deps.mockTaskManager.EXPECT().UpdateTaskList(gomock.Any(), &persistence.UpdateTaskListRequest{ @@ -1433,9 +1433,9 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { RangeID: 0, Kind: persistence.TaskListKindNormal, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: persistencePartitions(3), + WritePartitions: persistencePartitions(1), }, }, }).Return(&persistence.UpdateTaskListResponse{}, nil) @@ -1444,9 +1444,9 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { TaskList: &types.TaskList{Name: "/__cadence_sys/tl/1", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }).Return(nil, errors.New("matching client error")) deps.mockMatchingClient.EXPECT().RefreshTaskListPartitionConfig(gomock.Any(), &types.MatchingRefreshTaskListPartitionConfigRequest{ @@ -1454,28 +1454,28 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { TaskList: &types.TaskList{Name: "/__cadence_sys/tl/2", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }).Return(nil, errors.New("matching client error")) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, }, { name: "failed to update", req: &types.TaskListPartitionConfig{ - NumReadPartitions: 3, - NumWritePartitions: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(1), }, originalConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, setupMocks: func(deps *mockDeps) { deps.mockTaskManager.EXPECT().UpdateTaskList(gomock.Any(), &persistence.UpdateTaskListRequest{ @@ -1487,17 +1487,17 @@ func TestUpdateTaskListPartitionConfig(t *testing.T) { RangeID: 0, Kind: persistence.TaskListKindNormal, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 2, - NumReadPartitions: 3, - NumWritePartitions: 1, + Version: 2, + ReadPartitions: persistencePartitions(3), + WritePartitions: persistencePartitions(1), }, }, }).Return(nil, errors.New("some error")) }, expectedConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, expectError: true, expectedError: "some error", @@ -1535,7 +1535,7 @@ func TestRefreshTaskListPartitionConfigConcurrency(t *testing.T) { for i := 0; i < 100; i++ { v := i g.Go(func() error { - return tlm.RefreshTaskListPartitionConfig(context.Background(), &types.TaskListPartitionConfig{Version: int64(v), NumReadPartitions: int32(v), NumWritePartitions: int32(v)}) + return tlm.RefreshTaskListPartitionConfig(context.Background(), &types.TaskListPartitionConfig{Version: int64(v), ReadPartitions: partitions(v), WritePartitions: partitions(v)}) }) } require.NoError(t, g.Wait()) @@ -1554,7 +1554,7 @@ func TestUpdateTaskListPartitionConfigConcurrency(t *testing.T) { for i := 2; i < 102; i++ { v := i g.Go(func() error { - return tlm.UpdateTaskListPartitionConfig(context.Background(), &types.TaskListPartitionConfig{NumReadPartitions: int32(v), NumWritePartitions: int32(v)}) + return tlm.UpdateTaskListPartitionConfig(context.Background(), &types.TaskListPartitionConfig{ReadPartitions: partitions(v), WritePartitions: partitions(v)}) }) } require.NoError(t, g.Wait()) @@ -1578,9 +1578,9 @@ func TestManagerStart_RootPartition(t *testing.T) { AckLevel: 0, RangeID: 0, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: persistencePartitions(2), + WritePartitions: persistencePartitions(2), }, }, }, nil) @@ -1589,13 +1589,13 @@ func TestManagerStart_RootPartition(t *testing.T) { TaskList: &types.TaskList{Name: "/__cadence_sys/tl/1", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 2, - NumWritePartitions: 2, + Version: 1, + ReadPartitions: partitions(2), + WritePartitions: partitions(2), }, }).Return(&types.MatchingRefreshTaskListPartitionConfigResponse{}, nil) assert.NoError(t, tlm.Start()) - assert.Equal(t, &types.TaskListPartitionConfig{Version: 1, NumReadPartitions: 2, NumWritePartitions: 2}, tlm.TaskListPartitionConfig()) + assert.Equal(t, &types.TaskListPartitionConfig{Version: 1, ReadPartitions: partitions(2), WritePartitions: partitions(2)}, tlm.TaskListPartitionConfig()) tlm.stopWG.Wait() } @@ -1616,9 +1616,9 @@ func TestManagerStart_NonRootPartition(t *testing.T) { AckLevel: 0, RangeID: 0, AdaptivePartitionConfig: &persistence.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: persistencePartitions(3), + WritePartitions: persistencePartitions(3), }, }, }, nil) @@ -1638,9 +1638,9 @@ func TestManagerStart_NonRootPartition(t *testing.T) { }, nil) assert.NoError(t, tlm.Start()) assert.Equal(t, &types.TaskListPartitionConfig{ - Version: 1, - NumReadPartitions: 3, - NumWritePartitions: 3, + Version: 1, + ReadPartitions: partitions(3), + WritePartitions: partitions(3), }, tlm.TaskListPartitionConfig()) } @@ -1782,3 +1782,19 @@ func TestGetNumPartitions(t *testing.T) { require.NoError(t, deps.dynamicClient.UpdateValue(dynamicconfig.MatchingEnableGetNumberOfPartitionsFromCache, true)) assert.NotPanics(t, func() { tlm.matcher.UpdateRatelimit(common.Ptr(float64(100))) }) } + +func partitions(num int) map[int]*types.TaskListPartition { + result := make(map[int]*types.TaskListPartition, num) + for i := 0; i < num; i++ { + result[i] = &types.TaskListPartition{} + } + return result +} + +func persistencePartitions(num int) map[int]*persistence.TaskListPartition { + result := make(map[int]*persistence.TaskListPartition, num) + for i := 0; i < num; i++ { + result[i] = &persistence.TaskListPartition{} + } + return result +} diff --git a/simulation/matching/matching_simulation_test.go b/simulation/matching/matching_simulation_test.go index 5a2fa850a34..189bef74d55 100644 --- a/simulation/matching/matching_simulation_test.go +++ b/simulation/matching/matching_simulation_test.go @@ -213,8 +213,8 @@ func (s *MatchingSimulationSuite) TestMatchingSimulation() { TaskList: &types.TaskList{Name: tasklist, Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - NumReadPartitions: int32(getPartitions(s.TestClusterConfig.MatchingConfig.SimulationConfig.TaskListReadPartitions)), - NumWritePartitions: int32(getPartitions(s.TestClusterConfig.MatchingConfig.SimulationConfig.TaskListWritePartitions)), + ReadPartitions: getPartitions(s.TestClusterConfig.MatchingConfig.SimulationConfig.TaskListReadPartitions), + WritePartitions: getPartitions(s.TestClusterConfig.MatchingConfig.SimulationConfig.TaskListWritePartitions), }, }) s.NoError(err) @@ -600,11 +600,17 @@ func getTaskIsolationGroups(c host.SimulationTaskConfiguration) []string { return c.IsolationGroups } -func getPartitions(i int) int { +func getPartitions(i int) map[int]*types.TaskListPartition { if i == 0 { - return 1 + return map[int]*types.TaskListPartition{ + 0: {}, + } } - return i + result := make(map[int]*types.TaskListPartition) + for j := 0; j < i; j++ { + result[j] = &types.TaskListPartition{} + } + return result } func getForwarderMaxOutstandingPolls(i int) int { diff --git a/tools/cli/admin_task_list_commands.go b/tools/cli/admin_task_list_commands.go index eedcaac61f9..f5ed272006e 100644 --- a/tools/cli/admin_task_list_commands.go +++ b/tools/cli/admin_task_list_commands.go @@ -47,9 +47,9 @@ type ( EndID int64 `header:"Lease End TaskID"` } TaskListPartitionConfigRow struct { - Version int64 `header:"Version"` - NumReadPartitions int32 `header:"Number of Read Partitions"` - NumWritePartitions int32 `header:"Number of Write Partitions"` + Version int64 `header:"Version"` + ReadPartitions map[int]*types.TaskListPartition `header:"Read Partitions"` + WritePartitions map[int]*types.TaskListPartition `header:"Write Partitions"` } ) @@ -159,9 +159,9 @@ func printTaskListStatus(w io.Writer, taskListStatus *types.TaskListStatus) erro func printTaskListPartitionConfig(w io.Writer, config *types.TaskListPartitionConfig) error { table := TaskListPartitionConfigRow{ - Version: config.Version, - NumReadPartitions: config.NumReadPartitions, - NumWritePartitions: config.NumWritePartitions, + Version: config.Version, + ReadPartitions: config.ReadPartitions, + WritePartitions: config.WritePartitions, } return RenderTable(w, table, RenderOptions{Color: true}) } @@ -205,8 +205,8 @@ func AdminUpdateTaskListPartitionConfig(c *cli.Context) error { TaskList: &types.TaskList{Name: taskList, Kind: types.TaskListKindNormal.Ptr()}, TaskListType: taskListType, PartitionConfig: &types.TaskListPartitionConfig{ - NumReadPartitions: int32(numReadPartitions), - NumWritePartitions: int32(numWritePartitions), + ReadPartitions: createPartitions(numReadPartitions), + WritePartitions: createPartitions(numWritePartitions), }, }) if err != nil { @@ -214,3 +214,11 @@ func AdminUpdateTaskListPartitionConfig(c *cli.Context) error { } return nil } + +func createPartitions(num int) map[int]*types.TaskListPartition { + result := make(map[int]*types.TaskListPartition, num) + for i := 0; i < num; i++ { + result[i] = &types.TaskListPartition{} + } + return result +} diff --git a/tools/cli/admin_task_list_commands_test.go b/tools/cli/admin_task_list_commands_test.go index cf7c926b142..e2716810aa8 100644 --- a/tools/cli/admin_task_list_commands_test.go +++ b/tools/cli/admin_task_list_commands_test.go @@ -283,8 +283,8 @@ func TestAdminUpdateTaskListPartitionConfig(t *testing.T) { TaskList: &types.TaskList{Name: "test-tasklist", Kind: types.TaskListKindNormal.Ptr()}, TaskListType: types.TaskListTypeDecision.Ptr(), PartitionConfig: &types.TaskListPartitionConfig{ - NumReadPartitions: 2, - NumWritePartitions: 2, + ReadPartitions: createPartitions(2), + WritePartitions: createPartitions(2), }, }). Return(&types.UpdateTaskListPartitionConfigResponse{}, nil). diff --git a/tools/cli/domain.go b/tools/cli/domain.go index f0ef9ce3cbc..cd77cb09910 100644 --- a/tools/cli/domain.go +++ b/tools/cli/domain.go @@ -22,6 +22,7 @@ package cli import ( "fmt" + "strings" "github.com/urfave/cli/v2" @@ -47,6 +48,13 @@ func checkRequiredDomainDataKVs(domainData map[string]string) error { return nil } +func checkNoAdditionalArgsPassed(c *cli.Context) error { + if c.NArg() > 0 { + return fmt.Errorf("Domain commands cannot have arguments: <%v>\nClusters are now specified as --clusters c1,c2 see help for more info", strings.Join(c.Args().Slice(), " ")) + } + return nil +} + func newDomainCommands() []*cli.Command { return []*cli.Command{ { @@ -55,6 +63,10 @@ func newDomainCommands() []*cli.Command { Usage: "Register workflow domain", Flags: registerDomainFlags, Action: func(c *cli.Context) error { + err := checkNoAdditionalArgsPassed(c) + if err != nil { + return err + } return withDomainClient(c, false, func(dc *domainCLIImpl) error { return dc.RegisterDomain(c) }) @@ -66,6 +78,10 @@ func newDomainCommands() []*cli.Command { Usage: "Update existing workflow domain", Flags: updateDomainFlags, Action: func(c *cli.Context) error { + err := checkNoAdditionalArgsPassed(c) + if err != nil { + return err + } return withDomainClient(c, false, func(dc *domainCLIImpl) error { return dc.UpdateDomain(c) }) @@ -77,6 +93,10 @@ func newDomainCommands() []*cli.Command { Usage: "Deprecate existing workflow domain", Flags: deprecateDomainFlags, Action: func(c *cli.Context) error { + err := checkNoAdditionalArgsPassed(c) + if err != nil { + return err + } return withDomainClient(c, false, func(dc *domainCLIImpl) error { return dc.DeprecateDomain(c) }) @@ -88,6 +108,10 @@ func newDomainCommands() []*cli.Command { Usage: "Describe existing workflow domain", Flags: describeDomainFlags, Action: func(c *cli.Context) error { + err := checkNoAdditionalArgsPassed(c) + if err != nil { + return err + } return withDomainClient(c, false, func(dc *domainCLIImpl) error { return dc.DescribeDomain(c) }) @@ -99,9 +123,13 @@ func newDomainCommands() []*cli.Command { Usage: "Migrate existing domain to new domain. This command only validates the settings. It does not perform actual data migration", Flags: migrateDomainFlags, Action: func(c *cli.Context) error { + err := checkNoAdditionalArgsPassed(c) + if err != nil { + return err + } // exit on error already handled in the command // TODO best practice is to return error if validation fails - err := NewDomainMigrationCommand(c).Validation(c) + err = NewDomainMigrationCommand(c).Validation(c) if err != nil { return commoncli.Problem("Failed validation: ", err) } diff --git a/tools/cli/domain_commands_test.go b/tools/cli/domain_commands_test.go index 26b72b4b7cf..0207e0f2f0a 100644 --- a/tools/cli/domain_commands_test.go +++ b/tools/cli/domain_commands_test.go @@ -129,6 +129,18 @@ func (s *cliAppSuite) TestDomainRegister() { "option domain is required", nil, }, + { + "fail on extra arguments at end", + "cadence --do test-domain domain register --global_domain true --retention 5 --desc description --active_cluster c1 --clusters c1,c2 unused_arg", + "Domain commands cannot have arguments: \nClusters are now specified as --clusters c1,c2 see help for more info", + nil, + }, + { + "fail on extra arguments at in command", + "cadence --do test-domain domain register --global_domain true --retention 5 --desc description --active_cluster c1 unused_arg --clusters c1,c2", + "Domain commands cannot have arguments: \nClusters are now specified as --clusters c1,c2 see help for more info", + nil, + }, { "invalid global domain flag", "cadence --do test-domain domain register --global_domain invalid",