diff --git a/api/adminservice/v1/request_response.pb.go b/api/adminservice/v1/request_response.pb.go index b20c2b136c0..a6d2a5c2ee3 100644 --- a/api/adminservice/v1/request_response.pb.go +++ b/api/adminservice/v1/request_response.pb.go @@ -3751,6 +3751,154 @@ func (m *GetDLQTasksResponse) GetNextPageToken() []byte { return nil } +type PurgeDLQTasksRequest struct { + DlqKey *v112.HistoryDLQKey `protobuf:"bytes,1,opt,name=dlq_key,json=dlqKey,proto3" json:"dlq_key,omitempty"` + InclusiveMaxTaskMetadata *v112.HistoryDLQTaskMetadata `protobuf:"bytes,2,opt,name=inclusive_max_task_metadata,json=inclusiveMaxTaskMetadata,proto3" json:"inclusive_max_task_metadata,omitempty"` +} + +func (m *PurgeDLQTasksRequest) Reset() { *m = PurgeDLQTasksRequest{} } +func (*PurgeDLQTasksRequest) ProtoMessage() {} +func (*PurgeDLQTasksRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_cc07c1a2abe7cb51, []int{63} +} +func (m *PurgeDLQTasksRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PurgeDLQTasksRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PurgeDLQTasksRequest.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 *PurgeDLQTasksRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PurgeDLQTasksRequest.Merge(m, src) +} +func (m *PurgeDLQTasksRequest) XXX_Size() int { + return m.Size() +} +func (m *PurgeDLQTasksRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PurgeDLQTasksRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PurgeDLQTasksRequest proto.InternalMessageInfo + +func (m *PurgeDLQTasksRequest) GetDlqKey() *v112.HistoryDLQKey { + if m != nil { + return m.DlqKey + } + return nil +} + +func (m *PurgeDLQTasksRequest) GetInclusiveMaxTaskMetadata() *v112.HistoryDLQTaskMetadata { + if m != nil { + return m.InclusiveMaxTaskMetadata + } + return nil +} + +type PurgeDLQTasksResponse struct { + // job_token is a token that can be used to query the status of the purge operation. + // TODO: add DescribeDLQJob an CancelDLQJob APIs for clients to use these tokens. + JobToken []byte `protobuf:"bytes,1,opt,name=job_token,json=jobToken,proto3" json:"job_token,omitempty"` +} + +func (m *PurgeDLQTasksResponse) Reset() { *m = PurgeDLQTasksResponse{} } +func (*PurgeDLQTasksResponse) ProtoMessage() {} +func (*PurgeDLQTasksResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_cc07c1a2abe7cb51, []int{64} +} +func (m *PurgeDLQTasksResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PurgeDLQTasksResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PurgeDLQTasksResponse.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 *PurgeDLQTasksResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PurgeDLQTasksResponse.Merge(m, src) +} +func (m *PurgeDLQTasksResponse) XXX_Size() int { + return m.Size() +} +func (m *PurgeDLQTasksResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PurgeDLQTasksResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PurgeDLQTasksResponse proto.InternalMessageInfo + +func (m *PurgeDLQTasksResponse) GetJobToken() []byte { + if m != nil { + return m.JobToken + } + return nil +} + +// DLQJobToken identifies a DLQ job. This proto is for internal use only and clients should not use it. +type DLQJobToken struct { + WorkflowId string `protobuf:"bytes,1,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + RunId string `protobuf:"bytes,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` +} + +func (m *DLQJobToken) Reset() { *m = DLQJobToken{} } +func (*DLQJobToken) ProtoMessage() {} +func (*DLQJobToken) Descriptor() ([]byte, []int) { + return fileDescriptor_cc07c1a2abe7cb51, []int{65} +} +func (m *DLQJobToken) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DLQJobToken) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DLQJobToken.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 *DLQJobToken) XXX_Merge(src proto.Message) { + xxx_messageInfo_DLQJobToken.Merge(m, src) +} +func (m *DLQJobToken) XXX_Size() int { + return m.Size() +} +func (m *DLQJobToken) XXX_DiscardUnknown() { + xxx_messageInfo_DLQJobToken.DiscardUnknown(m) +} + +var xxx_messageInfo_DLQJobToken proto.InternalMessageInfo + +func (m *DLQJobToken) GetWorkflowId() string { + if m != nil { + return m.WorkflowId + } + return "" +} + +func (m *DLQJobToken) GetRunId() string { + if m != nil { + return m.RunId + } + return "" +} + func init() { proto.RegisterType((*RebuildMutableStateRequest)(nil), "temporal.server.api.adminservice.v1.RebuildMutableStateRequest") proto.RegisterType((*RebuildMutableStateResponse)(nil), "temporal.server.api.adminservice.v1.RebuildMutableStateResponse") @@ -3822,6 +3970,9 @@ func init() { proto.RegisterType((*GetNamespaceResponse)(nil), "temporal.server.api.adminservice.v1.GetNamespaceResponse") proto.RegisterType((*GetDLQTasksRequest)(nil), "temporal.server.api.adminservice.v1.GetDLQTasksRequest") proto.RegisterType((*GetDLQTasksResponse)(nil), "temporal.server.api.adminservice.v1.GetDLQTasksResponse") + proto.RegisterType((*PurgeDLQTasksRequest)(nil), "temporal.server.api.adminservice.v1.PurgeDLQTasksRequest") + proto.RegisterType((*PurgeDLQTasksResponse)(nil), "temporal.server.api.adminservice.v1.PurgeDLQTasksResponse") + proto.RegisterType((*DLQJobToken)(nil), "temporal.server.api.adminservice.v1.DLQJobToken") } func init() { @@ -3829,222 +3980,227 @@ func init() { } var fileDescriptor_cc07c1a2abe7cb51 = []byte{ - // 3430 bytes of a gzipped FileDescriptorProto + // 3506 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x3b, 0x4b, 0x6c, 0x1c, 0xc7, - 0xb1, 0x9c, 0xfd, 0x90, 0xbb, 0xc5, 0xff, 0x88, 0x12, 0x57, 0x4b, 0x73, 0x49, 0xaf, 0x65, 0x99, - 0x92, 0xe5, 0xe5, 0x13, 0xfd, 0xde, 0x93, 0xfc, 0x11, 0x04, 0x91, 0x92, 0x49, 0xda, 0xa4, 0x3f, - 0x43, 0x59, 0x7a, 0xcf, 0x80, 0x31, 0x9e, 0xdd, 0x69, 0x2e, 0x07, 0x9a, 0x9d, 0x59, 0x4d, 0xf7, - 0x52, 0xa2, 0x81, 0x7c, 0x10, 0x27, 0x08, 0x7c, 0x08, 0x22, 0x20, 0x08, 0x60, 0xf8, 0xe4, 0x63, - 0x10, 0x24, 0xc8, 0x2d, 0xc7, 0x00, 0xbe, 0xe5, 0x68, 0x24, 0x17, 0xc3, 0x01, 0xe2, 0x58, 0xbe, - 0xe4, 0xe8, 0x73, 0x4e, 0x41, 0xff, 0xe6, 0xb7, 0xbd, 0xcb, 0x65, 0x44, 0xd9, 0x80, 0x6f, 0x9c, - 0xea, 0xaa, 0xea, 0xea, 0xfa, 0x75, 0x55, 0xf5, 0x12, 0x5e, 0x24, 0xa8, 0xd5, 0xf6, 0x03, 0xcb, - 0x5d, 0xc6, 0x28, 0xd8, 0x47, 0xc1, 0xb2, 0xd5, 0x76, 0x96, 0x2d, 0xbb, 0xe5, 0x78, 0xf4, 0xdb, - 0x69, 0xa0, 0xe5, 0xfd, 0x8b, 0xcb, 0x01, 0xba, 0xdb, 0x41, 0x98, 0x98, 0x01, 0xc2, 0x6d, 0xdf, - 0xc3, 0xa8, 0xd6, 0x0e, 0x7c, 0xe2, 0xeb, 0x4f, 0x49, 0xda, 0x1a, 0xa7, 0xad, 0x59, 0x6d, 0xa7, - 0x16, 0xa7, 0xad, 0xed, 0x5f, 0x2c, 0x2f, 0x34, 0x7d, 0xbf, 0xe9, 0xa2, 0x65, 0x46, 0x52, 0xef, - 0xec, 0x2e, 0x13, 0xa7, 0x85, 0x30, 0xb1, 0x5a, 0x6d, 0xce, 0xa5, 0x5c, 0x49, 0x23, 0xd8, 0x9d, - 0xc0, 0x22, 0x8e, 0xef, 0x89, 0xf5, 0x27, 0x6d, 0xd4, 0x46, 0x9e, 0x8d, 0xbc, 0x86, 0x83, 0xf0, - 0x72, 0xd3, 0x6f, 0xfa, 0x0c, 0xce, 0xfe, 0x12, 0x28, 0xd5, 0xf0, 0x10, 0x54, 0x7a, 0xe4, 0x75, - 0x5a, 0x98, 0x8a, 0xdd, 0xf0, 0x5b, 0xad, 0x90, 0xcd, 0x59, 0x35, 0x0e, 0xb1, 0xf0, 0x1d, 0xf3, - 0x6e, 0x07, 0x75, 0xc4, 0xa1, 0xca, 0x67, 0x12, 0x78, 0x9c, 0x05, 0x45, 0x6c, 0x21, 0x8c, 0xad, - 0xa6, 0xc4, 0x7a, 0x3a, 0x81, 0xb5, 0x8f, 0x02, 0xec, 0xa8, 0xd0, 0x92, 0x9b, 0xde, 0xf3, 0x83, - 0x3b, 0xbb, 0xae, 0x7f, 0xaf, 0x1b, 0xef, 0x99, 0x04, 0x9e, 0x67, 0xb5, 0x10, 0x6e, 0x5b, 0x5c, - 0xf7, 0x49, 0xc4, 0x73, 0x09, 0xc4, 0x00, 0xb5, 0x5d, 0xa7, 0xc1, 0x94, 0xd5, 0x8d, 0x7a, 0x41, - 0x65, 0xd9, 0x86, 0xdb, 0xc1, 0x04, 0x05, 0xfd, 0x18, 0xc7, 0xb0, 0xd5, 0x9a, 0x3c, 0xdf, 0x1f, - 0x95, 0xef, 0xd0, 0x75, 0x30, 0x15, 0x2e, 0x55, 0x7e, 0x3f, 0x69, 0xf7, 0x1c, 0x4c, 0xfc, 0xe0, - 0xa0, 0x5b, 0xda, 0x9a, 0x0a, 0xbb, 0x8f, 0xda, 0xfe, 0x4b, 0x85, 0xdf, 0x57, 0x7b, 0x2f, 0xa8, - 0x28, 0xda, 0xd4, 0xce, 0x98, 0x20, 0x8f, 0xef, 0x21, 0x8e, 0x6a, 0xb6, 0x10, 0xb1, 0x6c, 0x8b, - 0x58, 0x82, 0xf4, 0xf9, 0x01, 0x48, 0xd1, 0x7d, 0xd4, 0xe8, 0xd0, 0x9d, 0xb1, 0x20, 0xba, 0x3a, - 0x00, 0x91, 0xf4, 0x1f, 0xb3, 0xd5, 0x21, 0x56, 0xdd, 0x45, 0x26, 0x26, 0x16, 0xe9, 0xab, 0x92, - 0x14, 0x03, 0xaa, 0x6f, 0xdc, 0xcf, 0x32, 0x91, 0xbb, 0xdb, 0xee, 0x5d, 0x8e, 0x58, 0xfd, 0x40, - 0x83, 0xb2, 0x81, 0xea, 0x1d, 0xc7, 0xb5, 0xb7, 0xf9, 0xbe, 0x3b, 0x74, 0x5b, 0x83, 0xe7, 0x04, - 0xfd, 0x09, 0x28, 0x86, 0x8a, 0x2f, 0x69, 0x8b, 0xda, 0x52, 0xd1, 0x88, 0x00, 0xfa, 0x3a, 0x14, - 0xc3, 0xa3, 0x96, 0x32, 0x8b, 0xda, 0xd2, 0xe8, 0xca, 0xb9, 0x50, 0x52, 0x96, 0x2f, 0x84, 0x6b, - 0xed, 0x5f, 0xac, 0xdd, 0x16, 0xc7, 0xbb, 0x21, 0x09, 0x8c, 0x88, 0xb6, 0x3a, 0x0f, 0x73, 0x4a, - 0x21, 0x78, 0x42, 0xaa, 0x7e, 0x9a, 0x81, 0xca, 0x26, 0xe5, 0x4a, 0xba, 0xb9, 0x7c, 0xab, 0x82, - 0xea, 0x9b, 0x30, 0x29, 0xdc, 0xd6, 0xac, 0x5b, 0xa4, 0xb1, 0x87, 0x70, 0x29, 0xbb, 0x98, 0x5d, - 0x1a, 0x5d, 0x59, 0xec, 0xc5, 0xee, 0xba, 0x45, 0xac, 0x55, 0xd7, 0xaf, 0x1b, 0x13, 0x82, 0x70, - 0x95, 0xd3, 0xe9, 0xb7, 0x61, 0x52, 0x64, 0x16, 0x53, 0xac, 0x94, 0x72, 0x4c, 0xb2, 0x5a, 0x4d, - 0x95, 0x79, 0x05, 0x0e, 0x65, 0x79, 0x8b, 0x93, 0x6d, 0x70, 0x88, 0x31, 0xb1, 0x9f, 0xf8, 0xd6, - 0x67, 0x20, 0x4f, 0xfc, 0x3b, 0xc8, 0x2b, 0xe5, 0x17, 0xb5, 0xa5, 0x31, 0x83, 0x7f, 0x54, 0x2f, - 0xc1, 0x42, 0x4f, 0x15, 0x72, 0x35, 0x47, 0x84, 0x5a, 0x9c, 0xf0, 0xa7, 0x1a, 0xcc, 0x5d, 0x47, - 0xb8, 0x11, 0x38, 0x75, 0xf4, 0x1d, 0xba, 0xc8, 0x1f, 0x33, 0xf0, 0x84, 0x5a, 0x0c, 0x21, 0xfd, - 0x69, 0x28, 0xe0, 0x3d, 0x2b, 0xb0, 0x4d, 0xc7, 0x16, 0x62, 0x8c, 0xb0, 0xef, 0x4d, 0x5b, 0x7f, - 0x12, 0xc6, 0xa4, 0xd5, 0x2c, 0xdb, 0x0e, 0x98, 0x1c, 0x45, 0x63, 0x54, 0xc0, 0xae, 0xd9, 0x76, - 0xa0, 0xef, 0xc1, 0x89, 0x86, 0xd5, 0xd8, 0x43, 0xc9, 0xe8, 0x2b, 0x65, 0x99, 0xc4, 0x97, 0x95, - 0x16, 0x89, 0x85, 0x5f, 0x5c, 0xfa, 0x84, 0x70, 0xd3, 0x8c, 0x69, 0x1c, 0xa4, 0x7b, 0x70, 0x8a, - 0xa6, 0x93, 0xba, 0x85, 0xd3, 0x9b, 0xe5, 0x1e, 0x71, 0xb3, 0x19, 0xc9, 0x37, 0x0e, 0xad, 0xfe, - 0x45, 0x83, 0xb2, 0x54, 0x9c, 0x70, 0x91, 0x0d, 0x1f, 0x13, 0x69, 0x3e, 0xaa, 0x1b, 0x1f, 0x13, - 0xa6, 0x18, 0x84, 0xb1, 0x50, 0xdd, 0x28, 0x85, 0x5d, 0xe3, 0xa0, 0x84, 0x66, 0xa9, 0xea, 0xf2, - 0x91, 0x66, 0x13, 0xc6, 0xcf, 0xa6, 0x8d, 0xff, 0x7f, 0xa0, 0x87, 0x59, 0x2d, 0xf2, 0x82, 0xdc, - 0x51, 0xbd, 0x60, 0xfa, 0x5e, 0x1a, 0x54, 0xfd, 0x7b, 0xcc, 0x29, 0x13, 0x87, 0x12, 0xce, 0xf0, - 0x14, 0x8c, 0x33, 0x11, 0xb1, 0xe9, 0x75, 0x5a, 0x75, 0x14, 0xb0, 0x63, 0xe5, 0x8d, 0x31, 0x0e, - 0x7c, 0x9d, 0xc1, 0xf4, 0x39, 0x28, 0xca, 0x73, 0xe1, 0x52, 0x66, 0x31, 0xbb, 0x94, 0x37, 0x0a, - 0xe2, 0x60, 0x58, 0x7f, 0x17, 0x26, 0xc3, 0x83, 0x98, 0xcc, 0x8a, 0xc2, 0x19, 0xfe, 0x5b, 0x69, - 0x9f, 0x10, 0x97, 0x1e, 0xe1, 0x75, 0xf9, 0xb1, 0x46, 0xe9, 0x36, 0xbd, 0x5d, 0xdf, 0x98, 0xf0, - 0x12, 0x30, 0xbd, 0x04, 0x23, 0x52, 0xe3, 0x79, 0xee, 0xac, 0xe2, 0xf3, 0xd5, 0x5c, 0x21, 0x37, - 0x95, 0xaf, 0xd6, 0x60, 0x7a, 0xcd, 0xf5, 0x31, 0xda, 0xa1, 0xf2, 0x48, 0x5b, 0xa5, 0x5d, 0x3c, - 0x32, 0x44, 0x75, 0x06, 0xf4, 0x38, 0xbe, 0x48, 0x9c, 0x17, 0x60, 0x72, 0x1d, 0x91, 0x41, 0x79, - 0xbc, 0x07, 0x53, 0x11, 0xb6, 0x50, 0xe4, 0x16, 0x80, 0x40, 0xf7, 0x76, 0x7d, 0x46, 0x30, 0xba, - 0xf2, 0xdc, 0x20, 0x1e, 0xca, 0xd8, 0xb0, 0xa3, 0x73, 0x25, 0xd3, 0x3f, 0xab, 0xbf, 0xc8, 0xc0, - 0xec, 0x96, 0x83, 0x89, 0x30, 0xd9, 0x4d, 0x7a, 0x63, 0x1d, 0x2e, 0x98, 0xfe, 0x0a, 0x14, 0x1a, - 0x16, 0x41, 0x4d, 0x9a, 0x23, 0xa9, 0x03, 0x4e, 0xac, 0x9c, 0x57, 0x8a, 0xc0, 0x4a, 0x0f, 0xba, - 0x39, 0x65, 0xbc, 0x26, 0x28, 0x8c, 0x90, 0x56, 0xdf, 0x00, 0x60, 0x15, 0x61, 0x60, 0x79, 0x4d, - 0x69, 0xce, 0x73, 0x87, 0x65, 0x5b, 0xca, 0xcb, 0xa0, 0x04, 0x46, 0x91, 0xc8, 0x3f, 0xf5, 0x79, - 0x00, 0x96, 0xff, 0x4d, 0xec, 0xbc, 0xcf, 0x03, 0x37, 0x6f, 0x14, 0x19, 0x64, 0xc7, 0x79, 0x1f, - 0xe9, 0x67, 0x61, 0xd2, 0x43, 0xf7, 0x89, 0xd9, 0xb6, 0x9a, 0xc8, 0x8c, 0x27, 0xe3, 0x71, 0x0a, - 0x7e, 0xd3, 0x6a, 0xa2, 0x9b, 0x2c, 0xb7, 0x7e, 0xa0, 0x41, 0xa9, 0x5b, 0x1f, 0x42, 0xf5, 0x57, - 0x21, 0xcf, 0xae, 0xf4, 0x92, 0xc6, 0x6e, 0x18, 0xb5, 0xa0, 0xa9, 0x82, 0x9c, 0x4b, 0xcb, 0xe9, - 0x54, 0x52, 0x64, 0x54, 0x52, 0x7c, 0x94, 0x81, 0x1c, 0xa5, 0xa3, 0xb9, 0x20, 0xf2, 0xf9, 0x30, - 0x8d, 0x8e, 0x86, 0xb0, 0x4d, 0x5b, 0x5f, 0x80, 0xd1, 0x30, 0xa4, 0x45, 0x3a, 0x28, 0x1a, 0x20, - 0x41, 0x9b, 0xb6, 0x7e, 0x12, 0x86, 0x83, 0x8e, 0x47, 0xd7, 0x78, 0x3a, 0xc8, 0x07, 0x1d, 0x6f, - 0xd3, 0xd6, 0x67, 0x61, 0x84, 0xa9, 0xde, 0xb1, 0x99, 0xb6, 0xb2, 0xc6, 0x30, 0xfd, 0xdc, 0xb4, - 0xf5, 0x35, 0x60, 0x6a, 0x35, 0xc9, 0x41, 0x1b, 0x31, 0x25, 0x4d, 0xac, 0x9c, 0x3d, 0xdc, 0xb8, - 0x37, 0x0f, 0xda, 0xc8, 0x28, 0x10, 0xf1, 0x97, 0x7e, 0x05, 0x8a, 0xbb, 0x4e, 0x80, 0x4c, 0xda, - 0x7d, 0x94, 0x86, 0x99, 0x5d, 0xcb, 0x35, 0xde, 0x79, 0xd4, 0x64, 0xe7, 0x51, 0xbb, 0x29, 0x5b, - 0x93, 0xd5, 0xdc, 0x83, 0x2f, 0x17, 0x34, 0xa3, 0x40, 0x49, 0x28, 0x90, 0x06, 0xa3, 0xb8, 0x43, - 0x4b, 0x23, 0x4c, 0x38, 0xf9, 0x59, 0xfd, 0x42, 0x83, 0x69, 0x03, 0xb5, 0xfc, 0x7d, 0xc4, 0x14, - 0xfb, 0xed, 0xb9, 0x6a, 0x4c, 0x5f, 0xd9, 0x84, 0xbe, 0x36, 0x61, 0x72, 0xdf, 0xc1, 0x4e, 0xdd, - 0x71, 0x1d, 0x72, 0xc0, 0x0f, 0x9c, 0x1b, 0xf0, 0xc0, 0x13, 0x11, 0x21, 0x5d, 0xa2, 0x39, 0x23, - 0x7e, 0x36, 0x91, 0x33, 0x7e, 0x95, 0x85, 0x67, 0xd6, 0x91, 0xa2, 0x4c, 0xb0, 0xee, 0x09, 0x37, - 0xbd, 0xb5, 0x12, 0xbb, 0x3c, 0x12, 0x0e, 0x53, 0xec, 0x76, 0x98, 0x63, 0x2b, 0xbd, 0xce, 0xc0, - 0x04, 0x26, 0x56, 0x40, 0x4c, 0xb4, 0x8f, 0x3c, 0x12, 0x29, 0x66, 0x8c, 0x41, 0x6f, 0x50, 0xe0, - 0xa6, 0xad, 0xd7, 0xe0, 0x44, 0x1c, 0x4b, 0x9a, 0x95, 0xfb, 0xdc, 0x74, 0x84, 0x2a, 0x6a, 0x28, - 0x7d, 0x11, 0xc6, 0x90, 0x67, 0x47, 0x3c, 0xf3, 0x0c, 0x11, 0x90, 0x67, 0x4b, 0x8e, 0xe7, 0x61, - 0x3a, 0xc2, 0x90, 0xfc, 0x86, 0x19, 0xda, 0xa4, 0x44, 0x93, 0xdc, 0xce, 0xc3, 0x74, 0xcb, 0xba, - 0xef, 0xb4, 0x3a, 0x2d, 0x1e, 0x74, 0x2c, 0x3b, 0x8c, 0x30, 0x0f, 0x99, 0x14, 0x0b, 0x34, 0xec, - 0x7a, 0xe5, 0x88, 0x82, 0x22, 0x3a, 0x5f, 0xcd, 0x15, 0xb4, 0xa9, 0x4c, 0xf5, 0x93, 0x0c, 0x2c, - 0x1d, 0x6e, 0x15, 0x91, 0x39, 0x14, 0xac, 0x35, 0x05, 0x6b, 0x55, 0x35, 0x9b, 0x39, 0xbe, 0x6a, - 0x36, 0x7b, 0x2c, 0xd5, 0xec, 0x12, 0x4c, 0x49, 0x19, 0x3d, 0xdf, 0x46, 0xec, 0xae, 0xce, 0x2d, - 0x66, 0x97, 0xb2, 0xa1, 0x08, 0xaf, 0xfb, 0x36, 0xda, 0xb4, 0x71, 0xf5, 0x81, 0x06, 0xf3, 0xeb, - 0x88, 0x18, 0x51, 0xe3, 0xb7, 0xcd, 0x9b, 0xbe, 0xf0, 0x8a, 0xd9, 0x82, 0x61, 0xa6, 0x0d, 0x99, - 0x52, 0xd5, 0x57, 0x79, 0xac, 0x73, 0xa4, 0xf2, 0xc5, 0xf8, 0x31, 0xad, 0x19, 0x82, 0x07, 0x75, - 0x7e, 0xd9, 0x23, 0x52, 0x87, 0x97, 0x55, 0xa5, 0x80, 0xd1, 0x1a, 0xa0, 0xfa, 0x71, 0x06, 0x2a, - 0xbd, 0x44, 0x12, 0xb6, 0xfa, 0x01, 0x4c, 0xf0, 0x5c, 0x22, 0x3a, 0x54, 0x29, 0xdb, 0xad, 0x81, - 0xd2, 0x7d, 0x7f, 0xe6, 0xfc, 0x12, 0x96, 0xd0, 0x1b, 0x1e, 0x09, 0x0e, 0x0c, 0x5e, 0x17, 0x49, - 0x58, 0xf9, 0x00, 0xf4, 0x6e, 0x24, 0x7d, 0x0a, 0xb2, 0x77, 0xd0, 0x81, 0xc8, 0x6d, 0xf4, 0x4f, - 0x7d, 0x1b, 0xf2, 0xfb, 0x96, 0xdb, 0x41, 0x22, 0x84, 0x2f, 0x1d, 0x51, 0x73, 0xa1, 0x64, 0x9c, - 0xcb, 0x8b, 0x99, 0xcb, 0x5a, 0xf5, 0x53, 0x0d, 0xce, 0xae, 0x23, 0x12, 0x16, 0x4b, 0x7d, 0x0c, - 0xf7, 0x02, 0x9c, 0x76, 0x2d, 0x36, 0xa2, 0x22, 0x81, 0x83, 0xf6, 0x51, 0xa8, 0x2d, 0x99, 0x81, - 0xb3, 0xc6, 0x29, 0x8a, 0x60, 0xc8, 0x75, 0xc1, 0x60, 0xd3, 0x0e, 0x49, 0xdb, 0x81, 0xdf, 0x40, - 0x18, 0x27, 0x49, 0x33, 0x11, 0xe9, 0x9b, 0x72, 0x3d, 0x22, 0x4d, 0x1b, 0x38, 0xdb, 0x6d, 0xe0, - 0x1f, 0xb2, 0x5c, 0xd9, 0xff, 0x08, 0xc2, 0xd0, 0x3b, 0x50, 0x88, 0x99, 0xf8, 0x91, 0x94, 0x18, - 0x32, 0xaa, 0xbe, 0x0f, 0x8b, 0xeb, 0x88, 0x5c, 0xdf, 0x7a, 0xab, 0x8f, 0xf2, 0x6e, 0x89, 0xaa, - 0x87, 0x56, 0x70, 0xd2, 0xbb, 0x8e, 0xba, 0x35, 0xbd, 0x21, 0x78, 0x31, 0x47, 0xc4, 0x5f, 0xb8, - 0xfa, 0x33, 0x0d, 0x9e, 0xec, 0xb3, 0xb9, 0x38, 0xf6, 0x7b, 0x30, 0x1d, 0x63, 0x6b, 0xc6, 0x2b, - 0x9a, 0xe7, 0xff, 0x03, 0x21, 0x8c, 0xa9, 0x20, 0x09, 0xc0, 0xd5, 0xbf, 0x6a, 0x30, 0x63, 0x20, - 0xab, 0xdd, 0x76, 0x0f, 0x58, 0x32, 0xc6, 0xbd, 0x6e, 0xa7, 0x5c, 0xf7, 0xed, 0xa4, 0xee, 0x50, - 0x32, 0x8f, 0xde, 0xa1, 0xe8, 0x97, 0x61, 0x98, 0x5d, 0x19, 0x58, 0xe4, 0xc1, 0xc3, 0x53, 0xaa, - 0xc0, 0x17, 0x09, 0x7f, 0x16, 0x4e, 0xa6, 0x0e, 0x25, 0xee, 0xe7, 0x7f, 0x65, 0xa0, 0x7c, 0xcd, - 0xb6, 0x77, 0x90, 0x15, 0x34, 0xf6, 0xae, 0x11, 0x12, 0x38, 0xf5, 0x0e, 0x89, 0xac, 0xfd, 0x13, - 0x0d, 0xa6, 0x31, 0x5b, 0x33, 0xad, 0x70, 0x51, 0x28, 0xfc, 0xed, 0x81, 0x72, 0x4a, 0x6f, 0xe6, - 0xb5, 0x34, 0x9c, 0xa7, 0x94, 0x29, 0x9c, 0x02, 0xd3, 0xf2, 0xd8, 0xf1, 0x6c, 0x74, 0x3f, 0x9e, - 0x18, 0x8b, 0x0c, 0x42, 0x43, 0x45, 0xbf, 0x00, 0x3a, 0xbe, 0xe3, 0xb4, 0x4d, 0xdc, 0xd8, 0x43, - 0x2d, 0xcb, 0xec, 0xb4, 0x6d, 0xd9, 0x6b, 0x17, 0x8c, 0x29, 0xba, 0xb2, 0xc3, 0x16, 0xde, 0x66, - 0xf0, 0x64, 0x8f, 0x99, 0x4b, 0xf5, 0x98, 0x65, 0x17, 0x4e, 0x2a, 0xa5, 0x8a, 0xe7, 0xb0, 0x22, - 0xcf, 0x61, 0x57, 0xe2, 0x39, 0x6c, 0x62, 0xe5, 0x99, 0xa4, 0x45, 0xc2, 0x8a, 0x6c, 0x93, 0xca, - 0x89, 0xec, 0x5b, 0x14, 0x95, 0xd5, 0x99, 0xb1, 0x9c, 0x35, 0x0f, 0x73, 0x4a, 0xf5, 0x08, 0xdb, - 0x7c, 0xa8, 0xc1, 0x3c, 0x2f, 0xa9, 0x7a, 0x99, 0xe7, 0xd9, 0x5e, 0xd6, 0x29, 0x1e, 0x5d, 0x8d, - 0x7d, 0x9b, 0xef, 0xea, 0x22, 0x54, 0x7a, 0x89, 0x22, 0xa4, 0xfd, 0x7f, 0x28, 0xd3, 0x7e, 0xaf, - 0x87, 0xa4, 0xc9, 0xcd, 0xb5, 0xbe, 0x9b, 0x67, 0xd2, 0x9b, 0x7f, 0x3c, 0x0c, 0x73, 0x4a, 0xde, - 0x22, 0x2b, 0x7c, 0xa0, 0xc1, 0x74, 0xa3, 0x83, 0x89, 0xdf, 0xea, 0xf6, 0xd2, 0x81, 0x6f, 0xbe, - 0x5e, 0xdc, 0x6b, 0x6b, 0x8c, 0x73, 0x97, 0x9b, 0x36, 0x52, 0x60, 0x26, 0x05, 0x3e, 0xc0, 0x04, - 0x25, 0xa4, 0xc8, 0x1c, 0x93, 0x14, 0x3b, 0x8c, 0x73, 0x77, 0xb0, 0xa4, 0xc0, 0x7a, 0x13, 0x46, - 0x5a, 0x56, 0xbb, 0xed, 0x78, 0x4d, 0x31, 0x4b, 0xdc, 0x7e, 0xe4, 0xad, 0xb7, 0x39, 0x3f, 0xbe, - 0xa3, 0xe4, 0xae, 0x7b, 0x30, 0x67, 0xd9, 0xb6, 0xd9, 0x9d, 0xf0, 0x78, 0x73, 0xcf, 0xdb, 0x88, - 0xe5, 0x64, 0x54, 0x48, 0x64, 0x65, 0xde, 0x63, 0x37, 0x42, 0xc9, 0xb2, 0x6d, 0xe5, 0x0a, 0x0d, - 0x4d, 0xa5, 0x25, 0x1e, 0x4b, 0x68, 0xb2, 0x44, 0xa0, 0xd2, 0xf8, 0xe3, 0xd9, 0xed, 0x45, 0x18, - 0x8b, 0x2b, 0x59, 0xb1, 0xc9, 0x4c, 0x7c, 0x93, 0x62, 0x3c, 0x89, 0xbc, 0x04, 0xa7, 0xe4, 0xec, - 0x6a, 0x8d, 0xd7, 0x12, 0xb1, 0x1b, 0x2b, 0x51, 0x71, 0x68, 0xdd, 0x15, 0xc7, 0x9f, 0x46, 0x60, - 0xb6, 0x8b, 0x5a, 0x44, 0xd5, 0x8f, 0x60, 0x1a, 0x77, 0xda, 0x6d, 0x3f, 0x20, 0xc8, 0x36, 0x1b, - 0xae, 0xc3, 0xae, 0x1f, 0x1e, 0x54, 0xc6, 0x40, 0x3e, 0xd5, 0x83, 0x71, 0x6d, 0x47, 0x72, 0x5d, - 0xe3, 0x4c, 0xa5, 0x2b, 0xa7, 0xc0, 0xfa, 0xd3, 0x30, 0xc1, 0xb9, 0x87, 0x8d, 0x12, 0x3f, 0xfc, - 0x38, 0x87, 0xca, 0x36, 0xe9, 0x36, 0x4c, 0xb6, 0x50, 0xab, 0x8e, 0x02, 0xbc, 0xe7, 0xb4, 0xb9, - 0xf3, 0xf5, 0x6b, 0x16, 0xe4, 0xa3, 0xd3, 0xfe, 0xc5, 0xda, 0x76, 0x48, 0xc6, 0xa7, 0x6a, 0xad, - 0xc4, 0x37, 0xcd, 0x59, 0x52, 0x7f, 0xe1, 0x7d, 0x5f, 0x14, 0x10, 0x45, 0x41, 0x97, 0xef, 0x52, - 0x2f, 0xed, 0x1f, 0x65, 0xbb, 0xc1, 0xcb, 0xf2, 0x86, 0xdf, 0xf1, 0x08, 0xeb, 0xf7, 0xf2, 0xc6, - 0xb4, 0x58, 0x62, 0x15, 0xf3, 0x1a, 0x5d, 0xa0, 0xf9, 0x3c, 0x36, 0xf8, 0x32, 0xe9, 0x32, 0xef, - 0xf8, 0x8a, 0xc6, 0x54, 0x6c, 0x61, 0x87, 0xc2, 0xf5, 0x73, 0x30, 0x15, 0xeb, 0xdd, 0x39, 0x6e, - 0x81, 0xe1, 0xc6, 0x7a, 0x7a, 0x8e, 0xba, 0x0e, 0x63, 0xb2, 0x9f, 0x62, 0xfa, 0x29, 0x32, 0xfd, - 0x9c, 0x49, 0x7a, 0xaa, 0xc0, 0x88, 0x75, 0x51, 0x4c, 0x2b, 0xa3, 0xfb, 0xd1, 0x87, 0xfe, 0x32, - 0x94, 0x77, 0x2d, 0xc7, 0xf5, 0x63, 0x46, 0x31, 0x1d, 0xaf, 0x11, 0xa0, 0x16, 0xf2, 0x48, 0x09, - 0x58, 0x01, 0x5c, 0x92, 0x18, 0x21, 0x17, 0xb1, 0xae, 0x5f, 0x86, 0x92, 0xe3, 0x39, 0xc4, 0xb1, - 0x5c, 0x33, 0xcd, 0xa5, 0x34, 0xca, 0x8b, 0x67, 0xb1, 0xfe, 0x4a, 0x92, 0x85, 0x7e, 0x05, 0xe6, - 0x1c, 0x6c, 0x36, 0x5d, 0xbf, 0x6e, 0xb9, 0x66, 0x54, 0x86, 0x21, 0xcf, 0xaa, 0xbb, 0xc8, 0x2e, - 0x8d, 0xb1, 0xcb, 0xbe, 0xe4, 0xe0, 0x75, 0x86, 0x11, 0x56, 0xd0, 0x37, 0xf8, 0xba, 0xfe, 0x0e, - 0xe4, 0x88, 0xd5, 0xc4, 0xa5, 0x71, 0xe6, 0xbd, 0xaf, 0x3c, 0x92, 0xf7, 0xde, 0xb4, 0x9a, 0xc2, - 0x63, 0x19, 0xcf, 0xf2, 0x1a, 0x9c, 0x54, 0x3a, 0xf4, 0x51, 0x82, 0xb8, 0x7c, 0x09, 0x8a, 0x21, - 0xdf, 0x23, 0x45, 0xff, 0x3b, 0x70, 0x62, 0xcb, 0xc1, 0x44, 0x08, 0x19, 0x5e, 0xb7, 0x73, 0x50, - 0x8c, 0x46, 0x06, 0xbc, 0xf1, 0x2a, 0xb4, 0xfb, 0xcc, 0x0a, 0x94, 0x93, 0xbc, 0x5f, 0x6a, 0x30, - 0x93, 0x64, 0x2e, 0x32, 0xc3, 0x1b, 0x50, 0x10, 0x5e, 0xde, 0xbf, 0xf8, 0x4e, 0x0d, 0x71, 0x05, - 0x9f, 0x6d, 0xf1, 0x04, 0x6a, 0x84, 0x4c, 0x06, 0x96, 0xe8, 0xd7, 0x1a, 0x2c, 0x5c, 0xb3, 0xed, - 0x37, 0x02, 0x5e, 0xcc, 0xd1, 0x8a, 0x84, 0xa4, 0xb3, 0xde, 0x39, 0x98, 0xda, 0x0d, 0x7c, 0x8f, - 0x20, 0xcf, 0x4e, 0x3d, 0x43, 0x4c, 0x4a, 0xb8, 0x7c, 0x8a, 0x58, 0x87, 0x45, 0xee, 0x41, 0x66, - 0xc0, 0x38, 0x99, 0x32, 0x9e, 0x1b, 0xbe, 0xe7, 0xa1, 0x46, 0x58, 0xbd, 0x17, 0x8c, 0x79, 0x8e, - 0x97, 0xd8, 0x70, 0x2d, 0x44, 0xaa, 0x56, 0x61, 0xb1, 0xb7, 0x58, 0xa2, 0x3e, 0xba, 0x0a, 0x65, - 0x5e, 0x41, 0x29, 0xa5, 0x1e, 0x20, 0x57, 0xb3, 0x67, 0x4d, 0x05, 0x83, 0x68, 0xd2, 0x76, 0x3a, - 0x66, 0x2d, 0x91, 0xdb, 0x24, 0xff, 0x1d, 0x38, 0xc9, 0x1a, 0xd7, 0x3d, 0x64, 0x05, 0xa4, 0x8e, - 0x2c, 0x62, 0xde, 0x73, 0xc8, 0x9e, 0xe3, 0x89, 0xe6, 0xf1, 0x74, 0xd7, 0xb8, 0xef, 0xba, 0xf8, - 0x65, 0xc5, 0x6a, 0xee, 0xa3, 0x2f, 0x17, 0x34, 0xe3, 0x04, 0xa5, 0xde, 0x90, 0xc4, 0xb7, 0x19, - 0xad, 0xbe, 0x00, 0xa3, 0x41, 0xbb, 0x11, 0x6a, 0x59, 0x8c, 0x6f, 0x83, 0x76, 0x43, 0x2a, 0x78, - 0x16, 0x46, 0xd8, 0x73, 0x50, 0x38, 0xbf, 0x1d, 0xa6, 0x9f, 0x6c, 0x4e, 0x9b, 0x0b, 0x7c, 0x97, - 0x17, 0xe0, 0x13, 0xf1, 0x2a, 0x41, 0x35, 0xd4, 0x4c, 0x9c, 0xc8, 0xf0, 0x5d, 0x64, 0x30, 0x62, - 0xfd, 0x5d, 0x28, 0x63, 0x84, 0x59, 0x0e, 0x62, 0xa3, 0x38, 0x64, 0x9b, 0xd6, 0x2e, 0xd5, 0x20, - 0x9b, 0x63, 0xe6, 0x07, 0x9c, 0x63, 0xce, 0x0a, 0x1e, 0x3b, 0x9c, 0xc5, 0x35, 0xca, 0x81, 0xcd, - 0x71, 0x13, 0x31, 0x34, 0x7c, 0x78, 0x0c, 0x8d, 0xa8, 0x3c, 0xf6, 0x63, 0x0d, 0xca, 0x2a, 0xab, - 0x88, 0x48, 0xba, 0x09, 0x13, 0x56, 0x83, 0x38, 0xfb, 0xc8, 0x14, 0x77, 0x8f, 0x88, 0xa7, 0xe7, - 0x0e, 0xbb, 0xba, 0x92, 0x3a, 0x19, 0xe7, 0x4c, 0x04, 0xf7, 0x81, 0xc3, 0xe9, 0xf7, 0x19, 0x38, - 0xc9, 0x7b, 0xee, 0x74, 0x97, 0x7f, 0x03, 0x72, 0x6c, 0x84, 0xae, 0x31, 0xfb, 0x5c, 0xec, 0x6f, - 0x9f, 0xeb, 0xc8, 0xb2, 0xb7, 0x10, 0x21, 0x28, 0x78, 0xab, 0x83, 0x44, 0x71, 0xc3, 0xc8, 0xfb, - 0xbd, 0xf5, 0xd1, 0xcb, 0xdd, 0xef, 0x04, 0x8d, 0x30, 0xe8, 0x84, 0x87, 0x8c, 0x73, 0xa8, 0x38, - 0x9f, 0x7e, 0x89, 0x5e, 0x19, 0x14, 0x83, 0xea, 0x88, 0x86, 0x74, 0x6c, 0xde, 0xc2, 0xc7, 0xb0, - 0x27, 0xc3, 0xf5, 0x1b, 0x5e, 0x6c, 0xdc, 0xa2, 0x1c, 0x9e, 0xe6, 0x07, 0x1e, 0x9e, 0x0e, 0xab, - 0xf4, 0xf5, 0x79, 0x06, 0x4e, 0xa5, 0xf5, 0x25, 0x0c, 0x79, 0x4c, 0x0a, 0x53, 0xce, 0x37, 0x32, - 0xc7, 0x38, 0xdf, 0x50, 0x9d, 0x35, 0xab, 0x9a, 0xe6, 0xb6, 0xe0, 0x54, 0x97, 0x24, 0xb2, 0xb2, - 0x7f, 0xa4, 0x99, 0xcf, 0x4c, 0x5a, 0x24, 0xf6, 0x96, 0xf7, 0x37, 0x0d, 0x66, 0xdf, 0xec, 0x04, - 0x4d, 0xf4, 0x7d, 0x74, 0xc6, 0x6a, 0x19, 0x4a, 0xdd, 0x87, 0x13, 0x79, 0xfb, 0x0f, 0x19, 0x98, - 0xdd, 0x46, 0xdf, 0xd3, 0x93, 0x3f, 0x96, 0x30, 0x5c, 0x85, 0x52, 0xb7, 0xc2, 0x8e, 0xf6, 0x58, - 0x41, 0x6b, 0x9b, 0x39, 0x03, 0xed, 0x06, 0x08, 0xef, 0xc9, 0x76, 0x33, 0xf1, 0x7e, 0x9c, 0x9e, - 0xf6, 0x65, 0x1f, 0xdf, 0x5b, 0x94, 0x18, 0xd1, 0x55, 0xe0, 0x09, 0xb5, 0x40, 0x91, 0x9f, 0xcc, - 0x1b, 0x08, 0x23, 0xcf, 0x4e, 0x45, 0x55, 0x4f, 0x99, 0x8f, 0xf1, 0xc1, 0xf5, 0x69, 0x98, 0x48, - 0x96, 0x48, 0xa2, 0x1d, 0x1a, 0x0f, 0xe2, 0xb5, 0x88, 0xe2, 0x55, 0x2d, 0xaf, 0x78, 0x55, 0x7b, - 0x0a, 0xc6, 0x39, 0x56, 0xf2, 0xfd, 0x8b, 0x23, 0xf5, 0x7a, 0x4a, 0x1b, 0xe9, 0x7a, 0x4a, 0x5b, - 0x80, 0x51, 0x8a, 0x21, 0x99, 0x14, 0x42, 0x04, 0xc1, 0x82, 0xcf, 0xac, 0xd4, 0x0a, 0x13, 0x3a, - 0xfd, 0x5d, 0x06, 0x4a, 0xeb, 0x88, 0x50, 0x20, 0x8f, 0x99, 0xb8, 0x3a, 0xfb, 0xff, 0x14, 0x69, - 0x5e, 0xcc, 0xc1, 0xd9, 0xef, 0x41, 0xe5, 0xc8, 0x8a, 0x48, 0x46, 0xfa, 0x16, 0x4c, 0x46, 0xcb, - 0xfc, 0x39, 0x3a, 0xcb, 0x82, 0xf8, 0x4c, 0x8f, 0xf1, 0x40, 0x24, 0x03, 0x8d, 0xdb, 0x71, 0x12, - 0xff, 0xd4, 0x2b, 0x30, 0xda, 0x72, 0x78, 0x12, 0x8e, 0x22, 0xae, 0xd8, 0x72, 0x78, 0x56, 0xb5, - 0xd9, 0xba, 0x75, 0x3f, 0x5c, 0xcf, 0x8b, 0x75, 0xeb, 0xbe, 0x58, 0x4f, 0xfe, 0xc0, 0x60, 0x78, - 0x80, 0x1f, 0x18, 0x28, 0x8b, 0x99, 0x07, 0x1a, 0x9c, 0x56, 0xa8, 0x4b, 0x84, 0xde, 0x6b, 0xc9, - 0x5f, 0x18, 0xfc, 0xcf, 0x20, 0x2d, 0xc1, 0x35, 0xd7, 0xf5, 0x1b, 0x16, 0x41, 0x76, 0x78, 0x3d, - 0x1c, 0xf1, 0xd7, 0x06, 0x3f, 0xd7, 0xa0, 0x72, 0x1d, 0xb9, 0x88, 0xa0, 0xef, 0xf8, 0xc7, 0x7c, - 0xd5, 0x2b, 0xb0, 0xd0, 0x53, 0x10, 0xa1, 0xa1, 0x32, 0x14, 0xee, 0x59, 0x81, 0xe7, 0x78, 0x4d, - 0x39, 0xa5, 0x0d, 0xbf, 0xab, 0xbf, 0xd5, 0x60, 0x69, 0x87, 0x04, 0xc8, 0x6a, 0x49, 0xfa, 0x3e, - 0x8f, 0x30, 0x6d, 0x38, 0x85, 0x0f, 0xbc, 0x86, 0x19, 0xbf, 0xa1, 0xf9, 0xaf, 0xbe, 0xb4, 0x3e, - 0xbf, 0xfa, 0x4a, 0x5d, 0xce, 0x3b, 0x07, 0x5e, 0x23, 0xb6, 0x07, 0xfb, 0x7d, 0xd7, 0xc6, 0x90, - 0x31, 0x83, 0x15, 0xf0, 0xd5, 0x31, 0x80, 0x68, 0xa8, 0x59, 0xfd, 0x48, 0x83, 0x73, 0x03, 0x08, - 0x2b, 0x8e, 0xfd, 0x6e, 0xd7, 0x5b, 0xd5, 0xd5, 0x41, 0xe4, 0xeb, 0xc3, 0x7a, 0x63, 0x28, 0x7a, - 0xb5, 0x4a, 0x89, 0xf6, 0x36, 0x9c, 0x48, 0xbe, 0xa1, 0x71, 0x8d, 0x55, 0xba, 0x9c, 0x60, 0x63, - 0x28, 0xee, 0x06, 0x53, 0x90, 0x91, 0xf9, 0x70, 0x63, 0xc8, 0xc8, 0x38, 0x76, 0x8a, 0xed, 0x17, - 0x59, 0x98, 0x49, 0xf2, 0x15, 0x87, 0x7b, 0x19, 0x72, 0xb1, 0x91, 0xd3, 0x52, 0xd2, 0x75, 0xd4, - 0xbf, 0xe3, 0x62, 0x7e, 0xce, 0xa8, 0xf4, 0x55, 0x18, 0x6e, 0xf8, 0xde, 0xae, 0xd3, 0x14, 0xf3, - 0xd2, 0xf3, 0x83, 0xd0, 0xaf, 0x31, 0x0a, 0x43, 0x50, 0xea, 0xbb, 0xa0, 0xc7, 0xfd, 0x40, 0xf0, - 0xcb, 0xa7, 0x1f, 0x05, 0x15, 0x1a, 0x56, 0xbd, 0x34, 0x0a, 0xe6, 0xf1, 0x32, 0x94, 0x83, 0xe8, - 0x1d, 0xc0, 0x79, 0xa7, 0xf2, 0xf6, 0x38, 0x87, 0xca, 0xc4, 0x4d, 0xfb, 0xef, 0xf4, 0x70, 0x87, - 0x27, 0xef, 0xc9, 0xd4, 0x60, 0x48, 0xbf, 0x15, 0x43, 0x95, 0xef, 0xfc, 0x05, 0x96, 0x3c, 0x9e, - 0xed, 0x2b, 0xb7, 0x9c, 0x0e, 0x51, 0xd7, 0xec, 0xe0, 0x88, 0xaf, 0x7c, 0xe5, 0xaf, 0xc1, 0x09, - 0xc5, 0xb4, 0x88, 0x4d, 0xbd, 0x0a, 0xc6, 0x74, 0xd7, 0x94, 0xa8, 0xfa, 0x89, 0x06, 0x3a, 0xaf, - 0xeb, 0x13, 0x17, 0xc0, 0x0d, 0x18, 0xb1, 0xdd, 0xbb, 0xa6, 0x9c, 0xc5, 0x8c, 0xae, 0x5c, 0x50, - 0x77, 0x65, 0x61, 0x7e, 0x10, 0xfb, 0x5f, 0xdf, 0x7a, 0xeb, 0x35, 0x74, 0x60, 0x0c, 0xdb, 0xee, - 0xdd, 0xd7, 0xd0, 0x41, 0xb2, 0x8f, 0xcc, 0x1c, 0xde, 0x47, 0xaa, 0xca, 0xf1, 0xea, 0x87, 0x1a, - 0xf3, 0xeb, 0x48, 0x44, 0xe1, 0x7e, 0xaf, 0x42, 0x91, 0xca, 0x18, 0x4f, 0xbc, 0xcf, 0x0d, 0x2c, - 0x25, 0x6b, 0x11, 0x0a, 0xb6, 0x7b, 0xf7, 0xe6, 0x51, 0x72, 0xee, 0xaa, 0xfb, 0xd9, 0x57, 0x95, - 0xa1, 0xcf, 0xbf, 0xaa, 0x0c, 0x7d, 0xf3, 0x55, 0x45, 0xfb, 0xf1, 0xc3, 0x8a, 0xf6, 0x9b, 0x87, - 0x15, 0xed, 0xcf, 0x0f, 0x2b, 0xda, 0x67, 0x0f, 0x2b, 0xda, 0x3f, 0x1e, 0x56, 0xb4, 0x7f, 0x3e, - 0xac, 0x0c, 0x7d, 0xf3, 0xb0, 0xa2, 0x3d, 0xf8, 0xba, 0x32, 0xf4, 0xd9, 0xd7, 0x95, 0xa1, 0xcf, - 0xbf, 0xae, 0x0c, 0xbd, 0xf3, 0xbf, 0x4d, 0x3f, 0x12, 0xcc, 0xf1, 0xfb, 0xfc, 0x0f, 0xc9, 0x4b, - 0xf1, 0xef, 0xfa, 0x30, 0xeb, 0xdc, 0x9f, 0xff, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x02, - 0x8e, 0x35, 0x7e, 0x32, 0x00, 0x00, + 0xb1, 0x9c, 0xfd, 0x90, 0xbb, 0xc5, 0xff, 0x88, 0x14, 0x57, 0x4b, 0x73, 0x49, 0xaf, 0x65, 0x99, + 0x92, 0xe5, 0xe5, 0x13, 0x6d, 0x3f, 0xc9, 0x1f, 0x41, 0x10, 0x3f, 0x26, 0x29, 0x93, 0xb6, 0x35, + 0x94, 0xa5, 0xf7, 0x0c, 0x18, 0xe3, 0xd9, 0x99, 0xe6, 0x72, 0xac, 0xd9, 0x99, 0xd5, 0x74, 0x2f, + 0x25, 0x1a, 0x78, 0x1f, 0xc4, 0x09, 0x02, 0x1f, 0x82, 0x08, 0x08, 0x02, 0x18, 0x3e, 0xf9, 0x18, + 0x04, 0x09, 0x72, 0xcb, 0x31, 0x80, 0x6f, 0x39, 0x1a, 0xf1, 0xc5, 0x70, 0x80, 0x38, 0x96, 0x2f, + 0x39, 0xfa, 0x9c, 0x53, 0xd0, 0xbf, 0xf9, 0xed, 0xec, 0x72, 0x19, 0x49, 0x36, 0xe0, 0xdb, 0x76, + 0x75, 0x55, 0x75, 0x75, 0x55, 0x75, 0x75, 0x55, 0xf5, 0x2c, 0xbc, 0x4c, 0x50, 0xb3, 0xe5, 0xf9, + 0x86, 0xb3, 0x84, 0x91, 0x7f, 0x80, 0xfc, 0x25, 0xa3, 0x65, 0x2f, 0x19, 0x56, 0xd3, 0x76, 0xe9, + 0xd8, 0x36, 0xd1, 0xd2, 0xc1, 0x85, 0x25, 0x1f, 0xdd, 0x69, 0x23, 0x4c, 0x74, 0x1f, 0xe1, 0x96, + 0xe7, 0x62, 0x54, 0x6b, 0xf9, 0x1e, 0xf1, 0xd4, 0xa7, 0x24, 0x6d, 0x8d, 0xd3, 0xd6, 0x8c, 0x96, + 0x5d, 0x8b, 0xd2, 0xd6, 0x0e, 0x2e, 0x94, 0xe7, 0x1b, 0x9e, 0xd7, 0x70, 0xd0, 0x12, 0x23, 0xa9, + 0xb7, 0xf7, 0x96, 0x88, 0xdd, 0x44, 0x98, 0x18, 0xcd, 0x16, 0xe7, 0x52, 0xae, 0x24, 0x11, 0xac, + 0xb6, 0x6f, 0x10, 0xdb, 0x73, 0xc5, 0xfc, 0x93, 0x16, 0x6a, 0x21, 0xd7, 0x42, 0xae, 0x69, 0x23, + 0xbc, 0xd4, 0xf0, 0x1a, 0x1e, 0x83, 0xb3, 0x5f, 0x02, 0xa5, 0x1a, 0x6c, 0x82, 0x4a, 0x8f, 0xdc, + 0x76, 0x13, 0x53, 0xb1, 0x4d, 0xaf, 0xd9, 0x0c, 0xd8, 0x9c, 0x49, 0xc7, 0x21, 0x06, 0xbe, 0xad, + 0xdf, 0x69, 0xa3, 0xb6, 0xd8, 0x54, 0xf9, 0x74, 0x0c, 0x8f, 0xb3, 0xa0, 0x88, 0x4d, 0x84, 0xb1, + 0xd1, 0x90, 0x58, 0x4f, 0xc7, 0xb0, 0x0e, 0x90, 0x8f, 0xed, 0x34, 0xb4, 0xf8, 0xa2, 0x77, 0x3d, + 0xff, 0xf6, 0x9e, 0xe3, 0xdd, 0xed, 0xc4, 0x7b, 0x26, 0x86, 0xe7, 0x1a, 0x4d, 0x84, 0x5b, 0x06, + 0xd7, 0x7d, 0x1c, 0xf1, 0x6c, 0x0c, 0xd1, 0x47, 0x2d, 0xc7, 0x36, 0x99, 0xb2, 0x3a, 0x51, 0xcf, + 0xa7, 0x59, 0xd6, 0x74, 0xda, 0x98, 0x20, 0xbf, 0x97, 0x04, 0x51, 0xec, 0x60, 0xf7, 0x96, 0x73, + 0xa7, 0x43, 0x82, 0x08, 0x62, 0xba, 0xca, 0xcf, 0xf5, 0x46, 0xe5, 0xa2, 0xf4, 0x5a, 0x3f, 0x66, + 0xa5, 0x5e, 0xdb, 0xda, 0xb7, 0x31, 0xf1, 0xfc, 0xc3, 0xce, 0x6d, 0xd5, 0xd2, 0xb0, 0x7b, 0xe8, + 0xf7, 0x3f, 0xd2, 0xf0, 0x7b, 0xaa, 0xf9, 0xa5, 0x34, 0x8a, 0x16, 0x75, 0x08, 0x4c, 0x90, 0xcb, + 0xd7, 0x10, 0x5b, 0xd5, 0x9b, 0x88, 0x18, 0x96, 0x41, 0x0c, 0x41, 0xfa, 0x7c, 0x1f, 0xa4, 0xe8, + 0x1e, 0x32, 0xdb, 0x74, 0x65, 0x2c, 0x88, 0xae, 0xf4, 0x41, 0x24, 0x1d, 0x4d, 0x6f, 0xb6, 0x89, + 0x51, 0x77, 0x90, 0x8e, 0x89, 0x41, 0x7a, 0xaa, 0x24, 0xc1, 0x80, 0xea, 0x5b, 0x2c, 0x58, 0xfd, + 0x50, 0x81, 0xb2, 0x86, 0xea, 0x6d, 0xdb, 0xb1, 0x76, 0x38, 0xbb, 0x5d, 0xca, 0x4d, 0xe3, 0x31, + 0x41, 0x7d, 0x02, 0x8a, 0x81, 0x3e, 0x4b, 0xca, 0x82, 0xb2, 0x58, 0xd4, 0x42, 0x80, 0xba, 0x01, + 0xc5, 0x60, 0x07, 0xa5, 0xcc, 0x82, 0xb2, 0x38, 0xbc, 0x7c, 0x36, 0x10, 0x80, 0xc5, 0x0b, 0xe1, + 0x31, 0x07, 0x17, 0x6a, 0xb7, 0x84, 0xd4, 0xeb, 0x92, 0x40, 0x0b, 0x69, 0xab, 0x73, 0x30, 0x9b, + 0x2a, 0x04, 0x0f, 0x48, 0xd5, 0xcf, 0x32, 0x50, 0xd9, 0xa2, 0x5c, 0x49, 0x27, 0x97, 0xef, 0x55, + 0x50, 0x75, 0x0b, 0xc6, 0x85, 0x37, 0xea, 0x75, 0x83, 0x98, 0xfb, 0x08, 0x97, 0xb2, 0x0b, 0xd9, + 0xc5, 0xe1, 0xe5, 0x85, 0x6e, 0xec, 0xd6, 0x0c, 0x62, 0xac, 0x38, 0x5e, 0x5d, 0x1b, 0x13, 0x84, + 0x2b, 0x9c, 0x4e, 0xbd, 0x05, 0xe3, 0x22, 0xb2, 0xe8, 0x62, 0xa6, 0x94, 0x63, 0x92, 0xd5, 0x6a, + 0x69, 0x91, 0x57, 0xe0, 0x50, 0x96, 0x37, 0x39, 0xd9, 0x26, 0x87, 0x68, 0x63, 0x07, 0xb1, 0xb1, + 0x3a, 0x05, 0x79, 0xe2, 0xdd, 0x46, 0x6e, 0x29, 0xbf, 0xa0, 0x2c, 0x8e, 0x68, 0x7c, 0x50, 0xbd, + 0x08, 0xf3, 0x5d, 0x55, 0xc8, 0xd5, 0x1c, 0x12, 0x2a, 0x51, 0xc2, 0x9f, 0x2a, 0x30, 0xbb, 0x86, + 0xb0, 0xe9, 0xdb, 0x75, 0xf4, 0x03, 0xba, 0xc8, 0x1f, 0x33, 0xf0, 0x44, 0xba, 0x18, 0x42, 0xfa, + 0x53, 0x50, 0xc0, 0xfb, 0x86, 0x6f, 0xe9, 0xb6, 0x25, 0xc4, 0x18, 0x62, 0xe3, 0x2d, 0x4b, 0x7d, + 0x12, 0x46, 0xa4, 0xd5, 0x0c, 0xcb, 0xf2, 0x99, 0x1c, 0x45, 0x6d, 0x58, 0xc0, 0xae, 0x5a, 0x96, + 0xaf, 0xee, 0xc3, 0x09, 0xd3, 0x30, 0xf7, 0x51, 0xfc, 0x50, 0x95, 0xb2, 0x4c, 0xe2, 0x4b, 0xa9, + 0x16, 0x89, 0x9c, 0xaa, 0xa8, 0xf4, 0x31, 0xe1, 0x26, 0x19, 0xd3, 0x28, 0x48, 0x75, 0xe1, 0x24, + 0x8d, 0x12, 0x75, 0x03, 0x27, 0x17, 0xcb, 0x3d, 0xe4, 0x62, 0x53, 0x92, 0x6f, 0x14, 0x5a, 0xfd, + 0x8b, 0x02, 0x65, 0xa9, 0x38, 0xe1, 0x22, 0x9b, 0x1e, 0x26, 0xd2, 0x7c, 0x54, 0x37, 0x1e, 0x26, + 0x4c, 0x31, 0x08, 0x63, 0xa1, 0xba, 0x61, 0x0a, 0xbb, 0xca, 0x41, 0x31, 0xcd, 0x52, 0xd5, 0xe5, + 0x43, 0xcd, 0xc6, 0x8c, 0x9f, 0x4d, 0x1a, 0xff, 0xbf, 0x40, 0x0d, 0x82, 0x55, 0xe8, 0x05, 0xb9, + 0xe3, 0x7a, 0xc1, 0xe4, 0xdd, 0x24, 0xa8, 0xfa, 0xb7, 0x88, 0x53, 0xc6, 0x36, 0x25, 0x9c, 0xe1, + 0x29, 0x18, 0x65, 0x22, 0x62, 0xdd, 0x6d, 0x37, 0xeb, 0xc8, 0x67, 0xdb, 0xca, 0x6b, 0x23, 0x1c, + 0xf8, 0x06, 0x83, 0xa9, 0xb3, 0x50, 0x94, 0xfb, 0xc2, 0xa5, 0xcc, 0x42, 0x76, 0x31, 0xaf, 0x15, + 0xc4, 0xc6, 0xb0, 0xfa, 0x2e, 0x8c, 0x07, 0x1b, 0xd1, 0x99, 0x15, 0x85, 0x33, 0xbc, 0x90, 0x6a, + 0x9f, 0x00, 0x97, 0x6e, 0xe1, 0x0d, 0x39, 0x58, 0xa5, 0x74, 0x5b, 0xee, 0x9e, 0xa7, 0x8d, 0xb9, + 0x31, 0x98, 0x5a, 0x82, 0x21, 0xa9, 0xf1, 0x3c, 0x77, 0x56, 0x31, 0xbc, 0x96, 0x2b, 0xe4, 0x26, + 0xf2, 0xd5, 0x1a, 0x4c, 0xae, 0x3a, 0x1e, 0x46, 0xbb, 0x54, 0x1e, 0x69, 0xab, 0xa4, 0x8b, 0x87, + 0x86, 0xa8, 0x4e, 0x81, 0x1a, 0xc5, 0x17, 0x81, 0xf3, 0x3c, 0x8c, 0x6f, 0x20, 0xd2, 0x2f, 0x8f, + 0xf7, 0x60, 0x22, 0xc4, 0x16, 0x8a, 0xdc, 0x06, 0x10, 0xe8, 0xee, 0x9e, 0xc7, 0x08, 0x86, 0x97, + 0x9f, 0xeb, 0xc7, 0x43, 0x19, 0x1b, 0xb6, 0x75, 0xae, 0x64, 0xfa, 0xb3, 0xfa, 0x8b, 0x0c, 0xcc, + 0x6c, 0xdb, 0x98, 0x08, 0x93, 0xdd, 0xa0, 0x17, 0xd1, 0xd1, 0x82, 0xa9, 0xaf, 0x41, 0xc1, 0x34, + 0x08, 0x6a, 0xd0, 0x18, 0x49, 0x1d, 0x70, 0x6c, 0xf9, 0x5c, 0xaa, 0x08, 0x2c, 0xa3, 0xa0, 0x8b, + 0x53, 0xc6, 0xab, 0x82, 0x42, 0x0b, 0x68, 0xd5, 0x4d, 0x00, 0x96, 0x11, 0xfa, 0x86, 0xdb, 0x90, + 0xe6, 0x3c, 0x7b, 0x54, 0xb4, 0xa5, 0xbc, 0x34, 0x4a, 0xa0, 0x15, 0x89, 0xfc, 0xa9, 0xce, 0x01, + 0xb0, 0xf8, 0xaf, 0x63, 0xfb, 0x03, 0x7e, 0x70, 0xf3, 0x5a, 0x91, 0x41, 0x76, 0xed, 0x0f, 0x90, + 0x7a, 0x06, 0xc6, 0x5d, 0x74, 0x8f, 0xe8, 0x2d, 0xa3, 0x81, 0xf4, 0x68, 0x30, 0x1e, 0xa5, 0xe0, + 0xb7, 0x8c, 0x06, 0xba, 0xc1, 0x62, 0xeb, 0x87, 0x0a, 0x94, 0x3a, 0xf5, 0x21, 0x54, 0x7f, 0x05, + 0xf2, 0xec, 0xa6, 0x2e, 0x29, 0xec, 0x86, 0x49, 0x17, 0x34, 0x91, 0x90, 0x73, 0x69, 0x39, 0x5d, + 0x9a, 0x14, 0x99, 0x34, 0x29, 0x3e, 0xce, 0x40, 0x8e, 0xd2, 0xd1, 0x58, 0x10, 0xfa, 0x7c, 0x10, + 0x46, 0x87, 0x03, 0xd8, 0x96, 0xa5, 0xce, 0xc3, 0x70, 0x70, 0xa4, 0x45, 0x38, 0x28, 0x6a, 0x20, + 0x41, 0x5b, 0x96, 0x3a, 0x0d, 0x83, 0x7e, 0xdb, 0xa5, 0x73, 0x3c, 0x1c, 0xe4, 0xfd, 0xb6, 0xbb, + 0x65, 0xa9, 0x33, 0x30, 0xc4, 0x54, 0x6f, 0x5b, 0x4c, 0x5b, 0x59, 0x6d, 0x90, 0x0e, 0xb7, 0x2c, + 0x75, 0x15, 0x98, 0x5a, 0x75, 0x72, 0xd8, 0x42, 0x4c, 0x49, 0x63, 0xcb, 0x67, 0x8e, 0x36, 0xee, + 0x8d, 0xc3, 0x16, 0xd2, 0x0a, 0x44, 0xfc, 0x52, 0x2f, 0x43, 0x71, 0xcf, 0xf6, 0x91, 0x4e, 0xab, + 0x8f, 0xd2, 0x20, 0xb3, 0x6b, 0xb9, 0xc6, 0x2b, 0x8f, 0x9a, 0xac, 0x3c, 0x6a, 0x37, 0x64, 0x69, + 0xb2, 0x92, 0xbb, 0xff, 0xf5, 0xbc, 0xa2, 0x15, 0x28, 0x09, 0x05, 0xd2, 0xc3, 0x28, 0xee, 0xd0, + 0xd2, 0x10, 0x13, 0x4e, 0x0e, 0xab, 0x5f, 0x29, 0x30, 0xa9, 0xa1, 0xa6, 0x77, 0x80, 0x98, 0x62, + 0xbf, 0x3f, 0x57, 0x8d, 0xe8, 0x2b, 0x1b, 0xd3, 0xd7, 0x16, 0x8c, 0x1f, 0xd8, 0xd8, 0xae, 0xdb, + 0x8e, 0x4d, 0x0e, 0xf9, 0x86, 0x73, 0x7d, 0x6e, 0x78, 0x2c, 0x24, 0xa4, 0x53, 0x34, 0x66, 0x44, + 0xf7, 0x26, 0x62, 0xc6, 0xaf, 0xb2, 0xf0, 0xcc, 0x06, 0x4a, 0x49, 0x13, 0x8c, 0xbb, 0xc2, 0x4d, + 0x6f, 0x2e, 0x47, 0x2e, 0x8f, 0x98, 0xc3, 0x14, 0x3b, 0x1d, 0xe6, 0x91, 0xa5, 0x5e, 0xa7, 0x61, + 0x0c, 0x13, 0xc3, 0x27, 0x3a, 0x3a, 0x40, 0x2e, 0x09, 0x15, 0x33, 0xc2, 0xa0, 0xeb, 0x14, 0xb8, + 0x65, 0xa9, 0x35, 0x38, 0x11, 0xc5, 0x92, 0x66, 0xe5, 0x3e, 0x37, 0x19, 0xa2, 0x8a, 0x1c, 0x4a, + 0x5d, 0x80, 0x11, 0xe4, 0x5a, 0x21, 0xcf, 0x3c, 0x43, 0x04, 0xe4, 0x5a, 0x92, 0xe3, 0x39, 0x98, + 0x0c, 0x31, 0x24, 0xbf, 0x41, 0x86, 0x36, 0x2e, 0xd1, 0x24, 0xb7, 0x73, 0x30, 0xd9, 0x34, 0xee, + 0xd9, 0xcd, 0x76, 0x93, 0x1f, 0x3a, 0x16, 0x1d, 0x86, 0x98, 0x87, 0x8c, 0x8b, 0x09, 0x7a, 0xec, + 0xba, 0xc5, 0x88, 0x42, 0xca, 0xe9, 0xbc, 0x96, 0x2b, 0x28, 0x13, 0x99, 0xea, 0xa7, 0x19, 0x58, + 0x3c, 0xda, 0x2a, 0x22, 0x72, 0xa4, 0xb0, 0x56, 0x52, 0x58, 0xa7, 0x65, 0xb3, 0x99, 0x47, 0x97, + 0xcd, 0x66, 0x1f, 0x49, 0x36, 0xbb, 0x08, 0x13, 0x52, 0x46, 0xd7, 0xb3, 0x10, 0xbb, 0xab, 0x73, + 0x0b, 0xd9, 0xc5, 0x6c, 0x20, 0xc2, 0x1b, 0x9e, 0x85, 0xb6, 0x2c, 0x5c, 0xbd, 0xaf, 0xc0, 0xdc, + 0x06, 0x22, 0x5a, 0x58, 0xcf, 0xed, 0xf0, 0x5a, 0x2e, 0xb8, 0x62, 0xb6, 0x61, 0x90, 0x69, 0x43, + 0x86, 0xd4, 0xf4, 0xab, 0x3c, 0x52, 0x10, 0x52, 0xf9, 0x22, 0xfc, 0x98, 0xd6, 0x34, 0xc1, 0x83, + 0x3a, 0xbf, 0x2c, 0xfd, 0xa8, 0xc3, 0xcb, 0xac, 0x52, 0xc0, 0x68, 0x0e, 0x50, 0xfd, 0x24, 0x03, + 0x95, 0x6e, 0x22, 0x09, 0x5b, 0xfd, 0x0f, 0x8c, 0xf1, 0x58, 0x22, 0x0a, 0x4f, 0x29, 0xdb, 0xcd, + 0xbe, 0xc2, 0x7d, 0x6f, 0xe6, 0xfc, 0x12, 0x96, 0xd0, 0x75, 0x97, 0xf8, 0x87, 0x1a, 0xcf, 0x8b, + 0x24, 0xac, 0x7c, 0x08, 0x6a, 0x27, 0x92, 0x3a, 0x01, 0xd9, 0xdb, 0xe8, 0x50, 0xc4, 0x36, 0xfa, + 0x53, 0xdd, 0x81, 0xfc, 0x81, 0xe1, 0xb4, 0x91, 0x38, 0xc2, 0x17, 0x8f, 0xa9, 0xb9, 0x40, 0x32, + 0xce, 0xe5, 0xe5, 0xcc, 0x25, 0xa5, 0xfa, 0x99, 0x02, 0x67, 0x36, 0x10, 0x09, 0x92, 0xa5, 0x1e, + 0x86, 0x7b, 0x09, 0x4e, 0x39, 0x06, 0x6b, 0x51, 0x11, 0xdf, 0x46, 0x07, 0x28, 0xd0, 0x96, 0x8c, + 0xc0, 0x59, 0xed, 0x24, 0x45, 0xd0, 0xe4, 0xbc, 0x60, 0xb0, 0x65, 0x05, 0xa4, 0x2d, 0xdf, 0x33, + 0x11, 0xc6, 0x71, 0xd2, 0x4c, 0x48, 0xfa, 0x96, 0x9c, 0x0f, 0x49, 0x93, 0x06, 0xce, 0x76, 0x1a, + 0xf8, 0x7f, 0x59, 0xac, 0xec, 0xbd, 0x05, 0x61, 0xe8, 0x5d, 0x28, 0x44, 0x4c, 0xfc, 0x50, 0x4a, + 0x0c, 0x18, 0x55, 0x3f, 0x80, 0x85, 0x0d, 0x44, 0xd6, 0xb6, 0xaf, 0xf7, 0x50, 0xde, 0x4d, 0x91, + 0xf5, 0xd0, 0x0c, 0x4e, 0x7a, 0xd7, 0x71, 0x97, 0xa6, 0x37, 0x04, 0x4f, 0xe6, 0x88, 0xf8, 0x85, + 0xab, 0x3f, 0x53, 0xe0, 0xc9, 0x1e, 0x8b, 0x8b, 0x6d, 0xbf, 0x07, 0x93, 0x11, 0xb6, 0x7a, 0x34, + 0xa3, 0x79, 0xfe, 0xdf, 0x10, 0x42, 0x9b, 0xf0, 0xe3, 0x00, 0x5c, 0xfd, 0x42, 0x81, 0x29, 0x0d, + 0x19, 0xad, 0x96, 0x73, 0xc8, 0x82, 0x31, 0xee, 0x76, 0x3b, 0xe5, 0x3a, 0x6f, 0xa7, 0xf4, 0x0a, + 0x25, 0xf3, 0xf0, 0x15, 0x8a, 0x7a, 0x09, 0x06, 0xd9, 0x95, 0x81, 0x45, 0x1c, 0x3c, 0x3a, 0xa4, + 0x0a, 0x7c, 0x11, 0xf0, 0x67, 0x60, 0x3a, 0xb1, 0x29, 0x71, 0x3f, 0xff, 0x33, 0x03, 0xe5, 0xab, + 0x96, 0xb5, 0x8b, 0x0c, 0xdf, 0xdc, 0xbf, 0x4a, 0x88, 0x6f, 0xd7, 0xdb, 0x24, 0xb4, 0xf6, 0x4f, + 0x14, 0x98, 0xc4, 0x6c, 0x4e, 0x37, 0x82, 0x49, 0xa1, 0xf0, 0xb7, 0xfb, 0x8a, 0x29, 0xdd, 0x99, + 0xd7, 0x92, 0x70, 0x1e, 0x52, 0x26, 0x70, 0x02, 0x4c, 0xd3, 0x63, 0xdb, 0xb5, 0xd0, 0xbd, 0x68, + 0x60, 0x2c, 0x32, 0x08, 0x3d, 0x2a, 0xea, 0x79, 0x50, 0xf1, 0x6d, 0xbb, 0xa5, 0x63, 0x73, 0x1f, + 0x35, 0x0d, 0xbd, 0xdd, 0xb2, 0x64, 0xad, 0x5d, 0xd0, 0x26, 0xe8, 0xcc, 0x2e, 0x9b, 0x78, 0x9b, + 0xc1, 0xe3, 0x35, 0x66, 0x2e, 0x51, 0x63, 0x96, 0x1d, 0x98, 0x4e, 0x95, 0x2a, 0x1a, 0xc3, 0x8a, + 0x3c, 0x86, 0x5d, 0x8e, 0xc6, 0xb0, 0xb1, 0xe5, 0x67, 0xe2, 0x16, 0x09, 0x32, 0xb2, 0x2d, 0x2a, + 0x27, 0xb2, 0x6e, 0x52, 0x54, 0x96, 0x67, 0x46, 0x62, 0xd6, 0x1c, 0xcc, 0xa6, 0xaa, 0x47, 0xd8, + 0xe6, 0x23, 0x05, 0xe6, 0x78, 0x4a, 0xd5, 0xcd, 0x3c, 0xcf, 0x76, 0xb3, 0x4e, 0xf1, 0xf8, 0x6a, + 0xec, 0x59, 0x7c, 0x57, 0x17, 0xa0, 0xd2, 0x4d, 0x14, 0x21, 0xed, 0x7f, 0x43, 0x99, 0xd6, 0x7b, + 0x5d, 0x24, 0x8d, 0x2f, 0xae, 0xf4, 0x5c, 0x3c, 0x93, 0x5c, 0xfc, 0x93, 0x41, 0x98, 0x4d, 0xe5, + 0x2d, 0xa2, 0xc2, 0x87, 0x0a, 0x4c, 0x9a, 0x6d, 0x4c, 0xbc, 0x66, 0xa7, 0x97, 0xf6, 0x7d, 0xf3, + 0x75, 0xe3, 0x5e, 0x5b, 0x65, 0x9c, 0x3b, 0xdc, 0xd4, 0x4c, 0x80, 0x99, 0x14, 0xf8, 0x10, 0x13, + 0x14, 0x93, 0x22, 0xf3, 0x88, 0xa4, 0xd8, 0x65, 0x9c, 0x3b, 0x0f, 0x4b, 0x02, 0xac, 0x36, 0x60, + 0xa8, 0x69, 0xb4, 0x5a, 0xb6, 0xdb, 0x10, 0xbd, 0xc4, 0x9d, 0x87, 0x5e, 0x7a, 0x87, 0xf3, 0xe3, + 0x2b, 0x4a, 0xee, 0xaa, 0x0b, 0xb3, 0x86, 0x65, 0xe9, 0x9d, 0x01, 0x8f, 0x17, 0xf7, 0xbc, 0x8c, + 0x58, 0x8a, 0x9f, 0x0a, 0x89, 0x9c, 0x1a, 0xf7, 0xd8, 0x8d, 0x50, 0x32, 0x2c, 0x2b, 0x75, 0x86, + 0x1e, 0xcd, 0x54, 0x4b, 0x3c, 0x96, 0xa3, 0xc9, 0x02, 0x41, 0x9a, 0xc6, 0x1f, 0xcf, 0x6a, 0x2f, + 0xc3, 0x48, 0x54, 0xc9, 0x29, 0x8b, 0x4c, 0x45, 0x17, 0x29, 0x46, 0x83, 0xc8, 0x2b, 0x70, 0x52, + 0xf6, 0xae, 0x56, 0x79, 0x2e, 0x11, 0xb9, 0xb1, 0x62, 0x19, 0x87, 0xd2, 0x99, 0x71, 0xfc, 0x69, + 0x08, 0x66, 0x3a, 0xa8, 0xc5, 0xa9, 0xfa, 0x3f, 0x98, 0xc4, 0xed, 0x56, 0xcb, 0xf3, 0x09, 0xb2, + 0x74, 0xd3, 0xb1, 0xd9, 0xf5, 0xc3, 0x0f, 0x95, 0xd6, 0x97, 0x4f, 0x75, 0x61, 0x5c, 0xdb, 0x95, + 0x5c, 0x57, 0x39, 0x53, 0xe9, 0xca, 0x09, 0xb0, 0xfa, 0x34, 0x8c, 0x71, 0xee, 0x41, 0xa1, 0xc4, + 0x37, 0x3f, 0xca, 0xa1, 0xb2, 0x4c, 0xba, 0x05, 0xe3, 0x4d, 0xd4, 0xac, 0x23, 0x1f, 0xef, 0xdb, + 0x2d, 0xee, 0x7c, 0xbd, 0x8a, 0x05, 0xf9, 0x96, 0x74, 0x70, 0xa1, 0xb6, 0x13, 0x90, 0xf1, 0xae, + 0x5a, 0x33, 0x36, 0xa6, 0x31, 0x4b, 0xea, 0x2f, 0xb8, 0xef, 0x8b, 0x02, 0x92, 0x92, 0xd0, 0xe5, + 0x3b, 0xd4, 0x4b, 0xeb, 0x47, 0x59, 0x6e, 0xf0, 0xb4, 0xdc, 0xf4, 0xda, 0x2e, 0x61, 0xf5, 0x5e, + 0x5e, 0x9b, 0x14, 0x53, 0x2c, 0x63, 0x5e, 0xa5, 0x13, 0x34, 0x9e, 0x47, 0x1a, 0x5f, 0x3a, 0x9d, + 0xe6, 0x15, 0x5f, 0x51, 0x9b, 0x88, 0x4c, 0xec, 0x52, 0xb8, 0x7a, 0x16, 0x26, 0x22, 0xb5, 0x3b, + 0xc7, 0x2d, 0x30, 0xdc, 0x48, 0x4d, 0xcf, 0x51, 0x37, 0x60, 0x44, 0xd6, 0x53, 0x4c, 0x3f, 0x45, + 0xa6, 0x9f, 0xd3, 0x71, 0x4f, 0x15, 0x18, 0x91, 0x2a, 0x8a, 0x69, 0x65, 0xf8, 0x20, 0x1c, 0xa8, + 0xaf, 0x42, 0x79, 0xcf, 0xb0, 0x1d, 0x2f, 0x62, 0x14, 0xdd, 0x76, 0x4d, 0x1f, 0x35, 0x91, 0x4b, + 0x4a, 0xc0, 0x12, 0xe0, 0x92, 0xc4, 0x08, 0xb8, 0x88, 0x79, 0xf5, 0x12, 0x94, 0x6c, 0xd7, 0x26, + 0xb6, 0xe1, 0xe8, 0x49, 0x2e, 0xa5, 0x61, 0x9e, 0x3c, 0x8b, 0xf9, 0xd7, 0xe2, 0x2c, 0xd4, 0xcb, + 0x30, 0x6b, 0x63, 0xbd, 0xe1, 0x78, 0x75, 0xc3, 0xd1, 0xc3, 0x34, 0x0c, 0xb9, 0x46, 0xdd, 0x41, + 0x56, 0x69, 0x84, 0x5d, 0xf6, 0x25, 0x1b, 0x6f, 0x30, 0x8c, 0x20, 0x83, 0x5e, 0xe7, 0xf3, 0xea, + 0x3b, 0x90, 0x23, 0x46, 0x03, 0x97, 0x46, 0x99, 0xf7, 0xbe, 0xf6, 0x50, 0xde, 0x7b, 0xc3, 0x68, + 0x08, 0x8f, 0x65, 0x3c, 0xcb, 0xab, 0x30, 0x9d, 0xea, 0xd0, 0xc7, 0x39, 0xc4, 0xe5, 0x8b, 0x50, + 0x0c, 0xf8, 0x1e, 0xeb, 0xf4, 0xbf, 0x03, 0x27, 0xb6, 0x6d, 0x4c, 0x84, 0x90, 0xc1, 0x75, 0x3b, + 0x0b, 0xc5, 0xb0, 0x65, 0xc0, 0x0b, 0xaf, 0x42, 0xab, 0x47, 0xaf, 0x20, 0xb5, 0x93, 0xf7, 0x4b, + 0x05, 0xa6, 0xe2, 0xcc, 0x45, 0x64, 0x78, 0x13, 0x0a, 0xc2, 0xcb, 0x7b, 0x27, 0xdf, 0x89, 0x26, + 0xae, 0xe0, 0xb3, 0x23, 0x5e, 0x36, 0xb5, 0x80, 0x49, 0xdf, 0x12, 0xfd, 0x5a, 0x81, 0xf9, 0xab, + 0x96, 0xf5, 0xa6, 0xcf, 0x93, 0x39, 0x9a, 0x91, 0x90, 0x64, 0xd4, 0x3b, 0x0b, 0x13, 0x7b, 0xbe, + 0xe7, 0x12, 0xe4, 0x5a, 0x89, 0x67, 0x88, 0x71, 0x09, 0x97, 0x4f, 0x11, 0x1b, 0xb0, 0xc0, 0x3d, + 0x48, 0xf7, 0x19, 0x27, 0x5d, 0x9e, 0x67, 0xd3, 0x73, 0x5d, 0x64, 0x06, 0xd9, 0x7b, 0x41, 0x9b, + 0xe3, 0x78, 0xb1, 0x05, 0x57, 0x03, 0xa4, 0x6a, 0x15, 0x16, 0xba, 0x8b, 0x25, 0xf2, 0xa3, 0x2b, + 0x50, 0xe6, 0x19, 0x54, 0xaa, 0xd4, 0x7d, 0xc4, 0x6a, 0xf6, 0xac, 0x99, 0xc2, 0x20, 0xec, 0xb4, + 0x9d, 0x8a, 0x58, 0x4b, 0xc4, 0x36, 0xc9, 0x7f, 0x17, 0xa6, 0x59, 0xe1, 0xba, 0x8f, 0x0c, 0x9f, + 0xd4, 0x91, 0x41, 0xf4, 0xbb, 0x36, 0xd9, 0xb7, 0x5d, 0x51, 0x3c, 0x9e, 0xea, 0x68, 0xf7, 0xad, + 0x89, 0x2f, 0x2b, 0x56, 0x72, 0x1f, 0x7f, 0x3d, 0xaf, 0x68, 0x27, 0x28, 0xf5, 0xa6, 0x24, 0xbe, + 0xc5, 0x68, 0xd5, 0x79, 0x18, 0xf6, 0x5b, 0x66, 0xa0, 0x65, 0xd1, 0xbe, 0xf5, 0x5b, 0xa6, 0x54, + 0xf0, 0x0c, 0x0c, 0xb1, 0xe7, 0xa0, 0xa0, 0x7f, 0x3b, 0x48, 0x87, 0xac, 0x4f, 0x9b, 0xf3, 0x3d, + 0x87, 0x27, 0xe0, 0x63, 0xd1, 0x2c, 0x21, 0xad, 0xa9, 0x19, 0xdb, 0x91, 0xe6, 0x39, 0x48, 0x63, + 0xc4, 0xea, 0xbb, 0x50, 0xc6, 0x08, 0xb3, 0x18, 0xc4, 0x5a, 0x71, 0xc8, 0xd2, 0x8d, 0x3d, 0xaa, + 0x41, 0xd6, 0xc7, 0xcc, 0xf7, 0xd9, 0xc7, 0x9c, 0x11, 0x3c, 0x76, 0x39, 0x8b, 0xab, 0x94, 0x03, + 0xeb, 0xe3, 0xc6, 0xce, 0xd0, 0xe0, 0xd1, 0x67, 0x68, 0x28, 0xcd, 0x63, 0x3f, 0x51, 0xa0, 0x9c, + 0x66, 0x15, 0x71, 0x92, 0x6e, 0xc0, 0x98, 0x61, 0x12, 0xfb, 0x00, 0xe9, 0xe2, 0xee, 0x11, 0xe7, + 0xe9, 0xb9, 0xa3, 0xae, 0xae, 0xb8, 0x4e, 0x46, 0x39, 0x13, 0xc1, 0xbd, 0xef, 0xe3, 0xf4, 0xfb, + 0x0c, 0x4c, 0xf3, 0x9a, 0x3b, 0x59, 0xe5, 0xaf, 0x43, 0x8e, 0xb5, 0xd0, 0x15, 0x66, 0x9f, 0x0b, + 0xbd, 0xed, 0xb3, 0x86, 0x0c, 0x6b, 0x1b, 0x11, 0x82, 0xfc, 0xeb, 0x6d, 0x24, 0x92, 0x1b, 0x46, + 0xde, 0xeb, 0xad, 0x8f, 0x5e, 0xee, 0x5e, 0xdb, 0x37, 0x83, 0x43, 0x27, 0x3c, 0x64, 0x94, 0x43, + 0xc5, 0xfe, 0xd4, 0x8b, 0xf4, 0xca, 0xa0, 0x18, 0x54, 0x47, 0xf4, 0x48, 0x47, 0xfa, 0x2d, 0xbc, + 0x0d, 0x3b, 0x1d, 0xcc, 0xaf, 0xbb, 0x91, 0x76, 0x4b, 0x6a, 0xf3, 0x34, 0xdf, 0x77, 0xf3, 0x74, + 0x30, 0x4d, 0x5f, 0x5f, 0x66, 0xe0, 0x64, 0x52, 0x5f, 0xc2, 0x90, 0x8f, 0x48, 0x61, 0xa9, 0xfd, + 0x8d, 0xcc, 0x23, 0xec, 0x6f, 0xa4, 0xed, 0x35, 0x9b, 0xd6, 0xcd, 0x6d, 0xc2, 0xc9, 0x0e, 0x49, + 0x64, 0x66, 0xff, 0x50, 0x3d, 0x9f, 0xa9, 0xa4, 0x48, 0xec, 0x2d, 0xef, 0xaf, 0x0a, 0xcc, 0xbc, + 0xd5, 0xf6, 0x1b, 0xe8, 0xc7, 0xe8, 0x8c, 0xd5, 0x32, 0x94, 0x3a, 0x37, 0x27, 0xe2, 0xf6, 0x1f, + 0x32, 0x30, 0xb3, 0x83, 0x7e, 0xa4, 0x3b, 0x7f, 0x2c, 0xc7, 0x70, 0x05, 0x4a, 0x9d, 0x0a, 0x3b, + 0xde, 0x63, 0x05, 0xcd, 0x6d, 0x66, 0x35, 0xb4, 0xe7, 0x23, 0xbc, 0x2f, 0xcb, 0xcd, 0xd8, 0xfb, + 0x71, 0xb2, 0xdb, 0x97, 0x7d, 0x7c, 0x6f, 0x51, 0xa2, 0x45, 0x57, 0x81, 0x27, 0xd2, 0x05, 0x0a, + 0xfd, 0x64, 0x4e, 0x43, 0x18, 0xb9, 0x56, 0xe2, 0x54, 0x75, 0x95, 0xf9, 0x11, 0x3e, 0xb8, 0x3e, + 0x0d, 0x63, 0xf1, 0x14, 0x49, 0x94, 0x43, 0xa3, 0x7e, 0x34, 0x17, 0x49, 0x79, 0x55, 0xcb, 0xa7, + 0xbc, 0xaa, 0x3d, 0x05, 0xa3, 0x1c, 0x2b, 0xfe, 0xfe, 0xc5, 0x91, 0xba, 0x3d, 0xa5, 0x0d, 0x75, + 0x3c, 0xa5, 0xcd, 0xc3, 0x30, 0xc5, 0x90, 0x4c, 0x0a, 0x01, 0x82, 0x60, 0xc1, 0x7b, 0x56, 0xe9, + 0x0a, 0x13, 0x3a, 0xfd, 0x5d, 0x06, 0x4a, 0x1b, 0x88, 0x50, 0x20, 0x3f, 0x33, 0x51, 0x75, 0xf6, + 0xfe, 0x14, 0x69, 0x4e, 0xf4, 0xc1, 0xd9, 0xf7, 0xa0, 0xb2, 0x65, 0x45, 0x24, 0x23, 0x75, 0x1b, + 0xc6, 0xc3, 0x69, 0xfe, 0x1c, 0x9d, 0x65, 0x87, 0xf8, 0x74, 0x97, 0xf6, 0x40, 0x28, 0x03, 0x3d, + 0xb7, 0xa3, 0x24, 0x3a, 0x54, 0x2b, 0x30, 0xdc, 0xb4, 0x79, 0x10, 0x0e, 0x4f, 0x5c, 0xb1, 0x69, + 0xf3, 0xa8, 0x6a, 0xb1, 0x79, 0xe3, 0x5e, 0x30, 0x9f, 0x17, 0xf3, 0xc6, 0x3d, 0x31, 0x1f, 0xff, + 0xc0, 0x60, 0xb0, 0x8f, 0x0f, 0x0c, 0x52, 0x93, 0x99, 0xfb, 0x0a, 0x9c, 0x4a, 0x51, 0x97, 0x38, + 0x7a, 0xaf, 0xc7, 0xbf, 0x30, 0x78, 0xb1, 0x9f, 0x92, 0xe0, 0xaa, 0xe3, 0x78, 0xa6, 0x41, 0x90, + 0x15, 0x5c, 0x0f, 0xc7, 0xfc, 0xda, 0xe0, 0xe7, 0x0a, 0x54, 0xd6, 0x90, 0x83, 0x08, 0xfa, 0x81, + 0x3f, 0xe6, 0xab, 0x5e, 0x86, 0xf9, 0xae, 0x82, 0x08, 0x0d, 0x95, 0xa1, 0x70, 0xd7, 0xf0, 0x5d, + 0xdb, 0x6d, 0xc8, 0x2e, 0x6d, 0x30, 0xae, 0xfe, 0x56, 0x81, 0xc5, 0x5d, 0xe2, 0x23, 0xa3, 0x29, + 0xe9, 0x7b, 0x3c, 0xc2, 0xb4, 0xe0, 0x24, 0x3e, 0x74, 0x4d, 0x3d, 0x7a, 0x43, 0xf3, 0xaf, 0xbe, + 0x94, 0x1e, 0x5f, 0x7d, 0x25, 0x2e, 0xe7, 0xdd, 0x43, 0xd7, 0x8c, 0xac, 0xc1, 0xbe, 0xef, 0xda, + 0x1c, 0xd0, 0xa6, 0x70, 0x0a, 0x7c, 0x65, 0x04, 0x20, 0x6c, 0x6a, 0x56, 0x3f, 0x56, 0xe0, 0x6c, + 0x1f, 0xc2, 0x8a, 0x6d, 0xbf, 0xdb, 0xf1, 0x56, 0x75, 0xa5, 0x1f, 0xf9, 0x7a, 0xb0, 0xde, 0x1c, + 0x08, 0x5f, 0xad, 0x12, 0xa2, 0xbd, 0x0d, 0x27, 0xe2, 0x6f, 0x68, 0x5c, 0x63, 0x95, 0x0e, 0x27, + 0xd8, 0x1c, 0x88, 0xba, 0xc1, 0x04, 0x64, 0x64, 0x3c, 0xdc, 0x1c, 0xd0, 0x32, 0xb6, 0x95, 0x60, + 0xfb, 0x55, 0x16, 0xa6, 0xe2, 0x7c, 0xc5, 0xe6, 0x5e, 0x85, 0x5c, 0xa4, 0xe5, 0xb4, 0x18, 0x77, + 0x9d, 0xf4, 0xef, 0xb8, 0x98, 0x9f, 0x33, 0x2a, 0x75, 0x05, 0x06, 0x4d, 0xcf, 0xdd, 0xb3, 0x1b, + 0xa2, 0x5f, 0x7a, 0xae, 0x1f, 0xfa, 0x55, 0x46, 0xa1, 0x09, 0x4a, 0x75, 0x0f, 0xd4, 0xa8, 0x1f, + 0x08, 0x7e, 0xf9, 0xe4, 0xa3, 0x60, 0x8a, 0x86, 0xd3, 0x5e, 0x1a, 0x05, 0xf3, 0x68, 0x1a, 0xca, + 0x41, 0xf4, 0x0e, 0xe0, 0xbc, 0x13, 0x71, 0x7b, 0x94, 0x43, 0x65, 0xe0, 0xa6, 0xf5, 0x77, 0xb2, + 0xb9, 0xc3, 0x83, 0xf7, 0x78, 0xa2, 0x31, 0xa4, 0xde, 0x8c, 0xa0, 0xca, 0x77, 0xfe, 0x02, 0x0b, + 0x1e, 0xcf, 0xf6, 0x94, 0x5b, 0x76, 0x87, 0xa8, 0x6b, 0xb6, 0x71, 0xc8, 0x57, 0xbe, 0xf2, 0xd7, + 0xe0, 0x44, 0x4a, 0xb7, 0x88, 0x75, 0xbd, 0x0a, 0xda, 0x64, 0x47, 0x97, 0xa8, 0xfa, 0xa9, 0x02, + 0x2a, 0xcf, 0xeb, 0x63, 0x17, 0xc0, 0x3a, 0x0c, 0x59, 0xce, 0x1d, 0x5d, 0xf6, 0x62, 0x86, 0x97, + 0xcf, 0xa7, 0x57, 0x65, 0x41, 0x7c, 0x10, 0xeb, 0xaf, 0x6d, 0x5f, 0x7f, 0x1d, 0x1d, 0x6a, 0x83, + 0x96, 0x73, 0xe7, 0x75, 0x74, 0x18, 0xaf, 0x23, 0x33, 0x47, 0xd7, 0x91, 0x69, 0xe9, 0x78, 0xf5, + 0x23, 0x85, 0xf9, 0x75, 0x28, 0xa2, 0x70, 0xbf, 0x6b, 0x50, 0xa4, 0x32, 0x46, 0x03, 0xef, 0x73, + 0x7d, 0x4b, 0xc9, 0x4a, 0x84, 0x82, 0xe5, 0xdc, 0xb9, 0x71, 0xac, 0x98, 0xfb, 0x85, 0x02, 0x53, + 0x32, 0x9d, 0x7d, 0x1c, 0x0a, 0x23, 0x30, 0x1b, 0x26, 0x9b, 0xc1, 0xbd, 0x26, 0x3f, 0x88, 0x17, + 0x41, 0xfa, 0xc5, 0x63, 0xed, 0x32, 0xe8, 0x39, 0x85, 0x69, 0xec, 0x0e, 0xbf, 0x1d, 0xe5, 0x4c, + 0xf5, 0x05, 0x98, 0x4e, 0x6c, 0x4a, 0xa8, 0x78, 0x16, 0x8a, 0xef, 0x7b, 0xf5, 0x58, 0x32, 0x59, + 0x78, 0xdf, 0xab, 0x73, 0x5d, 0xac, 0xc3, 0xf0, 0xda, 0xf6, 0xf5, 0x6b, 0x62, 0x98, 0xcc, 0xaf, + 0x94, 0x1e, 0xf9, 0x55, 0x26, 0x92, 0x5f, 0xad, 0x38, 0x9f, 0x7f, 0x53, 0x19, 0xf8, 0xf2, 0x9b, + 0xca, 0xc0, 0x77, 0xdf, 0x54, 0x94, 0xff, 0x7f, 0x50, 0x51, 0x7e, 0xf3, 0xa0, 0xa2, 0xfc, 0xf9, + 0x41, 0x45, 0xf9, 0xfc, 0x41, 0x45, 0xf9, 0xfb, 0x83, 0x8a, 0xf2, 0x8f, 0x07, 0x95, 0x81, 0xef, + 0x1e, 0x54, 0x94, 0xfb, 0xdf, 0x56, 0x06, 0x3e, 0xff, 0xb6, 0x32, 0xf0, 0xe5, 0xb7, 0x95, 0x81, + 0x77, 0xfe, 0xb3, 0xe1, 0x85, 0x5a, 0xb0, 0xbd, 0x1e, 0x7f, 0xcb, 0x79, 0x25, 0x3a, 0xae, 0x0f, + 0xb2, 0x66, 0xc8, 0xf3, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x08, 0x0a, 0xfc, 0x0e, 0xd1, 0x33, + 0x00, 0x00, } func (this *RebuildMutableStateRequest) Equal(that interface{}) bool { @@ -6126,6 +6282,84 @@ func (this *GetDLQTasksResponse) Equal(that interface{}) bool { } return true } +func (this *PurgeDLQTasksRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PurgeDLQTasksRequest) + if !ok { + that2, ok := that.(PurgeDLQTasksRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.DlqKey.Equal(that1.DlqKey) { + return false + } + if !this.InclusiveMaxTaskMetadata.Equal(that1.InclusiveMaxTaskMetadata) { + return false + } + return true +} +func (this *PurgeDLQTasksResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PurgeDLQTasksResponse) + if !ok { + that2, ok := that.(PurgeDLQTasksResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.JobToken, that1.JobToken) { + return false + } + return true +} +func (this *DLQJobToken) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*DLQJobToken) + if !ok { + that2, ok := that.(DLQJobToken) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.WorkflowId != that1.WorkflowId { + return false + } + if this.RunId != that1.RunId { + return false + } + return true +} func (this *RebuildMutableStateRequest) GoString() string { if this == nil { return "nil" @@ -7057,6 +7291,42 @@ func (this *GetDLQTasksResponse) GoString() string { s = append(s, "}") return strings.Join(s, "") } +func (this *PurgeDLQTasksRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&adminservice.PurgeDLQTasksRequest{") + if this.DlqKey != nil { + s = append(s, "DlqKey: "+fmt.Sprintf("%#v", this.DlqKey)+",\n") + } + if this.InclusiveMaxTaskMetadata != nil { + s = append(s, "InclusiveMaxTaskMetadata: "+fmt.Sprintf("%#v", this.InclusiveMaxTaskMetadata)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *PurgeDLQTasksResponse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&adminservice.PurgeDLQTasksResponse{") + s = append(s, "JobToken: "+fmt.Sprintf("%#v", this.JobToken)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *DLQJobToken) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&adminservice.DLQJobToken{") + s = append(s, "WorkflowId: "+fmt.Sprintf("%#v", this.WorkflowId)+",\n") + s = append(s, "RunId: "+fmt.Sprintf("%#v", this.RunId)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} func valueToGoStringRequestResponse(v interface{}, typ string) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -10014,48 +10284,162 @@ func (m *GetDLQTasksResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarintRequestResponse(dAtA []byte, offset int, v uint64) int { - offset -= sovRequestResponse(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *PurgeDLQTasksRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *RebuildMutableStateRequest) Size() (n int) { - if m == nil { - return 0 - } + +func (m *PurgeDLQTasksRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PurgeDLQTasksRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.Namespace) - if l > 0 { - n += 1 + l + sovRequestResponse(uint64(l)) + if m.InclusiveMaxTaskMetadata != nil { + { + size, err := m.InclusiveMaxTaskMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRequestResponse(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 } - if m.Execution != nil { - l = m.Execution.Size() - n += 1 + l + sovRequestResponse(uint64(l)) + if m.DlqKey != nil { + { + size, err := m.DlqKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRequestResponse(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *RebuildMutableStateResponse) Size() (n int) { - if m == nil { - return 0 +func (m *PurgeDLQTasksResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - var l int - _ = l - return n + return dAtA[:n], nil } -func (m *ImportWorkflowExecutionRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int +func (m *PurgeDLQTasksResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PurgeDLQTasksResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.JobToken) > 0 { + i -= len(m.JobToken) + copy(dAtA[i:], m.JobToken) + i = encodeVarintRequestResponse(dAtA, i, uint64(len(m.JobToken))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *DLQJobToken) 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 *DLQJobToken) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DLQJobToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RunId) > 0 { + i -= len(m.RunId) + copy(dAtA[i:], m.RunId) + i = encodeVarintRequestResponse(dAtA, i, uint64(len(m.RunId))) + i-- + dAtA[i] = 0x12 + } + if len(m.WorkflowId) > 0 { + i -= len(m.WorkflowId) + copy(dAtA[i:], m.WorkflowId) + i = encodeVarintRequestResponse(dAtA, i, uint64(len(m.WorkflowId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintRequestResponse(dAtA []byte, offset int, v uint64) int { + offset -= sovRequestResponse(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *RebuildMutableStateRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Namespace) + if l > 0 { + n += 1 + l + sovRequestResponse(uint64(l)) + } + if m.Execution != nil { + l = m.Execution.Size() + n += 1 + l + sovRequestResponse(uint64(l)) + } + return n +} + +func (m *RebuildMutableStateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *ImportWorkflowExecutionRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int _ = l l = len(m.Namespace) if l > 0 { @@ -11321,6 +11705,53 @@ func (m *GetDLQTasksResponse) Size() (n int) { return n } +func (m *PurgeDLQTasksRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DlqKey != nil { + l = m.DlqKey.Size() + n += 1 + l + sovRequestResponse(uint64(l)) + } + if m.InclusiveMaxTaskMetadata != nil { + l = m.InclusiveMaxTaskMetadata.Size() + n += 1 + l + sovRequestResponse(uint64(l)) + } + return n +} + +func (m *PurgeDLQTasksResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.JobToken) + if l > 0 { + n += 1 + l + sovRequestResponse(uint64(l)) + } + return n +} + +func (m *DLQJobToken) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.WorkflowId) + if l > 0 { + n += 1 + l + sovRequestResponse(uint64(l)) + } + l = len(m.RunId) + if l > 0 { + n += 1 + l + sovRequestResponse(uint64(l)) + } + return n +} + func sovRequestResponse(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -12237,6 +12668,38 @@ func (this *GetDLQTasksResponse) String() string { }, "") return s } +func (this *PurgeDLQTasksRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PurgeDLQTasksRequest{`, + `DlqKey:` + strings.Replace(fmt.Sprintf("%v", this.DlqKey), "HistoryDLQKey", "v112.HistoryDLQKey", 1) + `,`, + `InclusiveMaxTaskMetadata:` + strings.Replace(fmt.Sprintf("%v", this.InclusiveMaxTaskMetadata), "HistoryDLQTaskMetadata", "v112.HistoryDLQTaskMetadata", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PurgeDLQTasksResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PurgeDLQTasksResponse{`, + `JobToken:` + fmt.Sprintf("%v", this.JobToken) + `,`, + `}`, + }, "") + return s +} +func (this *DLQJobToken) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&DLQJobToken{`, + `WorkflowId:` + fmt.Sprintf("%v", this.WorkflowId) + `,`, + `RunId:` + fmt.Sprintf("%v", this.RunId) + `,`, + `}`, + }, "") + return s +} func valueToStringRequestResponse(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -21186,6 +21649,335 @@ func (m *GetDLQTasksResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *PurgeDLQTasksRequest) 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 ErrIntOverflowRequestResponse + } + 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: PurgeDLQTasksRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PurgeDLQTasksRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DlqKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestResponse + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRequestResponse + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRequestResponse + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DlqKey == nil { + m.DlqKey = &v112.HistoryDLQKey{} + } + if err := m.DlqKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InclusiveMaxTaskMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestResponse + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRequestResponse + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRequestResponse + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.InclusiveMaxTaskMetadata == nil { + m.InclusiveMaxTaskMetadata = &v112.HistoryDLQTaskMetadata{} + } + if err := m.InclusiveMaxTaskMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestResponse(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PurgeDLQTasksResponse) 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 ErrIntOverflowRequestResponse + } + 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: PurgeDLQTasksResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PurgeDLQTasksResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field JobToken", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestResponse + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthRequestResponse + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthRequestResponse + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.JobToken = append(m.JobToken[:0], dAtA[iNdEx:postIndex]...) + if m.JobToken == nil { + m.JobToken = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestResponse(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DLQJobToken) 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 ErrIntOverflowRequestResponse + } + 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: DLQJobToken: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DLQJobToken: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WorkflowId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestResponse + } + 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 ErrInvalidLengthRequestResponse + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestResponse + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.WorkflowId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RunId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestResponse + } + 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 ErrInvalidLengthRequestResponse + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestResponse + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RunId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestResponse(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRequestResponse + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipRequestResponse(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/api/adminservice/v1/service.pb.go b/api/adminservice/v1/service.pb.go index a8c8606f93a..4641eb8d0f2 100644 --- a/api/adminservice/v1/service.pb.go +++ b/api/adminservice/v1/service.pb.go @@ -54,67 +54,68 @@ func init() { } var fileDescriptor_cf5ca5e0c737570d = []byte{ - // 949 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0xcb, 0x6b, 0x23, 0x37, - 0x1c, 0xc7, 0xad, 0x4b, 0x29, 0x6a, 0xfa, 0x9a, 0x96, 0x3e, 0x72, 0x98, 0xbe, 0x28, 0xf4, 0x64, - 0x37, 0x69, 0x9b, 0xf7, 0xcb, 0xb1, 0x5d, 0xa7, 0xd4, 0x4e, 0x1b, 0xbb, 0x0f, 0xe8, 0xa5, 0xc8, - 0x9e, 0x5f, 0x92, 0x21, 0x63, 0xcf, 0x54, 0xd2, 0x38, 0xcd, 0xa9, 0xa5, 0x50, 0x28, 0x14, 0x4a, - 0x0b, 0x85, 0x42, 0x61, 0x4f, 0x0b, 0xcb, 0x2e, 0xec, 0xdf, 0xb0, 0xb0, 0xb7, 0x1c, 0x73, 0xcc, - 0x71, 0xe3, 0x5c, 0xf6, 0x98, 0xdb, 0x5e, 0x97, 0xc9, 0x58, 0xca, 0x8c, 0x2d, 0x67, 0xa5, 0x71, - 0x6e, 0x71, 0xac, 0xcf, 0x57, 0x9f, 0xd1, 0x48, 0xfa, 0x49, 0xc6, 0x33, 0x1c, 0x3a, 0x81, 0x4f, - 0x89, 0x57, 0x60, 0x40, 0x7b, 0x40, 0x0b, 0x24, 0x70, 0x0b, 0xc4, 0xe9, 0xb8, 0xdd, 0xe8, 0xb3, - 0xdb, 0x86, 0x42, 0x6f, 0xa6, 0x30, 0xf8, 0x33, 0x1f, 0x50, 0x9f, 0xfb, 0xd6, 0x07, 0x02, 0xc9, - 0xc7, 0x48, 0x9e, 0x04, 0x6e, 0x3e, 0x89, 0xe4, 0x7b, 0x33, 0xd3, 0x4b, 0x3a, 0xb9, 0x14, 0x7e, - 0x0a, 0x81, 0xf1, 0x1f, 0x29, 0xb0, 0xc0, 0xef, 0xb2, 0x41, 0x07, 0xb3, 0x4f, 0x3e, 0xc4, 0x53, - 0xc5, 0xa8, 0x69, 0x33, 0x6e, 0x6a, 0xfd, 0x8f, 0xf0, 0x6b, 0x0d, 0x68, 0x85, 0xae, 0xe7, 0xd4, - 0x43, 0x4e, 0x5a, 0x1e, 0x34, 0x39, 0xe1, 0x60, 0xad, 0xe7, 0x35, 0x54, 0xf2, 0x0a, 0xb2, 0x11, - 0x77, 0x3c, 0xbd, 0x91, 0x3d, 0x20, 0x36, 0x7e, 0x3f, 0x67, 0xdd, 0x41, 0xf8, 0xcd, 0x2f, 0xa2, - 0x10, 0xfe, 0xbd, 0x4f, 0x0f, 0x76, 0x3d, 0xff, 0xb0, 0xf2, 0x33, 0xb4, 0x43, 0xee, 0xfa, 0x5d, - 0xab, 0xa4, 0x95, 0x3f, 0x86, 0x16, 0x92, 0xe5, 0xc9, 0x42, 0xa4, 0xe8, 0x2d, 0x84, 0x5f, 0x2f, - 0x03, 0x6b, 0x53, 0xb7, 0x05, 0xa9, 0x61, 0xd4, 0x1b, 0x05, 0x15, 0x2a, 0x14, 0x8b, 0x13, 0x24, - 0x48, 0xbf, 0xe8, 0x2d, 0x8b, 0x26, 0x5b, 0x2e, 0xe3, 0x3e, 0x3d, 0xda, 0xf2, 0x19, 0xd7, 0x7c, - 0xcb, 0x0a, 0xd2, 0xec, 0x2d, 0x2b, 0x03, 0xa4, 0xdc, 0x11, 0x7e, 0xbe, 0x0a, 0xbc, 0xb9, 0x4f, - 0xa8, 0x63, 0x7d, 0xaa, 0x95, 0x27, 0x9a, 0x0b, 0x8b, 0xcf, 0x0c, 0x29, 0xd9, 0xf5, 0x2f, 0x18, - 0x97, 0x3c, 0x9f, 0x41, 0xdc, 0xf9, 0x9c, 0x56, 0xcc, 0x15, 0x20, 0xba, 0x9f, 0x37, 0xe6, 0xa4, - 0xc0, 0x3f, 0x08, 0xbf, 0x52, 0x73, 0x19, 0x1f, 0x8c, 0xcc, 0x37, 0x84, 0x1d, 0x30, 0x6b, 0x45, - 0x2b, 0x6f, 0x18, 0x13, 0x36, 0xab, 0x19, 0xe9, 0xe4, 0xa0, 0x34, 0xa0, 0xe3, 0xf7, 0x20, 0xfa, - 0x42, 0x73, 0x50, 0xae, 0x00, 0xb3, 0x41, 0x49, 0x72, 0x52, 0xe0, 0x21, 0xc2, 0xef, 0x56, 0x41, - 0xb1, 0xe0, 0xc8, 0xe1, 0x40, 0xf9, 0xbb, 0x59, 0xab, 0xa6, 0xfb, 0xce, 0xaf, 0x8d, 0x11, 0xb6, - 0xf5, 0x1b, 0x4a, 0x93, 0xcf, 0x70, 0x1b, 0xe1, 0x37, 0xaa, 0xc0, 0x1b, 0x10, 0x78, 0x6e, 0x9b, - 0x44, 0x0d, 0xeb, 0xc0, 0x18, 0xd9, 0x03, 0x66, 0x6d, 0xea, 0xf6, 0xa5, 0x80, 0x85, 0x6f, 0x69, - 0xa2, 0x0c, 0x69, 0xf9, 0x00, 0xe1, 0x77, 0xaa, 0xc0, 0xb7, 0x49, 0x07, 0x58, 0x40, 0xda, 0xa0, - 0xd2, 0xfd, 0x52, 0xb7, 0xab, 0xeb, 0x52, 0x84, 0x77, 0xed, 0x66, 0xc2, 0xe4, 0x03, 0xdc, 0x47, - 0xf8, 0xed, 0x2a, 0xf0, 0x72, 0x6d, 0x47, 0xa5, 0x5e, 0xd1, 0xed, 0x4d, 0xcd, 0x0b, 0xe9, 0xcf, - 0x27, 0x8d, 0x91, 0xba, 0x7f, 0x20, 0xfc, 0x62, 0x03, 0x48, 0x10, 0x78, 0x47, 0x95, 0x1e, 0x74, - 0x39, 0xb3, 0x16, 0x35, 0x97, 0x49, 0x82, 0x11, 0x5a, 0x4b, 0x59, 0xd0, 0x54, 0x49, 0x28, 0x3a, - 0x4e, 0x13, 0x08, 0x6d, 0xef, 0x17, 0x39, 0xa7, 0x6e, 0x2b, 0xe4, 0xc0, 0x34, 0x4b, 0x82, 0x82, - 0x34, 0x2b, 0x09, 0xca, 0x80, 0xd4, 0xea, 0x89, 0xb7, 0x86, 0x11, 0xbf, 0x4d, 0x83, 0x7d, 0x65, - 0x9c, 0x62, 0x69, 0xa2, 0x8c, 0xd4, 0x10, 0x46, 0x45, 0x25, 0xdb, 0x10, 0x2a, 0x48, 0xb3, 0x21, - 0x54, 0x06, 0x48, 0xb9, 0xbf, 0x10, 0x7e, 0x59, 0xd4, 0xdd, 0x92, 0x17, 0x32, 0x0e, 0xd4, 0x5a, - 0x36, 0xaa, 0xd6, 0x03, 0x4a, 0x48, 0xad, 0x64, 0x83, 0xa5, 0xd0, 0xef, 0x08, 0x4f, 0x45, 0x55, - 0x67, 0xf0, 0x0d, 0xb3, 0x16, 0xb4, 0x0b, 0x95, 0x40, 0x84, 0xca, 0x62, 0x06, 0x52, 0x7a, 0xfc, - 0x87, 0xb0, 0x95, 0xf8, 0xaa, 0x0e, 0x9d, 0x56, 0x64, 0xb3, 0x66, 0x9a, 0x39, 0x00, 0x85, 0xd3, - 0x7a, 0x66, 0x5e, 0x9a, 0xdd, 0x43, 0xf8, 0xad, 0xa2, 0xe3, 0x7c, 0x45, 0xbf, 0x0d, 0x9c, 0xcb, - 0xf3, 0x5b, 0xc7, 0xe7, 0xf2, 0xdd, 0x95, 0x75, 0x97, 0x95, 0x12, 0x17, 0x96, 0x95, 0x09, 0x53, - 0x52, 0x73, 0x3f, 0x5e, 0x20, 0x69, 0xcd, 0x75, 0x83, 0xa5, 0xa5, 0x34, 0xdc, 0xc8, 0x1e, 0x20, - 0xe5, 0xfe, 0x44, 0xf8, 0xa5, 0x78, 0x3b, 0x96, 0xa5, 0x60, 0xc9, 0x60, 0x0f, 0x1f, 0xde, 0xff, - 0x97, 0x33, 0xb1, 0xa9, 0x33, 0xde, 0xd7, 0x21, 0xdd, 0x83, 0xa4, 0x8f, 0xde, 0x6a, 0x1a, 0xc6, - 0xcc, 0xce, 0x78, 0xa3, 0x74, 0xca, 0xa9, 0x0e, 0x99, 0x9c, 0x86, 0x31, 0x33, 0xa7, 0x51, 0x3a, - 0x75, 0x89, 0x6a, 0xc0, 0x2e, 0x05, 0xb6, 0x2f, 0x4e, 0x59, 0xf1, 0x79, 0x58, 0x77, 0x4a, 0x8c, - 0xa2, 0x66, 0x97, 0x28, 0x75, 0xc2, 0x50, 0x51, 0x62, 0xd0, 0x75, 0x12, 0x45, 0x3e, 0x36, 0xd4, - 0x2d, 0x4a, 0x2a, 0xd8, 0xb4, 0x28, 0xa9, 0x33, 0xa4, 0xe5, 0xbf, 0x08, 0xbf, 0x5a, 0x05, 0x1e, - 0xfd, 0x7b, 0x27, 0x84, 0x10, 0x62, 0xc1, 0x55, 0xdd, 0x29, 0x9c, 0xe6, 0x84, 0xdb, 0x5a, 0x56, - 0x3c, 0x75, 0x95, 0x2f, 0x83, 0x07, 0x1c, 0xb2, 0x5e, 0xe5, 0xc7, 0xd0, 0x66, 0x57, 0xf9, 0xb1, - 0x21, 0x52, 0xf4, 0x18, 0xe1, 0xf7, 0x9a, 0x9c, 0x02, 0xe9, 0x88, 0x56, 0xaa, 0x93, 0xa5, 0xde, - 0x7d, 0xe1, 0x99, 0x39, 0x42, 0x7e, 0xfb, 0xa6, 0xe2, 0xc4, 0x63, 0x7c, 0x84, 0x3e, 0x46, 0x97, - 0x15, 0x37, 0x79, 0x94, 0xd6, 0xac, 0xb8, 0xe9, 0xd3, 0xb7, 0x49, 0xc5, 0x4d, 0x93, 0x72, 0x48, - 0x7f, 0x43, 0xf8, 0x85, 0x78, 0x77, 0x8c, 0x27, 0xe3, 0xbc, 0xc1, 0x7e, 0x9a, 0x9a, 0x86, 0x0b, - 0xe6, 0xa0, 0x90, 0xd8, 0xf4, 0x4e, 0xce, 0xec, 0xdc, 0xe9, 0x99, 0x9d, 0xbb, 0x38, 0xb3, 0xd1, - 0xaf, 0x7d, 0x1b, 0xdd, 0xed, 0xdb, 0xe8, 0xb8, 0x6f, 0xa3, 0x93, 0xbe, 0x8d, 0x1e, 0xf5, 0x6d, - 0xf4, 0xb8, 0x6f, 0xe7, 0x2e, 0xfa, 0x36, 0xfa, 0xfb, 0xdc, 0xce, 0x9d, 0x9c, 0xdb, 0xb9, 0xd3, - 0x73, 0x3b, 0xf7, 0xc3, 0xdc, 0x9e, 0x7f, 0xd5, 0xa7, 0xeb, 0x5f, 0xf3, 0x8b, 0xdb, 0x72, 0xf2, - 0x73, 0xeb, 0xb9, 0xcb, 0x9f, 0xdb, 0x3e, 0x79, 0x1a, 0x00, 0x00, 0xff, 0xff, 0x13, 0xf1, 0x55, - 0xca, 0x04, 0x14, 0x00, 0x00, + // 963 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0x4b, 0x6f, 0x2b, 0x35, + 0x18, 0x86, 0xe3, 0x0d, 0x42, 0xe6, 0x70, 0x1b, 0x10, 0x97, 0xb3, 0x18, 0x6e, 0x0b, 0x58, 0x25, + 0xf4, 0x00, 0xe7, 0xb4, 0xe9, 0x35, 0x4d, 0x42, 0x8a, 0x48, 0x0a, 0x4d, 0xb8, 0x48, 0x6c, 0x90, + 0x93, 0xf9, 0xda, 0x8e, 0x3a, 0xc9, 0x0c, 0xb6, 0x27, 0xa5, 0x2b, 0x50, 0x25, 0x24, 0x24, 0x24, + 0x04, 0x12, 0x12, 0x12, 0x12, 0x2b, 0x24, 0x04, 0x12, 0xbf, 0x01, 0x89, 0x5d, 0x97, 0x5d, 0x76, + 0x49, 0xd3, 0x0d, 0xcb, 0xfe, 0x04, 0x34, 0x9d, 0xd8, 0x1d, 0x27, 0x4e, 0x8f, 0x3d, 0xe9, 0xae, + 0x69, 0xfc, 0xbc, 0x7e, 0xc6, 0x63, 0xfb, 0xb3, 0x83, 0x17, 0x38, 0xf4, 0xa3, 0x90, 0x92, 0xa0, + 0xc4, 0x80, 0x0e, 0x81, 0x96, 0x48, 0xe4, 0x97, 0x88, 0xd7, 0xf7, 0x07, 0xc9, 0x67, 0xbf, 0x07, + 0xa5, 0xe1, 0x42, 0x69, 0xfc, 0x67, 0x31, 0xa2, 0x21, 0x0f, 0x9d, 0xd7, 0x04, 0x52, 0x4c, 0x91, + 0x22, 0x89, 0xfc, 0x62, 0x16, 0x29, 0x0e, 0x17, 0xee, 0x96, 0x4d, 0x72, 0x29, 0x7c, 0x11, 0x03, + 0xe3, 0x9f, 0x53, 0x60, 0x51, 0x38, 0x60, 0xe3, 0x0e, 0xee, 0x1d, 0xbf, 0x8e, 0xef, 0x54, 0x92, + 0xa6, 0x9d, 0xb4, 0xa9, 0xf3, 0x0b, 0xc2, 0xcf, 0xb4, 0xa1, 0x1b, 0xfb, 0x81, 0xd7, 0x8a, 0x39, + 0xe9, 0x06, 0xd0, 0xe1, 0x84, 0x83, 0xb3, 0x5e, 0x34, 0x50, 0x29, 0x6a, 0xc8, 0x76, 0xda, 0xf1, + 0xdd, 0x8d, 0xfc, 0x01, 0xa9, 0xf1, 0xab, 0x05, 0xe7, 0x77, 0x84, 0x9f, 0x7f, 0x2f, 0x09, 0xe1, + 0x9f, 0x86, 0xf4, 0x60, 0x37, 0x08, 0x0f, 0xeb, 0x5f, 0x42, 0x2f, 0xe6, 0x7e, 0x38, 0x70, 0xaa, + 0x46, 0xf9, 0x33, 0x68, 0x21, 0x59, 0x9b, 0x2f, 0x44, 0x8a, 0xfe, 0x8a, 0xf0, 0xb3, 0x35, 0x60, + 0x3d, 0xea, 0x77, 0x41, 0x19, 0x46, 0xb3, 0x51, 0xd0, 0xa1, 0x42, 0xb1, 0x32, 0x47, 0x82, 0xf4, + 0x4b, 0xde, 0xb2, 0x68, 0xb2, 0xe5, 0x33, 0x1e, 0xd2, 0xa3, 0xad, 0x90, 0x71, 0xc3, 0xb7, 0xac, + 0x21, 0xed, 0xde, 0xb2, 0x36, 0x40, 0xca, 0x1d, 0xe1, 0x47, 0x1b, 0xc0, 0x3b, 0xfb, 0x84, 0x7a, + 0xce, 0xdb, 0x46, 0x79, 0xa2, 0xb9, 0xb0, 0x78, 0xc7, 0x92, 0x92, 0x5d, 0x7f, 0x85, 0x71, 0x35, + 0x08, 0x19, 0xa4, 0x9d, 0xdf, 0x37, 0x8a, 0xb9, 0x06, 0x44, 0xf7, 0x0f, 0xac, 0x39, 0x29, 0xf0, + 0x23, 0xc2, 0x4f, 0x35, 0x7d, 0xc6, 0xc7, 0x23, 0xf3, 0x11, 0x61, 0x07, 0xcc, 0x59, 0x31, 0xca, + 0x9b, 0xc4, 0x84, 0xcd, 0x6a, 0x4e, 0x3a, 0x3b, 0x28, 0x6d, 0xe8, 0x87, 0x43, 0x48, 0xbe, 0x30, + 0x1c, 0x94, 0x6b, 0xc0, 0x6e, 0x50, 0xb2, 0x9c, 0x14, 0xf8, 0x07, 0xe1, 0x97, 0x1b, 0xa0, 0x59, + 0x70, 0xe4, 0x70, 0xac, 0xfc, 0xc9, 0x3d, 0xa7, 0x69, 0xfa, 0xce, 0x6f, 0x8c, 0x11, 0xb6, 0xad, + 0x5b, 0x4a, 0x93, 0xcf, 0xf0, 0x1b, 0xc2, 0xcf, 0x35, 0x80, 0xb7, 0x21, 0x0a, 0xfc, 0x1e, 0x49, + 0x1a, 0xb6, 0x80, 0x31, 0xb2, 0x07, 0xcc, 0xd9, 0x34, 0xed, 0x4b, 0x03, 0x0b, 0xdf, 0xea, 0x5c, + 0x19, 0xd2, 0xf2, 0x6f, 0x84, 0x5f, 0x6a, 0x00, 0xdf, 0x26, 0x7d, 0x60, 0x11, 0xe9, 0x81, 0x4e, + 0xf7, 0x7d, 0xd3, 0xae, 0x6e, 0x4a, 0x11, 0xde, 0xcd, 0xdb, 0x09, 0x93, 0x0f, 0xf0, 0x17, 0xc2, + 0x2f, 0x36, 0x80, 0xd7, 0x9a, 0x3b, 0x3a, 0xf5, 0xba, 0x69, 0x6f, 0x7a, 0x5e, 0x48, 0xbf, 0x3b, + 0x6f, 0x8c, 0xd4, 0xfd, 0x16, 0xe1, 0xc7, 0xdb, 0x40, 0xa2, 0x28, 0x38, 0xaa, 0x0f, 0x61, 0xc0, + 0x99, 0xb3, 0x64, 0xb8, 0x4c, 0x32, 0x8c, 0xd0, 0x2a, 0xe7, 0x41, 0x95, 0x92, 0x50, 0xf1, 0xbc, + 0x0e, 0x10, 0xda, 0xdb, 0xaf, 0x70, 0x4e, 0xfd, 0x6e, 0xcc, 0x81, 0x19, 0x96, 0x04, 0x0d, 0x69, + 0x57, 0x12, 0xb4, 0x01, 0xca, 0xea, 0x49, 0xb7, 0x86, 0x29, 0xbf, 0x4d, 0x8b, 0x7d, 0x65, 0x96, + 0x62, 0x75, 0xae, 0x0c, 0x65, 0x08, 0x93, 0xa2, 0x92, 0x6f, 0x08, 0x35, 0xa4, 0xdd, 0x10, 0x6a, + 0x03, 0xa4, 0xdc, 0xf7, 0x08, 0x3f, 0x29, 0xea, 0x6e, 0x35, 0x88, 0x19, 0x07, 0xea, 0x2c, 0x5b, + 0x55, 0xeb, 0x31, 0x25, 0xa4, 0x56, 0xf2, 0xc1, 0x52, 0xe8, 0x1b, 0x84, 0xef, 0x24, 0x55, 0x67, + 0xfc, 0x0d, 0x73, 0x16, 0x8d, 0x0b, 0x95, 0x40, 0x84, 0xca, 0x52, 0x0e, 0x52, 0x7a, 0xfc, 0x8c, + 0xb0, 0x93, 0xf9, 0xaa, 0x05, 0xfd, 0x6e, 0x62, 0xb3, 0x66, 0x9b, 0x39, 0x06, 0x85, 0xd3, 0x7a, + 0x6e, 0x5e, 0x9a, 0xfd, 0x89, 0xf0, 0x0b, 0x15, 0xcf, 0xfb, 0x80, 0x7e, 0x1c, 0x79, 0x57, 0xe7, + 0xb7, 0x7e, 0xc8, 0xe5, 0xbb, 0xab, 0x99, 0x2e, 0x2b, 0x2d, 0x2e, 0x2c, 0xeb, 0x73, 0xa6, 0x28, + 0x73, 0x3f, 0x5d, 0x20, 0xaa, 0xe6, 0xba, 0xc5, 0xd2, 0xd2, 0x1a, 0x6e, 0xe4, 0x0f, 0x90, 0x72, + 0xdf, 0x21, 0xfc, 0x44, 0xba, 0x1d, 0xcb, 0x52, 0x50, 0xb6, 0xd8, 0xc3, 0x27, 0xf7, 0xff, 0xe5, + 0x5c, 0xac, 0x72, 0xc6, 0xfb, 0x30, 0xa6, 0x7b, 0x90, 0xf5, 0x31, 0x5b, 0x4d, 0x93, 0x98, 0xdd, + 0x19, 0x6f, 0x9a, 0x56, 0x9c, 0x5a, 0x90, 0xcb, 0x69, 0x12, 0xb3, 0x73, 0x9a, 0xa6, 0x95, 0x4b, + 0x54, 0x1b, 0x76, 0x29, 0xb0, 0x7d, 0x71, 0xca, 0x4a, 0xcf, 0xc3, 0xa6, 0x53, 0x62, 0x1a, 0xb5, + 0xbb, 0x44, 0xe9, 0x13, 0x26, 0x8a, 0x12, 0x83, 0x81, 0x97, 0x29, 0xf2, 0xa9, 0xa1, 0x69, 0x51, + 0xd2, 0xc1, 0xb6, 0x45, 0x49, 0x9f, 0x21, 0x2d, 0x7f, 0x42, 0xf8, 0xe9, 0x06, 0xf0, 0xe4, 0xdf, + 0x3b, 0x31, 0xc4, 0x90, 0x0a, 0xae, 0x9a, 0x4e, 0x61, 0x95, 0x13, 0x6e, 0x6b, 0x79, 0x71, 0xe5, + 0x2a, 0x5f, 0x83, 0x00, 0x38, 0xe4, 0xbd, 0xca, 0xcf, 0xa0, 0xed, 0xae, 0xf2, 0x33, 0x43, 0xa4, + 0xe8, 0x09, 0xc2, 0xaf, 0x74, 0x38, 0x05, 0xd2, 0x17, 0xad, 0x74, 0x27, 0x4b, 0xb3, 0xfb, 0xc2, + 0x43, 0x73, 0x84, 0xfc, 0xf6, 0x6d, 0xc5, 0x89, 0xc7, 0x78, 0x03, 0xbd, 0x89, 0xae, 0x2a, 0x6e, + 0xf6, 0x28, 0x6d, 0x58, 0x71, 0xd5, 0xd3, 0xb7, 0x4d, 0xc5, 0x55, 0x49, 0x39, 0xa4, 0xc7, 0x08, + 0x3f, 0x96, 0xee, 0x8e, 0xe9, 0x64, 0x7c, 0x60, 0xb1, 0x9f, 0x2a, 0xd3, 0x70, 0xd1, 0x1e, 0x54, + 0x8e, 0xde, 0x62, 0x43, 0x4c, 0x35, 0x96, 0xac, 0x36, 0x51, 0x45, 0xa4, 0x9c, 0x07, 0x15, 0x2a, + 0x9b, 0xc1, 0xe9, 0xb9, 0x5b, 0x38, 0x3b, 0x77, 0x0b, 0x97, 0xe7, 0x2e, 0xfa, 0x7a, 0xe4, 0xa2, + 0x3f, 0x46, 0x2e, 0x3a, 0x19, 0xb9, 0xe8, 0x74, 0xe4, 0xa2, 0x7f, 0x47, 0x2e, 0xfa, 0x6f, 0xe4, + 0x16, 0x2e, 0x47, 0x2e, 0xfa, 0xe1, 0xc2, 0x2d, 0x9c, 0x5e, 0xb8, 0x85, 0xb3, 0x0b, 0xb7, 0xf0, + 0xd9, 0xfd, 0xbd, 0xf0, 0xba, 0x57, 0x3f, 0xbc, 0xe1, 0xc7, 0xbf, 0xe5, 0xec, 0xe7, 0xee, 0x23, + 0x57, 0xbf, 0xfc, 0xbd, 0xf5, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x23, 0x87, 0x4b, 0xb8, 0x8f, + 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -194,6 +195,9 @@ type AdminServiceClient interface { StreamWorkflowReplicationMessages(ctx context.Context, opts ...grpc.CallOption) (AdminService_StreamWorkflowReplicationMessagesClient, error) GetNamespace(ctx context.Context, in *GetNamespaceRequest, opts ...grpc.CallOption) (*GetNamespaceResponse, error) GetDLQTasks(ctx context.Context, in *GetDLQTasksRequest, opts ...grpc.CallOption) (*GetDLQTasksResponse, error) + // (-- api-linter: core::0165::response-message-name=disabled + // aip.dev/not-precedent: --) + PurgeDLQTasks(ctx context.Context, in *PurgeDLQTasksRequest, opts ...grpc.CallOption) (*PurgeDLQTasksResponse, error) } type adminServiceClient struct { @@ -505,6 +509,15 @@ func (c *adminServiceClient) GetDLQTasks(ctx context.Context, in *GetDLQTasksReq return out, nil } +func (c *adminServiceClient) PurgeDLQTasks(ctx context.Context, in *PurgeDLQTasksRequest, opts ...grpc.CallOption) (*PurgeDLQTasksResponse, error) { + out := new(PurgeDLQTasksResponse) + err := c.cc.Invoke(ctx, "/temporal.server.api.adminservice.v1.AdminService/PurgeDLQTasks", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // AdminServiceServer is the server API for AdminService service. type AdminServiceServer interface { // RebuildMutableState attempts to rebuild mutable state according to persisted history events. @@ -572,6 +585,9 @@ type AdminServiceServer interface { StreamWorkflowReplicationMessages(AdminService_StreamWorkflowReplicationMessagesServer) error GetNamespace(context.Context, *GetNamespaceRequest) (*GetNamespaceResponse, error) GetDLQTasks(context.Context, *GetDLQTasksRequest) (*GetDLQTasksResponse, error) + // (-- api-linter: core::0165::response-message-name=disabled + // aip.dev/not-precedent: --) + PurgeDLQTasks(context.Context, *PurgeDLQTasksRequest) (*PurgeDLQTasksResponse, error) } // UnimplementedAdminServiceServer can be embedded to have forward compatible implementations. @@ -671,6 +687,9 @@ func (*UnimplementedAdminServiceServer) GetNamespace(ctx context.Context, req *G func (*UnimplementedAdminServiceServer) GetDLQTasks(ctx context.Context, req *GetDLQTasksRequest) (*GetDLQTasksResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetDLQTasks not implemented") } +func (*UnimplementedAdminServiceServer) PurgeDLQTasks(ctx context.Context, req *PurgeDLQTasksRequest) (*PurgeDLQTasksResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PurgeDLQTasks not implemented") +} func RegisterAdminServiceServer(s *grpc.Server, srv AdminServiceServer) { s.RegisterService(&_AdminService_serviceDesc, srv) @@ -1242,6 +1261,24 @@ func _AdminService_GetDLQTasks_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _AdminService_PurgeDLQTasks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PurgeDLQTasksRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).PurgeDLQTasks(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/temporal.server.api.adminservice.v1.AdminService/PurgeDLQTasks", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).PurgeDLQTasks(ctx, req.(*PurgeDLQTasksRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _AdminService_serviceDesc = grpc.ServiceDesc{ ServiceName: "temporal.server.api.adminservice.v1.AdminService", HandlerType: (*AdminServiceServer)(nil), @@ -1366,6 +1403,10 @@ var _AdminService_serviceDesc = grpc.ServiceDesc{ MethodName: "GetDLQTasks", Handler: _AdminService_GetDLQTasks_Handler, }, + { + MethodName: "PurgeDLQTasks", + Handler: _AdminService_PurgeDLQTasks_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/api/adminservicemock/v1/service.pb.mock.go b/api/adminservicemock/v1/service.pb.mock.go index b2d39aba33d..b32492a14af 100644 --- a/api/adminservicemock/v1/service.pb.mock.go +++ b/api/adminservicemock/v1/service.pb.mock.go @@ -521,6 +521,26 @@ func (mr *MockAdminServiceClientMockRecorder) PurgeDLQMessages(ctx, in interface return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgeDLQMessages", reflect.TypeOf((*MockAdminServiceClient)(nil).PurgeDLQMessages), varargs...) } +// PurgeDLQTasks mocks base method. +func (m *MockAdminServiceClient) PurgeDLQTasks(ctx context.Context, in *adminservice.PurgeDLQTasksRequest, opts ...grpc.CallOption) (*adminservice.PurgeDLQTasksResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, in} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "PurgeDLQTasks", varargs...) + ret0, _ := ret[0].(*adminservice.PurgeDLQTasksResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PurgeDLQTasks indicates an expected call of PurgeDLQTasks. +func (mr *MockAdminServiceClientMockRecorder) PurgeDLQTasks(ctx, in interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, in}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgeDLQTasks", reflect.TypeOf((*MockAdminServiceClient)(nil).PurgeDLQTasks), varargs...) +} + // ReapplyEvents mocks base method. func (m *MockAdminServiceClient) ReapplyEvents(ctx context.Context, in *adminservice.ReapplyEventsRequest, opts ...grpc.CallOption) (*adminservice.ReapplyEventsResponse, error) { m.ctrl.T.Helper() @@ -1186,6 +1206,21 @@ func (mr *MockAdminServiceServerMockRecorder) PurgeDLQMessages(arg0, arg1 interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgeDLQMessages", reflect.TypeOf((*MockAdminServiceServer)(nil).PurgeDLQMessages), arg0, arg1) } +// PurgeDLQTasks mocks base method. +func (m *MockAdminServiceServer) PurgeDLQTasks(arg0 context.Context, arg1 *adminservice.PurgeDLQTasksRequest) (*adminservice.PurgeDLQTasksResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PurgeDLQTasks", arg0, arg1) + ret0, _ := ret[0].(*adminservice.PurgeDLQTasksResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PurgeDLQTasks indicates an expected call of PurgeDLQTasks. +func (mr *MockAdminServiceServerMockRecorder) PurgeDLQTasks(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgeDLQTasks", reflect.TypeOf((*MockAdminServiceServer)(nil).PurgeDLQTasks), arg0, arg1) +} + // ReapplyEvents mocks base method. func (m *MockAdminServiceServer) ReapplyEvents(arg0 context.Context, arg1 *adminservice.ReapplyEventsRequest) (*adminservice.ReapplyEventsResponse, error) { m.ctrl.T.Helper() diff --git a/client/admin/client_gen.go b/client/admin/client_gen.go index 5de9d534019..da2b9fbab01 100644 --- a/client/admin/client_gen.go +++ b/client/admin/client_gen.go @@ -263,6 +263,16 @@ func (c *clientImpl) PurgeDLQMessages( return c.client.PurgeDLQMessages(ctx, request, opts...) } +func (c *clientImpl) PurgeDLQTasks( + ctx context.Context, + request *adminservice.PurgeDLQTasksRequest, + opts ...grpc.CallOption, +) (*adminservice.PurgeDLQTasksResponse, error) { + ctx, cancel := c.createContext(ctx) + defer cancel() + return c.client.PurgeDLQTasks(ctx, request, opts...) +} + func (c *clientImpl) ReapplyEvents( ctx context.Context, request *adminservice.ReapplyEventsRequest, diff --git a/client/admin/metric_client_gen.go b/client/admin/metric_client_gen.go index 0fabbd433cb..0a32e874c48 100644 --- a/client/admin/metric_client_gen.go +++ b/client/admin/metric_client_gen.go @@ -355,6 +355,20 @@ func (c *metricClient) PurgeDLQMessages( return c.client.PurgeDLQMessages(ctx, request, opts...) } +func (c *metricClient) PurgeDLQTasks( + ctx context.Context, + request *adminservice.PurgeDLQTasksRequest, + opts ...grpc.CallOption, +) (_ *adminservice.PurgeDLQTasksResponse, retError error) { + + metricsHandler, startTime := c.startMetricsRecording(ctx, "AdminClientPurgeDLQTasks") + defer func() { + c.finishMetricsRecording(metricsHandler, startTime, retError) + }() + + return c.client.PurgeDLQTasks(ctx, request, opts...) +} + func (c *metricClient) ReapplyEvents( ctx context.Context, request *adminservice.ReapplyEventsRequest, diff --git a/client/admin/retryable_client_gen.go b/client/admin/retryable_client_gen.go index d43b8398941..fc33a66055c 100644 --- a/client/admin/retryable_client_gen.go +++ b/client/admin/retryable_client_gen.go @@ -380,6 +380,21 @@ func (c *retryableClient) PurgeDLQMessages( return resp, err } +func (c *retryableClient) PurgeDLQTasks( + ctx context.Context, + request *adminservice.PurgeDLQTasksRequest, + opts ...grpc.CallOption, +) (*adminservice.PurgeDLQTasksResponse, error) { + var resp *adminservice.PurgeDLQTasksResponse + op := func(ctx context.Context) error { + var err error + resp, err = c.client.PurgeDLQTasks(ctx, request, opts...) + return err + } + err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable) + return resp, err +} + func (c *retryableClient) ReapplyEvents( ctx context.Context, request *adminservice.ReapplyEventsRequest, diff --git a/common/persistence/cassandra/queue_v2_store.go b/common/persistence/cassandra/queue_v2_store.go index 7db0cc6cc24..3da8678c4ed 100644 --- a/common/persistence/cassandra/queue_v2_store.go +++ b/common/persistence/cassandra/queue_v2_store.go @@ -415,8 +415,9 @@ func getPartition( if numPartitions != 1 { return nil, serviceerror.NewInternal( fmt.Sprintf( - "queue with type %v and queueName %v has %d partitions, but this implementation only supports"+ - " queues with 1 partition. Did you downgrade your Temporal server?", + "Invalid partition count for queue: queue with type = %v and queueName = %v has %d "+ + "partitions, but this implementation only supports queues with 1 partition. Did you downgrade "+ + "your Temporal server?", queueType, queueName, numPartitions, @@ -508,10 +509,10 @@ func GetQueue( if queueEncodingStr != enums.ENCODING_TYPE_PROTO3.String() { return nil, fmt.Errorf( - "queue with type %v and name %v has invalid encoding: %w", + "%w: invalid queue encoding type: queue with type %v and name %v has invalid encoding", + serialization.NewUnknownEncodingTypeError(queueEncodingStr, enums.ENCODING_TYPE_PROTO3), queueType, queueName, - serialization.NewUnknownEncodingTypeError(queueEncodingStr, enums.ENCODING_TYPE_PROTO3), ) } @@ -520,7 +521,8 @@ func GetQueue( if err != nil { return nil, serialization.NewDeserializationError( enums.ENCODING_TYPE_PROTO3, - fmt.Errorf("unmarshal payload for queue with type %v and name %v failed: %w", queueType, queueName, err), + fmt.Errorf("%w: unmarshal queue payload: failed for queue with type %v and name %v", + err, queueType, queueName), ) } diff --git a/common/persistence/history_task_queue_manager.go b/common/persistence/history_task_queue_manager.go index e8d9b719a6f..e275c5ac2af 100644 --- a/common/persistence/history_task_queue_manager.go +++ b/common/persistence/history_task_queue_manager.go @@ -62,6 +62,7 @@ const ( var ( ErrReadTasksNonPositivePageSize = errors.New("page size to read history tasks must be positive") ErrHistoryTaskBlobIsNil = errors.New("history task from queue has nil blob") + ErrEnqueueTaskRequestTaskIsNil = errors.New("enqueue task request task is nil") ErrQueueAlreadyExists = errors.New("queue already exists") ) @@ -77,6 +78,9 @@ func (m *HistoryTaskQueueManagerImpl) EnqueueTask( ctx context.Context, request *EnqueueTaskRequest, ) (*EnqueueTaskResponse, error) { + if request.Task == nil { + return nil, ErrEnqueueTaskRequestTaskIsNil + } blob, err := m.serializer.SerializeTask(request.Task) if err != nil { return nil, fmt.Errorf("%v: %w", ErrMsgSerializeTaskToEnqueue, err) diff --git a/common/persistence/queue_v2.go b/common/persistence/queue_v2.go index fd9f06bcd82..1ab4acacab7 100644 --- a/common/persistence/queue_v2.go +++ b/common/persistence/queue_v2.go @@ -53,7 +53,7 @@ var ( func NewQueueNotFoundError(queueType QueueV2Type, queueName string) error { return serviceerror.NewNotFound(fmt.Sprintf( - "queue with type %v and name %v not found", + "queue not found: type = %v and name = %v", queueType, queueName, )) diff --git a/common/primitives/task_queues.go b/common/primitives/task_queues.go index 7bb80777c8a..9935ae04e11 100644 --- a/common/primitives/task_queues.go +++ b/common/primitives/task_queues.go @@ -32,4 +32,5 @@ const ( MigrationActivityTQ = "temporal-sys-migration-activity-tq" AddSearchAttributesActivityTQ = "temporal-sys-add-search-attributes-activity-tq" DeleteNamespaceActivityTQ = "temporal-sys-delete-namespace-activity-tq" + DLQActivityTQ = "temporal-sys-dlq-activity-tq" ) diff --git a/proto/internal/temporal/server/api/adminservice/v1/request_response.proto b/proto/internal/temporal/server/api/adminservice/v1/request_response.proto index e3daf8f37db..610d4409019 100644 --- a/proto/internal/temporal/server/api/adminservice/v1/request_response.proto +++ b/proto/internal/temporal/server/api/adminservice/v1/request_response.proto @@ -37,6 +37,7 @@ import "temporal/api/namespace/v1/message.proto"; import "temporal/api/replication/v1/message.proto"; import "temporal/server/api/cluster/v1/message.proto"; +import "temporal/server/api/common/v1/dlq.proto"; import "temporal/server/api/enums/v1/common.proto"; import "temporal/server/api/enums/v1/cluster.proto"; import "temporal/server/api/enums/v1/task.proto"; @@ -47,7 +48,6 @@ import "temporal/server/api/persistence/v1/cluster_metadata.proto"; import "temporal/server/api/persistence/v1/executions.proto"; import "temporal/server/api/persistence/v1/workflow_mutable_state.proto"; import "temporal/server/api/persistence/v1/tasks.proto"; -import "temporal/server/api/common/v1/dlq.proto"; message RebuildMutableStateRequest { string namespace = 1; @@ -436,3 +436,20 @@ message GetDLQTasksResponse { // there are more results. bytes next_page_token = 2; } + +message PurgeDLQTasksRequest { + temporal.server.api.common.v1.HistoryDLQKey dlq_key = 1; + temporal.server.api.common.v1. HistoryDLQTaskMetadata inclusive_max_task_metadata = 2; +} + +message PurgeDLQTasksResponse { + // job_token is a token that can be used to query the status of the purge operation. + // TODO: add DescribeDLQJob an CancelDLQJob APIs for clients to use these tokens. + bytes job_token = 1; +} + +// DLQJobToken identifies a DLQ job. This proto is for internal use only and clients should not use it. +message DLQJobToken { + string workflow_id = 1; + string run_id = 2; +} \ No newline at end of file diff --git a/proto/internal/temporal/server/api/adminservice/v1/service.proto b/proto/internal/temporal/server/api/adminservice/v1/service.proto index 78c002ea449..0d626e16944 100644 --- a/proto/internal/temporal/server/api/adminservice/v1/service.proto +++ b/proto/internal/temporal/server/api/adminservice/v1/service.proto @@ -153,5 +153,8 @@ service AdminService { rpc GetDLQTasks (GetDLQTasksRequest) returns (GetDLQTasksResponse) { } + // (-- api-linter: core::0165::response-message-name=disabled + // aip.dev/not-precedent: --) + rpc PurgeDLQTasks (PurgeDLQTasksRequest) returns (PurgeDLQTasksResponse) {} } diff --git a/service/frontend/admin_handler.go b/service/frontend/admin_handler.go index 22bfb08a108..88c467d586b 100644 --- a/service/frontend/admin_handler.go +++ b/service/frontend/admin_handler.go @@ -36,11 +36,15 @@ import ( replicationpb "go.temporal.io/api/replication/v1" "google.golang.org/grpc/metadata" + "go.temporal.io/server/api/adminservice/v1" + "go.temporal.io/server/api/historyservice/v1" "go.temporal.io/server/client/history" "go.temporal.io/server/common/channel" "go.temporal.io/server/common/clock" "go.temporal.io/server/common/primitives" "go.temporal.io/server/common/util" + "go.temporal.io/server/service/history/api" + "go.temporal.io/server/service/worker/dlq" "github.com/pborman/uuid" enumspb "go.temporal.io/api/enums/v1" @@ -53,10 +57,8 @@ import ( "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" - "go.temporal.io/server/api/adminservice/v1" clusterspb "go.temporal.io/server/api/cluster/v1" enumsspb "go.temporal.io/server/api/enums/v1" - "go.temporal.io/server/api/historyservice/v1" persistencespb "go.temporal.io/server/api/persistence/v1" replicationspb "go.temporal.io/server/api/replication/v1" serverClient "go.temporal.io/server/client" @@ -1782,6 +1784,55 @@ func (adh *AdminHandler) GetDLQTasks( }, nil } +func (adh *AdminHandler) PurgeDLQTasks( + ctx context.Context, + request *adminservice.PurgeDLQTasksRequest, +) (*adminservice.PurgeDLQTasksResponse, error) { + category, err := api.GetTaskCategory(int(request.DlqKey.TaskCategory), adh.taskCategoryRegistry) + if err != nil { + return nil, err + } + sourceCluster := request.DlqKey.SourceCluster + if len(sourceCluster) == 0 { + return nil, errSourceClusterNotSet + } + targetCluster := request.DlqKey.TargetCluster + if len(targetCluster) == 0 { + return nil, errTargetClusterNotSet + } + key := persistence.QueueKey{ + QueueType: persistence.QueueTypeHistoryDLQ, + Category: category, + SourceCluster: sourceCluster, + TargetCluster: request.DlqKey.TargetCluster, + } + workflowID := fmt.Sprintf("delete-dlq-tasks-%s", key.GetQueueName()) + client := adh.sdkClientFactory.GetSystemClient() + future, err := client.ExecuteWorkflow(ctx, sdkclient.StartWorkflowOptions{ + ID: workflowID, + TaskQueue: primitives.DefaultWorkerTaskQueue, + }, dlq.WorkflowName, dlq.WorkflowParams{ + WorkflowType: dlq.WorkflowTypeDelete, + DeleteParams: dlq.DeleteParams{ + TaskCategory: int(category.ID()), + SourceCluster: sourceCluster, + TargetCluster: targetCluster, + MaxMessageID: request.InclusiveMaxTaskMetadata.MessageId, + }, + }) + if err != nil { + return nil, err + } + jobToken := adminservice.DLQJobToken{ + WorkflowId: workflowID, + RunId: future.GetRunID(), + } + jobTokenBytes, _ := jobToken.Marshal() + return &adminservice.PurgeDLQTasksResponse{ + JobToken: jobTokenBytes, + }, nil +} + func convertClusterReplicationConfigToProto( input []string, ) []*replicationpb.ClusterReplicationConfig { diff --git a/service/frontend/admin_handler_test.go b/service/frontend/admin_handler_test.go index 4b28bb766b2..4de30733349 100644 --- a/service/frontend/admin_handler_test.go +++ b/service/frontend/admin_handler_test.go @@ -32,48 +32,44 @@ import ( "sync" "testing" - commonpb "go.temporal.io/api/common/v1" - namespacepb "go.temporal.io/api/namespace/v1" - - commonspb "go.temporal.io/server/api/common/v1" - "go.temporal.io/server/service/history/tasks" - - "google.golang.org/grpc/metadata" - - historyclient "go.temporal.io/server/client/history" - "go.temporal.io/server/common/clock" - "go.temporal.io/server/common/primitives" - "go.temporal.io/server/common/primitives/timestamp" - "go.temporal.io/server/common/resourcetest" - - "google.golang.org/grpc/health" - - "go.temporal.io/server/api/adminservicemock/v1" - persistencespb "go.temporal.io/server/api/persistence/v1" - "go.temporal.io/server/common/cluster" - "go.temporal.io/server/common/dynamicconfig" - "go.temporal.io/server/common/membership" - "go.temporal.io/server/common/testing/mocksdk" - "github.com/golang/mock/gomock" "github.com/pborman/uuid" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + commonpb "go.temporal.io/api/common/v1" enumspb "go.temporal.io/api/enums/v1" + namespacepb "go.temporal.io/api/namespace/v1" "go.temporal.io/api/serviceerror" "go.temporal.io/api/workflowservice/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/health" + "google.golang.org/grpc/metadata" "go.temporal.io/server/api/adminservice/v1" + "go.temporal.io/server/api/adminservicemock/v1" + commonspb "go.temporal.io/server/api/common/v1" "go.temporal.io/server/api/historyservice/v1" "go.temporal.io/server/api/historyservicemock/v1" + persistencespb "go.temporal.io/server/api/persistence/v1" clientmocks "go.temporal.io/server/client" + historyclient "go.temporal.io/server/client/history" + "go.temporal.io/server/common/clock" + "go.temporal.io/server/common/cluster" "go.temporal.io/server/common/config" + "go.temporal.io/server/common/dynamicconfig" + "go.temporal.io/server/common/membership" "go.temporal.io/server/common/namespace" "go.temporal.io/server/common/persistence" "go.temporal.io/server/common/persistence/serialization" "go.temporal.io/server/common/persistence/visibility/manager" "go.temporal.io/server/common/persistence/visibility/store/elasticsearch" + "go.temporal.io/server/common/primitives" + "go.temporal.io/server/common/primitives/timestamp" + "go.temporal.io/server/common/resourcetest" "go.temporal.io/server/common/searchattribute" + "go.temporal.io/server/common/testing/mocksdk" + "go.temporal.io/server/service/history/tasks" + "go.temporal.io/server/service/worker/dlq" ) type ( @@ -1217,3 +1213,83 @@ func (s *adminHandlerSuite) TestGetDLQTasks() { }) } } + +func (s *adminHandlerSuite) TestPurgeDLQTasks() { + for _, tc := range []struct { + name string + err error + }{ + { + name: "Success", + err: nil, + }, + { + name: "WorkflowExecutionFailed", + err: serviceerror.NewNotFound("example sdk worfklow start failure"), + }, + } { + s.Run(tc.name, func() { + mockSdkClient := mocksdk.NewMockClient(s.controller) + s.mockResource.SDKClientFactory.EXPECT().GetSystemClient().Return(mockSdkClient) + expectation := mockSdkClient.EXPECT().ExecuteWorkflow( + gomock.Any(), + gomock.Any(), + dlq.WorkflowName, + dlq.WorkflowParams{ + WorkflowType: dlq.WorkflowTypeDelete, + DeleteParams: dlq.DeleteParams{ + TaskCategory: int(tasks.CategoryTransfer.ID()), + SourceCluster: "test-source-cluster", + TargetCluster: "test-target-cluster", + MaxMessageID: 42, + }, + }, + ) + if tc.err != nil { + expectation.Return(nil, tc.err) + } else { + run := mocksdk.NewMockWorkflowRun(s.controller) + run.EXPECT().GetRunID().Return("test-run-id") + expectation.Return(run, nil) + } + response, err := s.handler.PurgeDLQTasks(context.Background(), &adminservice.PurgeDLQTasksRequest{ + DlqKey: &commonspb.HistoryDLQKey{ + TaskCategory: int32(tasks.CategoryTransfer.ID()), + SourceCluster: "test-source-cluster", + TargetCluster: "test-target-cluster", + }, + InclusiveMaxTaskMetadata: &commonspb.HistoryDLQTaskMetadata{ + MessageId: 42, + }, + }) + if tc.err != nil { + s.ErrorIs(err, tc.err) + return + } + s.NoError(err) + s.NotNil(response) + var token adminservice.DLQJobToken + err = token.Unmarshal(response.JobToken) + s.NoError(err) + s.Equal("delete-dlq-tasks-1_test-source-cluster_test-target-cluster_aG2oua8T", token.WorkflowId) + s.Equal("test-run-id", token.RunId) + }) + } +} + +func (s *adminHandlerSuite) TestPurgeDLQTasks_InvalidCategory() { + _, err := s.handler.PurgeDLQTasks(context.Background(), &adminservice.PurgeDLQTasksRequest{ + DlqKey: &commonspb.HistoryDLQKey{ + TaskCategory: -1, + SourceCluster: "test-source-cluster", + TargetCluster: "test-target-cluster", + }, + InclusiveMaxTaskMetadata: &commonspb.HistoryDLQTaskMetadata{ + MessageId: 42, + }, + }) + s.Error(err) + s.Equal(codes.InvalidArgument, serviceerror.ToStatus(err).Code()) + s.ErrorContains(err, "task category") + s.ErrorContains(err, "-1") +} diff --git a/service/frontend/errors.go b/service/frontend/errors.go index f7814c27a08..631609bc183 100644 --- a/service/frontend/errors.go +++ b/service/frontend/errors.go @@ -90,6 +90,8 @@ var ( errUpdateIDTooLong = serviceerror.NewInvalidArgument("UpdateId length exceeds limit.") errUpdateRefNotSet = serviceerror.NewInvalidArgument("UpdateRef is not set on request.") errUpdateWaitPolicyNotSet = serviceerror.NewInvalidArgument("WaitPolicy is not set on request.") + errSourceClusterNotSet = serviceerror.NewInvalidArgument("SourceCluster is not set on request.") + errTargetClusterNotSet = serviceerror.NewInvalidArgument("TargetCluster is not set on request.") errPageSizeTooBigMessage = "PageSize is larger than allowed %d." diff --git a/service/worker/addsearchattributes/fx.go b/service/worker/addsearchattributes/fx.go index e926069b321..d3ab2aa7e70 100644 --- a/service/worker/addsearchattributes/fx.go +++ b/service/worker/addsearchattributes/fx.go @@ -53,28 +53,16 @@ type ( MetricsHandler metrics.Handler Logger log.Logger } - - fxResult struct { - fx.Out - Component workercommon.WorkerComponent `group:"workerComponent"` - } ) -var Module = fx.Options( - fx.Provide(NewResult), -) +var Module = workercommon.AnnotateWorkerComponentProvider(newComponent) -func NewResult(params initParams) fxResult { - component := &addSearchAttributes{ - initParams: params, - } - return fxResult{ - Component: component, - } +func newComponent(params initParams) workercommon.WorkerComponent { + return &addSearchAttributes{initParams: params} } -func (wc *addSearchAttributes) RegisterWorkflow(worker sdkworker.Worker) { - worker.RegisterWorkflowWithOptions(AddSearchAttributesWorkflow, workflow.RegisterOptions{Name: WorkflowName}) +func (wc *addSearchAttributes) RegisterWorkflow(registry sdkworker.Registry) { + registry.RegisterWorkflowWithOptions(AddSearchAttributesWorkflow, workflow.RegisterOptions{Name: WorkflowName}) } func (wc *addSearchAttributes) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { @@ -82,8 +70,8 @@ func (wc *addSearchAttributes) DedicatedWorkflowWorkerOptions() *workercommon.De return nil } -func (wc *addSearchAttributes) RegisterActivities(worker sdkworker.Worker) { - worker.RegisterActivity(wc.activities()) +func (wc *addSearchAttributes) RegisterActivities(registry sdkworker.Registry) { + registry.RegisterActivity(wc.activities()) } func (wc *addSearchAttributes) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { diff --git a/service/worker/batcher/fx.go b/service/worker/batcher/fx.go index d01a7da7ae3..788ff899cf2 100644 --- a/service/worker/batcher/fx.go +++ b/service/worker/batcher/fx.go @@ -94,9 +94,9 @@ func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *worke } } -func (s *workerComponent) Register(worker sdkworker.Worker, ns *namespace.Namespace, _ workercommon.RegistrationDetails) { - worker.RegisterWorkflowWithOptions(BatchWorkflow, workflow.RegisterOptions{Name: BatchWFTypeName}) - worker.RegisterActivity(s.activities(ns.Name(), ns.ID())) +func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, _ workercommon.RegistrationDetails) { + registry.RegisterWorkflowWithOptions(BatchWorkflow, workflow.RegisterOptions{Name: BatchWFTypeName}) + registry.RegisterActivity(s.activities(ns.Name(), ns.ID())) } func (s *workerComponent) activities(name namespace.Name, id namespace.ID) *activities { diff --git a/service/worker/common/fx.go b/service/worker/common/fx.go new file mode 100644 index 00000000000..2b70f44aef5 --- /dev/null +++ b/service/worker/common/fx.go @@ -0,0 +1,38 @@ +// The MIT License +// +// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. +// +// Copyright (c) 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 common + +import "go.uber.org/fx" + +// WorkerComponentTag is the fx group tag for worker components. This is used to allow those who use Temporal as a +// library to dynamically register their own system workers. Use this to annotate a worker component consumer. Use the +// AnnotateWorkerComponentProvider function to annotate a worker component provider. +const WorkerComponentTag = `group:"workerComponent"` + +// AnnotateWorkerComponentProvider converts a WorkerComponent factory function into an fx provider which will add the +// WorkerComponentTag to the result. +func AnnotateWorkerComponentProvider[T any](f func(t T) WorkerComponent) fx.Option { + return fx.Provide(fx.Annotate(f, fx.ResultTags(WorkerComponentTag))) +} diff --git a/service/worker/common/interface.go b/service/worker/common/interface.go index 274b0fb8518..008920903ae 100644 --- a/service/worker/common/interface.go +++ b/service/worker/common/interface.go @@ -28,6 +28,7 @@ package common import ( sdkworker "go.temporal.io/sdk/worker" + "go.temporal.io/server/common/namespace" ) @@ -36,13 +37,13 @@ type ( WorkerComponent interface { // RegisterWorkflow registers Workflow types provided by this worker component. // Local Activities should also be registered here because they are executed on the workflow worker. - RegisterWorkflow(sdkworker.Worker) + RegisterWorkflow(registry sdkworker.Registry) // DedicatedWorkflowWorkerOptions returns a DedicatedWorkerOptions for this worker component. // Return nil to use default worker instance. DedicatedWorkflowWorkerOptions() *DedicatedWorkerOptions // RegisterActivities registers remote Activity types provided by this worker component. // Local Activities should be registered in RegisterWorkflow - RegisterActivities(sdkworker.Worker) + RegisterActivities(registry sdkworker.Registry) // DedicatedActivityWorkerOptions returns a DedicatedWorkerOptions for this worker component. // Return nil to use default worker instance. DedicatedActivityWorkerOptions() *DedicatedWorkerOptions @@ -61,7 +62,7 @@ type ( PerNSWorkerComponent interface { // Register registers Workflow and Activity types provided by this worker component. // The namespace that this worker is running in is also provided. - Register(sdkworker.Worker, *namespace.Namespace, RegistrationDetails) + Register(sdkworker.Registry, *namespace.Namespace, RegistrationDetails) // DedicatedWorkerOptions returns a PerNSDedicatedWorkerOptions for this worker component. DedicatedWorkerOptions(*namespace.Namespace) *PerNSDedicatedWorkerOptions } diff --git a/service/worker/common/interface_mock.go b/service/worker/common/interface_mock.go index 3e7178c361c..10acffea4bc 100644 --- a/service/worker/common/interface_mock.go +++ b/service/worker/common/interface_mock.go @@ -88,27 +88,27 @@ func (mr *MockWorkerComponentMockRecorder) DedicatedWorkflowWorkerOptions() *gom } // RegisterActivities mocks base method. -func (m *MockWorkerComponent) RegisterActivities(arg0 worker.Worker) { +func (m *MockWorkerComponent) RegisterActivities(registry worker.Registry) { m.ctrl.T.Helper() - m.ctrl.Call(m, "RegisterActivities", arg0) + m.ctrl.Call(m, "RegisterActivities", registry) } // RegisterActivities indicates an expected call of RegisterActivities. -func (mr *MockWorkerComponentMockRecorder) RegisterActivities(arg0 interface{}) *gomock.Call { +func (mr *MockWorkerComponentMockRecorder) RegisterActivities(registry interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterActivities", reflect.TypeOf((*MockWorkerComponent)(nil).RegisterActivities), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterActivities", reflect.TypeOf((*MockWorkerComponent)(nil).RegisterActivities), registry) } // RegisterWorkflow mocks base method. -func (m *MockWorkerComponent) RegisterWorkflow(arg0 worker.Worker) { +func (m *MockWorkerComponent) RegisterWorkflow(registry worker.Registry) { m.ctrl.T.Helper() - m.ctrl.Call(m, "RegisterWorkflow", arg0) + m.ctrl.Call(m, "RegisterWorkflow", registry) } // RegisterWorkflow indicates an expected call of RegisterWorkflow. -func (mr *MockWorkerComponentMockRecorder) RegisterWorkflow(arg0 interface{}) *gomock.Call { +func (mr *MockWorkerComponentMockRecorder) RegisterWorkflow(registry interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterWorkflow", reflect.TypeOf((*MockWorkerComponent)(nil).RegisterWorkflow), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterWorkflow", reflect.TypeOf((*MockWorkerComponent)(nil).RegisterWorkflow), registry) } // MockPerNSWorkerComponent is a mock of PerNSWorkerComponent interface. @@ -149,7 +149,7 @@ func (mr *MockPerNSWorkerComponentMockRecorder) DedicatedWorkerOptions(arg0 inte } // Register mocks base method. -func (m *MockPerNSWorkerComponent) Register(arg0 worker.Worker, arg1 *namespace.Namespace, arg2 RegistrationDetails) { +func (m *MockPerNSWorkerComponent) Register(arg0 worker.Registry, arg1 *namespace.Namespace, arg2 RegistrationDetails) { m.ctrl.T.Helper() m.ctrl.Call(m, "Register", arg0, arg1, arg2) } diff --git a/service/worker/deletenamespace/fx.go b/service/worker/deletenamespace/fx.go index 6070d5f9368..362b3525c71 100644 --- a/service/worker/deletenamespace/fx.go +++ b/service/worker/deletenamespace/fx.go @@ -52,43 +52,39 @@ type ( metricsHandler metrics.Handler logger log.Logger } - - component struct { - fx.Out - DeleteNamespaceComponent workercommon.WorkerComponent `group:"workerComponent"` + componentParams struct { + fx.In + VisibilityManager manager.VisibilityManager + MetadataManager persistence.MetadataManager + HistoryClient resource.HistoryClient + MetricsHandler metrics.Handler + Logger log.Logger } ) -var Module = fx.Options( - fx.Provide(newComponent), -) +var Module = workercommon.AnnotateWorkerComponentProvider(newComponent) func newComponent( - visibilityManager manager.VisibilityManager, - metadataManager persistence.MetadataManager, - historyClient resource.HistoryClient, - metricsHandler metrics.Handler, - logger log.Logger, -) component { - return component{ - DeleteNamespaceComponent: &deleteNamespaceComponent{ - visibilityManager: visibilityManager, - metadataManager: metadataManager, - historyClient: historyClient, - metricsHandler: metricsHandler, - logger: logger, - }} + params componentParams, +) workercommon.WorkerComponent { + return &deleteNamespaceComponent{ + visibilityManager: params.VisibilityManager, + metadataManager: params.MetadataManager, + historyClient: params.HistoryClient, + metricsHandler: params.MetricsHandler, + logger: params.Logger, + } } -func (wc *deleteNamespaceComponent) RegisterWorkflow(worker sdkworker.Worker) { - worker.RegisterWorkflowWithOptions(DeleteNamespaceWorkflow, workflow.RegisterOptions{Name: WorkflowName}) - worker.RegisterActivity(wc.deleteNamespaceLocalActivities()) +func (wc *deleteNamespaceComponent) RegisterWorkflow(registry sdkworker.Registry) { + registry.RegisterWorkflowWithOptions(DeleteNamespaceWorkflow, workflow.RegisterOptions{Name: WorkflowName}) + registry.RegisterActivity(wc.deleteNamespaceLocalActivities()) - worker.RegisterWorkflowWithOptions(reclaimresources.ReclaimResourcesWorkflow, workflow.RegisterOptions{Name: reclaimresources.WorkflowName}) - worker.RegisterActivity(wc.reclaimResourcesLocalActivities()) + registry.RegisterWorkflowWithOptions(reclaimresources.ReclaimResourcesWorkflow, workflow.RegisterOptions{Name: reclaimresources.WorkflowName}) + registry.RegisterActivity(wc.reclaimResourcesLocalActivities()) - worker.RegisterWorkflowWithOptions(deleteexecutions.DeleteExecutionsWorkflow, workflow.RegisterOptions{Name: deleteexecutions.WorkflowName}) - worker.RegisterActivity(wc.deleteExecutionsLocalActivities()) + registry.RegisterWorkflowWithOptions(deleteexecutions.DeleteExecutionsWorkflow, workflow.RegisterOptions{Name: deleteexecutions.WorkflowName}) + registry.RegisterActivity(wc.deleteExecutionsLocalActivities()) } func (wc *deleteNamespaceComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { @@ -96,9 +92,9 @@ func (wc *deleteNamespaceComponent) DedicatedWorkflowWorkerOptions() *workercomm return nil } -func (wc *deleteNamespaceComponent) RegisterActivities(worker sdkworker.Worker) { - worker.RegisterActivity(wc.reclaimResourcesActivities()) - worker.RegisterActivity(wc.deleteExecutionsActivities()) +func (wc *deleteNamespaceComponent) RegisterActivities(registry sdkworker.Registry) { + registry.RegisterActivity(wc.reclaimResourcesActivities()) + registry.RegisterActivity(wc.deleteExecutionsActivities()) } func (wc *deleteNamespaceComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { diff --git a/service/worker/dlq/workflow.go b/service/worker/dlq/workflow.go new file mode 100644 index 00000000000..a7ba9dda79a --- /dev/null +++ b/service/worker/dlq/workflow.go @@ -0,0 +1,169 @@ +// The MIT License +// +// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. +// +// Copyright (c) 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 dlq contains the workflow for deleting and re-enqueueing DLQ tasks. Both of these operations are performed by +// the same workflow to avoid concurrent deletion and re-enqueueing of the same task. +package dlq + +import ( + "context" + "time" + + "go.temporal.io/api/serviceerror" + "go.temporal.io/sdk/activity" + "go.temporal.io/sdk/temporal" + sdkworker "go.temporal.io/sdk/worker" + "go.temporal.io/sdk/workflow" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + + commonspb "go.temporal.io/server/api/common/v1" + "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/common/headers" + "go.temporal.io/server/common/primitives" + workercommon "go.temporal.io/server/service/worker/common" +) + +type ( + // WorkflowParams is the single argument to the DLQ workflow. + WorkflowParams struct { + // WorkflowType options are available via the WorkflowType* constants. + WorkflowType string + // DeleteParams is only used for WorkflowTypeDelete. + DeleteParams DeleteParams + } + // DeleteParams contain the target DLQ and the max message ID to delete up to. + DeleteParams struct { + TaskCategory int + SourceCluster string + TargetCluster string + MaxMessageID int64 + } + // HistoryServiceClient is a subset of the [historyservice.HistoryServiceClient] interface. + HistoryServiceClient interface { + DeleteDLQTasks( + ctx context.Context, + in *historyservice.DeleteDLQTasksRequest, + opts ...grpc.CallOption, + ) (*historyservice.DeleteDLQTasksResponse, error) + } + workerComponent struct { + client HistoryServiceClient + } +) + +const ( + // WorkflowName is the name of the DLQ workflow. + WorkflowName = "temporal-sys-dlq-workflow" + // WorkflowTypeDelete is what the value of WorkflowParams.WorkflowType should be to delete DLQ tasks. + WorkflowTypeDelete = "delete" + + errorTypeInvalidWorkflowType = "dlq-error-type-invalid-workflow-type" + errorTypeInvalidRequest = "dlq-error-type-invalid-request" + deleteTasksActivityName = "dlq-delete-tasks-activity" + + deleteTasksTimeout = 15 * time.Second +) + +// Module provides a [workercommon.WorkerComponent] annotated with [workercommon.WorkerComponentTag] to the graph, given +// a [HistoryServiceClient] dependency. +var Module = workercommon.AnnotateWorkerComponentProvider(newComponent) + +func newComponent(client HistoryServiceClient) workercommon.WorkerComponent { + return &workerComponent{ + client: client, + } +} + +//revive:disable:import-shadowing this doesn't actually shadow imports because it's a method, not a function +func (c *workerComponent) workflow(ctx workflow.Context, params WorkflowParams) error { + if params.WorkflowType == WorkflowTypeDelete { + ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + StartToCloseTimeout: deleteTasksTimeout, + TaskQueue: primitives.DLQActivityTQ, + }) + future := workflow.ExecuteActivity(ctx, deleteTasksActivityName, params.DeleteParams) + + return future.Get(ctx, nil) + } + + return temporal.NewNonRetryableApplicationError(params.WorkflowType, errorTypeInvalidWorkflowType, nil) +} + +func (c *workerComponent) deleteTasks(ctx context.Context, params DeleteParams) error { + req := &historyservice.DeleteDLQTasksRequest{ + DlqKey: &commonspb.HistoryDLQKey{ + TaskCategory: int32(params.TaskCategory), + SourceCluster: params.SourceCluster, + TargetCluster: params.TargetCluster, + }, + InclusiveMaxTaskMetadata: &commonspb.HistoryDLQTaskMetadata{ + MessageId: params.MaxMessageID, + }, + } + + _, err := c.client.DeleteDLQTasks(ctx, req) + if err != nil { + // Don't retry invalid-argument or not-found errors. + code := serviceerror.ToStatus(err).Code() + if code == codes.InvalidArgument || code == codes.NotFound { + return temporal.NewNonRetryableApplicationError( + "invalid argument deleting DLQ tasks", errorTypeInvalidRequest, err, + ) + } + // Use the default retry policy for all other errors. + return err + } + + return err +} + +func (c *workerComponent) RegisterWorkflow(registry sdkworker.Registry) { + registry.RegisterWorkflowWithOptions(c.workflow, workflow.RegisterOptions{ + Name: WorkflowName, + }) +} + +func (c *workerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { + // use default worker + return nil +} + +func (c *workerComponent) RegisterActivities(registry sdkworker.Registry) { + registry.RegisterActivityWithOptions(c.deleteTasks, activity.RegisterOptions{ + Name: deleteTasksActivityName, + }) +} + +func (c *workerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { + return &workercommon.DedicatedWorkerOptions{ + TaskQueue: primitives.DLQActivityTQ, + Options: sdkworker.Options{ + BackgroundActivityContext: headers.SetCallerType( + context.Background(), + headers.CallerTypePreemptable, + ), + }, + } +} diff --git a/service/worker/dlq/workflow_test.go b/service/worker/dlq/workflow_test.go new file mode 100644 index 00000000000..8e15d86eafd --- /dev/null +++ b/service/worker/dlq/workflow_test.go @@ -0,0 +1,176 @@ +// The MIT License +// +// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. +// +// Copyright (c) 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 dlq_test + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.temporal.io/api/serviceerror" + "go.temporal.io/sdk/temporal" + "go.temporal.io/sdk/testsuite" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + "google.golang.org/grpc" + + "go.temporal.io/server/api/historyservice/v1" + "go.temporal.io/server/service/history/tasks" + workercommon "go.temporal.io/server/service/worker/common" + "go.temporal.io/server/service/worker/dlq" +) + +type ( + testCase struct { + name string + // configure the test to override the default params + configure func(t *testing.T, params *testParams) + } + testParams struct { + workflowParams dlq.WorkflowParams + client *faultyHistoryClient + // expectation is run with the result of the workflow execution + expectation func(err error) + } + faultyHistoryClient struct { + err error + } +) + +// TestModule tests the [dlq.Module] instead of a constructor because we only export the module, and that implicitly +// tests the constructor. +func TestModule(t *testing.T) { + for _, tc := range []testCase{ + { + name: "happy path", + configure: func(t *testing.T, params *testParams) { + }, + }, + { + name: "invalid workflow type", + configure: func(t *testing.T, params *testParams) { + params.workflowParams.WorkflowType = "my-invalid-workflow-type" + params.expectation = func(err error) { + var applicationErr *temporal.ApplicationError + require.ErrorAs(t, err, &applicationErr) + assert.True(t, applicationErr.NonRetryable(), + "Invalid workflow type should be non-retryable") + assert.ErrorContains(t, err, "my-invalid-workflow-type") + } + }, + }, + { + name: "invalid argument error", + configure: func(t *testing.T, params *testParams) { + params.client.err = new(serviceerror.InvalidArgument) + verifyRetry(t, params, false) + }, + }, + { + name: "not found error", + configure: func(t *testing.T, params *testParams) { + params.client.err = new(serviceerror.NotFound) + verifyRetry(t, params, false) + }, + }, + { + name: "some other error", + configure: func(t *testing.T, params *testParams) { + params.client.err = assert.AnError + verifyRetry(t, params, true) + }, + }, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + params := getDefaultTestParams(t) + tc.configure(t, params) + + var components []workercommon.WorkerComponent + + fxtest.New( + t, + dlq.Module, + fx.Provide(func() dlq.HistoryServiceClient { + return params.client + }), + fx.Populate(fx.Annotate(&components, fx.ParamTags(workercommon.WorkerComponentTag))), + ) + require.Len(t, components, 1) + component := components[0] + testSuite := &testsuite.WorkflowTestSuite{} + env := testSuite.NewTestWorkflowEnvironment() + component.RegisterWorkflow(env) + component.RegisterActivities(env) + + env.ExecuteWorkflow(dlq.WorkflowName, params.workflowParams) + err := env.GetWorkflowError() + params.expectation(err) + }) + } +} + +func verifyRetry(t *testing.T, params *testParams, shouldRetry bool) { + params.expectation = func(err error) { + var applicationErr *temporal.ApplicationError + + require.ErrorAs(t, err, &applicationErr) + assert.Equal(t, applicationErr.NonRetryable(), !shouldRetry, + fmt.Sprintf( + "%v error should be considered retryable: %v", + params.client.err, shouldRetry, + ), + ) + } +} + +func getDefaultTestParams(t *testing.T) *testParams { + return &testParams{ + workflowParams: dlq.WorkflowParams{ + WorkflowType: dlq.WorkflowTypeDelete, + DeleteParams: dlq.DeleteParams{ + TaskCategory: tasks.CategoryTransfer.ID(), + SourceCluster: "source-cluster", + TargetCluster: "target-cluster", + }, + }, + client: &faultyHistoryClient{}, + expectation: func(err error) { + require.NoError(t, err) + }, + } +} + +func (t *faultyHistoryClient) DeleteDLQTasks( + context.Context, + *historyservice.DeleteDLQTasksRequest, + ...grpc.CallOption, +) (*historyservice.DeleteDLQTasksResponse, error) { + return nil, t.err +} diff --git a/service/worker/fx.go b/service/worker/fx.go index 02b97da42a1..602a766ca13 100644 --- a/service/worker/fx.go +++ b/service/worker/fx.go @@ -42,7 +42,9 @@ import ( "go.temporal.io/server/service" "go.temporal.io/server/service/worker/addsearchattributes" "go.temporal.io/server/service/worker/batcher" + workercommon "go.temporal.io/server/service/worker/common" "go.temporal.io/server/service/worker/deletenamespace" + "go.temporal.io/server/service/worker/dlq" "go.temporal.io/server/service/worker/migration" "go.temporal.io/server/service/worker/scheduler" ) @@ -54,6 +56,10 @@ var Module = fx.Options( deletenamespace.Module, scheduler.Module, batcher.Module, + dlq.Module, + fx.Provide(func(c resource.HistoryClient) dlq.HistoryServiceClient { + return c + }), fx.Provide(VisibilityManagerProvider), fx.Provide(dynamicconfig.NewCollection), fx.Provide(ThrottledLoggerRpsFnProvider), @@ -62,7 +68,7 @@ var Module = fx.Options( service.PersistenceLazyLoadedServiceResolverModule, fx.Provide(ServiceResolverProvider), fx.Provide(NewService), - fx.Provide(NewWorkerManager), + fx.Provide(fx.Annotate(NewWorkerManager, fx.ParamTags(workercommon.WorkerComponentTag))), fx.Provide(NewPerNamespaceWorkerManager), fx.Invoke(ServiceLifetimeHooks), ) diff --git a/service/worker/migration/fx.go b/service/worker/migration/fx.go index 4b6f4638653..20368e21089 100644 --- a/service/worker/migration/fx.go +++ b/service/worker/migration/fx.go @@ -59,35 +59,23 @@ type ( MetricsHandler metrics.Handler } - fxResult struct { - fx.Out - Component workercommon.WorkerComponent `group:"workerComponent"` - } - replicationWorkerComponent struct { initParams } ) -var Module = fx.Options( - fx.Provide(NewResult), -) +var Module = workercommon.AnnotateWorkerComponentProvider(newComponent) -func NewResult(params initParams) fxResult { - component := &replicationWorkerComponent{ - initParams: params, - } - return fxResult{ - Component: component, - } +func newComponent(params initParams) workercommon.WorkerComponent { + return &replicationWorkerComponent{initParams: params} } -func (wc *replicationWorkerComponent) RegisterWorkflow(worker sdkworker.Worker) { - worker.RegisterWorkflowWithOptions(ForceReplicationWorkflow, workflow.RegisterOptions{Name: forceReplicationWorkflowName}) - worker.RegisterWorkflowWithOptions(NamespaceHandoverWorkflow, workflow.RegisterOptions{Name: namespaceHandoverWorkflowName}) - worker.RegisterWorkflow(ForceTaskQueueUserDataReplicationWorkflow) +func (wc *replicationWorkerComponent) RegisterWorkflow(registry sdkworker.Registry) { + registry.RegisterWorkflowWithOptions(ForceReplicationWorkflow, workflow.RegisterOptions{Name: forceReplicationWorkflowName}) + registry.RegisterWorkflowWithOptions(NamespaceHandoverWorkflow, workflow.RegisterOptions{Name: namespaceHandoverWorkflowName}) + registry.RegisterWorkflow(ForceTaskQueueUserDataReplicationWorkflow) - worker.RegisterActivity(wc.activities().GetMetadata) // may be run locally + registry.RegisterActivity(wc.activities().GetMetadata) // may be run locally } func (wc *replicationWorkerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { @@ -95,8 +83,8 @@ func (wc *replicationWorkerComponent) DedicatedWorkflowWorkerOptions() *workerco return nil } -func (wc *replicationWorkerComponent) RegisterActivities(worker sdkworker.Worker) { - worker.RegisterActivity(wc.activities()) +func (wc *replicationWorkerComponent) RegisterActivities(registry sdkworker.Registry) { + registry.RegisterActivity(wc.activities()) } func (wc *replicationWorkerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { diff --git a/service/worker/scheduler/fx.go b/service/worker/scheduler/fx.go index 37220bc8595..0c59719f413 100644 --- a/service/worker/scheduler/fx.go +++ b/service/worker/scheduler/fx.go @@ -91,9 +91,9 @@ func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *worke } } -func (s *workerComponent) Register(worker sdkworker.Worker, ns *namespace.Namespace, details workercommon.RegistrationDetails) { - worker.RegisterWorkflowWithOptions(SchedulerWorkflow, workflow.RegisterOptions{Name: WorkflowType}) - worker.RegisterActivity(s.activities(ns.Name(), ns.ID(), details)) +func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, details workercommon.RegistrationDetails) { + registry.RegisterWorkflowWithOptions(SchedulerWorkflow, workflow.RegisterOptions{Name: WorkflowType}) + registry.RegisterActivity(s.activities(ns.Name(), ns.ID(), details)) } func (s *workerComponent) activities(name namespace.Name, id namespace.ID, details workercommon.RegistrationDetails) *activities { diff --git a/service/worker/worker.go b/service/worker/worker.go index e4aa30c7444..6102a083247 100644 --- a/service/worker/worker.go +++ b/service/worker/worker.go @@ -29,7 +29,6 @@ import ( "sync/atomic" sdkworker "go.temporal.io/sdk/worker" - "go.uber.org/fx" "go.temporal.io/server/common" "go.temporal.io/server/common/headers" @@ -49,20 +48,19 @@ type ( workers []sdkworker.Worker workerComponents []workercommon.WorkerComponent } - - initParams struct { - fx.In - Logger log.Logger - SdkClientFactory sdk.ClientFactory - WorkerComponents []workercommon.WorkerComponent `group:"workerComponent"` - } ) -func NewWorkerManager(params initParams) *workerManager { +// NewWorkerManager creates a new worker manager. The workerComponents argument must be first in order for the fx param +// tag to work correctly. +func NewWorkerManager( + workerComponents []workercommon.WorkerComponent, + logger log.Logger, + sdkClientFactory sdk.ClientFactory, +) *workerManager { return &workerManager{ - logger: params.Logger, - sdkClientFactory: params.SdkClientFactory, - workerComponents: params.WorkerComponents, + logger: logger, + sdkClientFactory: sdkClientFactory, + workerComponents: workerComponents, } } diff --git a/tests/purge_dlq_tasks_test.go b/tests/purge_dlq_tasks_test.go new file mode 100644 index 00000000000..56d269177a0 --- /dev/null +++ b/tests/purge_dlq_tasks_test.go @@ -0,0 +1,252 @@ +// The MIT License +// +// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. +// +// Copyright (c) 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 tests + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "go.temporal.io/api/serviceerror" + "go.uber.org/fx" + "google.golang.org/grpc/codes" + + "go.temporal.io/server/api/adminservice/v1" + commonspb "go.temporal.io/server/api/common/v1" + "go.temporal.io/server/common/config" + "go.temporal.io/server/common/persistence" + "go.temporal.io/server/common/persistence/persistencetest" + "go.temporal.io/server/common/primitives" + "go.temporal.io/server/common/sdk" + "go.temporal.io/server/service/history/tasks" +) + +type ( + purgeDLQTasksSuite struct { + *require.Assertions + FunctionalTestBase + dlq *faultyDLQ + sdkClientFactory sdk.ClientFactory + } + purgeDLQTasksTestCase struct { + name string + configure func(p *purgeDLQTasksTestParams) + } + purgeDLQTasksTestParams struct { + category tasks.Category + sourceCluster string + targetCluster string + maxMessageID int64 + apiCallErrorExpectation func(err error) + workflowErrorExpectation func(err error) + deleteTasksErr error + } + faultyDLQ struct { + persistence.HistoryTaskQueueManager + err error + } +) + +func (q *faultyDLQ) DeleteTasks( + ctx context.Context, + request *persistence.DeleteTasksRequest, +) (*persistence.DeleteTasksResponse, error) { + if q.err != nil { + return nil, q.err + } + + return q.HistoryTaskQueueManager.DeleteTasks(ctx, request) +} + +func (s *purgeDLQTasksSuite) SetupSuite() { + s.Assertions = require.New(s.T()) + s.setupSuite( + "testdata/cluster.yaml", + WithFxOptionsForService(primitives.HistoryService, + fx.Decorate(func(manager persistence.HistoryTaskQueueManager) persistence.HistoryTaskQueueManager { + s.dlq = &faultyDLQ{HistoryTaskQueueManager: manager} + return s.dlq + }), + ), + WithFxOptionsForService(primitives.FrontendService, + fx.Populate(&s.sdkClientFactory), + ), + ) +} + +func (s *purgeDLQTasksSuite) TearDownSuite() { + s.tearDownSuite() +} + +func (s *purgeDLQTasksSuite) SetupTest() { + s.Assertions = require.New(s.T()) +} + +func TestPurgeDLQTasksSuite(t *testing.T) { + if TestFlags.PersistenceType != config.StoreTypeNoSQL { + t.Skip("skipping dlq tests for non-cassandra persistence") + } + + suite.Run(t, new(purgeDLQTasksSuite)) +} + +func (s *purgeDLQTasksSuite) TestPurgeDLQTasks() { + for _, tc := range []purgeDLQTasksTestCase{ + { + name: "HappyPath", + }, + { + name: "MissingSourceCluster", + configure: func(p *purgeDLQTasksTestParams) { + p.sourceCluster = "" + p.apiCallErrorExpectation = func(err error) { + s.Error(err) + s.ErrorContains(err, "SourceCluster") + s.Equal(codes.InvalidArgument, serviceerror.ToStatus(err).Code()) + } + }, + }, + { + name: "MissingTargetCluster", + configure: func(p *purgeDLQTasksTestParams) { + p.targetCluster = "" + p.apiCallErrorExpectation = func(err error) { + s.Error(err) + s.ErrorContains(err, "TargetCluster") + s.Equal(codes.InvalidArgument, serviceerror.ToStatus(err).Code()) + } + }, + }, + { + name: "QueueDoesNotExist", + configure: func(p *purgeDLQTasksTestParams) { + p.targetCluster = "does-not-exist" + p.workflowErrorExpectation = func(err error) { + s.Error(err) + s.ErrorContains(err, "queue not found") + } + }, + }, + { + name: "DeleteTasksUnavailableError", + configure: func(p *purgeDLQTasksTestParams) { + p.deleteTasksErr = serviceerror.NewUnavailable("DLQ unavailable") + p.workflowErrorExpectation = func(err error) { + s.NoError(err) + } + }, + }, + } { + s.Run(tc.name, func() { + defaultParams := s.defaultDlqTestParams() + + params := defaultParams + if tc.configure != nil { + tc.configure(¶ms) + } + + ctx := context.Background() + + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + queueKey := persistence.QueueKey{ + QueueType: persistence.QueueTypeHistoryDLQ, + Category: defaultParams.category, + SourceCluster: defaultParams.sourceCluster, + TargetCluster: defaultParams.targetCluster, + } + s.enqueueTasks(ctx, queueKey, &tasks.WorkflowTask{}) + + purgeDLQTasksResponse, err := s.adminClient.PurgeDLQTasks(ctx, &adminservice.PurgeDLQTasksRequest{ + DlqKey: &commonspb.HistoryDLQKey{ + TaskCategory: int32(params.category.ID()), + SourceCluster: params.sourceCluster, + TargetCluster: params.targetCluster, + }, + InclusiveMaxTaskMetadata: &commonspb.HistoryDLQTaskMetadata{ + MessageId: persistence.FirstQueueMessageID + 1, + }, + }) + if params.apiCallErrorExpectation != nil { + params.apiCallErrorExpectation(err) + return + } + + s.NoError(err) + client := s.sdkClientFactory.GetSystemClient() + + var jobToken adminservice.DLQJobToken + err = jobToken.Unmarshal(purgeDLQTasksResponse.JobToken) + s.NoError(err) + + workflow := client.GetWorkflow(ctx, jobToken.WorkflowId, jobToken.RunId) + + err = workflow.Get(ctx, nil) + if params.workflowErrorExpectation != nil { + params.workflowErrorExpectation(err) + return + } + + s.NoError(err) + readRawTasksResponse, err := s.dlq.ReadRawTasks(ctx, &persistence.ReadRawTasksRequest{ + QueueKey: queueKey, + PageSize: 10, + }) + s.NoError(err) + s.Len(readRawTasksResponse.Tasks, 1) + s.Assert().Equal(int64(persistence.FirstQueueMessageID+2), readRawTasksResponse.Tasks[0].MessageMetadata.ID) + }) + } +} + +func (s *purgeDLQTasksSuite) defaultDlqTestParams() purgeDLQTasksTestParams { + queueKey := persistencetest.GetQueueKey(s.T()) + + return purgeDLQTasksTestParams{ + category: tasks.CategoryTransfer, + sourceCluster: queueKey.SourceCluster, + targetCluster: queueKey.TargetCluster, + } +} + +func (s *purgeDLQTasksSuite) enqueueTasks(ctx context.Context, queueKey persistence.QueueKey, task *tasks.WorkflowTask) { + _, err := s.dlq.CreateQueue(ctx, &persistence.CreateQueueRequest{ + QueueKey: queueKey, + }) + s.NoError(err) + + for i := 0; i < 3; i++ { + _, err := s.dlq.EnqueueTask(ctx, &persistence.EnqueueTaskRequest{ + QueueType: queueKey.QueueType, + SourceCluster: queueKey.SourceCluster, + TargetCluster: queueKey.TargetCluster, + Task: task, + }) + s.NoError(err) + } +}