support complex delete expression (#25752)

Signed-off-by: aoiasd <zhicheng.yue@zilliz.com>
pull/26976/head
aoiasd 2023-09-12 10:19:17 +08:00 committed by GitHub
parent dde3cd2f93
commit e107d0794c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 4231 additions and 1259 deletions

View File

@ -353,6 +353,7 @@ generate-mockery-proxy: getdeps
$(INSTALL_PATH)/mockery --name=LBPolicy --dir=$(PWD)/internal/proxy --output=$(PWD)/internal/proxy --filename=mock_lb_policy.go --structname=MockLBPolicy --with-expecter --outpkg=proxy --inpackage
$(INSTALL_PATH)/mockery --name=LBBalancer --dir=$(PWD)/internal/proxy --output=$(PWD)/internal/proxy --filename=mock_lb_balancer.go --structname=MockLBBalancer --with-expecter --outpkg=proxy --inpackage
$(INSTALL_PATH)/mockery --name=shardClientMgr --dir=$(PWD)/internal/proxy --output=$(PWD)/internal/proxy --filename=mock_shardclient_manager.go --structname=MockShardClientManager --with-expecter --outpkg=proxy --inpackage
$(INSTALL_PATH)/mockery --name=channelsMgr --dir=$(PWD)/internal/proxy --output=$(PWD)/internal/proxy --filename=mock_channels_manager.go --structname=MockChannelsMgr --with-expecter --outpkg=proxy --inpackage
generate-mockery-querycoord: getdeps
$(INSTALL_PATH)/mockery --name=QueryNodeServer --dir=$(PWD)/internal/proto/querypb/ --output=$(PWD)/internal/querycoordv2/mocks --filename=mock_querynode.go --with-expecter --structname=MockQueryNodeServer

View File

@ -520,116 +520,116 @@ const char descriptor_table_protodef_common_2eproto[] PROTOBUF_SECTION_VARIABLE(
"\020\004\022\t\n\005Retry\020\005*\202\001\n\014SegmentState\022\024\n\020Segmen"
"tStateNone\020\000\022\014\n\010NotExist\020\001\022\013\n\007Growing\020\002\022"
"\n\n\006Sealed\020\003\022\013\n\007Flushed\020\004\022\014\n\010Flushing\020\005\022\013"
"\n\007Dropped\020\006\022\r\n\tImporting\020\007*i\n\017Placeholde"
"\n\007Dropped\020\006\022\r\n\tImporting\020\007*V\n\017Placeholde"
"rType\022\010\n\004None\020\000\022\020\n\014BinaryVector\020d\022\017\n\013Flo"
"atVector\020e\022\021\n\rFloat16Vector\020f\022\t\n\005Int64\020\005"
"\022\013\n\007VarChar\020\025*\264\020\n\007MsgType\022\r\n\tUndefined\020\000"
"\022\024\n\020CreateCollection\020d\022\022\n\016DropCollection"
"\020e\022\021\n\rHasCollection\020f\022\026\n\022DescribeCollect"
"ion\020g\022\023\n\017ShowCollections\020h\022\024\n\020GetSystemC"
"onfigs\020i\022\022\n\016LoadCollection\020j\022\025\n\021ReleaseC"
"ollection\020k\022\017\n\013CreateAlias\020l\022\r\n\tDropAlia"
"s\020m\022\016\n\nAlterAlias\020n\022\023\n\017AlterCollection\020o"
"\022\024\n\020RenameCollection\020p\022\021\n\rDescribeAlias\020"
"q\022\017\n\013ListAliases\020r\022\024\n\017CreatePartition\020\310\001"
"\022\022\n\rDropPartition\020\311\001\022\021\n\014HasPartition\020\312\001\022"
"\026\n\021DescribePartition\020\313\001\022\023\n\016ShowPartition"
"s\020\314\001\022\023\n\016LoadPartitions\020\315\001\022\026\n\021ReleasePart"
"itions\020\316\001\022\021\n\014ShowSegments\020\372\001\022\024\n\017Describe"
"Segment\020\373\001\022\021\n\014LoadSegments\020\374\001\022\024\n\017Release"
"Segments\020\375\001\022\024\n\017HandoffSegments\020\376\001\022\030\n\023Loa"
"dBalanceSegments\020\377\001\022\025\n\020DescribeSegments\020"
"\200\002\022\034\n\027FederListIndexedSegment\020\201\002\022\"\n\035Fede"
"rDescribeSegmentIndexData\020\202\002\022\020\n\013CreateIn"
"dex\020\254\002\022\022\n\rDescribeIndex\020\255\002\022\016\n\tDropIndex\020"
"\256\002\022\027\n\022GetIndexStatistics\020\257\002\022\013\n\006Insert\020\220\003"
"\022\013\n\006Delete\020\221\003\022\n\n\005Flush\020\222\003\022\027\n\022ResendSegme"
"ntStats\020\223\003\022\013\n\006Upsert\020\224\003\022\013\n\006Search\020\364\003\022\021\n\014"
"SearchResult\020\365\003\022\022\n\rGetIndexState\020\366\003\022\032\n\025G"
"etIndexBuildProgress\020\367\003\022\034\n\027GetCollection"
"Statistics\020\370\003\022\033\n\026GetPartitionStatistics\020"
"\371\003\022\r\n\010Retrieve\020\372\003\022\023\n\016RetrieveResult\020\373\003\022\024"
"\n\017WatchDmChannels\020\374\003\022\025\n\020RemoveDmChannels"
"\020\375\003\022\027\n\022WatchQueryChannels\020\376\003\022\030\n\023RemoveQu"
"eryChannels\020\377\003\022\035\n\030SealedSegmentsChangeIn"
"fo\020\200\004\022\027\n\022WatchDeltaChannels\020\201\004\022\024\n\017GetSha"
"rdLeaders\020\202\004\022\020\n\013GetReplicas\020\203\004\022\023\n\016UnsubD"
"mChannel\020\204\004\022\024\n\017GetDistribution\020\205\004\022\025\n\020Syn"
"cDistribution\020\206\004\022\020\n\013SegmentInfo\020\330\004\022\017\n\nSy"
"stemInfo\020\331\004\022\024\n\017GetRecoveryInfo\020\332\004\022\024\n\017Get"
"SegmentState\020\333\004\022\r\n\010TimeTick\020\260\t\022\023\n\016QueryN"
"odeStats\020\261\t\022\016\n\tLoadIndex\020\262\t\022\016\n\tRequestID"
"\020\263\t\022\017\n\nRequestTSO\020\264\t\022\024\n\017AllocateSegment\020"
"\265\t\022\026\n\021SegmentStatistics\020\266\t\022\025\n\020SegmentFlu"
"shDone\020\267\t\022\017\n\nDataNodeTt\020\270\t\022\014\n\007Connect\020\271\t"
"\022\024\n\017ListClientInfos\020\272\t\022\023\n\016AllocTimestamp"
"\020\273\t\022\025\n\020CreateCredential\020\334\013\022\022\n\rGetCredent"
"ial\020\335\013\022\025\n\020DeleteCredential\020\336\013\022\025\n\020UpdateC"
"redential\020\337\013\022\026\n\021ListCredUsernames\020\340\013\022\017\n\n"
"CreateRole\020\300\014\022\r\n\010DropRole\020\301\014\022\024\n\017OperateU"
"serRole\020\302\014\022\017\n\nSelectRole\020\303\014\022\017\n\nSelectUse"
"r\020\304\014\022\023\n\016SelectResource\020\305\014\022\025\n\020OperatePriv"
"ilege\020\306\014\022\020\n\013SelectGrant\020\307\014\022\033\n\026RefreshPol"
"icyInfoCache\020\310\014\022\017\n\nListPolicy\020\311\014\022\030\n\023Crea"
"teResourceGroup\020\244\r\022\026\n\021DropResourceGroup\020"
"\245\r\022\027\n\022ListResourceGroups\020\246\r\022\032\n\025DescribeR"
"esourceGroup\020\247\r\022\021\n\014TransferNode\020\250\r\022\024\n\017Tr"
"ansferReplica\020\251\r\022\023\n\016CreateDatabase\020\211\016\022\021\n"
"\014DropDatabase\020\212\016\022\022\n\rListDatabases\020\213\016*\"\n\007"
"DslType\022\007\n\003Dsl\020\000\022\016\n\nBoolExprV1\020\001*B\n\017Comp"
"actionState\022\021\n\rUndefiedState\020\000\022\r\n\tExecut"
"ing\020\001\022\r\n\tCompleted\020\002*X\n\020ConsistencyLevel"
"\022\n\n\006Strong\020\000\022\013\n\007Session\020\001\022\013\n\007Bounded\020\002\022\016"
"\n\nEventually\020\003\022\016\n\nCustomized\020\004*\236\001\n\013Impor"
"tState\022\021\n\rImportPending\020\000\022\020\n\014ImportFaile"
"d\020\001\022\021\n\rImportStarted\020\002\022\023\n\017ImportPersiste"
"d\020\005\022\021\n\rImportFlushed\020\010\022\023\n\017ImportComplete"
"d\020\006\022\032\n\026ImportFailedAndCleaned\020\007*2\n\nObjec"
"tType\022\016\n\nCollection\020\000\022\n\n\006Global\020\001\022\010\n\004Use"
"r\020\002*\241\010\n\017ObjectPrivilege\022\020\n\014PrivilegeAll\020"
"\000\022\035\n\031PrivilegeCreateCollection\020\001\022\033\n\027Priv"
"ilegeDropCollection\020\002\022\037\n\033PrivilegeDescri"
"beCollection\020\003\022\034\n\030PrivilegeShowCollectio"
"ns\020\004\022\021\n\rPrivilegeLoad\020\005\022\024\n\020PrivilegeRele"
"ase\020\006\022\027\n\023PrivilegeCompaction\020\007\022\023\n\017Privil"
"egeInsert\020\010\022\023\n\017PrivilegeDelete\020\t\022\032\n\026Priv"
"ilegeGetStatistics\020\n\022\030\n\024PrivilegeCreateI"
"ndex\020\013\022\030\n\024PrivilegeIndexDetail\020\014\022\026\n\022Priv"
"ilegeDropIndex\020\r\022\023\n\017PrivilegeSearch\020\016\022\022\n"
"\016PrivilegeFlush\020\017\022\022\n\016PrivilegeQuery\020\020\022\030\n"
"\024PrivilegeLoadBalance\020\021\022\023\n\017PrivilegeImpo"
"rt\020\022\022\034\n\030PrivilegeCreateOwnership\020\023\022\027\n\023Pr"
"ivilegeUpdateUser\020\024\022\032\n\026PrivilegeDropOwne"
"rship\020\025\022\034\n\030PrivilegeSelectOwnership\020\026\022\034\n"
"\030PrivilegeManageOwnership\020\027\022\027\n\023Privilege"
"SelectUser\020\030\022\023\n\017PrivilegeUpsert\020\031\022 \n\034Pri"
"vilegeCreateResourceGroup\020\032\022\036\n\032Privilege"
"DropResourceGroup\020\033\022\"\n\036PrivilegeDescribe"
"ResourceGroup\020\034\022\037\n\033PrivilegeListResource"
"Groups\020\035\022\031\n\025PrivilegeTransferNode\020\036\022\034\n\030P"
"rivilegeTransferReplica\020\037\022\037\n\033PrivilegeGe"
"tLoadingProgress\020 \022\031\n\025PrivilegeGetLoadSt"
"ate\020!\022\035\n\031PrivilegeRenameCollection\020\"\022\033\n\027"
"PrivilegeCreateDatabase\020#\022\031\n\025PrivilegeDr"
"opDatabase\020$\022\032\n\026PrivilegeListDatabases\020%"
"\022\025\n\021PrivilegeFlushAll\020&*S\n\tStateCode\022\020\n\014"
"Initializing\020\000\022\013\n\007Healthy\020\001\022\014\n\010Abnormal\020"
"\002\022\013\n\007StandBy\020\003\022\014\n\010Stopping\020\004*c\n\tLoadStat"
"e\022\025\n\021LoadStateNotExist\020\000\022\024\n\020LoadStateNot"
"Load\020\001\022\024\n\020LoadStateLoading\020\002\022\023\n\017LoadStat"
"eLoaded\020\003:^\n\021privilege_ext_obj\022\037.google."
"protobuf.MessageOptions\030\351\007 \001(\0132!.milvus."
"proto.common.PrivilegeExtBm\n\016io.milvus.g"
"rpcB\013CommonProtoP\001Z4github.com/milvus-io"
"/milvus-proto/go-api/v2/commonpb\240\001\001\252\002\022Mi"
"lvus.Client.Grpcb\006proto3"
"atVector\020e\022\t\n\005Int64\020\005\022\013\n\007VarChar\020\025*\264\020\n\007M"
"sgType\022\r\n\tUndefined\020\000\022\024\n\020CreateCollectio"
"n\020d\022\022\n\016DropCollection\020e\022\021\n\rHasCollection"
"\020f\022\026\n\022DescribeCollection\020g\022\023\n\017ShowCollec"
"tions\020h\022\024\n\020GetSystemConfigs\020i\022\022\n\016LoadCol"
"lection\020j\022\025\n\021ReleaseCollection\020k\022\017\n\013Crea"
"teAlias\020l\022\r\n\tDropAlias\020m\022\016\n\nAlterAlias\020n"
"\022\023\n\017AlterCollection\020o\022\024\n\020RenameCollectio"
"n\020p\022\021\n\rDescribeAlias\020q\022\017\n\013ListAliases\020r\022"
"\024\n\017CreatePartition\020\310\001\022\022\n\rDropPartition\020\311"
"\001\022\021\n\014HasPartition\020\312\001\022\026\n\021DescribePartitio"
"n\020\313\001\022\023\n\016ShowPartitions\020\314\001\022\023\n\016LoadPartiti"
"ons\020\315\001\022\026\n\021ReleasePartitions\020\316\001\022\021\n\014ShowSe"
"gments\020\372\001\022\024\n\017DescribeSegment\020\373\001\022\021\n\014LoadS"
"egments\020\374\001\022\024\n\017ReleaseSegments\020\375\001\022\024\n\017Hand"
"offSegments\020\376\001\022\030\n\023LoadBalanceSegments\020\377\001"
"\022\025\n\020DescribeSegments\020\200\002\022\034\n\027FederListInde"
"xedSegment\020\201\002\022\"\n\035FederDescribeSegmentInd"
"exData\020\202\002\022\020\n\013CreateIndex\020\254\002\022\022\n\rDescribeI"
"ndex\020\255\002\022\016\n\tDropIndex\020\256\002\022\027\n\022GetIndexStati"
"stics\020\257\002\022\013\n\006Insert\020\220\003\022\013\n\006Delete\020\221\003\022\n\n\005Fl"
"ush\020\222\003\022\027\n\022ResendSegmentStats\020\223\003\022\013\n\006Upser"
"t\020\224\003\022\013\n\006Search\020\364\003\022\021\n\014SearchResult\020\365\003\022\022\n\r"
"GetIndexState\020\366\003\022\032\n\025GetIndexBuildProgres"
"s\020\367\003\022\034\n\027GetCollectionStatistics\020\370\003\022\033\n\026Ge"
"tPartitionStatistics\020\371\003\022\r\n\010Retrieve\020\372\003\022\023"
"\n\016RetrieveResult\020\373\003\022\024\n\017WatchDmChannels\020\374"
"\003\022\025\n\020RemoveDmChannels\020\375\003\022\027\n\022WatchQueryCh"
"annels\020\376\003\022\030\n\023RemoveQueryChannels\020\377\003\022\035\n\030S"
"ealedSegmentsChangeInfo\020\200\004\022\027\n\022WatchDelta"
"Channels\020\201\004\022\024\n\017GetShardLeaders\020\202\004\022\020\n\013Get"
"Replicas\020\203\004\022\023\n\016UnsubDmChannel\020\204\004\022\024\n\017GetD"
"istribution\020\205\004\022\025\n\020SyncDistribution\020\206\004\022\020\n"
"\013SegmentInfo\020\330\004\022\017\n\nSystemInfo\020\331\004\022\024\n\017GetR"
"ecoveryInfo\020\332\004\022\024\n\017GetSegmentState\020\333\004\022\r\n\010"
"TimeTick\020\260\t\022\023\n\016QueryNodeStats\020\261\t\022\016\n\tLoad"
"Index\020\262\t\022\016\n\tRequestID\020\263\t\022\017\n\nRequestTSO\020\264"
"\t\022\024\n\017AllocateSegment\020\265\t\022\026\n\021SegmentStatis"
"tics\020\266\t\022\025\n\020SegmentFlushDone\020\267\t\022\017\n\nDataNo"
"deTt\020\270\t\022\014\n\007Connect\020\271\t\022\024\n\017ListClientInfos"
"\020\272\t\022\023\n\016AllocTimestamp\020\273\t\022\025\n\020CreateCreden"
"tial\020\334\013\022\022\n\rGetCredential\020\335\013\022\025\n\020DeleteCre"
"dential\020\336\013\022\025\n\020UpdateCredential\020\337\013\022\026\n\021Lis"
"tCredUsernames\020\340\013\022\017\n\nCreateRole\020\300\014\022\r\n\010Dr"
"opRole\020\301\014\022\024\n\017OperateUserRole\020\302\014\022\017\n\nSelec"
"tRole\020\303\014\022\017\n\nSelectUser\020\304\014\022\023\n\016SelectResou"
"rce\020\305\014\022\025\n\020OperatePrivilege\020\306\014\022\020\n\013SelectG"
"rant\020\307\014\022\033\n\026RefreshPolicyInfoCache\020\310\014\022\017\n\n"
"ListPolicy\020\311\014\022\030\n\023CreateResourceGroup\020\244\r\022"
"\026\n\021DropResourceGroup\020\245\r\022\027\n\022ListResourceG"
"roups\020\246\r\022\032\n\025DescribeResourceGroup\020\247\r\022\021\n\014"
"TransferNode\020\250\r\022\024\n\017TransferReplica\020\251\r\022\023\n"
"\016CreateDatabase\020\211\016\022\021\n\014DropDatabase\020\212\016\022\022\n"
"\rListDatabases\020\213\016*\"\n\007DslType\022\007\n\003Dsl\020\000\022\016\n"
"\nBoolExprV1\020\001*B\n\017CompactionState\022\021\n\rUnde"
"fiedState\020\000\022\r\n\tExecuting\020\001\022\r\n\tCompleted\020"
"\002*X\n\020ConsistencyLevel\022\n\n\006Strong\020\000\022\013\n\007Ses"
"sion\020\001\022\013\n\007Bounded\020\002\022\016\n\nEventually\020\003\022\016\n\nC"
"ustomized\020\004*\236\001\n\013ImportState\022\021\n\rImportPen"
"ding\020\000\022\020\n\014ImportFailed\020\001\022\021\n\rImportStarte"
"d\020\002\022\023\n\017ImportPersisted\020\005\022\021\n\rImportFlushe"
"d\020\010\022\023\n\017ImportCompleted\020\006\022\032\n\026ImportFailed"
"AndCleaned\020\007*2\n\nObjectType\022\016\n\nCollection"
"\020\000\022\n\n\006Global\020\001\022\010\n\004User\020\002*\241\010\n\017ObjectPrivi"
"lege\022\020\n\014PrivilegeAll\020\000\022\035\n\031PrivilegeCreat"
"eCollection\020\001\022\033\n\027PrivilegeDropCollection"
"\020\002\022\037\n\033PrivilegeDescribeCollection\020\003\022\034\n\030P"
"rivilegeShowCollections\020\004\022\021\n\rPrivilegeLo"
"ad\020\005\022\024\n\020PrivilegeRelease\020\006\022\027\n\023PrivilegeC"
"ompaction\020\007\022\023\n\017PrivilegeInsert\020\010\022\023\n\017Priv"
"ilegeDelete\020\t\022\032\n\026PrivilegeGetStatistics\020"
"\n\022\030\n\024PrivilegeCreateIndex\020\013\022\030\n\024Privilege"
"IndexDetail\020\014\022\026\n\022PrivilegeDropIndex\020\r\022\023\n"
"\017PrivilegeSearch\020\016\022\022\n\016PrivilegeFlush\020\017\022\022"
"\n\016PrivilegeQuery\020\020\022\030\n\024PrivilegeLoadBalan"
"ce\020\021\022\023\n\017PrivilegeImport\020\022\022\034\n\030PrivilegeCr"
"eateOwnership\020\023\022\027\n\023PrivilegeUpdateUser\020\024"
"\022\032\n\026PrivilegeDropOwnership\020\025\022\034\n\030Privileg"
"eSelectOwnership\020\026\022\034\n\030PrivilegeManageOwn"
"ership\020\027\022\027\n\023PrivilegeSelectUser\020\030\022\023\n\017Pri"
"vilegeUpsert\020\031\022 \n\034PrivilegeCreateResourc"
"eGroup\020\032\022\036\n\032PrivilegeDropResourceGroup\020\033"
"\022\"\n\036PrivilegeDescribeResourceGroup\020\034\022\037\n\033"
"PrivilegeListResourceGroups\020\035\022\031\n\025Privile"
"geTransferNode\020\036\022\034\n\030PrivilegeTransferRep"
"lica\020\037\022\037\n\033PrivilegeGetLoadingProgress\020 \022"
"\031\n\025PrivilegeGetLoadState\020!\022\035\n\031PrivilegeR"
"enameCollection\020\"\022\033\n\027PrivilegeCreateData"
"base\020#\022\031\n\025PrivilegeDropDatabase\020$\022\032\n\026Pri"
"vilegeListDatabases\020%\022\025\n\021PrivilegeFlushA"
"ll\020&*S\n\tStateCode\022\020\n\014Initializing\020\000\022\013\n\007H"
"ealthy\020\001\022\014\n\010Abnormal\020\002\022\013\n\007StandBy\020\003\022\014\n\010S"
"topping\020\004*c\n\tLoadState\022\025\n\021LoadStateNotEx"
"ist\020\000\022\024\n\020LoadStateNotLoad\020\001\022\024\n\020LoadState"
"Loading\020\002\022\023\n\017LoadStateLoaded\020\003:^\n\021privil"
"ege_ext_obj\022\037.google.protobuf.MessageOpt"
"ions\030\351\007 \001(\0132!.milvus.proto.common.Privil"
"egeExtBi\n\016io.milvus.grpcB\013CommonProtoP\001Z"
"4github.com/milvus-io/milvus-proto/go-ap"
"i/v2/commonpb\240\001\001\252\002\016IO.Milvus.Grpcb\006proto"
"3"
;
static const ::_pbi::DescriptorTable* const descriptor_table_common_2eproto_deps[1] = {
&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
};
static ::_pbi::once_flag descriptor_table_common_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_common_2eproto = {
false, false, 7104, descriptor_table_protodef_common_2eproto,
false, false, 7081, descriptor_table_protodef_common_2eproto,
"common.proto",
&descriptor_table_common_2eproto_once, descriptor_table_common_2eproto_deps, 1, 16,
schemas, file_default_instances, TableStruct_common_2eproto::offsets,
@ -765,7 +765,6 @@ bool PlaceholderType_IsValid(int value) {
case 21:
case 100:
case 101:
case 102:
return true;
default:
return false;

View File

@ -271,7 +271,6 @@ enum PlaceholderType : int {
None = 0,
BinaryVector = 100,
FloatVector = 101,
Float16Vector = 102,
Int64 = 5,
VarChar = 21,
PlaceholderType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
@ -279,7 +278,7 @@ enum PlaceholderType : int {
};
bool PlaceholderType_IsValid(int value);
constexpr PlaceholderType PlaceholderType_MIN = None;
constexpr PlaceholderType PlaceholderType_MAX = Float16Vector;
constexpr PlaceholderType PlaceholderType_MAX = FloatVector;
constexpr int PlaceholderType_ARRAYSIZE = PlaceholderType_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* PlaceholderType_descriptor();

View File

@ -421,7 +421,6 @@ const uint32_t TableStruct_schema_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p
PROTOBUF_FIELD_OFFSET(::milvus::proto::schema::VectorField, _impl_.dim_),
::_pbi::kInvalidFieldOffsetTag,
::_pbi::kInvalidFieldOffsetTag,
::_pbi::kInvalidFieldOffsetTag,
PROTOBUF_FIELD_OFFSET(::milvus::proto::schema::VectorField, _impl_.data_),
~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(::milvus::proto::schema::FieldData, _internal_metadata_),
@ -474,9 +473,9 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode
{ 94, -1, -1, sizeof(::milvus::proto::schema::ValueField)},
{ 108, -1, -1, sizeof(::milvus::proto::schema::ScalarField)},
{ 124, -1, -1, sizeof(::milvus::proto::schema::VectorField)},
{ 135, -1, -1, sizeof(::milvus::proto::schema::FieldData)},
{ 148, -1, -1, sizeof(::milvus::proto::schema::IDs)},
{ 157, -1, -1, sizeof(::milvus::proto::schema::SearchResultData)},
{ 134, -1, -1, sizeof(::milvus::proto::schema::FieldData)},
{ 147, -1, -1, sizeof(::milvus::proto::schema::IDs)},
{ 156, -1, -1, sizeof(::milvus::proto::schema::SearchResultData)},
};
static const ::_pb::Message* const file_default_instances[] = {
@ -542,42 +541,40 @@ const char descriptor_table_protodef_schema_2eproto[] PROTOBUF_SECTION_VARIABLE(
"oto.schema.BytesArrayH\000\0225\n\narray_data\030\010 "
"\001(\0132\037.milvus.proto.schema.ArrayArrayH\000\0223"
"\n\tjson_data\030\t \001(\0132\036.milvus.proto.schema."
"JSONArrayH\000B\006\n\004data\"\216\001\n\013VectorField\022\013\n\003d"
"im\030\001 \001(\003\0227\n\014float_vector\030\002 \001(\0132\037.milvus."
"proto.schema.FloatArrayH\000\022\027\n\rbinary_vect"
"or\030\003 \001(\014H\000\022\030\n\016float16_vector\030\004 \001(\014H\000B\006\n\004"
"data\"\345\001\n\tFieldData\022+\n\004type\030\001 \001(\0162\035.milvu"
"s.proto.schema.DataType\022\022\n\nfield_name\030\002 "
"\001(\t\0223\n\007scalars\030\003 \001(\0132 .milvus.proto.sche"
"ma.ScalarFieldH\000\0223\n\007vectors\030\004 \001(\0132 .milv"
"us.proto.schema.VectorFieldH\000\022\020\n\010field_i"
"d\030\005 \001(\003\022\022\n\nis_dynamic\030\006 \001(\010B\007\n\005field\"w\n\003"
"IDs\0220\n\006int_id\030\001 \001(\0132\036.milvus.proto.schem"
"a.LongArrayH\000\0222\n\006str_id\030\002 \001(\0132 .milvus.p"
"roto.schema.StringArrayH\000B\n\n\010id_field\"\310\001"
"\n\020SearchResultData\022\023\n\013num_queries\030\001 \001(\003\022"
"\r\n\005top_k\030\002 \001(\003\0223\n\013fields_data\030\003 \003(\0132\036.mi"
"lvus.proto.schema.FieldData\022\016\n\006scores\030\004 "
"\003(\002\022%\n\003ids\030\005 \001(\0132\030.milvus.proto.schema.I"
"Ds\022\r\n\005topks\030\006 \003(\003\022\025\n\routput_fields\030\007 \003(\t"
"*\304\001\n\010DataType\022\010\n\004None\020\000\022\010\n\004Bool\020\001\022\010\n\004Int"
"8\020\002\022\t\n\005Int16\020\003\022\t\n\005Int32\020\004\022\t\n\005Int64\020\005\022\t\n\005"
"Float\020\n\022\n\n\006Double\020\013\022\n\n\006String\020\024\022\013\n\007VarCh"
"ar\020\025\022\t\n\005Array\020\026\022\010\n\004JSON\020\027\022\020\n\014BinaryVecto"
"r\020d\022\017\n\013FloatVector\020e\022\021\n\rFloat16Vector\020f*"
"V\n\nFieldState\022\020\n\014FieldCreated\020\000\022\021\n\rField"
"Creating\020\001\022\021\n\rFieldDropping\020\002\022\020\n\014FieldDr"
"opped\020\003Bm\n\016io.milvus.grpcB\013SchemaProtoP\001"
"Z4github.com/milvus-io/milvus-proto/go-a"
"pi/v2/schemapb\240\001\001\252\002\022Milvus.Client.Grpcb\006"
"proto3"
"JSONArrayH\000B\006\n\004data\"t\n\013VectorField\022\013\n\003di"
"m\030\001 \001(\003\0227\n\014float_vector\030\002 \001(\0132\037.milvus.p"
"roto.schema.FloatArrayH\000\022\027\n\rbinary_vecto"
"r\030\003 \001(\014H\000B\006\n\004data\"\345\001\n\tFieldData\022+\n\004type\030"
"\001 \001(\0162\035.milvus.proto.schema.DataType\022\022\n\n"
"field_name\030\002 \001(\t\0223\n\007scalars\030\003 \001(\0132 .milv"
"us.proto.schema.ScalarFieldH\000\0223\n\007vectors"
"\030\004 \001(\0132 .milvus.proto.schema.VectorField"
"H\000\022\020\n\010field_id\030\005 \001(\003\022\022\n\nis_dynamic\030\006 \001(\010"
"B\007\n\005field\"w\n\003IDs\0220\n\006int_id\030\001 \001(\0132\036.milvu"
"s.proto.schema.LongArrayH\000\0222\n\006str_id\030\002 \001"
"(\0132 .milvus.proto.schema.StringArrayH\000B\n"
"\n\010id_field\"\310\001\n\020SearchResultData\022\023\n\013num_q"
"ueries\030\001 \001(\003\022\r\n\005top_k\030\002 \001(\003\0223\n\013fields_da"
"ta\030\003 \003(\0132\036.milvus.proto.schema.FieldData"
"\022\016\n\006scores\030\004 \003(\002\022%\n\003ids\030\005 \001(\0132\030.milvus.p"
"roto.schema.IDs\022\r\n\005topks\030\006 \003(\003\022\025\n\routput"
"_fields\030\007 \003(\t*\261\001\n\010DataType\022\010\n\004None\020\000\022\010\n\004"
"Bool\020\001\022\010\n\004Int8\020\002\022\t\n\005Int16\020\003\022\t\n\005Int32\020\004\022\t"
"\n\005Int64\020\005\022\t\n\005Float\020\n\022\n\n\006Double\020\013\022\n\n\006Stri"
"ng\020\024\022\013\n\007VarChar\020\025\022\t\n\005Array\020\026\022\010\n\004JSON\020\027\022\020"
"\n\014BinaryVector\020d\022\017\n\013FloatVector\020e*V\n\nFie"
"ldState\022\020\n\014FieldCreated\020\000\022\021\n\rFieldCreati"
"ng\020\001\022\021\n\rFieldDropping\020\002\022\020\n\014FieldDropped\020"
"\003Bi\n\016io.milvus.grpcB\013SchemaProtoP\001Z4gith"
"ub.com/milvus-io/milvus-proto/go-api/v2/"
"schemapb\240\001\001\252\002\016IO.Milvus.Grpcb\006proto3"
;
static const ::_pbi::DescriptorTable* const descriptor_table_schema_2eproto_deps[1] = {
&::descriptor_table_common_2eproto,
};
static ::_pbi::once_flag descriptor_table_schema_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_schema_2eproto = {
false, false, 2806, descriptor_table_protodef_schema_2eproto,
false, false, 2756, descriptor_table_protodef_schema_2eproto,
"schema.proto",
&descriptor_table_schema_2eproto_once, descriptor_table_schema_2eproto_deps, 1, 17,
schemas, file_default_instances, TableStruct_schema_2eproto::offsets,
@ -613,7 +610,6 @@ bool DataType_IsValid(int value) {
case 23:
case 100:
case 101:
case 102:
return true;
default:
return false;
@ -4460,10 +4456,6 @@ VectorField::VectorField(const VectorField& from)
_this->_internal_set_binary_vector(from._internal_binary_vector());
break;
}
case kFloat16Vector: {
_this->_internal_set_float16_vector(from._internal_float16_vector());
break;
}
case DATA_NOT_SET: {
break;
}
@ -4517,10 +4509,6 @@ void VectorField::clear_data() {
_impl_.data_.binary_vector_.Destroy();
break;
}
case kFloat16Vector: {
_impl_.data_.float16_vector_.Destroy();
break;
}
case DATA_NOT_SET: {
break;
}
@ -4571,15 +4559,6 @@ const char* VectorField::_InternalParse(const char* ptr, ::_pbi::ParseContext* c
} else
goto handle_unusual;
continue;
// bytes float16_vector = 4;
case 4:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
auto str = _internal_mutable_float16_vector();
ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
CHK_(ptr);
} else
goto handle_unusual;
continue;
default:
goto handle_unusual;
} // switch
@ -4628,12 +4607,6 @@ uint8_t* VectorField::_InternalSerialize(
3, this->_internal_binary_vector(), target);
}
// bytes float16_vector = 4;
if (_internal_has_float16_vector()) {
target = stream->WriteBytesMaybeAliased(
4, this->_internal_float16_vector(), target);
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
@ -4670,13 +4643,6 @@ size_t VectorField::ByteSizeLong() const {
this->_internal_binary_vector());
break;
}
// bytes float16_vector = 4;
case kFloat16Vector: {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
this->_internal_float16_vector());
break;
}
case DATA_NOT_SET: {
break;
}
@ -4712,10 +4678,6 @@ void VectorField::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PR
_this->_internal_set_binary_vector(from._internal_binary_vector());
break;
}
case kFloat16Vector: {
_this->_internal_set_float16_vector(from._internal_float16_vector());
break;
}
case DATA_NOT_SET: {
break;
}

View File

@ -141,13 +141,12 @@ enum DataType : int {
JSON = 23,
BinaryVector = 100,
FloatVector = 101,
Float16Vector = 102,
DataType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
DataType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool DataType_IsValid(int value);
constexpr DataType DataType_MIN = None;
constexpr DataType DataType_MAX = Float16Vector;
constexpr DataType DataType_MAX = FloatVector;
constexpr int DataType_ARRAYSIZE = DataType_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* DataType_descriptor();
@ -2862,7 +2861,6 @@ class VectorField final :
enum DataCase {
kFloatVector = 2,
kBinaryVector = 3,
kFloat16Vector = 4,
DATA_NOT_SET = 0,
};
@ -2947,7 +2945,6 @@ class VectorField final :
kDimFieldNumber = 1,
kFloatVectorFieldNumber = 2,
kBinaryVectorFieldNumber = 3,
kFloat16VectorFieldNumber = 4,
};
// int64 dim = 1;
void clear_dim();
@ -2994,24 +2991,6 @@ class VectorField final :
std::string* _internal_mutable_binary_vector();
public:
// bytes float16_vector = 4;
bool has_float16_vector() const;
private:
bool _internal_has_float16_vector() const;
public:
void clear_float16_vector();
const std::string& float16_vector() const;
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_float16_vector(ArgT0&& arg0, ArgT... args);
std::string* mutable_float16_vector();
PROTOBUF_NODISCARD std::string* release_float16_vector();
void set_allocated_float16_vector(std::string* float16_vector);
private:
const std::string& _internal_float16_vector() const;
inline PROTOBUF_ALWAYS_INLINE void _internal_set_float16_vector(const std::string& value);
std::string* _internal_mutable_float16_vector();
public:
void clear_data();
DataCase data_case() const;
// @@protoc_insertion_point(class_scope:milvus.proto.schema.VectorField)
@ -3019,7 +2998,6 @@ class VectorField final :
class _Internal;
void set_has_float_vector();
void set_has_binary_vector();
void set_has_float16_vector();
inline bool has_data() const;
inline void clear_has_data();
@ -3034,7 +3012,6 @@ class VectorField final :
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized _constinit_;
::milvus::proto::schema::FloatArray* float_vector_;
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr binary_vector_;
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr float16_vector_;
} data_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
uint32_t _oneof_case_[1];
@ -6144,83 +6121,6 @@ inline void VectorField::set_allocated_binary_vector(std::string* binary_vector)
// @@protoc_insertion_point(field_set_allocated:milvus.proto.schema.VectorField.binary_vector)
}
// bytes float16_vector = 4;
inline bool VectorField::_internal_has_float16_vector() const {
return data_case() == kFloat16Vector;
}
inline bool VectorField::has_float16_vector() const {
return _internal_has_float16_vector();
}
inline void VectorField::set_has_float16_vector() {
_impl_._oneof_case_[0] = kFloat16Vector;
}
inline void VectorField::clear_float16_vector() {
if (_internal_has_float16_vector()) {
_impl_.data_.float16_vector_.Destroy();
clear_has_data();
}
}
inline const std::string& VectorField::float16_vector() const {
// @@protoc_insertion_point(field_get:milvus.proto.schema.VectorField.float16_vector)
return _internal_float16_vector();
}
template <typename ArgT0, typename... ArgT>
inline void VectorField::set_float16_vector(ArgT0&& arg0, ArgT... args) {
if (!_internal_has_float16_vector()) {
clear_data();
set_has_float16_vector();
_impl_.data_.float16_vector_.InitDefault();
}
_impl_.data_.float16_vector_.SetBytes( static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
// @@protoc_insertion_point(field_set:milvus.proto.schema.VectorField.float16_vector)
}
inline std::string* VectorField::mutable_float16_vector() {
std::string* _s = _internal_mutable_float16_vector();
// @@protoc_insertion_point(field_mutable:milvus.proto.schema.VectorField.float16_vector)
return _s;
}
inline const std::string& VectorField::_internal_float16_vector() const {
if (_internal_has_float16_vector()) {
return _impl_.data_.float16_vector_.Get();
}
return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited();
}
inline void VectorField::_internal_set_float16_vector(const std::string& value) {
if (!_internal_has_float16_vector()) {
clear_data();
set_has_float16_vector();
_impl_.data_.float16_vector_.InitDefault();
}
_impl_.data_.float16_vector_.Set(value, GetArenaForAllocation());
}
inline std::string* VectorField::_internal_mutable_float16_vector() {
if (!_internal_has_float16_vector()) {
clear_data();
set_has_float16_vector();
_impl_.data_.float16_vector_.InitDefault();
}
return _impl_.data_.float16_vector_.Mutable( GetArenaForAllocation());
}
inline std::string* VectorField::release_float16_vector() {
// @@protoc_insertion_point(field_release:milvus.proto.schema.VectorField.float16_vector)
if (_internal_has_float16_vector()) {
clear_has_data();
return _impl_.data_.float16_vector_.Release();
} else {
return nullptr;
}
}
inline void VectorField::set_allocated_float16_vector(std::string* float16_vector) {
if (has_data()) {
clear_data();
}
if (float16_vector != nullptr) {
set_has_float16_vector();
_impl_.data_.float16_vector_.InitAllocated(float16_vector, GetArenaForAllocation());
}
// @@protoc_insertion_point(field_set_allocated:milvus.proto.schema.VectorField.float16_vector)
}
inline bool VectorField::has_data() const {
return data_case() != DATA_NOT_SET;
}

View File

@ -27,6 +27,7 @@ import (
"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/util/commonpbutil"
"github.com/milvus-io/milvus/pkg/util/funcutil"
"github.com/milvus-io/milvus/pkg/util/paramtable"
@ -216,12 +217,40 @@ func (c *Client) Query(ctx context.Context, req *querypb.QueryRequest) (*interna
})
}
func (c *Client) QueryStream(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
_, err := c.grpcClient.ReCall(ctx, func(client querypb.QueryNodeClient) (any, error) {
if !funcutil.CheckCtxValid(ctx) {
return nil, ctx.Err()
}
cli, err := client.QueryStream(ctx, req)
if err == nil {
streamer.SetClient(cli)
}
return nil, err
})
return err
}
func (c *Client) QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
return wrapGrpcCall(ctx, c, func(client querypb.QueryNodeClient) (*internalpb.RetrieveResults, error) {
return client.QuerySegments(ctx, req)
})
}
func (c *Client) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
_, err := c.grpcClient.ReCall(ctx, func(client querypb.QueryNodeClient) (any, error) {
if !funcutil.CheckCtxValid(ctx) {
return nil, ctx.Err()
}
cli, err := client.QueryStreamSegments(ctx, req)
if err == nil {
streamer.SetClient(cli)
}
return nil, err
})
return err
}
// GetSegmentInfo gets the information of the specified segments in QueryNode.
func (c *Client) GetSegmentInfo(ctx context.Context, req *querypb.GetSegmentInfoRequest) (*querypb.GetSegmentInfoResponse, error) {
req = typeutil.Clone(req)

View File

@ -22,6 +22,7 @@ import (
"github.com/cockroachdb/errors"
"github.com/milvus-io/milvus/internal/util/mock"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/pkg/util/paramtable"
@ -113,6 +114,15 @@ func Test_NewClient(t *testing.T) {
r20, err := client.SearchSegments(ctx, nil)
retCheck(retNotNil, r20, err)
//stream rpc
streamer1 := streamrpc.NewGrpcQueryStreamer()
err = client.QueryStream(ctx, nil, streamer1)
retCheck(retNotNil, streamer1.AsClient(), err)
streamer2 := streamrpc.NewGrpcQueryStreamer()
err = client.QueryStreamSegments(ctx, nil, streamer2)
retCheck(retNotNil, streamer2.AsClient(), err)
}
client.grpcClient = &mock.GRPCClientBase[querypb.QueryNodeClient]{

View File

@ -26,6 +26,7 @@ import (
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/milvus-io/milvus/internal/util/dependency"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/tracer"
"github.com/milvus-io/milvus/pkg/util/interceptor"
clientv3 "go.etcd.io/etcd/client/v3"
@ -332,6 +333,18 @@ func (s *Server) Query(ctx context.Context, req *querypb.QueryRequest) (*interna
return s.querynode.Query(ctx, req)
}
func (s *Server) QueryStream(req *querypb.QueryRequest, srv querypb.QueryNode_QueryStreamServer) error {
streamer := streamrpc.NewGrpcQueryStreamer()
streamer.SetServer(streamrpc.NewConcurrentQueryStreamServer(srv))
return s.querynode.QueryStream(srv.Context(), req, streamer)
}
func (s *Server) QueryStreamSegments(req *querypb.QueryRequest, srv querypb.QueryNode_QueryStreamSegmentsServer) error {
streamer := streamrpc.NewGrpcQueryStreamer()
streamer.SetServer(streamrpc.NewConcurrentQueryStreamServer(srv))
return s.querynode.QueryStreamSegments(srv.Context(), req, streamer)
}
func (s *Server) QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
return s.querynode.QuerySegments(ctx, req)
}

View File

@ -25,6 +25,7 @@ import (
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/types"
streamMocks "github.com/milvus-io/milvus/internal/util/streamrpc/mocks"
"github.com/milvus-io/milvus/pkg/util/paramtable"
"github.com/stretchr/testify/assert"
@ -222,6 +223,16 @@ func Test_NewServer(t *testing.T) {
assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode())
})
t.Run("QueryStream", func(t *testing.T) {
mockQN.EXPECT().QueryStream(mock.Anything, mock.Anything, mock.Anything).Return(nil)
req := &querypb.QueryRequest{}
streamer := streamMocks.NewMockQueryStreamServer(t)
streamer.EXPECT().Context().Return(ctx)
err := server.QueryStream(req, streamer)
assert.NoError(t, err)
})
t.Run("QuerySegments", func(t *testing.T) {
mockQN.EXPECT().QuerySegments(mock.Anything, mock.Anything).Return(&internalpb.RetrieveResults{
Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}}, nil)
@ -231,6 +242,16 @@ func Test_NewServer(t *testing.T) {
assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode())
})
t.Run("QueryStreamSegments", func(t *testing.T) {
mockQN.EXPECT().QueryStreamSegments(mock.Anything, mock.Anything, mock.Anything).Return(nil)
req := &querypb.QueryRequest{}
streamer := streamMocks.NewMockQueryStreamSegmentsServer(t)
streamer.EXPECT().Context().Return(ctx)
err := server.QueryStreamSegments(req, streamer)
assert.NoError(t, err)
})
t.Run("SyncReplicaSegments", func(t *testing.T) {
mockQN.EXPECT().SyncReplicaSegments(mock.Anything, mock.Anything).Return(&commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}, nil)
req := &querypb.SyncReplicaSegmentsRequest{}

View File

@ -15,6 +15,8 @@ import (
mock "github.com/stretchr/testify/mock"
querypb "github.com/milvus-io/milvus/internal/proto/querypb"
streamrpc "github.com/milvus-io/milvus/internal/util/streamrpc"
)
// MockQueryNode is an autogenerated mock type for the QueryNodeComponent type
@ -769,6 +771,94 @@ func (_c *MockQueryNode_QuerySegments_Call) RunAndReturn(run func(context.Contex
return _c
}
// QueryStream provides a mock function with given fields: ctx, req, streamer
func (_m *MockQueryNode) QueryStream(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
ret := _m.Called(ctx, req, streamer)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamer) error); ok {
r0 = rf(ctx, req, streamer)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryNode_QueryStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStream'
type MockQueryNode_QueryStream_Call struct {
*mock.Call
}
// QueryStream is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.QueryRequest
// - streamer streamrpc.QueryStreamer
func (_e *MockQueryNode_Expecter) QueryStream(ctx interface{}, req interface{}, streamer interface{}) *MockQueryNode_QueryStream_Call {
return &MockQueryNode_QueryStream_Call{Call: _e.mock.On("QueryStream", ctx, req, streamer)}
}
func (_c *MockQueryNode_QueryStream_Call) Run(run func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer)) *MockQueryNode_QueryStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*querypb.QueryRequest), args[2].(streamrpc.QueryStreamer))
})
return _c
}
func (_c *MockQueryNode_QueryStream_Call) Return(_a0 error) *MockQueryNode_QueryStream_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryNode_QueryStream_Call) RunAndReturn(run func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamer) error) *MockQueryNode_QueryStream_Call {
_c.Call.Return(run)
return _c
}
// QueryStreamSegments provides a mock function with given fields: ctx, req, streamer
func (_m *MockQueryNode) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
ret := _m.Called(ctx, req, streamer)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamer) error); ok {
r0 = rf(ctx, req, streamer)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryNode_QueryStreamSegments_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStreamSegments'
type MockQueryNode_QueryStreamSegments_Call struct {
*mock.Call
}
// QueryStreamSegments is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.QueryRequest
// - streamer streamrpc.QueryStreamer
func (_e *MockQueryNode_Expecter) QueryStreamSegments(ctx interface{}, req interface{}, streamer interface{}) *MockQueryNode_QueryStreamSegments_Call {
return &MockQueryNode_QueryStreamSegments_Call{Call: _e.mock.On("QueryStreamSegments", ctx, req, streamer)}
}
func (_c *MockQueryNode_QueryStreamSegments_Call) Run(run func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer)) *MockQueryNode_QueryStreamSegments_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*querypb.QueryRequest), args[2].(streamrpc.QueryStreamer))
})
return _c
}
func (_c *MockQueryNode_QueryStreamSegments_Call) Return(_a0 error) *MockQueryNode_QueryStreamSegments_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryNode_QueryStreamSegments_Call) RunAndReturn(run func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamer) error) *MockQueryNode_QueryStreamSegments_Call {
_c.Call.Return(run)
return _c
}
// Register provides a mock function with given fields:
func (_m *MockQueryNode) Register() error {
ret := _m.Called()

View File

@ -67,7 +67,9 @@ service QueryNode {
rpc Search(SearchRequest) returns (internal.SearchResults) {}
rpc SearchSegments(SearchRequest) returns (internal.SearchResults) {}
rpc Query(QueryRequest) returns (internal.RetrieveResults) {}
rpc QueryStream(QueryRequest) returns (stream internal.RetrieveResults){}
rpc QuerySegments(QueryRequest) returns (internal.RetrieveResults) {}
rpc QueryStreamSegments(QueryRequest) returns (stream internal.RetrieveResults){}
rpc ShowConfigurations(internal.ShowConfigurationsRequest) returns (internal.ShowConfigurationsResponse){}
// https://wiki.lfaidata.foundation/display/MIL/MEP+8+--+Add+metrics+for+proxy

View File

@ -4574,306 +4574,307 @@ func init() {
func init() { proto.RegisterFile("query_coord.proto", fileDescriptor_aab7cc9a69ed26e8) }
var fileDescriptor_aab7cc9a69ed26e8 = []byte{
// 4769 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3c, 0x4b, 0x73, 0x24, 0x47,
0x5a, 0xd3, 0x4f, 0x75, 0x7f, 0xfd, 0x2a, 0xa5, 0xa4, 0x99, 0xde, 0xde, 0x99, 0xb1, 0x5c, 0xe3,
0x87, 0x56, 0xb6, 0xa5, 0x59, 0xcd, 0xda, 0x3b, 0xbb, 0xb6, 0xc3, 0xcc, 0x48, 0x9e, 0xb1, 0xd6,
0x63, 0x59, 0x5b, 0xd2, 0xcc, 0x12, 0xc6, 0xbb, 0xed, 0x52, 0x57, 0xaa, 0x55, 0x31, 0xf5, 0xe8,
0xa9, 0xaa, 0x96, 0x46, 0x26, 0x82, 0xe0, 0xc0, 0x85, 0x85, 0x05, 0x02, 0x0e, 0x70, 0x20, 0x38,
0x40, 0x10, 0xb1, 0x10, 0x70, 0x21, 0x20, 0x82, 0x03, 0x07, 0x6e, 0x9c, 0x78, 0xdc, 0xf8, 0x03,
0x70, 0x23, 0x82, 0x0b, 0x1b, 0x84, 0x6f, 0x44, 0x3e, 0xea, 0x91, 0x55, 0xd9, 0xea, 0x92, 0x7a,
0xbc, 0xb6, 0x89, 0xbd, 0x75, 0x7d, 0xf9, 0xf8, 0xbe, 0xfc, 0xf2, 0x7b, 0x67, 0x66, 0xc3, 0xfc,
0x93, 0x31, 0xf6, 0x4e, 0xfb, 0x03, 0xd7, 0xf5, 0x8c, 0xb5, 0x91, 0xe7, 0x06, 0x2e, 0x42, 0xb6,
0x69, 0x1d, 0x8f, 0x7d, 0xf6, 0xb5, 0x46, 0xdb, 0x7b, 0xcd, 0x81, 0x6b, 0xdb, 0xae, 0xc3, 0x60,
0xbd, 0x66, 0xb2, 0x47, 0xaf, 0x6d, 0x3a, 0x01, 0xf6, 0x1c, 0xdd, 0x0a, 0x5b, 0xfd, 0xc1, 0x11,
0xb6, 0x75, 0xfe, 0x55, 0xb7, 0xfd, 0x21, 0xff, 0xa9, 0x18, 0x7a, 0xa0, 0x27, 0x51, 0xf5, 0xe6,
0x4d, 0xc7, 0xc0, 0x4f, 0x93, 0x20, 0xf5, 0x37, 0x0a, 0x70, 0x79, 0xef, 0xc8, 0x3d, 0xd9, 0x74,
0x2d, 0x0b, 0x0f, 0x02, 0xd3, 0x75, 0x7c, 0x0d, 0x3f, 0x19, 0x63, 0x3f, 0x40, 0x37, 0xa1, 0x7c,
0xa0, 0xfb, 0xb8, 0x5b, 0x58, 0x2e, 0xac, 0x34, 0x36, 0xae, 0xae, 0x09, 0x74, 0x72, 0x02, 0x3f,
0xf0, 0x87, 0x77, 0x75, 0x1f, 0x6b, 0xb4, 0x27, 0x42, 0x50, 0x36, 0x0e, 0xb6, 0xb7, 0xba, 0xc5,
0xe5, 0xc2, 0x4a, 0x49, 0xa3, 0xbf, 0xd1, 0x0b, 0xd0, 0x1a, 0x44, 0x73, 0x6f, 0x6f, 0xf9, 0xdd,
0xd2, 0x72, 0x69, 0xa5, 0xa4, 0x89, 0x40, 0xf5, 0xc7, 0x45, 0xb8, 0x92, 0x21, 0xc3, 0x1f, 0xb9,
0x8e, 0x8f, 0xd1, 0x2d, 0xa8, 0xfa, 0x81, 0x1e, 0x8c, 0x7d, 0x4e, 0xc9, 0xd7, 0xa5, 0x94, 0xec,
0xd1, 0x2e, 0x1a, 0xef, 0x9a, 0x45, 0x5b, 0x94, 0xa0, 0x45, 0xdf, 0x84, 0x45, 0xd3, 0xf9, 0x00,
0xdb, 0xae, 0x77, 0xda, 0x1f, 0x61, 0x6f, 0x80, 0x9d, 0x40, 0x1f, 0xe2, 0x90, 0xc6, 0x85, 0xb0,
0x6d, 0x37, 0x6e, 0x42, 0x6f, 0xc0, 0x15, 0xb6, 0x87, 0x3e, 0xf6, 0x8e, 0xcd, 0x01, 0xee, 0xeb,
0xc7, 0xba, 0x69, 0xe9, 0x07, 0x16, 0xee, 0x96, 0x97, 0x4b, 0x2b, 0x35, 0x6d, 0x89, 0x36, 0xef,
0xb1, 0xd6, 0x3b, 0x61, 0x23, 0xfa, 0x06, 0x28, 0x1e, 0x3e, 0xf4, 0xb0, 0x7f, 0xd4, 0x1f, 0x79,
0xee, 0xd0, 0xc3, 0xbe, 0xdf, 0xad, 0x50, 0x34, 0x1d, 0x0e, 0xdf, 0xe5, 0x60, 0xf5, 0xcf, 0x0b,
0xb0, 0x44, 0x98, 0xb1, 0xab, 0x7b, 0x81, 0xf9, 0x39, 0x6c, 0x89, 0x0a, 0xcd, 0x24, 0x1b, 0xba,
0x25, 0xda, 0x26, 0xc0, 0x48, 0x9f, 0x51, 0x88, 0x9e, 0xb0, 0xaf, 0x4c, 0x49, 0x15, 0x60, 0xea,
0xbf, 0x72, 0xd9, 0x49, 0xd2, 0x39, 0xcb, 0x9e, 0xa5, 0x71, 0x16, 0xb3, 0x38, 0x2f, 0xb2, 0x63,
0x32, 0xce, 0x97, 0xe5, 0x9c, 0xff, 0xe7, 0x12, 0x2c, 0x3d, 0x70, 0x75, 0x23, 0x16, 0xc3, 0x9f,
0x3f, 0xe7, 0xdf, 0x86, 0x2a, 0xd3, 0xe8, 0x6e, 0x99, 0xe2, 0x7a, 0x51, 0xc4, 0xc5, 0xb5, 0x3d,
0xa6, 0x70, 0x8f, 0x02, 0x34, 0x3e, 0x08, 0xbd, 0x08, 0x6d, 0x0f, 0x8f, 0x2c, 0x73, 0xa0, 0xf7,
0x9d, 0xb1, 0x7d, 0x80, 0xbd, 0x6e, 0x65, 0xb9, 0xb0, 0x52, 0xd1, 0x5a, 0x1c, 0xba, 0x43, 0x81,
0xe8, 0x13, 0x68, 0x1d, 0x9a, 0xd8, 0x32, 0xfa, 0xd4, 0x24, 0x6c, 0x6f, 0x75, 0xab, 0xcb, 0xa5,
0x95, 0xc6, 0xc6, 0x9b, 0x6b, 0x59, 0x6b, 0xb4, 0x26, 0xe5, 0xc8, 0xda, 0x3d, 0x32, 0x7c, 0x9b,
0x8d, 0x7e, 0xd7, 0x09, 0xbc, 0x53, 0xad, 0x79, 0x98, 0x00, 0xa1, 0x2e, 0xcc, 0x71, 0xf6, 0x76,
0xe7, 0x96, 0x0b, 0x2b, 0x35, 0x2d, 0xfc, 0x44, 0x2f, 0x43, 0xc7, 0xc3, 0xbe, 0x3b, 0xf6, 0x06,
0xb8, 0x3f, 0xf4, 0xdc, 0xf1, 0xc8, 0xef, 0xd6, 0x96, 0x4b, 0x2b, 0x75, 0xad, 0x1d, 0x82, 0xef,
0x53, 0x68, 0xef, 0x1d, 0x98, 0xcf, 0x60, 0x41, 0x0a, 0x94, 0x1e, 0xe3, 0x53, 0xba, 0x11, 0x25,
0x8d, 0xfc, 0x44, 0x8b, 0x50, 0x39, 0xd6, 0xad, 0x31, 0xe6, 0xac, 0x66, 0x1f, 0xdf, 0x2d, 0xde,
0x2e, 0xa8, 0x7f, 0x5c, 0x80, 0xae, 0x86, 0x2d, 0xac, 0xfb, 0xf8, 0x8b, 0xdc, 0xd2, 0xcb, 0x50,
0x75, 0x5c, 0x03, 0x6f, 0x6f, 0xd1, 0x2d, 0x2d, 0x69, 0xfc, 0x4b, 0xfd, 0xac, 0x00, 0x8b, 0xf7,
0x71, 0x40, 0xd4, 0xc0, 0xf4, 0x03, 0x73, 0x10, 0xe9, 0xf9, 0xdb, 0x50, 0xf2, 0xf0, 0x13, 0x4e,
0xd9, 0x2b, 0x22, 0x65, 0x91, 0xf9, 0x97, 0x8d, 0xd4, 0xc8, 0x38, 0xf4, 0x3c, 0x34, 0x0d, 0xdb,
0xea, 0x0f, 0x8e, 0x74, 0xc7, 0xc1, 0x16, 0x53, 0xa4, 0xba, 0xd6, 0x30, 0x6c, 0x6b, 0x93, 0x83,
0xd0, 0x75, 0x00, 0x1f, 0x0f, 0x6d, 0xec, 0x04, 0xb1, 0x4d, 0x4e, 0x40, 0xd0, 0x2a, 0xcc, 0x1f,
0x7a, 0xae, 0xdd, 0xf7, 0x8f, 0x74, 0xcf, 0xe8, 0x5b, 0x58, 0x37, 0xb0, 0x47, 0xa9, 0xaf, 0x69,
0x1d, 0xd2, 0xb0, 0x47, 0xe0, 0x0f, 0x28, 0x18, 0xdd, 0x82, 0x8a, 0x3f, 0x70, 0x47, 0x98, 0x4a,
0x5a, 0x7b, 0xe3, 0x9a, 0x4c, 0x86, 0xb6, 0xf4, 0x40, 0xdf, 0x23, 0x9d, 0x34, 0xd6, 0x57, 0xfd,
0xfb, 0x32, 0x53, 0xb5, 0x2f, 0xb9, 0x91, 0x4b, 0xa8, 0x63, 0xe5, 0xd9, 0xa8, 0x63, 0x35, 0x97,
0x3a, 0xce, 0x9d, 0xad, 0x8e, 0x19, 0xae, 0x9d, 0x47, 0x1d, 0x6b, 0x53, 0xd5, 0xb1, 0x2e, 0x53,
0x47, 0xf4, 0x2e, 0x74, 0x58, 0x00, 0x61, 0x3a, 0x87, 0x6e, 0xdf, 0x32, 0xfd, 0xa0, 0x0b, 0x94,
0xcc, 0x6b, 0x69, 0x09, 0x35, 0xf0, 0xd3, 0x35, 0x86, 0xd8, 0x39, 0x74, 0xb5, 0x96, 0x19, 0xfe,
0x7c, 0x60, 0xfa, 0xc1, 0xec, 0x5a, 0xfd, 0x8f, 0xb1, 0x56, 0x7f, 0xd9, 0xa5, 0x27, 0xd6, 0xfc,
0x8a, 0xa0, 0xf9, 0x7f, 0x51, 0x80, 0xaf, 0xdd, 0xc7, 0x41, 0x44, 0x3e, 0x51, 0x64, 0xfc, 0x25,
0x75, 0xf3, 0x7f, 0x5d, 0x80, 0x9e, 0x8c, 0xd6, 0x59, 0x5c, 0xfd, 0x47, 0x70, 0x39, 0xc2, 0xd1,
0x37, 0xb0, 0x3f, 0xf0, 0xcc, 0x11, 0xdd, 0x46, 0x6a, 0xab, 0x1a, 0x1b, 0x37, 0x64, 0x82, 0x9f,
0xa6, 0x60, 0x29, 0x9a, 0x62, 0x2b, 0x31, 0x83, 0xfa, 0x93, 0x02, 0x2c, 0x11, 0xdb, 0xc8, 0x8d,
0x19, 0x91, 0xc0, 0x0b, 0xf3, 0x55, 0x34, 0x93, 0xc5, 0x8c, 0x99, 0xcc, 0xc1, 0x63, 0x1a, 0x62,
0xa7, 0xe9, 0x99, 0x85, 0x77, 0xaf, 0x43, 0x85, 0x28, 0x60, 0xc8, 0xaa, 0xe7, 0x64, 0xac, 0x4a,
0x22, 0x63, 0xbd, 0x55, 0x87, 0x51, 0x11, 0xdb, 0xed, 0x19, 0xc4, 0x2d, 0xbd, 0xec, 0xa2, 0x64,
0xd9, 0xbf, 0x5d, 0x80, 0x2b, 0x19, 0x84, 0xb3, 0xac, 0xfb, 0x2d, 0xa8, 0x52, 0x6f, 0x14, 0x2e,
0xfc, 0x05, 0xe9, 0xc2, 0x13, 0xe8, 0x88, 0xb5, 0xd1, 0xf8, 0x18, 0xd5, 0x05, 0x25, 0xdd, 0x46,
0xfc, 0x24, 0xf7, 0x91, 0x7d, 0x47, 0xb7, 0x19, 0x03, 0xea, 0x5a, 0x83, 0xc3, 0x76, 0x74, 0x1b,
0xa3, 0xaf, 0x41, 0x8d, 0xa8, 0x6c, 0xdf, 0x34, 0xc2, 0xed, 0x9f, 0xa3, 0x2a, 0x6c, 0xf8, 0xe8,
0x1a, 0x00, 0x6d, 0xd2, 0x0d, 0xc3, 0x63, 0x2e, 0xb4, 0xae, 0xd5, 0x09, 0xe4, 0x0e, 0x01, 0xa8,
0x7f, 0x54, 0x80, 0xeb, 0x7b, 0xa7, 0xce, 0x60, 0x07, 0x9f, 0x6c, 0x7a, 0x58, 0x0f, 0x70, 0x6c,
0xb4, 0x3f, 0x57, 0xc6, 0xa3, 0x65, 0x68, 0x24, 0xf4, 0x97, 0x8b, 0x64, 0x12, 0xa4, 0xfe, 0x4d,
0x01, 0x9a, 0xc4, 0x8b, 0x7c, 0x80, 0x03, 0x9d, 0x88, 0x08, 0xfa, 0x0e, 0xd4, 0x2d, 0x57, 0x37,
0xfa, 0xc1, 0xe9, 0x88, 0x51, 0xd3, 0x4e, 0x53, 0x13, 0xbb, 0x9e, 0xfd, 0xd3, 0x11, 0xd6, 0x6a,
0x16, 0xff, 0x95, 0x8b, 0xa2, 0xb4, 0x95, 0x29, 0x49, 0x2c, 0xe5, 0x73, 0xd0, 0xb0, 0x71, 0xe0,
0x99, 0x03, 0x46, 0x44, 0x99, 0x6e, 0x05, 0x30, 0x10, 0x41, 0xa4, 0xfe, 0xa4, 0x0a, 0x97, 0x7f,
0xa0, 0x07, 0x83, 0xa3, 0x2d, 0x3b, 0x8c, 0x62, 0x2e, 0xce, 0xc7, 0xd8, 0x2e, 0x17, 0x93, 0x76,
0xf9, 0x99, 0xd9, 0xfd, 0x48, 0x47, 0x2b, 0x32, 0x1d, 0x25, 0x89, 0xf9, 0xda, 0x23, 0x2e, 0x66,
0x09, 0x1d, 0x4d, 0x04, 0x1b, 0xd5, 0x8b, 0x04, 0x1b, 0x9b, 0xd0, 0xc2, 0x4f, 0x07, 0xd6, 0x98,
0xc8, 0x2b, 0xc5, 0xce, 0xa2, 0x88, 0xeb, 0x12, 0xec, 0x49, 0x03, 0xd1, 0xe4, 0x83, 0xb6, 0x39,
0x0d, 0x4c, 0x16, 0x6c, 0x1c, 0xe8, 0x34, 0x54, 0x68, 0x6c, 0x2c, 0x4f, 0x92, 0x85, 0x50, 0x80,
0x98, 0x3c, 0x90, 0x2f, 0x74, 0x15, 0xea, 0x3c, 0xb4, 0xd9, 0xde, 0xea, 0xd6, 0x29, 0xfb, 0x62,
0x00, 0xd2, 0xa1, 0xc5, 0xad, 0x27, 0xa7, 0x90, 0x05, 0x10, 0x6f, 0xc9, 0x10, 0xc8, 0x37, 0x3b,
0x49, 0xb9, 0xcf, 0x03, 0x1d, 0x3f, 0x01, 0x22, 0x99, 0xbf, 0x7b, 0x78, 0x68, 0x99, 0x0e, 0xde,
0x61, 0x3b, 0xdc, 0xa0, 0x44, 0x88, 0x40, 0x12, 0x0e, 0x1d, 0x63, 0xcf, 0x37, 0x5d, 0xa7, 0xdb,
0xa4, 0xed, 0xe1, 0xa7, 0x2c, 0xca, 0x69, 0x5d, 0x20, 0xca, 0xe9, 0xc3, 0x7c, 0x86, 0x52, 0x49,
0x94, 0xf3, 0xad, 0x64, 0x94, 0x33, 0x7d, 0xab, 0x12, 0x51, 0xd0, 0x4f, 0x0b, 0xb0, 0xf4, 0xd0,
0xf1, 0xc7, 0x07, 0x11, 0x8b, 0xbe, 0x18, 0x75, 0x48, 0x1b, 0xd1, 0x72, 0xc6, 0x88, 0xaa, 0xff,
0x53, 0x81, 0x0e, 0x5f, 0x05, 0x91, 0x1a, 0x6a, 0x72, 0xae, 0x42, 0x3d, 0xf2, 0xa3, 0x9c, 0x21,
0x31, 0x20, 0x6d, 0xc3, 0x8a, 0x19, 0x1b, 0x96, 0x8b, 0xb4, 0x30, 0x2a, 0x2a, 0x27, 0xa2, 0xa2,
0x6b, 0x00, 0x87, 0xd6, 0xd8, 0x3f, 0xea, 0x07, 0xa6, 0x8d, 0x79, 0x54, 0x56, 0xa7, 0x90, 0x7d,
0xd3, 0xc6, 0xe8, 0x0e, 0x34, 0x0f, 0x4c, 0xc7, 0x72, 0x87, 0xfd, 0x91, 0x1e, 0x1c, 0xf9, 0x3c,
0x2d, 0x96, 0x6d, 0x0b, 0x8d, 0x61, 0xef, 0xd2, 0xbe, 0x5a, 0x83, 0x8d, 0xd9, 0x25, 0x43, 0xd0,
0x75, 0x68, 0x38, 0x63, 0xbb, 0xef, 0x1e, 0xf6, 0x3d, 0xf7, 0xc4, 0xa7, 0xc9, 0x6f, 0x49, 0xab,
0x3b, 0x63, 0xfb, 0xc3, 0x43, 0xcd, 0x3d, 0x21, 0x7e, 0xac, 0x4e, 0x3c, 0x9a, 0x6f, 0xb9, 0x43,
0x96, 0xf8, 0x4e, 0x9f, 0x3f, 0x1e, 0x40, 0x46, 0x1b, 0xd8, 0x0a, 0x74, 0x3a, 0xba, 0x9e, 0x6f,
0x74, 0x34, 0x00, 0xbd, 0x04, 0xed, 0x81, 0x6b, 0x8f, 0x74, 0xca, 0xa1, 0x7b, 0x9e, 0x6b, 0x53,
0x05, 0x2c, 0x69, 0x29, 0x28, 0xda, 0x84, 0x46, 0xac, 0x04, 0x7e, 0xb7, 0x41, 0xf1, 0xa8, 0x32,
0x2d, 0x4d, 0x84, 0xf2, 0x44, 0x40, 0x21, 0xd2, 0x02, 0x9f, 0x48, 0x46, 0xa8, 0xec, 0xbe, 0xf9,
0x29, 0xe6, 0x8a, 0xd6, 0xe0, 0xb0, 0x3d, 0xf3, 0x53, 0x4c, 0xd2, 0x23, 0xd3, 0xf1, 0xb1, 0x17,
0x84, 0xc9, 0x6a, 0xb7, 0x45, 0xc5, 0xa7, 0xc5, 0xa0, 0x5c, 0xb0, 0xd1, 0x16, 0xb4, 0xfd, 0x40,
0xf7, 0x82, 0xfe, 0xc8, 0xf5, 0xa9, 0x00, 0x74, 0xdb, 0x54, 0xb6, 0x53, 0x2a, 0x69, 0xfb, 0x43,
0x22, 0xd8, 0xbb, 0xbc, 0x93, 0xd6, 0xa2, 0x83, 0xc2, 0x4f, 0x32, 0x0b, 0xe5, 0x44, 0x3c, 0x4b,
0x27, 0xd7, 0x2c, 0x74, 0x50, 0x34, 0xcb, 0x0a, 0x49, 0x97, 0x74, 0x43, 0x3f, 0xb0, 0xf0, 0x23,
0x6e, 0x41, 0x14, 0xba, 0xb0, 0x34, 0x58, 0xfd, 0xef, 0x22, 0xb4, 0x45, 0xf6, 0x10, 0xb3, 0xc3,
0xb2, 0xb2, 0x50, 0xe6, 0xc3, 0x4f, 0xc2, 0x2c, 0xec, 0x90, 0xd1, 0x2c, 0x05, 0xa4, 0x22, 0x5f,
0xd3, 0x1a, 0x0c, 0x46, 0x27, 0x20, 0xa2, 0xcb, 0x36, 0x85, 0xea, 0x59, 0x89, 0x32, 0xaa, 0x4e,
0x21, 0x34, 0x54, 0xe9, 0xc2, 0x5c, 0x98, 0x3d, 0x32, 0x81, 0x0f, 0x3f, 0x49, 0xcb, 0xc1, 0xd8,
0xa4, 0x58, 0x99, 0xc0, 0x87, 0x9f, 0x68, 0x0b, 0x9a, 0x6c, 0xca, 0x91, 0xee, 0xe9, 0x76, 0x28,
0xee, 0xcf, 0x4b, 0x4d, 0xc6, 0xfb, 0xf8, 0xf4, 0x11, 0xb1, 0x3e, 0xbb, 0xba, 0xe9, 0x69, 0x4c,
0x3c, 0x76, 0xe9, 0x28, 0xb4, 0x02, 0x0a, 0x9b, 0xe5, 0xd0, 0xb4, 0x30, 0x57, 0x9c, 0x39, 0x96,
0x42, 0x52, 0xf8, 0x3d, 0xd3, 0xc2, 0x4c, 0x37, 0xa2, 0x25, 0x50, 0x81, 0xa8, 0x31, 0xd5, 0xa0,
0x10, 0x2a, 0x0e, 0x37, 0x80, 0x59, 0xd1, 0x7e, 0x68, 0x9b, 0x99, 0x03, 0x61, 0x34, 0x72, 0xb6,
0xd2, 0x90, 0x6c, 0x6c, 0x33, 0xe5, 0x02, 0xb6, 0x1c, 0x67, 0x6c, 0x13, 0xd5, 0x52, 0x7f, 0xbf,
0x02, 0x0b, 0xc4, 0xc2, 0x70, 0x63, 0x33, 0x43, 0x80, 0x70, 0x0d, 0xc0, 0xf0, 0x83, 0xbe, 0x60,
0x15, 0xeb, 0x86, 0x1f, 0x70, 0xf7, 0xf1, 0x9d, 0xd0, 0xbf, 0x97, 0x26, 0xa7, 0x2b, 0x29, 0x8b,
0x97, 0xf5, 0xf1, 0x17, 0xaa, 0xef, 0xdd, 0x80, 0x16, 0xcf, 0xd5, 0x85, 0xc4, 0xb2, 0xc9, 0x80,
0x3b, 0x72, 0xbb, 0x5d, 0x95, 0xd6, 0x19, 0x13, 0x7e, 0x7e, 0x6e, 0x36, 0x3f, 0x5f, 0x4b, 0xfb,
0xf9, 0x7b, 0xd0, 0x11, 0x55, 0x2d, 0xb4, 0x55, 0x53, 0x74, 0xad, 0x2d, 0xe8, 0x9a, 0x9f, 0x74,
0xd3, 0x20, 0xba, 0xe9, 0x1b, 0xd0, 0x72, 0x30, 0x36, 0xfa, 0x81, 0xa7, 0x3b, 0xfe, 0x21, 0xf6,
0xa8, 0x9b, 0xaf, 0x69, 0x4d, 0x02, 0xdc, 0xe7, 0x30, 0xf4, 0x16, 0x00, 0x5d, 0x23, 0x2b, 0x4f,
0x35, 0x27, 0x97, 0xa7, 0xa8, 0xd0, 0xd0, 0xf2, 0x14, 0x65, 0x0a, 0xfd, 0xf9, 0x8c, 0x22, 0x01,
0xf5, 0x5f, 0x8a, 0x70, 0x99, 0x97, 0x2b, 0x66, 0x97, 0xcb, 0x49, 0x9e, 0x3a, 0x74, 0x75, 0xa5,
0x33, 0x0a, 0x00, 0xe5, 0x1c, 0xc1, 0x6c, 0x45, 0x12, 0xcc, 0x8a, 0x49, 0x70, 0x35, 0x93, 0x04,
0x47, 0xf5, 0xbf, 0xb9, 0xfc, 0xf5, 0x3f, 0xb4, 0x08, 0x15, 0x9a, 0x99, 0x51, 0xd9, 0xa9, 0x6b,
0xec, 0x23, 0xd7, 0xae, 0xaa, 0x7f, 0x58, 0x84, 0xd6, 0x1e, 0xd6, 0xbd, 0xc1, 0x51, 0xc8, 0xc7,
0x37, 0x92, 0xf5, 0xd2, 0x17, 0x26, 0xd4, 0x4b, 0x85, 0x21, 0x5f, 0x99, 0x42, 0x29, 0x41, 0x10,
0xb8, 0x81, 0x1e, 0x51, 0xd9, 0x77, 0xc6, 0x36, 0x2f, 0x22, 0x76, 0x68, 0x03, 0x27, 0x75, 0x67,
0x6c, 0xab, 0xff, 0x55, 0x80, 0xe6, 0xf7, 0xc9, 0x34, 0x21, 0x63, 0x6e, 0x27, 0x19, 0xf3, 0xd2,
0x04, 0xc6, 0x68, 0x24, 0xc9, 0xc2, 0xc7, 0xf8, 0x2b, 0x57, 0x43, 0xfe, 0xa7, 0x02, 0xf4, 0x48,
0x8a, 0xad, 0x31, 0xbb, 0x33, 0xbb, 0x76, 0xdd, 0x80, 0xd6, 0xb1, 0x10, 0xcc, 0x16, 0xa9, 0x70,
0x36, 0x8f, 0x93, 0x25, 0x01, 0x0d, 0x94, 0xb0, 0xa4, 0xcb, 0x17, 0x1b, 0xba, 0x81, 0x97, 0x65,
0x54, 0xa7, 0x88, 0xa3, 0x16, 0xa2, 0xe3, 0x89, 0x40, 0xf5, 0x77, 0x0a, 0xb0, 0x20, 0xe9, 0x88,
0xae, 0xc0, 0x1c, 0x2f, 0x3f, 0xf0, 0x78, 0x81, 0xe9, 0xbb, 0x41, 0xb6, 0x27, 0x2e, 0xa0, 0x99,
0x46, 0x36, 0x42, 0x36, 0x48, 0x46, 0x1d, 0xe5, 0x5a, 0x46, 0x66, 0x7f, 0x0c, 0x1f, 0xf5, 0xa0,
0xc6, 0xad, 0x69, 0x98, 0xc4, 0x46, 0xdf, 0xea, 0x63, 0x40, 0xf7, 0x71, 0xec, 0xbb, 0x66, 0xe1,
0x68, 0x6c, 0x6f, 0x62, 0x42, 0x93, 0x46, 0xc8, 0x50, 0xff, 0xa3, 0x00, 0x0b, 0x02, 0xb6, 0x59,
0xca, 0x44, 0xb1, 0x7f, 0x2d, 0x5e, 0xc4, 0xbf, 0x0a, 0xa5, 0x90, 0xd2, 0xb9, 0x4a, 0x21, 0xd7,
0x01, 0x22, 0xfe, 0x87, 0x1c, 0x4d, 0x40, 0xd4, 0x7f, 0x28, 0xc0, 0xe5, 0xf7, 0x74, 0xc7, 0x70,
0x0f, 0x0f, 0x67, 0x17, 0xd5, 0x4d, 0x10, 0xd2, 0xde, 0xbc, 0xc5, 0x40, 0x31, 0x57, 0x7e, 0x05,
0xe6, 0x3d, 0xe6, 0x99, 0x0c, 0x51, 0x96, 0x4b, 0x9a, 0x12, 0x36, 0x44, 0x32, 0xfa, 0x57, 0x45,
0x40, 0x64, 0xd5, 0x77, 0x75, 0x4b, 0x77, 0x06, 0xf8, 0xe2, 0xa4, 0xbf, 0x08, 0x6d, 0x21, 0x84,
0x89, 0x0e, 0xe7, 0x93, 0x31, 0x8c, 0x8f, 0xde, 0x87, 0xf6, 0x01, 0x43, 0xd5, 0xf7, 0xb0, 0xee,
0xbb, 0x0e, 0xdf, 0x0e, 0x69, 0xdd, 0x6f, 0xdf, 0x33, 0x87, 0x43, 0xec, 0x6d, 0xba, 0x8e, 0xc1,
0xa3, 0xf6, 0x83, 0x90, 0x4c, 0x32, 0x94, 0x28, 0x43, 0x1c, 0xcf, 0x45, 0x9b, 0x13, 0x05, 0x74,
0x94, 0x15, 0x3e, 0xd6, 0xad, 0x98, 0x11, 0xb1, 0x37, 0x54, 0x58, 0xc3, 0xde, 0xe4, 0xb2, 0xaf,
0x24, 0xbe, 0x52, 0xff, 0xb6, 0x00, 0x28, 0x4a, 0xcd, 0x69, 0x2d, 0x83, 0x6a, 0x74, 0x7a, 0x68,
0x41, 0xe2, 0x94, 0xaf, 0x42, 0xdd, 0x08, 0x47, 0x72, 0x13, 0x14, 0x03, 0xa8, 0x8f, 0xa4, 0x44,
0xf7, 0x89, 0xe4, 0x61, 0x23, 0x4c, 0x7d, 0x19, 0xf0, 0x01, 0x85, 0x89, 0xe1, 0x59, 0x39, 0x1d,
0x9e, 0x25, 0xab, 0x9a, 0x15, 0xa1, 0xaa, 0xa9, 0xfe, 0xb4, 0x08, 0x0a, 0x75, 0x21, 0x9b, 0x71,
0x79, 0x2a, 0x17, 0xd1, 0x37, 0xa0, 0xc5, 0x2f, 0xb7, 0x08, 0x84, 0x37, 0x9f, 0x24, 0x26, 0x43,
0x37, 0x61, 0x91, 0x75, 0xf2, 0xb0, 0x3f, 0xb6, 0xe2, 0xac, 0x8f, 0x25, 0x33, 0xe8, 0x09, 0xf3,
0x5d, 0xa4, 0x29, 0x1c, 0xf1, 0x10, 0x2e, 0x0f, 0x2d, 0xf7, 0x40, 0xb7, 0xfa, 0xe2, 0xf6, 0xb0,
0x3d, 0xcc, 0x21, 0xf1, 0x8b, 0x6c, 0xf8, 0x5e, 0x72, 0x0f, 0x7d, 0x74, 0x17, 0x5a, 0x3e, 0xc6,
0x8f, 0xe3, 0x54, 0xb0, 0x92, 0x27, 0x15, 0x6c, 0x92, 0x31, 0xe1, 0x97, 0xfa, 0x27, 0x05, 0xe8,
0xa4, 0xce, 0x24, 0xd2, 0x85, 0x8b, 0x42, 0xb6, 0x70, 0x71, 0x1b, 0x2a, 0xc4, 0x52, 0x31, 0xdf,
0xd2, 0x96, 0x27, 0xd5, 0xe2, 0xac, 0x1a, 0x1b, 0x80, 0xd6, 0x61, 0x41, 0x72, 0xf7, 0x81, 0x6f,
0x3f, 0xca, 0x5e, 0x7d, 0x50, 0x7f, 0x56, 0x86, 0x46, 0x82, 0x15, 0x53, 0x6a, 0x2e, 0xcf, 0xa4,
0xb6, 0x3c, 0xe9, 0xac, 0x9b, 0x88, 0x9c, 0x8d, 0x6d, 0x96, 0xf7, 0xf1, 0x24, 0xd4, 0xc6, 0x36,
0xcd, 0xfa, 0x92, 0x09, 0x5d, 0x55, 0x48, 0xe8, 0x52, 0x29, 0xef, 0xdc, 0x19, 0x29, 0x6f, 0x4d,
0x4c, 0x79, 0x05, 0x15, 0xaa, 0xa7, 0x55, 0x28, 0x6f, 0x19, 0xe4, 0x26, 0x2c, 0x0c, 0x58, 0xed,
0xfe, 0xee, 0xe9, 0x66, 0xd4, 0xc4, 0x83, 0x52, 0x59, 0x13, 0xba, 0x17, 0x17, 0x38, 0xd9, 0x2e,
0xb3, 0xa4, 0x43, 0x9e, 0x51, 0xf3, 0xbd, 0x61, 0x9b, 0x1c, 0x5a, 0x66, 0xfa, 0x95, 0x2e, 0xc0,
0xb4, 0x2e, 0x54, 0x80, 0x79, 0x0e, 0x1a, 0x61, 0xa4, 0x42, 0x34, 0xbd, 0xcd, 0x8c, 0x5e, 0x68,
0x06, 0x0c, 0x5f, 0xb0, 0x03, 0x1d, 0xf1, 0x74, 0x23, 0x5d, 0x8f, 0x50, 0xb2, 0xf5, 0x88, 0x2b,
0x30, 0x67, 0xfa, 0xfd, 0x43, 0xfd, 0x31, 0xee, 0xce, 0xd3, 0xd6, 0xaa, 0xe9, 0xdf, 0xd3, 0x1f,
0x63, 0xf5, 0xdf, 0x4a, 0xd0, 0x8e, 0x1d, 0x6c, 0x6e, 0x0b, 0x92, 0xe7, 0xfe, 0xcf, 0x0e, 0x28,
0x71, 0xdc, 0x43, 0x39, 0x7c, 0x66, 0x0e, 0x9e, 0x3e, 0x32, 0xec, 0x8c, 0x52, 0xfa, 0x2a, 0xb8,
0xfb, 0xf2, 0xb9, 0xdc, 0xfd, 0x8c, 0x37, 0x03, 0x6e, 0xc1, 0x52, 0xe4, 0x7b, 0x85, 0x65, 0xb3,
0x04, 0x6b, 0x31, 0x6c, 0xdc, 0x4d, 0x2e, 0x7f, 0x82, 0x09, 0x98, 0x9b, 0x64, 0x02, 0xd2, 0x22,
0x50, 0xcb, 0x88, 0x40, 0xf6, 0x82, 0x42, 0x5d, 0x72, 0x41, 0x41, 0x7d, 0x08, 0x0b, 0xb4, 0xd8,
0xec, 0x0f, 0x3c, 0xf3, 0x00, 0x47, 0x29, 0x40, 0x9e, 0x6d, 0xed, 0x41, 0x2d, 0x95, 0x45, 0x44,
0xdf, 0xea, 0x8f, 0x0b, 0x70, 0x39, 0x3b, 0x2f, 0x95, 0x98, 0xd8, 0x90, 0x14, 0x04, 0x43, 0xf2,
0xcb, 0xb0, 0x90, 0x88, 0x28, 0x85, 0x99, 0x27, 0x44, 0xe0, 0x12, 0xc2, 0x35, 0x14, 0xcf, 0x11,
0xc2, 0xd4, 0x9f, 0x15, 0xa2, 0x9a, 0x3d, 0x81, 0x0d, 0xe9, 0x81, 0x08, 0xf1, 0x6b, 0xae, 0x63,
0x99, 0x4e, 0x54, 0x70, 0xe1, 0x6b, 0x64, 0x40, 0x5e, 0x70, 0x79, 0x0f, 0x3a, 0xbc, 0x53, 0xe4,
0x9e, 0x72, 0x06, 0x64, 0x6d, 0x36, 0x2e, 0x72, 0x4c, 0x2f, 0x42, 0x9b, 0x9f, 0x54, 0x84, 0xf8,
0x4a, 0xb2, 0xf3, 0x8b, 0xef, 0x81, 0x12, 0x76, 0x3b, 0xaf, 0x43, 0xec, 0xf0, 0x81, 0x51, 0x60,
0xf7, 0x9b, 0x05, 0xe8, 0x8a, 0xee, 0x31, 0xb1, 0xfc, 0xf3, 0x87, 0x77, 0x6f, 0x8a, 0xe7, 0xd3,
0x2f, 0x9e, 0x41, 0x4f, 0x8c, 0x27, 0x3c, 0xa5, 0xfe, 0xbd, 0x22, 0xbd, 0x6c, 0x40, 0x52, 0xbd,
0x2d, 0xd3, 0x0f, 0x3c, 0xf3, 0x60, 0x3c, 0xdb, 0x89, 0xa9, 0x0e, 0x8d, 0xc1, 0x11, 0x1e, 0x3c,
0x1e, 0xb9, 0x66, 0xbc, 0x2b, 0xef, 0xc8, 0x68, 0x9a, 0x8c, 0x76, 0x6d, 0x33, 0x9e, 0x81, 0x1d,
0x39, 0x25, 0xe7, 0xec, 0xfd, 0x10, 0x94, 0x74, 0x87, 0xe4, 0x49, 0x4f, 0x9d, 0x9d, 0xf4, 0xdc,
0x12, 0x4f, 0x7a, 0xa6, 0x44, 0x1a, 0x89, 0x83, 0x9e, 0xbf, 0x2b, 0xc2, 0xd7, 0xa5, 0xb4, 0xcd,
0x92, 0x25, 0x4d, 0xaa, 0x23, 0xdd, 0x85, 0x5a, 0x2a, 0xa9, 0x7d, 0xe9, 0x8c, 0xfd, 0xe3, 0x25,
0x59, 0x56, 0x1a, 0xf4, 0xe3, 0xd8, 0x2a, 0x56, 0xf8, 0xf2, 0xe4, 0x39, 0xb8, 0xde, 0x09, 0x73,
0x84, 0xe3, 0xd0, 0x1d, 0x68, 0xb2, 0x82, 0x41, 0xff, 0xd8, 0xc4, 0x27, 0xe1, 0x39, 0xea, 0x75,
0xa9, 0x69, 0xa6, 0xfd, 0x1e, 0x99, 0xf8, 0x44, 0x6b, 0x58, 0xd1, 0x6f, 0x5f, 0xfd, 0x83, 0x32,
0x40, 0xdc, 0x46, 0xb2, 0xb3, 0x58, 0xe7, 0xb9, 0x12, 0x27, 0x20, 0x24, 0x96, 0x10, 0x23, 0xd7,
0xf0, 0x13, 0x69, 0xf1, 0x39, 0x86, 0x61, 0xfa, 0x01, 0xe7, 0xcb, 0xfa, 0xd9, 0xb4, 0x84, 0x2c,
0x22, 0x5b, 0xc6, 0x65, 0xc6, 0x8f, 0x21, 0xe8, 0x35, 0x40, 0x43, 0xcf, 0x3d, 0x31, 0x9d, 0x61,
0x32, 0xdf, 0x60, 0x69, 0xc9, 0x3c, 0x6f, 0x49, 0x24, 0x1c, 0x3f, 0x02, 0x25, 0xd5, 0x3d, 0x64,
0xc9, 0xad, 0x29, 0x64, 0xdc, 0x17, 0xe6, 0xe2, 0xe2, 0xdb, 0x11, 0x31, 0xd0, 0x43, 0xd3, 0x7d,
0xdd, 0x1b, 0xe2, 0x70, 0x47, 0x79, 0x1c, 0x26, 0x02, 0x7b, 0x7d, 0x50, 0xd2, 0xab, 0x92, 0x1c,
0x69, 0xbe, 0x2e, 0x0a, 0xfa, 0x59, 0xf6, 0x88, 0x4c, 0x93, 0x10, 0xf5, 0x9e, 0x0e, 0x8b, 0x32,
0x7a, 0x25, 0x48, 0x2e, 0xac, 0x4d, 0xef, 0x44, 0x21, 0x31, 0xdd, 0x87, 0x49, 0x5e, 0x26, 0x51,
0x78, 0x2e, 0x0a, 0x85, 0x67, 0xf5, 0xd7, 0x4b, 0x80, 0xb2, 0xe2, 0x8f, 0xda, 0x50, 0x8c, 0x26,
0x29, 0x6e, 0x6f, 0xa5, 0xc4, 0xad, 0x98, 0x11, 0xb7, 0xab, 0x50, 0x8f, 0xbc, 0x3e, 0x37, 0xf1,
0x31, 0x20, 0x29, 0x8c, 0x65, 0x51, 0x18, 0x13, 0x84, 0x55, 0xc4, 0x8a, 0xf8, 0x4d, 0x58, 0xb4,
0x74, 0x3f, 0xe8, 0xb3, 0xc2, 0x7b, 0x60, 0xda, 0xd8, 0x0f, 0x74, 0x7b, 0x44, 0xb7, 0xb2, 0xac,
0x21, 0xd2, 0xb6, 0x45, 0x9a, 0xf6, 0xc3, 0x16, 0xb4, 0x1f, 0x46, 0xd7, 0xc4, 0xf6, 0xf2, 0xcb,
0x02, 0xaf, 0xe7, 0x53, 0xf7, 0xb8, 0xdc, 0xcd, 0x24, 0xaa, 0x1e, 0x85, 0x9d, 0xbd, 0x4f, 0xa0,
0x2d, 0x36, 0x4a, 0xb6, 0xef, 0xb6, 0xb8, 0x7d, 0x79, 0x02, 0xdb, 0xc4, 0x1e, 0x1e, 0x01, 0xca,
0x1a, 0x8f, 0x24, 0xcf, 0x0a, 0x22, 0xcf, 0xa6, 0xed, 0x45, 0x82, 0xa7, 0x25, 0x71, 0xb3, 0xff,
0xac, 0x04, 0x28, 0x8e, 0xe0, 0xa2, 0xc3, 0xeb, 0x3c, 0x61, 0xcf, 0x3a, 0x2c, 0x64, 0xe3, 0xbb,
0x30, 0xa8, 0x45, 0x99, 0xe8, 0x4e, 0x16, 0x89, 0x95, 0x64, 0x57, 0x45, 0xdf, 0x88, 0xcc, 0x3d,
0x0b, 0x57, 0xaf, 0x4f, 0x3c, 0xcf, 0x10, 0x2d, 0xfe, 0x0f, 0xd3, 0x57, 0x4c, 0x99, 0xfd, 0xb8,
0x2d, 0x35, 0xcd, 0x99, 0x25, 0x4f, 0xbd, 0x5f, 0x2a, 0x04, 0xd2, 0xd5, 0xf3, 0x04, 0xd2, 0xb3,
0x5f, 0x08, 0xfd, 0xf7, 0x22, 0xcc, 0x47, 0x8c, 0x3c, 0xd7, 0x26, 0x4d, 0xbf, 0x67, 0xf0, 0x39,
0xef, 0xca, 0xc7, 0xf2, 0x5d, 0xf9, 0xf6, 0x99, 0xc9, 0x4c, 0xde, 0x4d, 0x99, 0x9d, 0xb3, 0x9f,
0xc2, 0x1c, 0x2f, 0x4b, 0x67, 0x0c, 0x5c, 0x9e, 0x72, 0xc1, 0x22, 0x54, 0x88, 0x3d, 0x0d, 0x6b,
0x8a, 0xec, 0x83, 0xb1, 0x34, 0x79, 0xe1, 0x98, 0xdb, 0xb8, 0x96, 0x70, 0xdf, 0x58, 0xfd, 0xad,
0x12, 0xc0, 0xde, 0xa9, 0x33, 0xb8, 0xc3, 0x94, 0xf4, 0x26, 0x94, 0xa7, 0x5d, 0x4f, 0x23, 0xbd,
0xa9, 0x6c, 0xd1, 0x9e, 0x39, 0x36, 0x57, 0x28, 0x88, 0x94, 0xd2, 0x05, 0x91, 0x49, 0xa5, 0x8c,
0xc9, 0x26, 0xf8, 0xdb, 0x50, 0xa6, 0xa6, 0x94, 0xdd, 0xde, 0xca, 0x75, 0x2a, 0x4c, 0x07, 0xa0,
0x15, 0x08, 0x5d, 0xf2, 0xb6, 0xc3, 0x7c, 0x2e, 0x35, 0xc7, 0x25, 0x2d, 0x0d, 0x46, 0x2f, 0x41,
0x9b, 0x15, 0xc2, 0xa2, 0x8e, 0x2c, 0xa7, 0x4b, 0x41, 0xb3, 0x1e, 0xbd, 0x2e, 0xf1, 0xe8, 0x04,
0xaf, 0xe1, 0xb9, 0xa3, 0x51, 0x62, 0x3a, 0x56, 0x09, 0x49, 0x83, 0xd5, 0xcf, 0x8a, 0x70, 0x85,
0xf0, 0xf7, 0xd9, 0x44, 0xe5, 0x79, 0x84, 0x27, 0x61, 0xcf, 0x4b, 0xa2, 0x3d, 0xbf, 0x0d, 0x73,
0xac, 0xdc, 0x12, 0xc6, 0x97, 0xd7, 0x27, 0x49, 0x03, 0x93, 0x1d, 0x2d, 0xec, 0x3e, 0x6b, 0xce,
0x2e, 0x9c, 0x99, 0x57, 0x67, 0x3b, 0x33, 0x9f, 0x4b, 0x17, 0x65, 0x13, 0x62, 0x55, 0x13, 0xbd,
0xd0, 0x43, 0x68, 0x69, 0x49, 0xd5, 0x40, 0x08, 0xca, 0x89, 0x0b, 0xab, 0xf4, 0x37, 0x4d, 0xb3,
0xf5, 0x91, 0x3e, 0x30, 0x83, 0x53, 0xca, 0xce, 0x8a, 0x16, 0x7d, 0xcb, 0xf5, 0x50, 0xfd, 0xdf,
0x02, 0x5c, 0x0e, 0x0f, 0x55, 0xb9, 0x96, 0x5f, 0x7c, 0x47, 0x37, 0x60, 0x89, 0xab, 0x74, 0x4a,
0xb7, 0x59, 0x30, 0xbd, 0xc0, 0x60, 0xe2, 0x32, 0x36, 0x60, 0x29, 0xa0, 0xd2, 0x95, 0x1e, 0xc3,
0xf6, 0x7b, 0x81, 0x35, 0x8a, 0x63, 0xf2, 0x1c, 0x6a, 0x3f, 0xc7, 0x6e, 0x60, 0x71, 0xd6, 0x72,
0x25, 0x05, 0x67, 0x6c, 0xf3, 0x55, 0xaa, 0x27, 0x70, 0x95, 0x5d, 0x19, 0x3f, 0x10, 0x29, 0x9a,
0xe9, 0x4c, 0x43, 0xba, 0xee, 0x94, 0x4d, 0xfb, 0xd3, 0x02, 0x5c, 0x9b, 0x80, 0x79, 0x96, 0x6c,
0xee, 0x81, 0x14, 0xfb, 0x84, 0xdc, 0x5b, 0xc0, 0xcb, 0x2e, 0x2c, 0x88, 0x44, 0x7e, 0x56, 0x86,
0xf9, 0x4c, 0xa7, 0x73, 0xcb, 0xdc, 0xab, 0x80, 0xc8, 0x26, 0x44, 0xcf, 0x23, 0x69, 0x39, 0x83,
0x3b, 0x4f, 0xc5, 0x19, 0xdb, 0xd1, 0xd3, 0xc8, 0x1d, 0xd7, 0xc0, 0xc8, 0x64, 0xbd, 0xd9, 0x89,
0x46, 0xb4, 0x73, 0xe5, 0xc9, 0xaf, 0x60, 0x32, 0x04, 0xae, 0xed, 0x8c, 0x6d, 0x76, 0xf8, 0xc1,
0x77, 0x99, 0x39, 0x44, 0x82, 0x4a, 0x00, 0xa3, 0x43, 0x98, 0xa7, 0xf7, 0xf3, 0xc6, 0xc1, 0xd0,
0x25, 0x09, 0x15, 0xa5, 0x8b, 0xb9, 0xdd, 0xef, 0xe6, 0xc6, 0xf4, 0x21, 0x1f, 0x4d, 0x88, 0xe7,
0x39, 0x95, 0x23, 0x42, 0x43, 0x3c, 0xa6, 0x33, 0x70, 0xed, 0x08, 0x4f, 0xf5, 0x9c, 0x78, 0xb6,
0xf9, 0x68, 0x11, 0x4f, 0x12, 0xda, 0xdb, 0x84, 0x25, 0xe9, 0xd2, 0xa7, 0x39, 0xfa, 0x4a, 0x32,
0xf3, 0xba, 0x0b, 0x8b, 0xb2, 0x55, 0x5d, 0x60, 0x8e, 0x0c, 0xc5, 0xe7, 0x99, 0x43, 0xfd, 0xcb,
0x22, 0xb4, 0xb6, 0xb0, 0x85, 0x03, 0xfc, 0xf9, 0x9e, 0x39, 0x67, 0x0e, 0xd0, 0x4b, 0xd9, 0x03,
0xf4, 0xcc, 0x6d, 0x80, 0xb2, 0xe4, 0x36, 0xc0, 0xb5, 0xe8, 0x12, 0x04, 0x99, 0xa5, 0x22, 0xc6,
0x10, 0x06, 0x7a, 0x13, 0x9a, 0x23, 0xcf, 0xb4, 0x75, 0xef, 0xb4, 0xff, 0x18, 0x9f, 0xfa, 0xdc,
0x69, 0x74, 0xa5, 0x6e, 0x67, 0x7b, 0xcb, 0xd7, 0x1a, 0xbc, 0xf7, 0xfb, 0xf8, 0x94, 0x5e, 0xb0,
0x88, 0xd2, 0x38, 0x76, 0xa3, 0xae, 0xac, 0x25, 0x20, 0xab, 0xaf, 0x40, 0x3d, 0xba, 0xb8, 0x84,
0x6a, 0x50, 0xbe, 0x37, 0xb6, 0x2c, 0xe5, 0x12, 0xaa, 0x43, 0x85, 0x26, 0x7a, 0x4a, 0x81, 0xfc,
0xa4, 0xb1, 0x9f, 0x52, 0x5c, 0xfd, 0x25, 0xa8, 0x47, 0x17, 0x28, 0x50, 0x03, 0xe6, 0x1e, 0x3a,
0xef, 0x3b, 0xee, 0x89, 0xa3, 0x5c, 0x42, 0x73, 0x50, 0xba, 0x63, 0x59, 0x4a, 0x01, 0xb5, 0xa0,
0xbe, 0x17, 0x78, 0x58, 0x27, 0xdb, 0xa7, 0x14, 0x51, 0x1b, 0xe0, 0x3d, 0xd3, 0x0f, 0x5c, 0xcf,
0x1c, 0xe8, 0x96, 0x52, 0x5a, 0xfd, 0x14, 0xda, 0x62, 0x3d, 0x1d, 0x35, 0xa1, 0xb6, 0xe3, 0x06,
0xef, 0x3e, 0x35, 0xfd, 0x40, 0xb9, 0x44, 0xfa, 0xef, 0xb8, 0xc1, 0xae, 0x87, 0x7d, 0xec, 0x04,
0x4a, 0x01, 0x01, 0x54, 0x3f, 0x74, 0xb6, 0x4c, 0xff, 0xb1, 0x52, 0x44, 0x0b, 0xfc, 0xa8, 0x4c,
0xb7, 0xb6, 0x79, 0x91, 0x5a, 0x29, 0x91, 0xe1, 0xd1, 0x57, 0x19, 0x29, 0xd0, 0x8c, 0xba, 0xdc,
0xdf, 0x7d, 0xa8, 0x54, 0x18, 0xf5, 0xe4, 0x67, 0x75, 0xd5, 0x00, 0x25, 0x7d, 0xc4, 0x4b, 0xe6,
0x64, 0x8b, 0x88, 0x40, 0xca, 0x25, 0xb2, 0x32, 0x7e, 0xc6, 0xae, 0x14, 0x50, 0x07, 0x1a, 0x89,
0x13, 0x6b, 0xa5, 0x48, 0x00, 0xf7, 0xbd, 0xd1, 0x80, 0xcb, 0x16, 0x23, 0x81, 0x08, 0xea, 0x16,
0xe1, 0x44, 0x79, 0xf5, 0x2e, 0xd4, 0xc2, 0xfc, 0x84, 0x74, 0xe5, 0x2c, 0x22, 0x9f, 0xca, 0x25,
0x34, 0x0f, 0x2d, 0xe1, 0xe9, 0x9d, 0x52, 0x40, 0x08, 0xda, 0xe2, 0xe3, 0x58, 0xa5, 0xb8, 0xba,
0x01, 0x10, 0xc7, 0xf9, 0x84, 0x9c, 0x6d, 0xe7, 0x58, 0xb7, 0x4c, 0x83, 0xd1, 0x46, 0x9a, 0x08,
0x77, 0x29, 0x77, 0x98, 0xce, 0x2a, 0xc5, 0xd5, 0xb7, 0xa1, 0x16, 0xc6, 0xae, 0x04, 0xae, 0x61,
0xdb, 0x3d, 0xc6, 0x6c, 0x67, 0xf6, 0x70, 0xc0, 0xf6, 0xf1, 0x8e, 0x8d, 0x1d, 0x43, 0x29, 0x12,
0x32, 0x1e, 0x8e, 0x0c, 0x3d, 0x08, 0xaf, 0x99, 0x2a, 0xa5, 0x8d, 0xff, 0x5c, 0x00, 0x60, 0x67,
0xb6, 0xae, 0xeb, 0x19, 0xc8, 0xa2, 0x77, 0x37, 0x36, 0x5d, 0x7b, 0xe4, 0x3a, 0xe1, 0x81, 0x92,
0x8f, 0xd6, 0x52, 0x25, 0x12, 0xf6, 0x91, 0xed, 0xc8, 0x79, 0xd3, 0x7b, 0x41, 0xda, 0x3f, 0xd5,
0x59, 0xbd, 0x84, 0x6c, 0x8a, 0x6d, 0xdf, 0xb4, 0xf1, 0xbe, 0x39, 0x78, 0x1c, 0x1d, 0xf4, 0x4e,
0x7e, 0xb4, 0x9a, 0xea, 0x1a, 0xe2, 0xbb, 0x21, 0xc5, 0xb7, 0x17, 0x78, 0xa6, 0x33, 0x0c, 0xbd,
0xa3, 0x7a, 0x09, 0x3d, 0x49, 0x3d, 0x99, 0x0d, 0x11, 0x6e, 0xe4, 0x79, 0x25, 0x7b, 0x31, 0x94,
0x16, 0x74, 0x52, 0xff, 0x4d, 0x80, 0x56, 0xe5, 0x6f, 0x8f, 0x64, 0xff, 0xa3, 0xd0, 0x7b, 0x25,
0x57, 0xdf, 0x08, 0x9b, 0x09, 0x6d, 0xf1, 0x51, 0x3d, 0xfa, 0xc6, 0xa4, 0x09, 0x32, 0xaf, 0x1f,
0x7b, 0xab, 0x79, 0xba, 0x46, 0xa8, 0x3e, 0x62, 0xe2, 0x3b, 0x0d, 0x95, 0xf4, 0xc1, 0x69, 0xef,
0xac, 0xc0, 0x44, 0xbd, 0x84, 0x3e, 0x21, 0x31, 0x44, 0xea, 0x8d, 0x26, 0x7a, 0x55, 0xee, 0xf7,
0xe4, 0x4f, 0x39, 0xa7, 0x61, 0xf8, 0x28, 0xad, 0x7c, 0x93, 0xa9, 0xcf, 0x3c, 0xfe, 0xce, 0x4f,
0x7d, 0x62, 0xfa, 0xb3, 0xa8, 0x3f, 0x37, 0x06, 0x8b, 0xa5, 0x53, 0x92, 0xd7, 0x61, 0x69, 0x51,
0x8e, 0xb3, 0x99, 0xc9, 0x4f, 0xc9, 0xa6, 0x61, 0x1b, 0x53, 0x25, 0x4d, 0x5f, 0x56, 0x78, 0x6d,
0xc2, 0x31, 0x88, 0xfc, 0x59, 0x6a, 0x6f, 0x2d, 0x6f, 0xf7, 0xa4, 0x2c, 0x8b, 0x2f, 0x1f, 0xe5,
0x5b, 0x24, 0x7d, 0xad, 0x29, 0x97, 0x65, 0xf9, 0x43, 0x4a, 0xf5, 0x12, 0xda, 0x17, 0x4c, 0x3d,
0x7a, 0x69, 0x92, 0x28, 0x88, 0xb7, 0x97, 0xa6, 0xf1, 0xed, 0x57, 0x01, 0x31, 0x4d, 0x75, 0x0e,
0xcd, 0xe1, 0xd8, 0xd3, 0x99, 0x18, 0x4f, 0x32, 0x6e, 0xd9, 0xae, 0x21, 0x9a, 0x6f, 0x9e, 0x63,
0x44, 0xb4, 0xa4, 0x3e, 0xc0, 0x7d, 0x1c, 0x7c, 0x40, 0x9f, 0xc0, 0xf9, 0xe9, 0x15, 0xc5, 0xf6,
0x9b, 0x77, 0x08, 0x51, 0xbd, 0x3c, 0xb5, 0x5f, 0x84, 0xe0, 0x00, 0x1a, 0xf7, 0x49, 0x7e, 0x45,
0x63, 0x46, 0x1f, 0x4d, 0x1c, 0x19, 0xf6, 0x08, 0x51, 0xac, 0x4c, 0xef, 0x98, 0x34, 0x9e, 0xa9,
0x57, 0xa0, 0x68, 0xe2, 0xc6, 0x66, 0xdf, 0xa6, 0xca, 0x8d, 0xe7, 0x84, 0x67, 0xa5, 0x6c, 0x45,
0xf4, 0x28, 0xee, 0x3d, 0xac, 0x5b, 0xc1, 0xd1, 0x84, 0x15, 0x25, 0x7a, 0x9c, 0xbd, 0x22, 0xa1,
0x63, 0x84, 0x03, 0xc3, 0x02, 0xd3, 0x42, 0x31, 0x31, 0x5d, 0x97, 0x4f, 0x91, 0xed, 0x99, 0x53,
0xf4, 0x74, 0x98, 0xdf, 0xf2, 0xdc, 0x91, 0x88, 0xe4, 0x35, 0x29, 0x92, 0x4c, 0xbf, 0x9c, 0x28,
0x7e, 0x00, 0xcd, 0x30, 0xff, 0xa7, 0x19, 0x8b, 0x9c, 0x0b, 0xc9, 0x2e, 0x39, 0x27, 0xfe, 0x18,
0x3a, 0xa9, 0xc2, 0x82, 0x7c, 0xd3, 0xe5, 0xd5, 0x87, 0x69, 0xb3, 0x9f, 0x00, 0xa2, 0x4f, 0x7b,
0xc5, 0x7f, 0x27, 0x90, 0xc7, 0x37, 0xd9, 0x8e, 0x21, 0x92, 0xf5, 0xdc, 0xfd, 0xa3, 0x9d, 0xff,
0x35, 0x58, 0x92, 0x26, 0xef, 0x69, 0x83, 0xc0, 0xaf, 0x2b, 0x9f, 0x51, 0x61, 0x48, 0x1b, 0x84,
0x33, 0x47, 0x84, 0xf8, 0x37, 0x7e, 0x77, 0x1e, 0xea, 0x34, 0xce, 0xa3, 0xbb, 0xf5, 0x8b, 0x30,
0xef, 0xd9, 0x86, 0x79, 0x1f, 0x43, 0x27, 0xf5, 0xe4, 0x54, 0x2e, 0xb4, 0xf2, 0x77, 0xa9, 0x39,
0xa2, 0x15, 0xf1, 0xb5, 0xa6, 0xdc, 0x15, 0x4a, 0x5f, 0x74, 0x4e, 0x9b, 0xfb, 0x11, 0x7b, 0xce,
0x1d, 0x9d, 0xe6, 0xbe, 0x3c, 0xf1, 0xf0, 0x41, 0xbc, 0x76, 0xfc, 0xc5, 0x47, 0x41, 0x5f, 0xed,
0x08, 0xf4, 0x63, 0xe8, 0xa4, 0x1e, 0xf6, 0xc8, 0x25, 0x46, 0xfe, 0xfa, 0x67, 0xda, 0xec, 0x3f,
0xc7, 0xe0, 0xc9, 0x80, 0x05, 0xc9, 0x3b, 0x0a, 0xb4, 0x36, 0x29, 0x10, 0x95, 0x3f, 0xb8, 0x98,
0xbe, 0xa0, 0x96, 0xa0, 0xa6, 0x69, 0x7f, 0x13, 0x13, 0x99, 0xfe, 0x5b, 0xa3, 0xde, 0xab, 0xf9,
0xfe, 0x03, 0x29, 0x5a, 0xd0, 0x1e, 0x54, 0xd9, 0x73, 0x1f, 0xf4, 0xbc, 0xfc, 0x10, 0x26, 0xf1,
0x14, 0xa8, 0x37, 0xed, 0xc1, 0x90, 0x3f, 0xb6, 0x02, 0x42, 0xff, 0xaf, 0x40, 0x9b, 0x81, 0x22,
0x06, 0x3d, 0xc3, 0xc9, 0xf7, 0xa0, 0x42, 0x4d, 0x3b, 0x92, 0x1e, 0x28, 0x24, 0x1f, 0xf5, 0xf4,
0xa6, 0xbf, 0xe3, 0x89, 0x29, 0x6e, 0x7d, 0x9f, 0xfd, 0x1b, 0x1d, 0x27, 0xf8, 0x59, 0x4e, 0xfe,
0xff, 0x3b, 0x36, 0x7e, 0x4a, 0x9f, 0xa4, 0xa4, 0x2f, 0x5d, 0xa1, 0xb5, 0xf3, 0xdd, 0x1c, 0xeb,
0xad, 0xe7, 0xee, 0x1f, 0x61, 0xfe, 0x11, 0x28, 0xe9, 0x83, 0x36, 0xf4, 0xca, 0x24, 0x4d, 0x94,
0xe1, 0x9c, 0xa2, 0x86, 0xdf, 0x83, 0x2a, 0xab, 0xb0, 0xca, 0xc5, 0x57, 0xa8, 0xbe, 0x4e, 0x99,
0xeb, 0xee, 0xb7, 0x3e, 0xda, 0x18, 0x9a, 0xc1, 0xd1, 0xf8, 0x80, 0xb4, 0xac, 0xb3, 0xae, 0xaf,
0x99, 0x2e, 0xff, 0xb5, 0x1e, 0xee, 0xe5, 0x3a, 0x1d, 0xbd, 0x4e, 0x11, 0x8c, 0x0e, 0x0e, 0xaa,
0xf4, 0xf3, 0xd6, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x18, 0xc1, 0xb1, 0x0e, 0x53, 0x00,
0x00,
// 4789 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3c, 0x4b, 0x6f, 0x1c, 0x47,
0x7a, 0xea, 0x79, 0x71, 0xe6, 0x9b, 0x57, 0xb3, 0x48, 0x4a, 0xb3, 0xb3, 0x92, 0x2c, 0xb7, 0xfc,
0xe0, 0xca, 0x36, 0xa5, 0xa5, 0xd6, 0x5e, 0xed, 0xda, 0x86, 0x23, 0x91, 0x96, 0xcc, 0xb5, 0x4d,
0x33, 0x4d, 0xca, 0x1b, 0x78, 0xbd, 0x3b, 0x6e, 0x4e, 0x17, 0x87, 0x0d, 0xf5, 0x63, 0xd4, 0xdd,
0x43, 0x9a, 0x0e, 0x10, 0xe4, 0x90, 0x4b, 0x36, 0xd9, 0x20, 0x48, 0x0e, 0xc9, 0x21, 0xc8, 0x21,
0x41, 0x80, 0x4d, 0x90, 0x5c, 0x82, 0x04, 0xc8, 0x21, 0x87, 0xdc, 0x72, 0xca, 0xeb, 0x94, 0x3f,
0x90, 0xdc, 0x02, 0xe4, 0x92, 0x45, 0xe0, 0x5b, 0x50, 0x8f, 0x7e, 0x54, 0x77, 0x0d, 0xa7, 0xc9,
0x91, 0xd6, 0x76, 0xb0, 0xb7, 0xe9, 0xaf, 0x1e, 0xdf, 0x57, 0x5f, 0x7d, 0xef, 0xaa, 0x1a, 0x58,
0x7c, 0x3c, 0xc1, 0xfe, 0xc9, 0x60, 0xe8, 0x79, 0xbe, 0xb9, 0x36, 0xf6, 0xbd, 0xd0, 0x43, 0xc8,
0xb1, 0xec, 0xa3, 0x49, 0xc0, 0xbe, 0xd6, 0x68, 0x7b, 0xbf, 0x35, 0xf4, 0x1c, 0xc7, 0x73, 0x19,
0xac, 0xdf, 0x4a, 0xf7, 0xe8, 0x77, 0x2c, 0x37, 0xc4, 0xbe, 0x6b, 0xd8, 0x51, 0x6b, 0x30, 0x3c,
0xc4, 0x8e, 0xc1, 0xbf, 0x1a, 0x4e, 0x30, 0xe2, 0x3f, 0x55, 0xd3, 0x08, 0x8d, 0x34, 0xaa, 0xfe,
0xa2, 0xe5, 0x9a, 0xf8, 0xd3, 0x34, 0x48, 0xfb, 0x0d, 0x05, 0x2e, 0xee, 0x1e, 0x7a, 0xc7, 0x1b,
0x9e, 0x6d, 0xe3, 0x61, 0x68, 0x79, 0x6e, 0xa0, 0xe3, 0xc7, 0x13, 0x1c, 0x84, 0xe8, 0x16, 0x54,
0xf6, 0x8d, 0x00, 0xf7, 0x94, 0x6b, 0xca, 0x6a, 0x73, 0xfd, 0xf2, 0x9a, 0x40, 0x27, 0x27, 0xf0,
0xfd, 0x60, 0x74, 0xcf, 0x08, 0xb0, 0x4e, 0x7b, 0x22, 0x04, 0x15, 0x73, 0x7f, 0x6b, 0xb3, 0x57,
0xba, 0xa6, 0xac, 0x96, 0x75, 0xfa, 0x1b, 0x3d, 0x07, 0xed, 0x61, 0x3c, 0xf7, 0xd6, 0x66, 0xd0,
0x2b, 0x5f, 0x2b, 0xaf, 0x96, 0x75, 0x11, 0xa8, 0xfd, 0xb8, 0x04, 0x97, 0x72, 0x64, 0x04, 0x63,
0xcf, 0x0d, 0x30, 0xba, 0x0d, 0xb5, 0x20, 0x34, 0xc2, 0x49, 0xc0, 0x29, 0xf9, 0xba, 0x94, 0x92,
0x5d, 0xda, 0x45, 0xe7, 0x5d, 0xf3, 0x68, 0x4b, 0x12, 0xb4, 0xe8, 0x9b, 0xb0, 0x6c, 0xb9, 0xef,
0x63, 0xc7, 0xf3, 0x4f, 0x06, 0x63, 0xec, 0x0f, 0xb1, 0x1b, 0x1a, 0x23, 0x1c, 0xd1, 0xb8, 0x14,
0xb5, 0xed, 0x24, 0x4d, 0xe8, 0x35, 0xb8, 0xc4, 0xf6, 0x30, 0xc0, 0xfe, 0x91, 0x35, 0xc4, 0x03,
0xe3, 0xc8, 0xb0, 0x6c, 0x63, 0xdf, 0xc6, 0xbd, 0xca, 0xb5, 0xf2, 0x6a, 0x5d, 0x5f, 0xa1, 0xcd,
0xbb, 0xac, 0xf5, 0x6e, 0xd4, 0x88, 0xbe, 0x01, 0xaa, 0x8f, 0x0f, 0x7c, 0x1c, 0x1c, 0x0e, 0xc6,
0xbe, 0x37, 0xf2, 0x71, 0x10, 0xf4, 0xaa, 0x14, 0x4d, 0x97, 0xc3, 0x77, 0x38, 0x58, 0xfb, 0x33,
0x05, 0x56, 0x08, 0x33, 0x76, 0x0c, 0x3f, 0xb4, 0x9e, 0xc2, 0x96, 0x68, 0xd0, 0x4a, 0xb3, 0xa1,
0x57, 0xa6, 0x6d, 0x02, 0x8c, 0xf4, 0x19, 0x47, 0xe8, 0x09, 0xfb, 0x2a, 0x94, 0x54, 0x01, 0xa6,
0xfd, 0x0b, 0x97, 0x9d, 0x34, 0x9d, 0xf3, 0xec, 0x59, 0x16, 0x67, 0x29, 0x8f, 0xf3, 0x3c, 0x3b,
0x26, 0xe3, 0x7c, 0x45, 0xce, 0xf9, 0x7f, 0x2a, 0xc3, 0xca, 0x7b, 0x9e, 0x61, 0x26, 0x62, 0xf8,
0xf3, 0xe7, 0xfc, 0x9b, 0x50, 0x63, 0x1a, 0xdd, 0xab, 0x50, 0x5c, 0xcf, 0x8b, 0xb8, 0xb8, 0xb6,
0x27, 0x14, 0xee, 0x52, 0x80, 0xce, 0x07, 0xa1, 0xe7, 0xa1, 0xe3, 0xe3, 0xb1, 0x6d, 0x0d, 0x8d,
0x81, 0x3b, 0x71, 0xf6, 0xb1, 0xdf, 0xab, 0x5e, 0x53, 0x56, 0xab, 0x7a, 0x9b, 0x43, 0xb7, 0x29,
0x10, 0x7d, 0x02, 0xed, 0x03, 0x0b, 0xdb, 0xe6, 0x80, 0x9a, 0x84, 0xad, 0xcd, 0x5e, 0xed, 0x5a,
0x79, 0xb5, 0xb9, 0xfe, 0xfa, 0x5a, 0xde, 0x1a, 0xad, 0x49, 0x39, 0xb2, 0x76, 0x9f, 0x0c, 0xdf,
0x62, 0xa3, 0xdf, 0x76, 0x43, 0xff, 0x44, 0x6f, 0x1d, 0xa4, 0x40, 0xa8, 0x07, 0x0b, 0x9c, 0xbd,
0xbd, 0x85, 0x6b, 0xca, 0x6a, 0x5d, 0x8f, 0x3e, 0xd1, 0x8b, 0xd0, 0xf5, 0x71, 0xe0, 0x4d, 0xfc,
0x21, 0x1e, 0x8c, 0x7c, 0x6f, 0x32, 0x0e, 0x7a, 0xf5, 0x6b, 0xe5, 0xd5, 0x86, 0xde, 0x89, 0xc0,
0x0f, 0x28, 0xb4, 0xff, 0x16, 0x2c, 0xe6, 0xb0, 0x20, 0x15, 0xca, 0x8f, 0xf0, 0x09, 0xdd, 0x88,
0xb2, 0x4e, 0x7e, 0xa2, 0x65, 0xa8, 0x1e, 0x19, 0xf6, 0x04, 0x73, 0x56, 0xb3, 0x8f, 0xef, 0x96,
0xee, 0x28, 0xda, 0x1f, 0x29, 0xd0, 0xd3, 0xb1, 0x8d, 0x8d, 0x00, 0x7f, 0x91, 0x5b, 0x7a, 0x11,
0x6a, 0xae, 0x67, 0xe2, 0xad, 0x4d, 0xba, 0xa5, 0x65, 0x9d, 0x7f, 0x69, 0x9f, 0x2b, 0xb0, 0xfc,
0x00, 0x87, 0x44, 0x0d, 0xac, 0x20, 0xb4, 0x86, 0xb1, 0x9e, 0xbf, 0x09, 0x65, 0x1f, 0x3f, 0xe6,
0x94, 0xbd, 0x24, 0x52, 0x16, 0x9b, 0x7f, 0xd9, 0x48, 0x9d, 0x8c, 0x43, 0xcf, 0x42, 0xcb, 0x74,
0xec, 0xc1, 0xf0, 0xd0, 0x70, 0x5d, 0x6c, 0x33, 0x45, 0x6a, 0xe8, 0x4d, 0xd3, 0xb1, 0x37, 0x38,
0x08, 0x5d, 0x05, 0x08, 0xf0, 0xc8, 0xc1, 0x6e, 0x98, 0xd8, 0xe4, 0x14, 0x04, 0xdd, 0x80, 0xc5,
0x03, 0xdf, 0x73, 0x06, 0xc1, 0xa1, 0xe1, 0x9b, 0x03, 0x1b, 0x1b, 0x26, 0xf6, 0x29, 0xf5, 0x75,
0xbd, 0x4b, 0x1a, 0x76, 0x09, 0xfc, 0x3d, 0x0a, 0x46, 0xb7, 0xa1, 0x1a, 0x0c, 0xbd, 0x31, 0xa6,
0x92, 0xd6, 0x59, 0xbf, 0x22, 0x93, 0xa1, 0x4d, 0x23, 0x34, 0x76, 0x49, 0x27, 0x9d, 0xf5, 0xd5,
0xfe, 0xae, 0xc2, 0x54, 0xed, 0x4b, 0x6e, 0xe4, 0x52, 0xea, 0x58, 0x7d, 0x32, 0xea, 0x58, 0x2b,
0xa4, 0x8e, 0x0b, 0xa7, 0xab, 0x63, 0x8e, 0x6b, 0x67, 0x51, 0xc7, 0xfa, 0x4c, 0x75, 0x6c, 0xc8,
0xd4, 0x11, 0xbd, 0x0d, 0x5d, 0x16, 0x40, 0x58, 0xee, 0x81, 0x37, 0xb0, 0xad, 0x20, 0xec, 0x01,
0x25, 0xf3, 0x4a, 0x56, 0x42, 0x4d, 0xfc, 0xe9, 0x1a, 0x43, 0xec, 0x1e, 0x78, 0x7a, 0xdb, 0x8a,
0x7e, 0xbe, 0x67, 0x05, 0xe1, 0xfc, 0x5a, 0xfd, 0x0f, 0x89, 0x56, 0x7f, 0xd9, 0xa5, 0x27, 0xd1,
0xfc, 0xaa, 0xa0, 0xf9, 0x7f, 0xae, 0xc0, 0xd7, 0x1e, 0xe0, 0x30, 0x26, 0x9f, 0x28, 0x32, 0xfe,
0x92, 0xba, 0xf9, 0xbf, 0x52, 0xa0, 0x2f, 0xa3, 0x75, 0x1e, 0x57, 0xff, 0x11, 0x5c, 0x8c, 0x71,
0x0c, 0x4c, 0x1c, 0x0c, 0x7d, 0x6b, 0x4c, 0xb7, 0x91, 0xda, 0xaa, 0xe6, 0xfa, 0x75, 0x99, 0xe0,
0x67, 0x29, 0x58, 0x89, 0xa7, 0xd8, 0x4c, 0xcd, 0xa0, 0xfd, 0x44, 0x81, 0x15, 0x62, 0x1b, 0xb9,
0x31, 0x23, 0x12, 0x78, 0x6e, 0xbe, 0x8a, 0x66, 0xb2, 0x94, 0x33, 0x93, 0x05, 0x78, 0x4c, 0x43,
0xec, 0x2c, 0x3d, 0xf3, 0xf0, 0xee, 0x55, 0xa8, 0x12, 0x05, 0x8c, 0x58, 0xf5, 0x8c, 0x8c, 0x55,
0x69, 0x64, 0xac, 0xb7, 0xe6, 0x32, 0x2a, 0x12, 0xbb, 0x3d, 0x87, 0xb8, 0x65, 0x97, 0x5d, 0x92,
0x2c, 0xfb, 0xb7, 0x15, 0xb8, 0x94, 0x43, 0x38, 0xcf, 0xba, 0xdf, 0x80, 0x1a, 0xf5, 0x46, 0xd1,
0xc2, 0x9f, 0x93, 0x2e, 0x3c, 0x85, 0x8e, 0x58, 0x1b, 0x9d, 0x8f, 0xd1, 0x3c, 0x50, 0xb3, 0x6d,
0xc4, 0x4f, 0x72, 0x1f, 0x39, 0x70, 0x0d, 0x87, 0x31, 0xa0, 0xa1, 0x37, 0x39, 0x6c, 0xdb, 0x70,
0x30, 0xfa, 0x1a, 0xd4, 0x89, 0xca, 0x0e, 0x2c, 0x33, 0xda, 0xfe, 0x05, 0xaa, 0xc2, 0x66, 0x80,
0xae, 0x00, 0xd0, 0x26, 0xc3, 0x34, 0x7d, 0xe6, 0x42, 0x1b, 0x7a, 0x83, 0x40, 0xee, 0x12, 0x80,
0xf6, 0x87, 0x0a, 0x5c, 0xdd, 0x3d, 0x71, 0x87, 0xdb, 0xf8, 0x78, 0xc3, 0xc7, 0x46, 0x88, 0x13,
0xa3, 0xfd, 0x54, 0x19, 0x8f, 0xae, 0x41, 0x33, 0xa5, 0xbf, 0x5c, 0x24, 0xd3, 0x20, 0xed, 0xaf,
0x15, 0x68, 0x11, 0x2f, 0xf2, 0x3e, 0x0e, 0x0d, 0x22, 0x22, 0xe8, 0x3b, 0xd0, 0xb0, 0x3d, 0xc3,
0x1c, 0x84, 0x27, 0x63, 0x46, 0x4d, 0x27, 0x4b, 0x4d, 0xe2, 0x7a, 0xf6, 0x4e, 0xc6, 0x58, 0xaf,
0xdb, 0xfc, 0x57, 0x21, 0x8a, 0xb2, 0x56, 0xa6, 0x2c, 0xb1, 0x94, 0xcf, 0x40, 0xd3, 0xc1, 0xa1,
0x6f, 0x0d, 0x19, 0x11, 0x15, 0xba, 0x15, 0xc0, 0x40, 0x04, 0x91, 0xf6, 0x93, 0x1a, 0x5c, 0xfc,
0xbe, 0x11, 0x0e, 0x0f, 0x37, 0x9d, 0x28, 0x8a, 0x39, 0x3f, 0x1f, 0x13, 0xbb, 0x5c, 0x4a, 0xdb,
0xe5, 0x27, 0x66, 0xf7, 0x63, 0x1d, 0xad, 0xca, 0x74, 0x94, 0x24, 0xe6, 0x6b, 0x1f, 0x72, 0x31,
0x4b, 0xe9, 0x68, 0x2a, 0xd8, 0xa8, 0x9d, 0x27, 0xd8, 0xd8, 0x80, 0x36, 0xfe, 0x74, 0x68, 0x4f,
0x88, 0xbc, 0x52, 0xec, 0x2c, 0x8a, 0xb8, 0x2a, 0xc1, 0x9e, 0x36, 0x10, 0x2d, 0x3e, 0x68, 0x8b,
0xd3, 0xc0, 0x64, 0xc1, 0xc1, 0xa1, 0x41, 0x43, 0x85, 0xe6, 0xfa, 0xb5, 0x69, 0xb2, 0x10, 0x09,
0x10, 0x93, 0x07, 0xf2, 0x85, 0x2e, 0x43, 0x83, 0x87, 0x36, 0x5b, 0x9b, 0xbd, 0x06, 0x65, 0x5f,
0x02, 0x40, 0x06, 0xb4, 0xb9, 0xf5, 0xe4, 0x14, 0xb2, 0x00, 0xe2, 0x0d, 0x19, 0x02, 0xf9, 0x66,
0xa7, 0x29, 0x0f, 0x78, 0xa0, 0x13, 0xa4, 0x40, 0x24, 0xf3, 0xf7, 0x0e, 0x0e, 0x6c, 0xcb, 0xc5,
0xdb, 0x6c, 0x87, 0x9b, 0x94, 0x08, 0x11, 0x48, 0xc2, 0xa1, 0x23, 0xec, 0x07, 0x96, 0xe7, 0xf6,
0x5a, 0xb4, 0x3d, 0xfa, 0x94, 0x45, 0x39, 0xed, 0x73, 0x44, 0x39, 0x03, 0x58, 0xcc, 0x51, 0x2a,
0x89, 0x72, 0xbe, 0x95, 0x8e, 0x72, 0x66, 0x6f, 0x55, 0x2a, 0x0a, 0xfa, 0xa9, 0x02, 0x2b, 0x0f,
0xdd, 0x60, 0xb2, 0x1f, 0xb3, 0xe8, 0x8b, 0x51, 0x87, 0xac, 0x11, 0xad, 0xe4, 0x8c, 0xa8, 0xf6,
0x3f, 0x55, 0xe8, 0xf2, 0x55, 0x10, 0xa9, 0xa1, 0x26, 0xe7, 0x32, 0x34, 0x62, 0x3f, 0xca, 0x19,
0x92, 0x00, 0xb2, 0x36, 0xac, 0x94, 0xb3, 0x61, 0x85, 0x48, 0x8b, 0xa2, 0xa2, 0x4a, 0x2a, 0x2a,
0xba, 0x02, 0x70, 0x60, 0x4f, 0x82, 0xc3, 0x41, 0x68, 0x39, 0x98, 0x47, 0x65, 0x0d, 0x0a, 0xd9,
0xb3, 0x1c, 0x8c, 0xee, 0x42, 0x6b, 0xdf, 0x72, 0x6d, 0x6f, 0x34, 0x18, 0x1b, 0xe1, 0x61, 0xc0,
0xd3, 0x62, 0xd9, 0xb6, 0xd0, 0x18, 0xf6, 0x1e, 0xed, 0xab, 0x37, 0xd9, 0x98, 0x1d, 0x32, 0x04,
0x5d, 0x85, 0xa6, 0x3b, 0x71, 0x06, 0xde, 0xc1, 0xc0, 0xf7, 0x8e, 0x03, 0x9a, 0xfc, 0x96, 0xf5,
0x86, 0x3b, 0x71, 0x3e, 0x38, 0xd0, 0xbd, 0x63, 0xe2, 0xc7, 0x1a, 0xc4, 0xa3, 0x05, 0xb6, 0x37,
0x62, 0x89, 0xef, 0xec, 0xf9, 0x93, 0x01, 0x64, 0xb4, 0x89, 0xed, 0xd0, 0xa0, 0xa3, 0x1b, 0xc5,
0x46, 0xc7, 0x03, 0xd0, 0x0b, 0xd0, 0x19, 0x7a, 0xce, 0xd8, 0xa0, 0x1c, 0xba, 0xef, 0x7b, 0x0e,
0x55, 0xc0, 0xb2, 0x9e, 0x81, 0xa2, 0x0d, 0x68, 0x26, 0x4a, 0x10, 0xf4, 0x9a, 0x14, 0x8f, 0x26,
0xd3, 0xd2, 0x54, 0x28, 0x4f, 0x04, 0x14, 0x62, 0x2d, 0x08, 0x88, 0x64, 0x44, 0xca, 0x1e, 0x58,
0x9f, 0x61, 0xae, 0x68, 0x4d, 0x0e, 0xdb, 0xb5, 0x3e, 0xc3, 0x24, 0x3d, 0xb2, 0xdc, 0x00, 0xfb,
0x61, 0x94, 0xac, 0xf6, 0xda, 0x54, 0x7c, 0xda, 0x0c, 0xca, 0x05, 0x1b, 0x6d, 0x42, 0x27, 0x08,
0x0d, 0x3f, 0x1c, 0x8c, 0xbd, 0x80, 0x0a, 0x40, 0xaf, 0x43, 0x65, 0x3b, 0xa3, 0x92, 0x4e, 0x30,
0x22, 0x82, 0xbd, 0xc3, 0x3b, 0xe9, 0x6d, 0x3a, 0x28, 0xfa, 0x24, 0xb3, 0x50, 0x4e, 0x24, 0xb3,
0x74, 0x0b, 0xcd, 0x42, 0x07, 0xc5, 0xb3, 0xac, 0x92, 0x74, 0xc9, 0x30, 0x8d, 0x7d, 0x1b, 0x7f,
0xc8, 0x2d, 0x88, 0x4a, 0x17, 0x96, 0x05, 0x6b, 0xff, 0x5d, 0x82, 0x8e, 0xc8, 0x1e, 0x62, 0x76,
0x58, 0x56, 0x16, 0xc9, 0x7c, 0xf4, 0x49, 0x98, 0x85, 0x5d, 0x32, 0x9a, 0xa5, 0x80, 0x54, 0xe4,
0xeb, 0x7a, 0x93, 0xc1, 0xe8, 0x04, 0x44, 0x74, 0xd9, 0xa6, 0x50, 0x3d, 0x2b, 0x53, 0x46, 0x35,
0x28, 0x84, 0x86, 0x2a, 0x3d, 0x58, 0x88, 0xb2, 0x47, 0x26, 0xf0, 0xd1, 0x27, 0x69, 0xd9, 0x9f,
0x58, 0x14, 0x2b, 0x13, 0xf8, 0xe8, 0x13, 0x6d, 0x42, 0x8b, 0x4d, 0x39, 0x36, 0x7c, 0xc3, 0x89,
0xc4, 0xfd, 0x59, 0xa9, 0xc9, 0x78, 0x17, 0x9f, 0x7c, 0x48, 0xac, 0xcf, 0x8e, 0x61, 0xf9, 0x3a,
0x13, 0x8f, 0x1d, 0x3a, 0x0a, 0xad, 0x82, 0xca, 0x66, 0x39, 0xb0, 0x6c, 0xcc, 0x15, 0x67, 0x81,
0xa5, 0x90, 0x14, 0x7e, 0xdf, 0xb2, 0x31, 0xd3, 0x8d, 0x78, 0x09, 0x54, 0x20, 0xea, 0x4c, 0x35,
0x28, 0x84, 0x8a, 0xc3, 0x75, 0x60, 0x56, 0x74, 0x10, 0xd9, 0x66, 0xe6, 0x40, 0x18, 0x8d, 0x9c,
0xad, 0x34, 0x24, 0x9b, 0x38, 0x4c, 0xb9, 0x80, 0x2d, 0xc7, 0x9d, 0x38, 0x44, 0xb5, 0xb4, 0xdf,
0xab, 0xc2, 0x12, 0xb1, 0x30, 0xdc, 0xd8, 0xcc, 0x11, 0x20, 0x5c, 0x01, 0x30, 0x83, 0x70, 0x20,
0x58, 0xc5, 0x86, 0x19, 0x84, 0xdc, 0x7d, 0x7c, 0x27, 0xf2, 0xef, 0xe5, 0xe9, 0xe9, 0x4a, 0xc6,
0xe2, 0xe5, 0x7d, 0xfc, 0xb9, 0xea, 0x7b, 0xd7, 0xa1, 0xcd, 0x73, 0x75, 0x21, 0xb1, 0x6c, 0x31,
0xe0, 0xb6, 0xdc, 0x6e, 0xd7, 0xa4, 0x75, 0xc6, 0x94, 0x9f, 0x5f, 0x98, 0xcf, 0xcf, 0xd7, 0xb3,
0x7e, 0xfe, 0x3e, 0x74, 0x45, 0x55, 0x8b, 0x6c, 0xd5, 0x0c, 0x5d, 0xeb, 0x08, 0xba, 0x16, 0xa4,
0xdd, 0x34, 0x88, 0x6e, 0xfa, 0x3a, 0xb4, 0x5d, 0x8c, 0xcd, 0x41, 0xe8, 0x1b, 0x6e, 0x70, 0x80,
0x7d, 0xea, 0xe6, 0xeb, 0x7a, 0x8b, 0x00, 0xf7, 0x38, 0x0c, 0xbd, 0x01, 0x40, 0xd7, 0xc8, 0xca,
0x53, 0xad, 0xe9, 0xe5, 0x29, 0x2a, 0x34, 0xb4, 0x3c, 0x45, 0x99, 0x42, 0x7f, 0x3e, 0xa1, 0x48,
0x40, 0xfb, 0xe7, 0x12, 0x5c, 0xe4, 0xe5, 0x8a, 0xf9, 0xe5, 0x72, 0x9a, 0xa7, 0x8e, 0x5c, 0x5d,
0xf9, 0x94, 0x02, 0x40, 0xa5, 0x40, 0x30, 0x5b, 0x95, 0x04, 0xb3, 0x62, 0x12, 0x5c, 0xcb, 0x25,
0xc1, 0x71, 0xfd, 0x6f, 0xa1, 0x78, 0xfd, 0x0f, 0x2d, 0x43, 0x95, 0x66, 0x66, 0x54, 0x76, 0x1a,
0x3a, 0xfb, 0x28, 0xb4, 0xab, 0xda, 0x1f, 0x94, 0xa0, 0xbd, 0x8b, 0x0d, 0x7f, 0x78, 0x18, 0xf1,
0xf1, 0xb5, 0x74, 0xbd, 0xf4, 0xb9, 0x29, 0xf5, 0x52, 0x61, 0xc8, 0x57, 0xa6, 0x50, 0x4a, 0x10,
0x84, 0x5e, 0x68, 0xc4, 0x54, 0x0e, 0xdc, 0x89, 0xc3, 0x8b, 0x88, 0x5d, 0xda, 0xc0, 0x49, 0xdd,
0x9e, 0x38, 0xda, 0x7f, 0x29, 0xd0, 0xfa, 0x65, 0x32, 0x4d, 0xc4, 0x98, 0x3b, 0x69, 0xc6, 0xbc,
0x30, 0x85, 0x31, 0x3a, 0x49, 0xb2, 0xf0, 0x11, 0xfe, 0xca, 0xd5, 0x90, 0xff, 0x51, 0x81, 0x3e,
0x49, 0xb1, 0x75, 0x66, 0x77, 0xe6, 0xd7, 0xae, 0xeb, 0xd0, 0x3e, 0x12, 0x82, 0xd9, 0x12, 0x15,
0xce, 0xd6, 0x51, 0xba, 0x24, 0xa0, 0x83, 0x1a, 0x95, 0x74, 0xf9, 0x62, 0x23, 0x37, 0xf0, 0xa2,
0x8c, 0xea, 0x0c, 0x71, 0xd4, 0x42, 0x74, 0x7d, 0x11, 0xa8, 0xfd, 0x8e, 0x02, 0x4b, 0x92, 0x8e,
0xe8, 0x12, 0x2c, 0xf0, 0xf2, 0x03, 0x8f, 0x17, 0x98, 0xbe, 0x9b, 0x64, 0x7b, 0x92, 0x02, 0x9a,
0x65, 0xe6, 0x23, 0x64, 0x93, 0x64, 0xd4, 0x71, 0xae, 0x65, 0xe6, 0xf6, 0xc7, 0x0c, 0x50, 0x1f,
0xea, 0xdc, 0x9a, 0x46, 0x49, 0x6c, 0xfc, 0xad, 0x3d, 0x02, 0xf4, 0x00, 0x27, 0xbe, 0x6b, 0x1e,
0x8e, 0x26, 0xf6, 0x26, 0x21, 0x34, 0x6d, 0x84, 0x4c, 0xed, 0x3f, 0x14, 0x58, 0x12, 0xb0, 0xcd,
0x53, 0x26, 0x4a, 0xfc, 0x6b, 0xe9, 0x3c, 0xfe, 0x55, 0x28, 0x85, 0x94, 0xcf, 0x54, 0x0a, 0xb9,
0x0a, 0x10, 0xf3, 0x3f, 0xe2, 0x68, 0x0a, 0xa2, 0xfd, 0xbd, 0x02, 0x17, 0xdf, 0x31, 0x5c, 0xd3,
0x3b, 0x38, 0x98, 0x5f, 0x54, 0x37, 0x40, 0x48, 0x7b, 0x8b, 0x16, 0x03, 0xc5, 0x5c, 0xf9, 0x25,
0x58, 0xf4, 0x99, 0x67, 0x32, 0x45, 0x59, 0x2e, 0xeb, 0x6a, 0xd4, 0x10, 0xcb, 0xe8, 0x5f, 0x96,
0x00, 0x91, 0x55, 0xdf, 0x33, 0x6c, 0xc3, 0x1d, 0xe2, 0xf3, 0x93, 0xfe, 0x3c, 0x74, 0x84, 0x10,
0x26, 0x3e, 0x9c, 0x4f, 0xc7, 0x30, 0x01, 0x7a, 0x17, 0x3a, 0xfb, 0x0c, 0xd5, 0xc0, 0xc7, 0x46,
0xe0, 0xb9, 0x7c, 0x3b, 0xa4, 0x75, 0xbf, 0x3d, 0xdf, 0x1a, 0x8d, 0xb0, 0xbf, 0xe1, 0xb9, 0x26,
0x8f, 0xda, 0xf7, 0x23, 0x32, 0xc9, 0x50, 0xa2, 0x0c, 0x49, 0x3c, 0x17, 0x6f, 0x4e, 0x1c, 0xd0,
0x51, 0x56, 0x04, 0xd8, 0xb0, 0x13, 0x46, 0x24, 0xde, 0x50, 0x65, 0x0d, 0xbb, 0xd3, 0xcb, 0xbe,
0x92, 0xf8, 0x4a, 0xfb, 0x1b, 0x05, 0x50, 0x9c, 0x9a, 0xd3, 0x5a, 0x06, 0xd5, 0xe8, 0xec, 0x50,
0x45, 0xe2, 0x94, 0x2f, 0x43, 0xc3, 0x8c, 0x46, 0x72, 0x13, 0x94, 0x00, 0xa8, 0x8f, 0xa4, 0x44,
0x0f, 0x88, 0xe4, 0x61, 0x33, 0x4a, 0x7d, 0x19, 0xf0, 0x3d, 0x0a, 0x13, 0xc3, 0xb3, 0x4a, 0x36,
0x3c, 0x4b, 0x57, 0x35, 0xab, 0x42, 0x55, 0x53, 0xfb, 0x69, 0x09, 0x54, 0xea, 0x42, 0x36, 0x92,
0xf2, 0x54, 0x21, 0xa2, 0xaf, 0x43, 0x9b, 0x5f, 0x6e, 0x11, 0x08, 0x6f, 0x3d, 0x4e, 0x4d, 0x86,
0x6e, 0xc1, 0x32, 0xeb, 0xe4, 0xe3, 0x60, 0x62, 0x27, 0x59, 0x1f, 0x4b, 0x66, 0xd0, 0x63, 0xe6,
0xbb, 0x48, 0x53, 0x34, 0xe2, 0x21, 0x5c, 0x1c, 0xd9, 0xde, 0xbe, 0x61, 0x0f, 0xc4, 0xed, 0x61,
0x7b, 0x58, 0x40, 0xe2, 0x97, 0xd9, 0xf0, 0xdd, 0xf4, 0x1e, 0x06, 0xe8, 0x1e, 0xb4, 0x03, 0x8c,
0x1f, 0x25, 0xa9, 0x60, 0xb5, 0x48, 0x2a, 0xd8, 0x22, 0x63, 0xa2, 0x2f, 0xed, 0x8f, 0x15, 0xe8,
0x66, 0xce, 0x24, 0xb2, 0x85, 0x0b, 0x25, 0x5f, 0xb8, 0xb8, 0x03, 0x55, 0x62, 0xa9, 0x98, 0x6f,
0xe9, 0xc8, 0x93, 0x6a, 0x71, 0x56, 0x9d, 0x0d, 0x40, 0x37, 0x61, 0x49, 0x72, 0xf7, 0x81, 0x6f,
0x3f, 0xca, 0x5f, 0x7d, 0xd0, 0x7e, 0x56, 0x81, 0x66, 0x8a, 0x15, 0x33, 0x6a, 0x2e, 0x4f, 0xa4,
0xb6, 0x3c, 0xed, 0xac, 0x9b, 0x88, 0x9c, 0x83, 0x1d, 0x96, 0xf7, 0xf1, 0x24, 0xd4, 0xc1, 0x0e,
0xcd, 0xfa, 0xd2, 0x09, 0x5d, 0x4d, 0x48, 0xe8, 0x32, 0x29, 0xef, 0xc2, 0x29, 0x29, 0x6f, 0x5d,
0x4c, 0x79, 0x05, 0x15, 0x6a, 0x64, 0x55, 0xa8, 0x68, 0x19, 0xe4, 0x16, 0x2c, 0x0d, 0x59, 0xed,
0xfe, 0xde, 0xc9, 0x46, 0xdc, 0xc4, 0x83, 0x52, 0x59, 0x13, 0xba, 0x9f, 0x14, 0x38, 0xd9, 0x2e,
0xb3, 0xa4, 0x43, 0x9e, 0x51, 0xf3, 0xbd, 0x61, 0x9b, 0x1c, 0x59, 0x66, 0xfa, 0x95, 0x2d, 0xc0,
0xb4, 0xcf, 0x55, 0x80, 0x79, 0x06, 0x9a, 0x51, 0xa4, 0x42, 0x34, 0xbd, 0xc3, 0x8c, 0x5e, 0x64,
0x06, 0xcc, 0x40, 0xb0, 0x03, 0x5d, 0xf1, 0x74, 0x23, 0x5b, 0x8f, 0x50, 0xf3, 0xf5, 0x88, 0x4b,
0xb0, 0x60, 0x05, 0x83, 0x03, 0xe3, 0x11, 0xee, 0x2d, 0xd2, 0xd6, 0x9a, 0x15, 0xdc, 0x37, 0x1e,
0x61, 0xed, 0x5f, 0xcb, 0xd0, 0x49, 0x1c, 0x6c, 0x61, 0x0b, 0x52, 0xe4, 0xfe, 0xcf, 0x36, 0xa8,
0x49, 0xdc, 0x43, 0x39, 0x7c, 0x6a, 0x0e, 0x9e, 0x3d, 0x32, 0xec, 0x8e, 0x33, 0xfa, 0x2a, 0xb8,
0xfb, 0xca, 0x99, 0xdc, 0xfd, 0x9c, 0x37, 0x03, 0x6e, 0xc3, 0x4a, 0xec, 0x7b, 0x85, 0x65, 0xb3,
0x04, 0x6b, 0x39, 0x6a, 0xdc, 0x49, 0x2f, 0x7f, 0x8a, 0x09, 0x58, 0x98, 0x66, 0x02, 0xb2, 0x22,
0x50, 0xcf, 0x89, 0x40, 0xfe, 0x82, 0x42, 0x43, 0x72, 0x41, 0x41, 0x7b, 0x08, 0x4b, 0xb4, 0xd8,
0x1c, 0x0c, 0x7d, 0x6b, 0x1f, 0xc7, 0x29, 0x40, 0x91, 0x6d, 0xed, 0x43, 0x3d, 0x93, 0x45, 0xc4,
0xdf, 0xda, 0x8f, 0x15, 0xb8, 0x98, 0x9f, 0x97, 0x4a, 0x4c, 0x62, 0x48, 0x14, 0xc1, 0x90, 0xfc,
0x0a, 0x2c, 0xa5, 0x22, 0x4a, 0x61, 0xe6, 0x29, 0x11, 0xb8, 0x84, 0x70, 0x1d, 0x25, 0x73, 0x44,
0x30, 0xed, 0x67, 0x4a, 0x5c, 0xb3, 0x27, 0xb0, 0x11, 0x3d, 0x10, 0x21, 0x7e, 0xcd, 0x73, 0x6d,
0xcb, 0x8d, 0x0b, 0x2e, 0x7c, 0x8d, 0x0c, 0xc8, 0x0b, 0x2e, 0xef, 0x40, 0x97, 0x77, 0x8a, 0xdd,
0x53, 0xc1, 0x80, 0xac, 0xc3, 0xc6, 0xc5, 0x8e, 0xe9, 0x79, 0xe8, 0xf0, 0x93, 0x8a, 0x08, 0x5f,
0x59, 0x76, 0x7e, 0xf1, 0x3d, 0x50, 0xa3, 0x6e, 0x67, 0x75, 0x88, 0x5d, 0x3e, 0x30, 0x0e, 0xec,
0x7e, 0x53, 0x81, 0x9e, 0xe8, 0x1e, 0x53, 0xcb, 0x3f, 0x7b, 0x78, 0xf7, 0xba, 0x78, 0x3e, 0xfd,
0xfc, 0x29, 0xf4, 0x24, 0x78, 0xa2, 0x53, 0xea, 0xdf, 0x2d, 0xd1, 0xcb, 0x06, 0x24, 0xd5, 0xdb,
0xb4, 0x82, 0xd0, 0xb7, 0xf6, 0x27, 0xf3, 0x9d, 0x98, 0x1a, 0xd0, 0x1c, 0x1e, 0xe2, 0xe1, 0xa3,
0xb1, 0x67, 0x25, 0xbb, 0xf2, 0x96, 0x8c, 0xa6, 0xe9, 0x68, 0xd7, 0x36, 0x92, 0x19, 0xd8, 0x91,
0x53, 0x7a, 0xce, 0xfe, 0x0f, 0x41, 0xcd, 0x76, 0x48, 0x9f, 0xf4, 0x34, 0xd8, 0x49, 0xcf, 0x6d,
0xf1, 0xa4, 0x67, 0x46, 0xa4, 0x91, 0x3a, 0xe8, 0xf9, 0xdb, 0x12, 0x7c, 0x5d, 0x4a, 0xdb, 0x3c,
0x59, 0xd2, 0xb4, 0x3a, 0xd2, 0x3d, 0xa8, 0x67, 0x92, 0xda, 0x17, 0x4e, 0xd9, 0x3f, 0x5e, 0x92,
0x65, 0xa5, 0xc1, 0x20, 0x89, 0xad, 0x12, 0x85, 0xaf, 0x4c, 0x9f, 0x83, 0xeb, 0x9d, 0x30, 0x47,
0x34, 0x0e, 0xdd, 0x85, 0x16, 0x2b, 0x18, 0x0c, 0x8e, 0x2c, 0x7c, 0x1c, 0x9d, 0xa3, 0x5e, 0x95,
0x9a, 0x66, 0xda, 0xef, 0x43, 0x0b, 0x1f, 0xeb, 0x4d, 0x3b, 0xfe, 0x1d, 0x68, 0xbf, 0x5f, 0x01,
0x48, 0xda, 0x48, 0x76, 0x96, 0xe8, 0x3c, 0x57, 0xe2, 0x14, 0x84, 0xc4, 0x12, 0x62, 0xe4, 0x1a,
0x7d, 0x22, 0x3d, 0x39, 0xc7, 0x30, 0xad, 0x20, 0xe4, 0x7c, 0xb9, 0x79, 0x3a, 0x2d, 0x11, 0x8b,
0xc8, 0x96, 0x71, 0x99, 0x09, 0x12, 0x08, 0x7a, 0x05, 0xd0, 0xc8, 0xf7, 0x8e, 0x2d, 0x77, 0x94,
0xce, 0x37, 0x58, 0x5a, 0xb2, 0xc8, 0x5b, 0x52, 0x09, 0xc7, 0x8f, 0x40, 0xcd, 0x74, 0x8f, 0x58,
0x72, 0x7b, 0x06, 0x19, 0x0f, 0x84, 0xb9, 0xb8, 0xf8, 0x76, 0x45, 0x0c, 0xf4, 0xd0, 0x74, 0xcf,
0xf0, 0x47, 0x38, 0xda, 0x51, 0x1e, 0x87, 0x89, 0xc0, 0xfe, 0x00, 0xd4, 0xec, 0xaa, 0x24, 0x47,
0x9a, 0xaf, 0x8a, 0x82, 0x7e, 0x9a, 0x3d, 0x22, 0xd3, 0xa4, 0x44, 0xbd, 0x6f, 0xc0, 0xb2, 0x8c,
0x5e, 0x09, 0x92, 0x73, 0x6b, 0xd3, 0x5b, 0x71, 0x48, 0x4c, 0xf7, 0x61, 0x9a, 0x97, 0x49, 0x15,
0x9e, 0x4b, 0x42, 0xe1, 0x59, 0xfb, 0xf5, 0x32, 0xa0, 0xbc, 0xf8, 0xa3, 0x0e, 0x94, 0xe2, 0x49,
0x4a, 0x5b, 0x9b, 0x19, 0x71, 0x2b, 0xe5, 0xc4, 0xed, 0x32, 0x34, 0x62, 0xaf, 0xcf, 0x4d, 0x7c,
0x02, 0x48, 0x0b, 0x63, 0x45, 0x14, 0xc6, 0x14, 0x61, 0x55, 0xb1, 0x22, 0x7e, 0x0b, 0x96, 0x6d,
0x23, 0x08, 0x07, 0xac, 0xf0, 0x1e, 0x5a, 0x0e, 0x0e, 0x42, 0xc3, 0x19, 0xd3, 0xad, 0xac, 0xe8,
0x88, 0xb4, 0x6d, 0x92, 0xa6, 0xbd, 0xa8, 0x05, 0xed, 0x45, 0xd1, 0x35, 0xb1, 0xbd, 0xfc, 0xb2,
0xc0, 0xab, 0xc5, 0xd4, 0x3d, 0x29, 0x77, 0x33, 0x89, 0x6a, 0xc4, 0x61, 0x67, 0xff, 0x13, 0xe8,
0x88, 0x8d, 0x92, 0xed, 0xbb, 0x23, 0x6e, 0x5f, 0x91, 0xc0, 0x36, 0xb5, 0x87, 0x87, 0x80, 0xf2,
0xc6, 0x23, 0xcd, 0x33, 0x45, 0xe4, 0xd9, 0xac, 0xbd, 0x48, 0xf1, 0xb4, 0x2c, 0x6e, 0xf6, 0x9f,
0x96, 0x01, 0x25, 0x11, 0x5c, 0x7c, 0x78, 0x5d, 0x24, 0xec, 0xb9, 0x09, 0x4b, 0xf9, 0xf8, 0x2e,
0x0a, 0x6a, 0x51, 0x2e, 0xba, 0x93, 0x45, 0x62, 0x65, 0xd9, 0x55, 0xd1, 0xd7, 0x62, 0x73, 0xcf,
0xc2, 0xd5, 0xab, 0x53, 0xcf, 0x33, 0x44, 0x8b, 0xff, 0xc3, 0xec, 0x15, 0x53, 0x66, 0x3f, 0xee,
0x48, 0x4d, 0x73, 0x6e, 0xc9, 0x33, 0xef, 0x97, 0x0a, 0x81, 0x74, 0xed, 0x2c, 0x81, 0xf4, 0xfc,
0x17, 0x42, 0xff, 0xbd, 0x04, 0x8b, 0x31, 0x23, 0xcf, 0xb4, 0x49, 0xb3, 0xef, 0x19, 0x3c, 0xe5,
0x5d, 0xf9, 0x58, 0xbe, 0x2b, 0xdf, 0x3e, 0x35, 0x99, 0x29, 0xba, 0x29, 0xf3, 0x73, 0xf6, 0x33,
0x58, 0xe0, 0x65, 0xe9, 0x9c, 0x81, 0x2b, 0x52, 0x2e, 0x58, 0x86, 0x2a, 0xb1, 0xa7, 0x51, 0x4d,
0x91, 0x7d, 0x30, 0x96, 0xa6, 0x2f, 0x1c, 0x73, 0x1b, 0xd7, 0x16, 0xee, 0x1b, 0x6b, 0xbf, 0x55,
0x06, 0xd8, 0x3d, 0x71, 0x87, 0x77, 0x99, 0x92, 0xde, 0x82, 0xca, 0xac, 0xeb, 0x69, 0xa4, 0x37,
0x95, 0x2d, 0xda, 0xb3, 0xc0, 0xe6, 0x0a, 0x05, 0x91, 0x72, 0xb6, 0x20, 0x32, 0xad, 0x94, 0x31,
0xdd, 0x04, 0x7f, 0x1b, 0x2a, 0xd4, 0x94, 0xb2, 0xdb, 0x5b, 0x85, 0x4e, 0x85, 0xe9, 0x00, 0xb4,
0x0a, 0x91, 0x4b, 0xde, 0x72, 0x99, 0xcf, 0xa5, 0xe6, 0xb8, 0xac, 0x67, 0xc1, 0xe8, 0x05, 0xe8,
0xb0, 0x42, 0x58, 0xdc, 0x91, 0xe5, 0x74, 0x19, 0x68, 0xde, 0xa3, 0x37, 0x24, 0x1e, 0x9d, 0xe0,
0x35, 0x7d, 0x6f, 0x3c, 0x4e, 0x4d, 0xc7, 0x2a, 0x21, 0x59, 0xb0, 0xf6, 0x79, 0x09, 0x2e, 0x11,
0xfe, 0x3e, 0x99, 0xa8, 0xbc, 0x88, 0xf0, 0xa4, 0xec, 0x79, 0x59, 0xb4, 0xe7, 0x77, 0x60, 0x81,
0x95, 0x5b, 0xa2, 0xf8, 0xf2, 0xea, 0x34, 0x69, 0x60, 0xb2, 0xa3, 0x47, 0xdd, 0xe7, 0xcd, 0xd9,
0x85, 0x33, 0xf3, 0xda, 0x7c, 0x67, 0xe6, 0x0b, 0xd9, 0xa2, 0x6c, 0x4a, 0xac, 0xea, 0xa2, 0x17,
0x7a, 0x08, 0x6d, 0x3d, 0xad, 0x1a, 0x08, 0x41, 0x25, 0x75, 0x61, 0x95, 0xfe, 0xa6, 0x69, 0xb6,
0x31, 0x36, 0x86, 0x56, 0x78, 0x42, 0xd9, 0x59, 0xd5, 0xe3, 0x6f, 0xb9, 0x1e, 0x6a, 0xff, 0xab,
0xc0, 0xc5, 0xe8, 0x50, 0x95, 0x6b, 0xf9, 0xf9, 0x77, 0x74, 0x1d, 0x56, 0xb8, 0x4a, 0x67, 0x74,
0x9b, 0x05, 0xd3, 0x4b, 0x0c, 0x26, 0x2e, 0x63, 0x1d, 0x56, 0x42, 0x2a, 0x5d, 0xd9, 0x31, 0x6c,
0xbf, 0x97, 0x58, 0xa3, 0x38, 0xa6, 0xc8, 0xa1, 0xf6, 0x33, 0xec, 0x06, 0x16, 0x67, 0x2d, 0x57,
0x52, 0x70, 0x27, 0x0e, 0x5f, 0xa5, 0x76, 0x0c, 0x97, 0xd9, 0x95, 0xf1, 0x7d, 0x91, 0xa2, 0xb9,
0xce, 0x34, 0xa4, 0xeb, 0xce, 0xd8, 0xb4, 0x3f, 0x51, 0xe0, 0xca, 0x14, 0xcc, 0xf3, 0x64, 0x73,
0xef, 0x49, 0xb1, 0x4f, 0xc9, 0xbd, 0x05, 0xbc, 0xec, 0xc2, 0x82, 0x48, 0xe4, 0xe7, 0x15, 0x58,
0xcc, 0x75, 0x3a, 0xb3, 0xcc, 0xbd, 0x0c, 0x88, 0x6c, 0x42, 0xfc, 0x3c, 0x92, 0x96, 0x33, 0xb8,
0xf3, 0x54, 0xdd, 0x89, 0x13, 0x3f, 0x8d, 0xdc, 0xf6, 0x4c, 0x8c, 0x2c, 0xd6, 0x9b, 0x9d, 0x68,
0xc4, 0x3b, 0x57, 0x99, 0xfe, 0x0a, 0x26, 0x47, 0xe0, 0xda, 0xf6, 0xc4, 0x61, 0x87, 0x1f, 0x7c,
0x97, 0x99, 0x43, 0x24, 0xa8, 0x04, 0x30, 0x3a, 0x80, 0x45, 0x7a, 0x3f, 0x6f, 0x12, 0x8e, 0x3c,
0x92, 0x50, 0x51, 0xba, 0x98, 0xdb, 0xfd, 0x6e, 0x61, 0x4c, 0x1f, 0xf0, 0xd1, 0x84, 0x78, 0x9e,
0x53, 0xb9, 0x22, 0x34, 0xc2, 0x63, 0xb9, 0x43, 0xcf, 0x89, 0xf1, 0xd4, 0xce, 0x88, 0x67, 0x8b,
0x8f, 0x16, 0xf1, 0xa4, 0xa1, 0xfd, 0x0d, 0x58, 0x91, 0x2e, 0x7d, 0x96, 0xa3, 0xaf, 0xa6, 0x33,
0xaf, 0x7b, 0xb0, 0x2c, 0x5b, 0xd5, 0x39, 0xe6, 0xc8, 0x51, 0x7c, 0x96, 0x39, 0xb4, 0xbf, 0x28,
0x41, 0x7b, 0x13, 0xdb, 0x38, 0xc4, 0x4f, 0xf7, 0xcc, 0x39, 0x77, 0x80, 0x5e, 0xce, 0x1f, 0xa0,
0xe7, 0x6e, 0x03, 0x54, 0x24, 0xb7, 0x01, 0xae, 0xc4, 0x97, 0x20, 0xc8, 0x2c, 0x55, 0x31, 0x86,
0x30, 0xd1, 0xeb, 0xd0, 0x1a, 0xfb, 0x96, 0x63, 0xf8, 0x27, 0x83, 0x47, 0xf8, 0x24, 0xe0, 0x4e,
0xa3, 0x27, 0x75, 0x3b, 0x5b, 0x9b, 0x81, 0xde, 0xe4, 0xbd, 0xdf, 0xc5, 0x27, 0xf4, 0x82, 0x45,
0x9c, 0xc6, 0xb1, 0x1b, 0x75, 0x15, 0x3d, 0x05, 0xb9, 0xf1, 0x12, 0x34, 0xe2, 0x8b, 0x4b, 0xa8,
0x0e, 0x95, 0xfb, 0x13, 0xdb, 0x56, 0x2f, 0xa0, 0x06, 0x54, 0x69, 0xa2, 0xa7, 0x2a, 0xe4, 0x27,
0x8d, 0xfd, 0xd4, 0xd2, 0x8d, 0x5f, 0x82, 0x46, 0x7c, 0x81, 0x02, 0x35, 0x61, 0xe1, 0xa1, 0xfb,
0xae, 0xeb, 0x1d, 0xbb, 0xea, 0x05, 0xb4, 0x00, 0xe5, 0xbb, 0xb6, 0xad, 0x2a, 0xa8, 0x0d, 0x8d,
0xdd, 0xd0, 0xc7, 0x06, 0xd9, 0x3e, 0xb5, 0x84, 0x3a, 0x00, 0xef, 0x58, 0x41, 0xe8, 0xf9, 0xd6,
0xd0, 0xb0, 0xd5, 0xf2, 0x8d, 0xcf, 0xa0, 0x23, 0xd6, 0xd3, 0x51, 0x0b, 0xea, 0xdb, 0x5e, 0xf8,
0xf6, 0xa7, 0x56, 0x10, 0xaa, 0x17, 0x48, 0xff, 0x6d, 0x2f, 0xdc, 0xf1, 0x71, 0x80, 0xdd, 0x50,
0x55, 0x10, 0x40, 0xed, 0x03, 0x77, 0xd3, 0x0a, 0x1e, 0xa9, 0x25, 0xb4, 0xc4, 0x8f, 0xca, 0x0c,
0x7b, 0x8b, 0x17, 0xa9, 0xd5, 0x32, 0x19, 0x1e, 0x7f, 0x55, 0x90, 0x0a, 0xad, 0xb8, 0xcb, 0x83,
0x9d, 0x87, 0x6a, 0x95, 0x51, 0x4f, 0x7e, 0xd6, 0x6e, 0x98, 0xa0, 0x66, 0x8f, 0x78, 0xc9, 0x9c,
0x6c, 0x11, 0x31, 0x48, 0xbd, 0x40, 0x56, 0xc6, 0xcf, 0xd8, 0x55, 0x05, 0x75, 0xa1, 0x99, 0x3a,
0xb1, 0x56, 0x4b, 0x04, 0xf0, 0xc0, 0x1f, 0x0f, 0xb9, 0x6c, 0x31, 0x12, 0x88, 0xa0, 0x6e, 0x12,
0x4e, 0x54, 0x6e, 0xdc, 0x83, 0x7a, 0x94, 0x9f, 0x90, 0xae, 0x9c, 0x45, 0xe4, 0x53, 0xbd, 0x80,
0x16, 0xa1, 0x2d, 0x3c, 0xbd, 0x53, 0x15, 0x84, 0xa0, 0x23, 0x3e, 0x8e, 0x55, 0x4b, 0x37, 0xd6,
0x01, 0x92, 0x38, 0x9f, 0x90, 0xb3, 0xe5, 0x1e, 0x19, 0xb6, 0x65, 0x32, 0xda, 0x48, 0x13, 0xe1,
0x2e, 0xe5, 0x0e, 0xd3, 0x59, 0xb5, 0x74, 0xe3, 0x4d, 0xa8, 0x47, 0xb1, 0x2b, 0x81, 0xeb, 0xd8,
0xf1, 0x8e, 0x30, 0xdb, 0x99, 0x5d, 0x1c, 0xb2, 0x7d, 0xbc, 0xeb, 0x60, 0xd7, 0x54, 0x4b, 0x84,
0x8c, 0x87, 0x63, 0xd3, 0x08, 0xa3, 0x6b, 0xa6, 0x6a, 0x79, 0xfd, 0x3f, 0x97, 0x00, 0xd8, 0x99,
0xad, 0xe7, 0xf9, 0x26, 0xb2, 0xe9, 0xdd, 0x8d, 0x0d, 0xcf, 0x19, 0x7b, 0x6e, 0x74, 0xa0, 0x14,
0xa0, 0xb5, 0x4c, 0x89, 0x84, 0x7d, 0xe4, 0x3b, 0x72, 0xde, 0xf4, 0x9f, 0x93, 0xf6, 0xcf, 0x74,
0xd6, 0x2e, 0x20, 0x87, 0x62, 0xdb, 0xb3, 0x1c, 0xbc, 0x67, 0x0d, 0x1f, 0xc5, 0x07, 0xbd, 0xd3,
0x1f, 0xad, 0x66, 0xba, 0x46, 0xf8, 0xae, 0x4b, 0xf1, 0xed, 0x86, 0xbe, 0xe5, 0x8e, 0x22, 0xef,
0xa8, 0x5d, 0x40, 0x8f, 0x33, 0x4f, 0x66, 0x23, 0x84, 0xeb, 0x45, 0x5e, 0xc9, 0x9e, 0x0f, 0xa5,
0x0d, 0xdd, 0xcc, 0x7f, 0x13, 0xa0, 0x1b, 0xf2, 0xb7, 0x47, 0xb2, 0xff, 0x51, 0xe8, 0xbf, 0x54,
0xa8, 0x6f, 0x8c, 0xcd, 0x82, 0x8e, 0xf8, 0xa8, 0x1e, 0x7d, 0x63, 0xda, 0x04, 0xb9, 0xd7, 0x8f,
0xfd, 0x1b, 0x45, 0xba, 0xc6, 0xa8, 0x3e, 0x62, 0xe2, 0x3b, 0x0b, 0x95, 0xf4, 0xc1, 0x69, 0xff,
0xb4, 0xc0, 0x44, 0xbb, 0x80, 0x3e, 0x21, 0x31, 0x44, 0xe6, 0x8d, 0x26, 0x7a, 0x59, 0xee, 0xf7,
0xe4, 0x4f, 0x39, 0x67, 0x61, 0xf8, 0x28, 0xab, 0x7c, 0xd3, 0xa9, 0xcf, 0x3d, 0xfe, 0x2e, 0x4e,
0x7d, 0x6a, 0xfa, 0xd3, 0xa8, 0x3f, 0x33, 0x06, 0x9b, 0xa5, 0x53, 0x92, 0xd7, 0x61, 0x59, 0x51,
0x4e, 0xb2, 0x99, 0xe9, 0x4f, 0xc9, 0x66, 0x61, 0x9b, 0x50, 0x25, 0xcd, 0x5e, 0x56, 0x78, 0x65,
0xca, 0x31, 0x88, 0xfc, 0x59, 0x6a, 0x7f, 0xad, 0x68, 0xf7, 0xb4, 0x2c, 0x8b, 0x2f, 0x1f, 0xe5,
0x5b, 0x24, 0x7d, 0xad, 0x29, 0x97, 0x65, 0xf9, 0x43, 0x4a, 0xed, 0x02, 0xda, 0x13, 0x4c, 0x3d,
0x7a, 0x61, 0x9a, 0x28, 0x88, 0xb7, 0x97, 0x66, 0xf1, 0xed, 0x57, 0x01, 0x31, 0x4d, 0x75, 0x0f,
0xac, 0xd1, 0xc4, 0x37, 0x98, 0x18, 0x4f, 0x33, 0x6e, 0xf9, 0xae, 0x11, 0x9a, 0x6f, 0x9e, 0x61,
0x44, 0xbc, 0xa4, 0x01, 0xc0, 0x03, 0x1c, 0xbe, 0x4f, 0x9f, 0xc0, 0x05, 0xd9, 0x15, 0x25, 0xf6,
0x9b, 0x77, 0x88, 0x50, 0xbd, 0x38, 0xb3, 0x5f, 0x8c, 0x60, 0x1f, 0x9a, 0x0f, 0x48, 0x7e, 0x45,
0x63, 0xc6, 0x00, 0x4d, 0x1d, 0x19, 0xf5, 0x88, 0x50, 0xac, 0xce, 0xee, 0x98, 0x36, 0x9e, 0x99,
0x57, 0xa0, 0x68, 0xea, 0xc6, 0xe6, 0xdf, 0xa6, 0xca, 0x8d, 0xe7, 0x94, 0x67, 0xa5, 0x6c, 0x45,
0xf4, 0x28, 0xee, 0x1d, 0x6c, 0xd8, 0xe1, 0xe1, 0x94, 0x15, 0xa5, 0x7a, 0x9c, 0xbe, 0x22, 0xa1,
0x63, 0x8c, 0x03, 0xc3, 0x12, 0xd3, 0x42, 0x31, 0x31, 0xbd, 0x29, 0x9f, 0x22, 0xdf, 0xb3, 0xa0,
0xe8, 0x19, 0xb0, 0xb8, 0xe9, 0x7b, 0x63, 0x11, 0xc9, 0x2b, 0x52, 0x24, 0xb9, 0x7e, 0x05, 0x51,
0x7c, 0x1f, 0x5a, 0x51, 0xfe, 0x4f, 0x33, 0x16, 0x39, 0x17, 0xd2, 0x5d, 0x0a, 0x4e, 0xfc, 0x31,
0x74, 0x33, 0x85, 0x05, 0xf9, 0xa6, 0xcb, 0xab, 0x0f, 0xb3, 0x66, 0x3f, 0x06, 0x44, 0x9f, 0xf6,
0x8a, 0xff, 0x4e, 0x20, 0x8f, 0x6f, 0xf2, 0x1d, 0x23, 0x24, 0x37, 0x0b, 0xf7, 0x8f, 0x77, 0xfe,
0xd7, 0x60, 0x45, 0x9a, 0xbc, 0x67, 0x0d, 0x02, 0xbf, 0xae, 0x7c, 0x4a, 0x85, 0x21, 0x6b, 0x10,
0x4e, 0x1d, 0x11, 0xe1, 0x5f, 0xff, 0x37, 0x04, 0x0d, 0x1a, 0xe7, 0xd1, 0xdd, 0xfa, 0x45, 0x98,
0xf7, 0x64, 0xc3, 0xbc, 0x8f, 0xa1, 0x9b, 0x79, 0x72, 0x2a, 0x17, 0x5a, 0xf9, 0xbb, 0xd4, 0x02,
0xd1, 0x8a, 0xf8, 0x5a, 0x53, 0xee, 0x0a, 0xa5, 0x2f, 0x3a, 0x67, 0xcd, 0xfd, 0x21, 0x7b, 0xce,
0x1d, 0x9f, 0xe6, 0xbe, 0x38, 0xf5, 0xf0, 0x41, 0xbc, 0x76, 0xfc, 0xc5, 0x47, 0x41, 0x5f, 0xed,
0x08, 0xf4, 0x63, 0xe8, 0x66, 0x1e, 0xf6, 0xc8, 0x25, 0x46, 0xfe, 0xfa, 0x67, 0xd6, 0xec, 0x3f,
0xc7, 0xe0, 0xc9, 0x84, 0x25, 0xc9, 0x3b, 0x0a, 0xb4, 0x36, 0x2d, 0x10, 0x95, 0x3f, 0xb8, 0x98,
0xbd, 0xa0, 0xb6, 0xa0, 0xa6, 0x59, 0x7f, 0x93, 0x10, 0x99, 0xfd, 0x5b, 0xa3, 0xfe, 0xcb, 0xc5,
0xfe, 0x03, 0x29, 0x5e, 0xd0, 0x2e, 0xd4, 0xd8, 0x73, 0x1f, 0xf4, 0xac, 0xfc, 0x10, 0x26, 0xf5,
0x14, 0xa8, 0x3f, 0xeb, 0xc1, 0x50, 0x30, 0xb1, 0x43, 0x42, 0xff, 0x0f, 0xa0, 0xc3, 0x40, 0x31,
0x83, 0x9e, 0xe0, 0xe4, 0xbb, 0x50, 0xa5, 0xa6, 0x1d, 0x49, 0x0f, 0x14, 0xd2, 0x8f, 0x7a, 0xfa,
0xb3, 0xdf, 0xf1, 0x24, 0x14, 0x37, 0xe9, 0x48, 0x56, 0xd5, 0x79, 0x92, 0x53, 0xdf, 0x52, 0xd0,
0x0f, 0xa0, 0xcd, 0x26, 0x8f, 0xb8, 0xf1, 0x24, 0x29, 0x1f, 0xc2, 0x52, 0x8a, 0xf2, 0xa7, 0x81,
0xe2, 0x96, 0xf2, 0xff, 0x3c, 0xba, 0xff, 0x94, 0x3e, 0xaa, 0xc9, 0x5e, 0x1b, 0x43, 0x6b, 0x67,
0xbb, 0xfb, 0xd6, 0xbf, 0x59, 0xb8, 0x7f, 0x8c, 0xf9, 0x47, 0xa0, 0x66, 0x8f, 0x0a, 0xd1, 0x4b,
0xd3, 0x6c, 0x89, 0x0c, 0xe7, 0x0c, 0x43, 0xf2, 0x3d, 0xa8, 0xb1, 0x1a, 0xb1, 0x5c, 0x01, 0x85,
0xfa, 0xf1, 0x8c, 0xb9, 0xee, 0x7d, 0xeb, 0xa3, 0xf5, 0x91, 0x15, 0x1e, 0x4e, 0xf6, 0x49, 0xcb,
0x4d, 0xd6, 0xf5, 0x15, 0xcb, 0xe3, 0xbf, 0x6e, 0x46, 0x7b, 0x79, 0x93, 0x8e, 0xbe, 0x49, 0x11,
0x8c, 0xf7, 0xf7, 0x6b, 0xf4, 0xf3, 0xf6, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xc4, 0x63,
0x89, 0xd0, 0x53, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -5808,7 +5809,9 @@ type QueryNodeClient interface {
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*internalpb.SearchResults, error)
SearchSegments(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*internalpb.SearchResults, error)
Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*internalpb.RetrieveResults, error)
QueryStream(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (QueryNode_QueryStreamClient, error)
QuerySegments(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*internalpb.RetrieveResults, error)
QueryStreamSegments(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (QueryNode_QueryStreamSegmentsClient, error)
ShowConfigurations(ctx context.Context, in *internalpb.ShowConfigurationsRequest, opts ...grpc.CallOption) (*internalpb.ShowConfigurationsResponse, error)
// https://wiki.lfaidata.foundation/display/MIL/MEP+8+--+Add+metrics+for+proxy
GetMetrics(ctx context.Context, in *milvuspb.GetMetricsRequest, opts ...grpc.CallOption) (*milvuspb.GetMetricsResponse, error)
@ -5969,6 +5972,38 @@ func (c *queryNodeClient) Query(ctx context.Context, in *QueryRequest, opts ...g
return out, nil
}
func (c *queryNodeClient) QueryStream(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (QueryNode_QueryStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_QueryNode_serviceDesc.Streams[0], "/milvus.proto.query.QueryNode/QueryStream", opts...)
if err != nil {
return nil, err
}
x := &queryNodeQueryStreamClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type QueryNode_QueryStreamClient interface {
Recv() (*internalpb.RetrieveResults, error)
grpc.ClientStream
}
type queryNodeQueryStreamClient struct {
grpc.ClientStream
}
func (x *queryNodeQueryStreamClient) Recv() (*internalpb.RetrieveResults, error) {
m := new(internalpb.RetrieveResults)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *queryNodeClient) QuerySegments(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*internalpb.RetrieveResults, error) {
out := new(internalpb.RetrieveResults)
err := c.cc.Invoke(ctx, "/milvus.proto.query.QueryNode/QuerySegments", in, out, opts...)
@ -5978,6 +6013,38 @@ func (c *queryNodeClient) QuerySegments(ctx context.Context, in *QueryRequest, o
return out, nil
}
func (c *queryNodeClient) QueryStreamSegments(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (QueryNode_QueryStreamSegmentsClient, error) {
stream, err := c.cc.NewStream(ctx, &_QueryNode_serviceDesc.Streams[1], "/milvus.proto.query.QueryNode/QueryStreamSegments", opts...)
if err != nil {
return nil, err
}
x := &queryNodeQueryStreamSegmentsClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type QueryNode_QueryStreamSegmentsClient interface {
Recv() (*internalpb.RetrieveResults, error)
grpc.ClientStream
}
type queryNodeQueryStreamSegmentsClient struct {
grpc.ClientStream
}
func (x *queryNodeQueryStreamSegmentsClient) Recv() (*internalpb.RetrieveResults, error) {
m := new(internalpb.RetrieveResults)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *queryNodeClient) ShowConfigurations(ctx context.Context, in *internalpb.ShowConfigurationsRequest, opts ...grpc.CallOption) (*internalpb.ShowConfigurationsResponse, error) {
out := new(internalpb.ShowConfigurationsResponse)
err := c.cc.Invoke(ctx, "/milvus.proto.query.QueryNode/ShowConfigurations", in, out, opts...)
@ -6041,7 +6108,9 @@ type QueryNodeServer interface {
Search(context.Context, *SearchRequest) (*internalpb.SearchResults, error)
SearchSegments(context.Context, *SearchRequest) (*internalpb.SearchResults, error)
Query(context.Context, *QueryRequest) (*internalpb.RetrieveResults, error)
QueryStream(*QueryRequest, QueryNode_QueryStreamServer) error
QuerySegments(context.Context, *QueryRequest) (*internalpb.RetrieveResults, error)
QueryStreamSegments(*QueryRequest, QueryNode_QueryStreamSegmentsServer) error
ShowConfigurations(context.Context, *internalpb.ShowConfigurationsRequest) (*internalpb.ShowConfigurationsResponse, error)
// https://wiki.lfaidata.foundation/display/MIL/MEP+8+--+Add+metrics+for+proxy
GetMetrics(context.Context, *milvuspb.GetMetricsRequest) (*milvuspb.GetMetricsResponse, error)
@ -6102,9 +6171,15 @@ func (*UnimplementedQueryNodeServer) SearchSegments(ctx context.Context, req *Se
func (*UnimplementedQueryNodeServer) Query(ctx context.Context, req *QueryRequest) (*internalpb.RetrieveResults, error) {
return nil, status.Errorf(codes.Unimplemented, "method Query not implemented")
}
func (*UnimplementedQueryNodeServer) QueryStream(req *QueryRequest, srv QueryNode_QueryStreamServer) error {
return status.Errorf(codes.Unimplemented, "method QueryStream not implemented")
}
func (*UnimplementedQueryNodeServer) QuerySegments(ctx context.Context, req *QueryRequest) (*internalpb.RetrieveResults, error) {
return nil, status.Errorf(codes.Unimplemented, "method QuerySegments not implemented")
}
func (*UnimplementedQueryNodeServer) QueryStreamSegments(req *QueryRequest, srv QueryNode_QueryStreamSegmentsServer) error {
return status.Errorf(codes.Unimplemented, "method QueryStreamSegments not implemented")
}
func (*UnimplementedQueryNodeServer) ShowConfigurations(ctx context.Context, req *internalpb.ShowConfigurationsRequest) (*internalpb.ShowConfigurationsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ShowConfigurations not implemented")
}
@ -6413,6 +6488,27 @@ func _QueryNode_Query_Handler(srv interface{}, ctx context.Context, dec func(int
return interceptor(ctx, in, info, handler)
}
func _QueryNode_QueryStream_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(QueryRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(QueryNodeServer).QueryStream(m, &queryNodeQueryStreamServer{stream})
}
type QueryNode_QueryStreamServer interface {
Send(*internalpb.RetrieveResults) error
grpc.ServerStream
}
type queryNodeQueryStreamServer struct {
grpc.ServerStream
}
func (x *queryNodeQueryStreamServer) Send(m *internalpb.RetrieveResults) error {
return x.ServerStream.SendMsg(m)
}
func _QueryNode_QuerySegments_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryRequest)
if err := dec(in); err != nil {
@ -6431,6 +6527,27 @@ func _QueryNode_QuerySegments_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _QueryNode_QueryStreamSegments_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(QueryRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(QueryNodeServer).QueryStreamSegments(m, &queryNodeQueryStreamSegmentsServer{stream})
}
type QueryNode_QueryStreamSegmentsServer interface {
Send(*internalpb.RetrieveResults) error
grpc.ServerStream
}
type queryNodeQueryStreamSegmentsServer struct {
grpc.ServerStream
}
func (x *queryNodeQueryStreamSegmentsServer) Send(m *internalpb.RetrieveResults) error {
return x.ServerStream.SendMsg(m)
}
func _QueryNode_ShowConfigurations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(internalpb.ShowConfigurationsRequest)
if err := dec(in); err != nil {
@ -6614,6 +6731,17 @@ var _QueryNode_serviceDesc = grpc.ServiceDesc{
Handler: _QueryNode_Delete_Handler,
},
},
Streams: []grpc.StreamDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "QueryStream",
Handler: _QueryNode_QueryStream_Handler,
ServerStreams: true,
},
{
StreamName: "QueryStreamSegments",
Handler: _QueryNode_QueryStreamSegments_Handler,
ServerStreams: true,
},
},
Metadata: "query_coord.proto",
}

View File

@ -2243,27 +2243,13 @@ func (node *Proxy) Delete(ctx context.Context, request *milvuspb.DeleteRequest)
metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(paramtable.GetNodeID(), 10), method,
metrics.TotalLabel).Inc()
dt := &deleteTask{
ctx: ctx,
Condition: NewTaskCondition(ctx),
deleteExpr: request.Expr,
deleteMsg: &BaseDeleteTask{
BaseMsg: msgstream.BaseMsg{
HashValues: request.HashKeys,
},
DeleteRequest: msgpb.DeleteRequest{
Base: commonpbutil.NewMsgBase(
commonpbutil.WithMsgType(commonpb.MsgType_Delete),
commonpbutil.WithMsgID(0),
),
DbName: request.DbName,
CollectionName: request.CollectionName,
PartitionName: request.PartitionName,
// RowData: transfer column based request to this
},
},
ctx: ctx,
Condition: NewTaskCondition(ctx),
req: request,
idAllocator: node.rowIDAllocator,
chMgr: node.chMgr,
chTicker: node.chTicker,
lb: node.lbPolicy,
}
log.Debug("Enqueue delete request in Proxy")
@ -2290,7 +2276,7 @@ func (node *Proxy) Delete(ctx context.Context, request *milvuspb.DeleteRequest)
}, nil
}
receiveSize := proto.Size(dt.deleteMsg)
receiveSize := proto.Size(dt.req)
rateCol.Add(internalpb.RateType_DMLDelete.String(), float64(receiveSize))
metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(paramtable.GetNodeID(), 10), method,

View File

@ -0,0 +1,262 @@
// Code generated by mockery v2.32.4. DO NOT EDIT.
package proxy
import (
msgstream "github.com/milvus-io/milvus/pkg/mq/msgstream"
mock "github.com/stretchr/testify/mock"
)
// MockChannelsMgr is an autogenerated mock type for the channelsMgr type
type MockChannelsMgr struct {
mock.Mock
}
type MockChannelsMgr_Expecter struct {
mock *mock.Mock
}
func (_m *MockChannelsMgr) EXPECT() *MockChannelsMgr_Expecter {
return &MockChannelsMgr_Expecter{mock: &_m.Mock}
}
// getChannels provides a mock function with given fields: collectionID
func (_m *MockChannelsMgr) getChannels(collectionID int64) ([]string, error) {
ret := _m.Called(collectionID)
var r0 []string
var r1 error
if rf, ok := ret.Get(0).(func(int64) ([]string, error)); ok {
return rf(collectionID)
}
if rf, ok := ret.Get(0).(func(int64) []string); ok {
r0 = rf(collectionID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if rf, ok := ret.Get(1).(func(int64) error); ok {
r1 = rf(collectionID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockChannelsMgr_getChannels_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'getChannels'
type MockChannelsMgr_getChannels_Call struct {
*mock.Call
}
// getChannels is a helper method to define mock.On call
// - collectionID int64
func (_e *MockChannelsMgr_Expecter) getChannels(collectionID interface{}) *MockChannelsMgr_getChannels_Call {
return &MockChannelsMgr_getChannels_Call{Call: _e.mock.On("getChannels", collectionID)}
}
func (_c *MockChannelsMgr_getChannels_Call) Run(run func(collectionID int64)) *MockChannelsMgr_getChannels_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int64))
})
return _c
}
func (_c *MockChannelsMgr_getChannels_Call) Return(_a0 []string, _a1 error) *MockChannelsMgr_getChannels_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockChannelsMgr_getChannels_Call) RunAndReturn(run func(int64) ([]string, error)) *MockChannelsMgr_getChannels_Call {
_c.Call.Return(run)
return _c
}
// getOrCreateDmlStream provides a mock function with given fields: collectionID
func (_m *MockChannelsMgr) getOrCreateDmlStream(collectionID int64) (msgstream.MsgStream, error) {
ret := _m.Called(collectionID)
var r0 msgstream.MsgStream
var r1 error
if rf, ok := ret.Get(0).(func(int64) (msgstream.MsgStream, error)); ok {
return rf(collectionID)
}
if rf, ok := ret.Get(0).(func(int64) msgstream.MsgStream); ok {
r0 = rf(collectionID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(msgstream.MsgStream)
}
}
if rf, ok := ret.Get(1).(func(int64) error); ok {
r1 = rf(collectionID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockChannelsMgr_getOrCreateDmlStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'getOrCreateDmlStream'
type MockChannelsMgr_getOrCreateDmlStream_Call struct {
*mock.Call
}
// getOrCreateDmlStream is a helper method to define mock.On call
// - collectionID int64
func (_e *MockChannelsMgr_Expecter) getOrCreateDmlStream(collectionID interface{}) *MockChannelsMgr_getOrCreateDmlStream_Call {
return &MockChannelsMgr_getOrCreateDmlStream_Call{Call: _e.mock.On("getOrCreateDmlStream", collectionID)}
}
func (_c *MockChannelsMgr_getOrCreateDmlStream_Call) Run(run func(collectionID int64)) *MockChannelsMgr_getOrCreateDmlStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int64))
})
return _c
}
func (_c *MockChannelsMgr_getOrCreateDmlStream_Call) Return(_a0 msgstream.MsgStream, _a1 error) *MockChannelsMgr_getOrCreateDmlStream_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockChannelsMgr_getOrCreateDmlStream_Call) RunAndReturn(run func(int64) (msgstream.MsgStream, error)) *MockChannelsMgr_getOrCreateDmlStream_Call {
_c.Call.Return(run)
return _c
}
// getVChannels provides a mock function with given fields: collectionID
func (_m *MockChannelsMgr) getVChannels(collectionID int64) ([]string, error) {
ret := _m.Called(collectionID)
var r0 []string
var r1 error
if rf, ok := ret.Get(0).(func(int64) ([]string, error)); ok {
return rf(collectionID)
}
if rf, ok := ret.Get(0).(func(int64) []string); ok {
r0 = rf(collectionID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if rf, ok := ret.Get(1).(func(int64) error); ok {
r1 = rf(collectionID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockChannelsMgr_getVChannels_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'getVChannels'
type MockChannelsMgr_getVChannels_Call struct {
*mock.Call
}
// getVChannels is a helper method to define mock.On call
// - collectionID int64
func (_e *MockChannelsMgr_Expecter) getVChannels(collectionID interface{}) *MockChannelsMgr_getVChannels_Call {
return &MockChannelsMgr_getVChannels_Call{Call: _e.mock.On("getVChannels", collectionID)}
}
func (_c *MockChannelsMgr_getVChannels_Call) Run(run func(collectionID int64)) *MockChannelsMgr_getVChannels_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int64))
})
return _c
}
func (_c *MockChannelsMgr_getVChannels_Call) Return(_a0 []string, _a1 error) *MockChannelsMgr_getVChannels_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockChannelsMgr_getVChannels_Call) RunAndReturn(run func(int64) ([]string, error)) *MockChannelsMgr_getVChannels_Call {
_c.Call.Return(run)
return _c
}
// removeAllDMLStream provides a mock function with given fields:
func (_m *MockChannelsMgr) removeAllDMLStream() {
_m.Called()
}
// MockChannelsMgr_removeAllDMLStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'removeAllDMLStream'
type MockChannelsMgr_removeAllDMLStream_Call struct {
*mock.Call
}
// removeAllDMLStream is a helper method to define mock.On call
func (_e *MockChannelsMgr_Expecter) removeAllDMLStream() *MockChannelsMgr_removeAllDMLStream_Call {
return &MockChannelsMgr_removeAllDMLStream_Call{Call: _e.mock.On("removeAllDMLStream")}
}
func (_c *MockChannelsMgr_removeAllDMLStream_Call) Run(run func()) *MockChannelsMgr_removeAllDMLStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockChannelsMgr_removeAllDMLStream_Call) Return() *MockChannelsMgr_removeAllDMLStream_Call {
_c.Call.Return()
return _c
}
func (_c *MockChannelsMgr_removeAllDMLStream_Call) RunAndReturn(run func()) *MockChannelsMgr_removeAllDMLStream_Call {
_c.Call.Return(run)
return _c
}
// removeDMLStream provides a mock function with given fields: collectionID
func (_m *MockChannelsMgr) removeDMLStream(collectionID int64) {
_m.Called(collectionID)
}
// MockChannelsMgr_removeDMLStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'removeDMLStream'
type MockChannelsMgr_removeDMLStream_Call struct {
*mock.Call
}
// removeDMLStream is a helper method to define mock.On call
// - collectionID int64
func (_e *MockChannelsMgr_Expecter) removeDMLStream(collectionID interface{}) *MockChannelsMgr_removeDMLStream_Call {
return &MockChannelsMgr_removeDMLStream_Call{Call: _e.mock.On("removeDMLStream", collectionID)}
}
func (_c *MockChannelsMgr_removeDMLStream_Call) Run(run func(collectionID int64)) *MockChannelsMgr_removeDMLStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int64))
})
return _c
}
func (_c *MockChannelsMgr_removeDMLStream_Call) Return() *MockChannelsMgr_removeDMLStream_Call {
_c.Call.Return()
return _c
}
func (_c *MockChannelsMgr_removeDMLStream_Call) RunAndReturn(run func(int64)) *MockChannelsMgr_removeDMLStream_Call {
_c.Call.Return(run)
return _c
}
// NewMockChannelsMgr creates a new instance of MockChannelsMgr. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockChannelsMgr(t interface {
mock.TestingT
Cleanup(func())
}) *MockChannelsMgr {
mock := &MockChannelsMgr{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -3,9 +3,10 @@ package proxy
import (
"context"
"fmt"
"strconv"
"io"
"github.com/cockroachdb/errors"
"github.com/golang/protobuf/proto"
"go.opentelemetry.io/otel"
"go.uber.org/zap"
@ -14,10 +15,14 @@ import (
"github.com/milvus-io/milvus-proto/go-api/v2/msgpb"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/internal/allocator"
"github.com/milvus-io/milvus/internal/parser/planparserv2"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/planpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/metrics"
"github.com/milvus-io/milvus/pkg/mq/msgstream"
"github.com/milvus-io/milvus/pkg/util/commonpbutil"
"github.com/milvus-io/milvus/pkg/util/merr"
@ -30,19 +35,28 @@ type BaseDeleteTask = msgstream.DeleteMsg
type deleteTask struct {
Condition
deleteMsg *BaseDeleteTask
ctx context.Context
deleteExpr string
//req *milvuspb.DeleteRequest
result *milvuspb.MutationResult
ctx context.Context
tr *timerecord.TimeRecorder
req *milvuspb.DeleteRequest
result *milvuspb.MutationResult
// channel
chMgr channelsMgr
chTicker channelsTimeTicker
vChannels []vChan
pChannels []pChan
vChannels []vChan
idAllocator *allocator.IDAllocator
collectionID UniqueID
idAllocator *allocator.IDAllocator
lb LBPolicy
// delete info
schema *schemapb.CollectionSchema
ts Timestamp
msgID UniqueID
collectionID UniqueID
partitionID UniqueID
count int
}
func (dt *deleteTask) TraceCtx() context.Context {
@ -50,15 +64,15 @@ func (dt *deleteTask) TraceCtx() context.Context {
}
func (dt *deleteTask) ID() UniqueID {
return dt.deleteMsg.Base.MsgID
return dt.msgID
}
func (dt *deleteTask) SetID(uid UniqueID) {
dt.deleteMsg.Base.MsgID = uid
dt.msgID = uid
}
func (dt *deleteTask) Type() commonpb.MsgType {
return dt.deleteMsg.Base.MsgType
return commonpb.MsgType_Delete
}
func (dt *deleteTask) Name() string {
@ -66,24 +80,23 @@ func (dt *deleteTask) Name() string {
}
func (dt *deleteTask) BeginTs() Timestamp {
return dt.deleteMsg.Base.Timestamp
return dt.ts
}
func (dt *deleteTask) EndTs() Timestamp {
return dt.deleteMsg.Base.Timestamp
return dt.ts
}
func (dt *deleteTask) SetTs(ts Timestamp) {
dt.deleteMsg.Base.Timestamp = ts
dt.ts = ts
}
func (dt *deleteTask) OnEnqueue() error {
dt.deleteMsg.Base = commonpbutil.NewMsgBase()
return nil
}
func (dt *deleteTask) setChannels() error {
collID, err := globalMetaCache.GetCollectionID(dt.ctx, dt.deleteMsg.GetDbName(), dt.deleteMsg.CollectionName)
collID, err := globalMetaCache.GetCollectionID(dt.ctx, dt.req.GetDbName(), dt.req.GetCollectionName())
if err != nil {
return err
}
@ -99,27 +112,20 @@ func (dt *deleteTask) getChannels() []pChan {
return dt.pChannels
}
func getPrimaryKeysFromExpr(schema *schemapb.CollectionSchema, expr string) (res *schemapb.IDs, rowNum int64, err error) {
if len(expr) == 0 {
log.Warn("empty expr")
return
}
plan, err := createExprPlan(schema, expr)
if err != nil {
return res, 0, fmt.Errorf("failed to create expr plan, expr = %s", expr)
}
// delete request only support expr "id in [a, b]"
termExpr, ok := plan.Node.(*planpb.PlanNode_Predicates).Predicates.Expr.(*planpb.Expr_TermExpr)
func getExpr(plan *planpb.PlanNode) (bool, *planpb.Expr_TermExpr) {
//simple delete request need expr with "pk in [a, b]"
termExpr, ok := plan.Node.(*planpb.PlanNode_Query).Query.Predicates.Expr.(*planpb.Expr_TermExpr)
if !ok {
return res, 0, fmt.Errorf("invalid plan node type, only pk in [1, 2] supported")
return false, nil
}
if !termExpr.TermExpr.GetColumnInfo().GetIsPrimaryKey() {
return res, 0, fmt.Errorf("invalid expression, we only support to delete by pk, expr: %s", expr)
return false, nil
}
return true, termExpr
}
func getPrimaryKeysFromExpr(schema *schemapb.CollectionSchema, termExpr *planpb.Expr_TermExpr) (res *schemapb.IDs, rowNum int64, err error) {
res = &schemapb.IDs{}
rowNum = int64(len(termExpr.TermExpr.Values))
switch termExpr.TermExpr.ColumnInfo.GetDataType() {
@ -151,9 +157,6 @@ func getPrimaryKeysFromExpr(schema *schemapb.CollectionSchema, expr string) (res
}
func (dt *deleteTask) PreExecute(ctx context.Context) error {
dt.deleteMsg.Base.MsgType = commonpb.MsgType_Delete
dt.deleteMsg.Base.SourceID = paramtable.GetNodeID()
dt.result = &milvuspb.MutationResult{
Status: merr.Status(nil),
IDs: &schemapb.IDs{
@ -163,65 +166,51 @@ func (dt *deleteTask) PreExecute(ctx context.Context) error {
}
log := log.Ctx(ctx)
collName := dt.deleteMsg.CollectionName
collName := dt.req.GetCollectionName()
if err := validateCollectionName(collName); err != nil {
return ErrWithLog(log, "Invalid collection name", err)
}
collID, err := globalMetaCache.GetCollectionID(ctx, dt.deleteMsg.GetDbName(), collName)
collID, err := globalMetaCache.GetCollectionID(ctx, dt.req.GetDbName(), collName)
if err != nil {
return ErrWithLog(log, "Failed to get collection id", err)
}
dt.deleteMsg.CollectionID = collID
dt.collectionID = collID
partitionKeyMode, err := isPartitionKeyMode(ctx, dt.deleteMsg.GetDbName(), dt.deleteMsg.CollectionName)
partitionKeyMode, err := isPartitionKeyMode(ctx, dt.req.GetDbName(), dt.req.GetCollectionName())
if err != nil {
return ErrWithLog(log, "Failed to get partition key mode", err)
}
if partitionKeyMode && len(dt.deleteMsg.PartitionName) != 0 {
return ErrWithLog(log, "", errors.New("not support manually specifying the partition names if partition key mode is used"))
if partitionKeyMode && len(dt.req.PartitionName) != 0 {
return errors.New("not support manually specifying the partition names if partition key mode is used")
}
// If partitionName is not empty, partitionID will be set.
if len(dt.deleteMsg.PartitionName) > 0 {
partName := dt.deleteMsg.PartitionName
if len(dt.req.PartitionName) > 0 {
partName := dt.req.GetPartitionName()
if err := validatePartitionTag(partName, true); err != nil {
return ErrWithLog(log, "Invalid partition name", err)
}
partID, err := globalMetaCache.GetPartitionID(ctx, dt.deleteMsg.GetDbName(), collName, partName)
partID, err := globalMetaCache.GetPartitionID(ctx, dt.req.GetDbName(), collName, partName)
if err != nil {
return ErrWithLog(log, "Failed to get partition id", err)
}
dt.deleteMsg.PartitionID = partID
dt.partitionID = partID
} else {
dt.deleteMsg.PartitionID = common.InvalidPartitionID
dt.partitionID = common.InvalidPartitionID
}
schema, err := globalMetaCache.GetCollectionSchema(ctx, dt.deleteMsg.GetDbName(), collName)
schema, err := globalMetaCache.GetCollectionSchema(ctx, dt.req.GetDbName(), collName)
if err != nil {
return ErrWithLog(log, "Failed to get collection schema", err)
}
dt.schema = schema
// get delete.primaryKeys from delete expr
primaryKeys, numRow, err := getPrimaryKeysFromExpr(schema, dt.deleteExpr)
// hash primary keys to channels
channelNames, err := dt.chMgr.getVChannels(dt.collectionID)
if err != nil {
return ErrWithLog(log, "Failed to get primary keys from expr", err)
}
dt.deleteMsg.NumRows = numRow
dt.deleteMsg.PrimaryKeys = primaryKeys
log.Debug("get primary keys from expr", zap.Int64("len of primary keys", dt.deleteMsg.NumRows))
// set result
dt.result.IDs = primaryKeys
dt.result.DeleteCnt = dt.deleteMsg.NumRows
dt.deleteMsg.Timestamps = make([]uint64, numRow)
for index := range dt.deleteMsg.Timestamps {
dt.deleteMsg.Timestamps[index] = dt.BeginTs()
}
dt.vChannels = channelNames
log.Debug("pre delete done", zap.Int64("collection_id", dt.collectionID))
@ -233,102 +222,222 @@ func (dt *deleteTask) Execute(ctx context.Context) (err error) {
defer sp.End()
log := log.Ctx(ctx)
tr := timerecord.NewTimeRecorder(fmt.Sprintf("proxy execute delete %d", dt.ID()))
if len(dt.req.GetExpr()) == 0 {
return merr.WrapErrParameterInvalid("valid expr", "empty expr", "invalid expression")
}
collID := dt.deleteMsg.CollectionID
stream, err := dt.chMgr.getOrCreateDmlStream(collID)
dt.tr = timerecord.NewTimeRecorder(fmt.Sprintf("proxy execute delete %d", dt.ID()))
stream, err := dt.chMgr.getOrCreateDmlStream(dt.collectionID)
if err != nil {
log.Warn("fail to get or create dml stream", zap.Error(err))
return err
}
// hash primary keys to channels
channelNames, err := dt.chMgr.getVChannels(collID)
plan, err := planparserv2.CreateRetrievePlan(dt.schema, dt.req.Expr)
if err != nil {
log.Warn("get vChannels failed", zap.Int64("collectionID", collID), zap.Error(err))
dt.result.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
dt.result.Status.Reason = err.Error()
return err
return fmt.Errorf("failed to create expr plan, expr = %s", dt.req.GetExpr())
}
dt.deleteMsg.HashValues = typeutil.HashPK2Channels(dt.result.IDs, channelNames)
// repack delete msg by dmChannel
result := make(map[uint32]msgstream.TsMsg)
collectionName := dt.deleteMsg.CollectionName
collectionID := dt.deleteMsg.CollectionID
partitionID := dt.deleteMsg.PartitionID
partitionName := dt.deleteMsg.PartitionName
proxyID := dt.deleteMsg.Base.SourceID
for index, key := range dt.deleteMsg.HashValues {
vchannel := channelNames[key]
ts := dt.deleteMsg.Timestamps[index]
_, ok := result[key]
if !ok {
msgid, err := dt.idAllocator.AllocOne()
if err != nil {
return errors.Wrap(err, "failed to allocate MsgID of delete")
}
sliceRequest := msgpb.DeleteRequest{
Base: commonpbutil.NewMsgBase(
commonpbutil.WithMsgType(commonpb.MsgType_Delete),
// msgid of delete msg must be set
// or it will be seen as duplicated msg in mq
commonpbutil.WithMsgID(msgid),
commonpbutil.WithTimeStamp(ts),
commonpbutil.WithSourceID(proxyID),
),
CollectionID: collectionID,
PartitionID: partitionID,
CollectionName: collectionName,
PartitionName: partitionName,
PrimaryKeys: &schemapb.IDs{},
}
deleteMsg := &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{
Ctx: ctx,
},
DeleteRequest: sliceRequest,
}
result[key] = deleteMsg
isSimple, termExp := getExpr(plan)
if isSimple {
// if could get delete.primaryKeys from delete expr
err := dt.simpleDelete(ctx, termExp, stream)
if err != nil {
return err
}
curMsg := result[key].(*msgstream.DeleteMsg)
curMsg.HashValues = append(curMsg.HashValues, dt.deleteMsg.HashValues[index])
curMsg.Timestamps = append(curMsg.Timestamps, dt.deleteMsg.Timestamps[index])
typeutil.AppendIDs(curMsg.PrimaryKeys, dt.deleteMsg.PrimaryKeys, index)
curMsg.NumRows++
curMsg.ShardName = vchannel
}
// send delete request to log broker
msgPack := &msgstream.MsgPack{
BeginTs: dt.BeginTs(),
EndTs: dt.EndTs(),
}
for _, msg := range result {
if msg != nil {
msgPack.Msgs = append(msgPack.Msgs, msg)
} else {
// if get complex delete expr
// need query from querynode before delete
err = dt.complexDelete(ctx, plan, stream)
if err != nil {
log.Warn("complex delete failed,but delete some data", zap.Int("count", dt.count), zap.String("expr", dt.req.GetExpr()))
return err
}
}
log.Debug("send delete request to virtual channels",
zap.String("collectionName", dt.deleteMsg.GetCollectionName()),
zap.Int64("collectionID", collID),
zap.Strings("virtual_channels", channelNames),
zap.Int64("taskID", dt.ID()),
zap.Duration("prepare duration", tr.RecordSpan()))
err = stream.Produce(msgPack)
if err != nil {
dt.result.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
dt.result.Status.Reason = err.Error()
return err
}
sendMsgDur := tr.ElapseSpan()
metrics.ProxySendMutationReqLatency.WithLabelValues(strconv.FormatInt(paramtable.GetNodeID(), 10), metrics.DeleteLabel).Observe(float64(sendMsgDur.Milliseconds()))
return nil
}
func (dt *deleteTask) PostExecute(ctx context.Context) error {
return nil
}
func (dt *deleteTask) getStreamingQueryAndDelteFunc(stream msgstream.MsgStream, plan *planpb.PlanNode) executeFunc {
return func(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs ...string) error {
// outputField := translateOutputFields(, dt.schema, true)
streamer := streamrpc.NewGrpcQueryStreamer()
partationIDs := []int64{}
if dt.partitionID != common.InvalidFieldID {
partationIDs = append(partationIDs, dt.partitionID)
}
// set plan
_, outputFieldIDs := translatePkOutputFields(dt.schema)
outputFieldIDs = append(outputFieldIDs, common.TimeStampField)
plan.OutputFieldIds = outputFieldIDs
serializedPlan, err := proto.Marshal(plan)
if err != nil {
return err
}
queryReq := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
Base: commonpbutil.NewMsgBase(
commonpbutil.WithMsgType(commonpb.MsgType_Retrieve),
commonpbutil.WithMsgID(dt.msgID),
commonpbutil.WithSourceID(paramtable.GetNodeID()),
commonpbutil.WithTargetID(nodeID),
),
MvccTimestamp: dt.ts,
ReqID: paramtable.GetNodeID(),
DbID: 0, // TODO
CollectionID: dt.collectionID,
PartitionIDs: partationIDs,
SerializedExprPlan: serializedPlan,
OutputFieldsId: outputFieldIDs,
GuaranteeTimestamp: parseGuaranteeTsFromConsistency(dt.ts, dt.ts, commonpb.ConsistencyLevel_Bounded),
},
DmlChannels: channelIDs,
Scope: querypb.DataScope_All,
}
err = qn.QueryStream(ctx, queryReq, streamer)
if err != nil {
log.Warn("query for delete return error", zap.Error(err))
return err
}
client := streamer.AsClient()
for {
result, err := client.Recv()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
err = merr.Error(result.GetStatus())
if err != nil {
return err
}
err = dt.produce(ctx, stream, result.GetIds())
if err != nil {
return err
}
}
}
}
func (dt *deleteTask) complexDelete(ctx context.Context, plan *planpb.PlanNode, stream msgstream.MsgStream) error {
err := dt.lb.Execute(ctx, CollectionWorkLoad{
db: dt.req.GetDbName(),
collectionName: dt.req.GetCollectionName(),
collectionID: dt.collectionID,
nq: 1,
exec: dt.getStreamingQueryAndDelteFunc(stream, plan),
})
if err != nil {
log.Warn("fail to get or create dml stream", zap.Error(err))
return err
}
return nil
}
func (dt *deleteTask) simpleDelete(ctx context.Context, termExp *planpb.Expr_TermExpr, stream msgstream.MsgStream) error {
primaryKeys, numRow, err := getPrimaryKeysFromExpr(dt.schema, termExp)
if err != nil {
log.Info("Failed to get primary keys from expr", zap.Error(err))
return err
}
log.Debug("get primary keys from expr", zap.Int64("len of primary keys", numRow))
err = dt.produce(ctx, stream, primaryKeys)
if err != nil {
return err
}
return nil
}
func (dt *deleteTask) produce(ctx context.Context, stream msgstream.MsgStream, primaryKeys *schemapb.IDs) error {
hashValues := typeutil.HashPK2Channels(primaryKeys, dt.vChannels)
// repack delete msg by dmChannel
result := make(map[uint32]msgstream.TsMsg)
numRows := int64(0)
for index, key := range hashValues {
vchannel := dt.vChannels[key]
_, ok := result[key]
if !ok {
deleteMsg, err := dt.newDeleteMsg(ctx)
if err != nil {
return err
}
deleteMsg.ShardName = vchannel
result[key] = deleteMsg
}
curMsg := result[key].(*msgstream.DeleteMsg)
curMsg.HashValues = append(curMsg.HashValues, hashValues[index])
curMsg.Timestamps = append(curMsg.Timestamps, dt.ts)
typeutil.AppendIDs(curMsg.PrimaryKeys, primaryKeys, index)
curMsg.NumRows++
numRows++
}
// send delete request to log broker
msgPack := &msgstream.MsgPack{
BeginTs: dt.BeginTs(),
EndTs: dt.EndTs(),
}
for _, msg := range result {
if msg != nil {
msgPack.Msgs = append(msgPack.Msgs, msg)
}
}
log.Debug("send delete request to virtual channels",
zap.String("collectionName", dt.req.GetCollectionName()),
zap.Int64("collectionID", dt.collectionID),
zap.Strings("virtual_channels", dt.vChannels),
zap.Int64("taskID", dt.ID()),
zap.Duration("prepare duration", dt.tr.RecordSpan()))
err := stream.Produce(msgPack)
if err != nil {
return err
}
dt.result.DeleteCnt += numRows
return nil
}
func (dt *deleteTask) newDeleteMsg(ctx context.Context) (*msgstream.DeleteMsg, error) {
msgid, err := dt.idAllocator.AllocOne()
if err != nil {
return nil, errors.Wrap(err, "failed to allocate MsgID of delete")
}
sliceRequest := msgpb.DeleteRequest{
Base: commonpbutil.NewMsgBase(
commonpbutil.WithMsgType(commonpb.MsgType_Delete),
// msgid of delete msg must be set
// or it will be seen as duplicated msg in mq
commonpbutil.WithMsgID(msgid),
commonpbutil.WithTimeStamp(dt.ts),
commonpbutil.WithSourceID(paramtable.GetNodeID()),
),
CollectionID: dt.collectionID,
PartitionID: dt.partitionID,
CollectionName: dt.req.GetCollectionName(),
PartitionName: dt.req.GetPartitionName(),
PrimaryKeys: &schemapb.IDs{},
}
return &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{
Ctx: ctx,
},
DeleteRequest: sliceRequest,
}, nil
}

View File

@ -5,105 +5,140 @@ import (
"fmt"
"testing"
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/cockroachdb/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/milvus-io/milvus-proto/go-api/v2/msgpb"
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/internal/allocator"
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/parser/planparserv2"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/planpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/proto/rootcoordpb"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/mq/msgstream"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/milvus-io/milvus/pkg/util/paramtable"
)
func Test_getPrimaryKeysFromExpr(t *testing.T) {
t.Run("delete on non-pk field", func(t *testing.T) {
schema := &schemapb.CollectionSchema{
Name: "test_delete",
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
func Test_GetExpr(t *testing.T) {
schema := &schemapb.CollectionSchema{
Name: "test_delete",
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
}
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
},
}
t.Run("delelte with complex pk expr", func(t *testing.T) {
expr := "pk < 4"
plan, err := planparserv2.CreateRetrievePlan(schema, expr)
assert.NoError(t, err)
isSimple, _ := getExpr(plan)
assert.False(t, isSimple)
})
t.Run("delete with no-pk field expr", func(t *testing.T) {
expr := "non_pk in [1, 2, 3]"
plan, err := planparserv2.CreateRetrievePlan(schema, expr)
assert.NoError(t, err)
isSimple, _ := getExpr(plan)
assert.False(t, isSimple)
})
_, _, err := getPrimaryKeysFromExpr(schema, expr)
assert.Error(t, err)
t.Run("delete with simple expr", func(t *testing.T) {
expr := "pk in [1, 2, 3]"
plan, err := planparserv2.CreateRetrievePlan(schema, expr)
assert.NoError(t, err)
isSimple, _ := getExpr(plan)
assert.True(t, isSimple)
})
}
func TestDeleteTask(t *testing.T) {
t.Run("test getChannels", func(t *testing.T) {
collectionID := UniqueID(0)
collectionName := "col-0"
channels := []pChan{"mock-chan-0", "mock-chan-1"}
cache := NewMockCache(t)
cache.On("GetCollectionID",
mock.Anything, // context.Context
mock.AnythingOfType("string"),
mock.AnythingOfType("string"),
).Return(collectionID, nil)
globalMetaCache = cache
chMgr := newMockChannelsMgr()
chMgr.getChannelsFunc = func(collectionID UniqueID) ([]pChan, error) {
return channels, nil
}
dt := deleteTask{
ctx: context.Background(),
deleteMsg: &msgstream.DeleteMsg{
DeleteRequest: msgpb.DeleteRequest{
CollectionName: collectionName,
},
},
chMgr: chMgr,
}
err := dt.setChannels()
assert.NoError(t, err)
resChannels := dt.getChannels()
assert.ElementsMatch(t, channels, resChannels)
assert.ElementsMatch(t, channels, dt.pChannels)
func TestDeleteTask_GetChannels(t *testing.T) {
collectionID := UniqueID(0)
collectionName := "col-0"
channels := []pChan{"mock-chan-0", "mock-chan-1"}
cache := NewMockCache(t)
cache.On("GetCollectionID",
mock.Anything, // context.Context
mock.AnythingOfType("string"),
mock.AnythingOfType("string"),
).Return(collectionID, nil)
globalMetaCache = cache
chMgr := newMockChannelsMgr()
chMgr.getChannelsFunc = func(collectionID UniqueID) ([]pChan, error) {
return channels, nil
}
dt := deleteTask{
ctx: context.Background(),
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
},
chMgr: chMgr,
}
err := dt.setChannels()
assert.NoError(t, err)
resChannels := dt.getChannels()
assert.ElementsMatch(t, channels, resChannels)
assert.ElementsMatch(t, channels, dt.pChannels)
chMgr.getChannelsFunc = func(collectionID UniqueID) ([]pChan, error) {
return nil, fmt.Errorf("mock err")
}
// get channels again, should return task's pChannels, so getChannelsFunc should not invoke again
resChannels = dt.getChannels()
assert.ElementsMatch(t, channels, resChannels)
})
chMgr.getChannelsFunc = func(collectionID UniqueID) ([]pChan, error) {
return nil, fmt.Errorf("mock err")
}
// get channels again, should return task's pChannels, so getChannelsFunc should not invoke again
resChannels = dt.getChannels()
assert.ElementsMatch(t, channels, resChannels)
}
func TestDeleteTask_PreExecute(t *testing.T) {
schema := &schemapb.CollectionSchema{
Name: "test_delete",
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
},
}
t.Run("empty collection name", func(t *testing.T) {
dt := deleteTask{
deleteMsg: &BaseDeleteTask{
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{},
},
},
}
dt := deleteTask{}
assert.Error(t, dt.PreExecute(context.Background()))
})
t.Run("fail to get collection id", func(t *testing.T) {
dt := deleteTask{deleteMsg: &BaseDeleteTask{
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{},
dt := deleteTask{
req: &milvuspb.DeleteRequest{
CollectionName: "foo",
},
}}
}}
cache := NewMockCache(t)
cache.On("GetCollectionID",
mock.Anything, // context.Context
@ -115,12 +150,9 @@ func TestDeleteTask(t *testing.T) {
})
t.Run("fail partition key mode", func(t *testing.T) {
dt := deleteTask{deleteMsg: &BaseDeleteTask{
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{},
CollectionName: "foo",
DbName: "db_1",
},
dt := deleteTask{req: &milvuspb.DeleteRequest{
CollectionName: "foo",
DbName: "db_1",
}}
cache := NewMockCache(t)
cache.On("GetCollectionID",
@ -139,13 +171,10 @@ func TestDeleteTask(t *testing.T) {
})
t.Run("invalid partition name", func(t *testing.T) {
dt := deleteTask{deleteMsg: &BaseDeleteTask{
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{},
CollectionName: "foo",
DbName: "db_1",
PartitionName: "aaa",
},
dt := deleteTask{req: &milvuspb.DeleteRequest{
CollectionName: "foo",
DbName: "db_1",
PartitionName: "aaa",
}}
cache := NewMockCache(t)
cache.On("GetCollectionID",
@ -176,37 +205,15 @@ func TestDeleteTask(t *testing.T) {
assert.Error(t, dt.PreExecute(context.Background()))
})
schema := &schemapb.CollectionSchema{
Name: "test_delete",
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
},
}
t.Run("invalie partition", func(t *testing.T) {
dt := deleteTask{
deleteMsg: &BaseDeleteTask{
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{},
CollectionName: "foo",
DbName: "db_1",
PartitionName: "_aaa",
},
req: &milvuspb.DeleteRequest{
CollectionName: "foo",
DbName: "db_1",
PartitionName: "aaa",
Expr: "non_pk in [1, 2, 3]",
},
deleteExpr: "non_pk in [1, 2, 3]",
}
cache := NewMockCache(t)
cache.On("GetCollectionID",
@ -229,7 +236,7 @@ func TestDeleteTask(t *testing.T) {
globalMetaCache = cache
assert.Error(t, dt.PreExecute(context.Background()))
dt.deleteMsg.PartitionName = "aaa"
dt.req.PartitionName = "aaa"
assert.Error(t, dt.PreExecute(context.Background()))
cache.On("GetPartitionID",
@ -241,3 +248,436 @@ func TestDeleteTask(t *testing.T) {
assert.Error(t, dt.PreExecute(context.Background()))
})
}
func TestDeleteTask_Execute(t *testing.T) {
collectionName := "test_delete"
collectionID := int64(111)
partitionName := "default"
partitionID := int64(222)
channels := []string{"test_channel"}
dbName := "test_1"
schema := &schemapb.CollectionSchema{
Name: collectionName,
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
},
}
t.Run("empty expr", func(t *testing.T) {
dt := deleteTask{}
assert.Error(t, dt.Execute(context.Background()))
})
t.Run("get channel failed", func(t *testing.T) {
mockMgr := NewMockChannelsMgr(t)
dt := deleteTask{
chMgr: mockMgr,
req: &milvuspb.DeleteRequest{
Expr: "pk in [1,2]",
},
}
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(nil, errors.New("mock error"))
assert.Error(t, dt.Execute(context.Background()))
})
t.Run("create plan failed", func(t *testing.T) {
mockMgr := NewMockChannelsMgr(t)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
req: &milvuspb.DeleteRequest{
Expr: "????",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
assert.Error(t, dt.Execute(context.Background()))
})
t.Run("alloc failed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mockMgr := NewMockChannelsMgr(t)
rc := mocks.NewRootCoord(t)
allocator, err := allocator.NewIDAllocator(ctx, rc, paramtable.GetNodeID())
assert.NoError(t, err)
allocator.Close()
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
idAllocator: allocator,
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk in [1,2]",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
assert.Error(t, dt.Execute(context.Background()))
})
t.Run("simple delete failed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mockMgr := NewMockChannelsMgr(t)
rc := mocks.NewRootCoord(t)
rc.EXPECT().AllocID(mock.Anything, mock.Anything).Return(
&rootcoordpb.AllocIDResponse{
Status: merr.Status(nil),
ID: 0,
Count: 1,
}, nil)
allocator, err := allocator.NewIDAllocator(ctx, rc, paramtable.GetNodeID())
allocator.Start()
assert.NoError(t, err)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
idAllocator: allocator,
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk in [1,2]",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
stream.EXPECT().Produce(mock.Anything).Return(errors.New("mock error"))
assert.Error(t, dt.Execute(context.Background()))
})
t.Run("complex delete query rpc failed", func(t *testing.T) {
mockMgr := NewMockChannelsMgr(t)
qn := mocks.NewMockQueryNode(t)
lb := NewMockLBPolicy(t)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
lb: lb,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
IDs: &schemapb.IDs{
IdField: nil,
},
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk < 3",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
lb.EXPECT().Execute(mock.Anything, mock.Anything).Call.Return(func(ctx context.Context, workload CollectionWorkLoad) error {
return workload.exec(ctx, 1, qn)
})
qn.EXPECT().QueryStream(mock.Anything, mock.Anything, mock.Anything).Return(errors.New("mock error"))
assert.Error(t, dt.Execute(context.Background()))
assert.Equal(t, int64(0), dt.result.DeleteCnt)
})
t.Run("complex delete query failed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mockMgr := NewMockChannelsMgr(t)
rc := mocks.NewRootCoord(t)
qn := mocks.NewMockQueryNode(t)
lb := NewMockLBPolicy(t)
rc.EXPECT().AllocID(mock.Anything, mock.Anything).Return(
&rootcoordpb.AllocIDResponse{
Status: merr.Status(nil),
ID: 0,
Count: 1,
}, nil)
allocator, err := allocator.NewIDAllocator(ctx, rc, paramtable.GetNodeID())
allocator.Start()
assert.NoError(t, err)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
idAllocator: allocator,
lb: lb,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
IDs: &schemapb.IDs{
IdField: nil,
},
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk < 3",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
lb.EXPECT().Execute(mock.Anything, mock.Anything).Call.Return(func(ctx context.Context, workload CollectionWorkLoad) error {
return workload.exec(ctx, 1, qn)
})
qn.EXPECT().QueryStream(mock.Anything, mock.Anything, mock.Anything).Run(
func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
streamer.SetClient(client)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{
Data: []int64{0, 1, 2},
},
},
},
})
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(errors.New("mock error")),
})
}).Return(nil)
stream.EXPECT().Produce(mock.Anything).Return(nil)
assert.Error(t, dt.Execute(context.Background()))
// query failed but still delete some data before failed.
assert.Equal(t, int64(3), dt.result.DeleteCnt)
})
t.Run("complex delete produce failed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mockMgr := NewMockChannelsMgr(t)
rc := mocks.NewRootCoord(t)
qn := mocks.NewMockQueryNode(t)
lb := NewMockLBPolicy(t)
rc.EXPECT().AllocID(mock.Anything, mock.Anything).Return(
&rootcoordpb.AllocIDResponse{
Status: merr.Status(nil),
ID: 0,
Count: 1,
}, nil)
allocator, err := allocator.NewIDAllocator(ctx, rc, paramtable.GetNodeID())
allocator.Start()
assert.NoError(t, err)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
idAllocator: allocator,
lb: lb,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
IDs: &schemapb.IDs{
IdField: nil,
},
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk < 3",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
lb.EXPECT().Execute(mock.Anything, mock.Anything).Call.Return(func(ctx context.Context, workload CollectionWorkLoad) error {
return workload.exec(ctx, 1, qn)
})
qn.EXPECT().QueryStream(mock.Anything, mock.Anything, mock.Anything).Run(
func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
streamer.SetClient(client)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{
Data: []int64{0, 1, 2},
},
},
},
})
server.FinishSend(nil)
}).Return(nil)
stream.EXPECT().Produce(mock.Anything).Return(errors.New("mock error"))
assert.Error(t, dt.Execute(context.Background()))
assert.Equal(t, int64(0), dt.result.DeleteCnt)
})
t.Run("complex delete success", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mockMgr := NewMockChannelsMgr(t)
rc := mocks.NewRootCoord(t)
qn := mocks.NewMockQueryNode(t)
lb := NewMockLBPolicy(t)
rc.EXPECT().AllocID(mock.Anything, mock.Anything).Return(
&rootcoordpb.AllocIDResponse{
Status: merr.Status(nil),
ID: 0,
Count: 1,
}, nil)
allocator, err := allocator.NewIDAllocator(ctx, rc, paramtable.GetNodeID())
allocator.Start()
assert.NoError(t, err)
dt := deleteTask{
chMgr: mockMgr,
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
vChannels: channels,
idAllocator: allocator,
lb: lb,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
},
IDs: &schemapb.IDs{
IdField: nil,
},
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
Expr: "pk < 3",
},
}
stream := msgstream.NewMockMsgStream(t)
mockMgr.EXPECT().getOrCreateDmlStream(mock.Anything).Return(stream, nil)
lb.EXPECT().Execute(mock.Anything, mock.Anything).Call.Return(func(ctx context.Context, workload CollectionWorkLoad) error {
return workload.exec(ctx, 1, qn)
})
qn.EXPECT().QueryStream(mock.Anything, mock.Anything, mock.Anything).Run(
func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
streamer.SetClient(client)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{
Data: []int64{0, 1, 2},
},
},
},
})
server.FinishSend(nil)
}).Return(nil)
stream.EXPECT().Produce(mock.Anything).Return(nil)
assert.NoError(t, dt.Execute(context.Background()))
assert.Equal(t, int64(3), dt.result.DeleteCnt)
})
}
func TestDeleteTask_SimpleDelete(t *testing.T) {
collectionName := "test_delete"
collectionID := int64(111)
partitionName := "default"
partitionID := int64(222)
dbName := "test_1"
schema := &schemapb.CollectionSchema{
Name: collectionName,
Description: "",
AutoID: false,
Fields: []*schemapb.FieldSchema{
{
FieldID: common.StartOfUserFieldID,
Name: "pk",
IsPrimaryKey: true,
DataType: schemapb.DataType_Int64,
},
{
FieldID: common.StartOfUserFieldID + 1,
Name: "non_pk",
IsPrimaryKey: false,
DataType: schemapb.DataType_Int64,
},
},
}
task := deleteTask{
schema: schema,
collectionID: collectionID,
partitionID: partitionID,
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
DbName: dbName,
},
}
t.Run("get PK failed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
expr := &planpb.Expr_TermExpr{
TermExpr: &planpb.TermExpr{
ColumnInfo: &planpb.ColumnInfo{
DataType: schemapb.DataType_BinaryVector,
}}}
stream := msgstream.NewMockMsgStream(t)
err := task.simpleDelete(ctx, expr, stream)
assert.Error(t, err)
})
}

View File

@ -1682,24 +1682,15 @@ func TestTask_Int64PrimaryKey(t *testing.T) {
assert.NoError(t, task.PostExecute(ctx))
})
t.Run("delete", func(t *testing.T) {
t.Run("simple delete", func(t *testing.T) {
task := &deleteTask{
Condition: NewTaskCondition(ctx),
deleteMsg: &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{},
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Delete,
MsgID: 0,
Timestamp: 0,
SourceID: paramtable.GetNodeID(),
},
CollectionName: collectionName,
PartitionName: partitionName,
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
Expr: "int64 in [0, 1]",
},
idAllocator: idAllocator,
deleteExpr: "int64 in [0, 1]",
ctx: ctx,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
@ -1725,8 +1716,6 @@ func TestTask_Int64PrimaryKey(t *testing.T) {
id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt())
task.SetID(id)
assert.Equal(t, id, task.ID())
task.deleteMsg.Base.MsgType = commonpb.MsgType_Delete
assert.Equal(t, commonpb.MsgType_Delete, task.Type())
ts := Timestamp(time.Now().UnixNano())
@ -1737,24 +1726,19 @@ func TestTask_Int64PrimaryKey(t *testing.T) {
assert.NoError(t, task.PreExecute(ctx))
assert.NoError(t, task.Execute(ctx))
assert.NoError(t, task.PostExecute(ctx))
})
task2 := &deleteTask{
t.Run("complex delete", func(t *testing.T) {
lb := NewMockLBPolicy(t)
task := &deleteTask{
Condition: NewTaskCondition(ctx),
deleteMsg: &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{},
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Delete,
MsgID: 0,
Timestamp: 0,
SourceID: paramtable.GetNodeID(),
},
CollectionName: collectionName,
PartitionName: partitionName,
},
lb: lb,
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
Expr: "int64 < 2",
},
idAllocator: idAllocator,
deleteExpr: "int64 not in [0, 1]",
ctx: ctx,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
@ -1773,7 +1757,23 @@ func TestTask_Int64PrimaryKey(t *testing.T) {
chMgr: chMgr,
chTicker: ticker,
}
assert.Error(t, task2.PreExecute(ctx))
lb.EXPECT().Execute(mock.Anything, mock.Anything).Return(nil)
assert.NoError(t, task.OnEnqueue())
assert.NotNil(t, task.TraceCtx())
id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt())
task.SetID(id)
assert.Equal(t, id, task.ID())
assert.Equal(t, commonpb.MsgType_Delete, task.Type())
ts := Timestamp(time.Now().UnixNano())
task.SetTs(ts)
assert.Equal(t, ts, task.BeginTs())
assert.Equal(t, ts, task.EndTs())
assert.NoError(t, task.PreExecute(ctx))
assert.NoError(t, task.Execute(ctx))
assert.NoError(t, task.PostExecute(ctx))
})
}
@ -2027,24 +2027,15 @@ func TestTask_VarCharPrimaryKey(t *testing.T) {
assert.NoError(t, task.PostExecute(ctx))
})
t.Run("delete", func(t *testing.T) {
t.Run("simple delete", func(t *testing.T) {
task := &deleteTask{
Condition: NewTaskCondition(ctx),
deleteMsg: &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{},
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Delete,
MsgID: 0,
Timestamp: 0,
SourceID: paramtable.GetNodeID(),
},
CollectionName: collectionName,
PartitionName: partitionName,
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
PartitionName: partitionName,
Expr: "varChar in [\"milvus\", \"test\"]",
},
idAllocator: idAllocator,
deleteExpr: "varChar in [\"milvus\", \"test\"]",
ctx: ctx,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
@ -2070,8 +2061,6 @@ func TestTask_VarCharPrimaryKey(t *testing.T) {
id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt())
task.SetID(id)
assert.Equal(t, id, task.ID())
task.deleteMsg.Base.MsgType = commonpb.MsgType_Delete
assert.Equal(t, commonpb.MsgType_Delete, task.Type())
ts := Timestamp(time.Now().UnixNano())
@ -2082,43 +2071,6 @@ func TestTask_VarCharPrimaryKey(t *testing.T) {
assert.NoError(t, task.PreExecute(ctx))
assert.NoError(t, task.Execute(ctx))
assert.NoError(t, task.PostExecute(ctx))
task2 := &deleteTask{
Condition: NewTaskCondition(ctx),
deleteMsg: &msgstream.DeleteMsg{
BaseMsg: msgstream.BaseMsg{},
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Delete,
MsgID: 0,
Timestamp: 0,
SourceID: paramtable.GetNodeID(),
},
CollectionName: collectionName,
PartitionName: partitionName,
},
},
idAllocator: idAllocator,
deleteExpr: "varChar not in [\"milvus\", \"test\"]",
ctx: ctx,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
Reason: "",
},
IDs: nil,
SuccIndex: nil,
ErrIndex: nil,
Acknowledged: false,
InsertCnt: 0,
DeleteCnt: 0,
UpsertCnt: 0,
Timestamp: 0,
},
chMgr: chMgr,
chTicker: ticker,
}
assert.Error(t, task2.PreExecute(ctx))
})
}
@ -3548,20 +3500,11 @@ func TestPartitionKey(t *testing.T) {
t.Run("delete", func(t *testing.T) {
dt := &deleteTask{
Condition: NewTaskCondition(ctx),
deleteMsg: &BaseDeleteTask{
BaseMsg: msgstream.BaseMsg{},
DeleteRequest: msgpb.DeleteRequest{
Base: &commonpb.MsgBase{
MsgType: commonpb.MsgType_Delete,
MsgID: 0,
Timestamp: 0,
SourceID: paramtable.GetNodeID(),
},
CollectionName: collectionName,
},
req: &milvuspb.DeleteRequest{
CollectionName: collectionName,
Expr: "int64_field in [0, 1]",
},
deleteExpr: "int64_field in [0, 1]",
ctx: ctx,
ctx: ctx,
result: &milvuspb.MutationResult{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_Success,
@ -3581,10 +3524,10 @@ func TestPartitionKey(t *testing.T) {
chTicker: ticker,
}
// don't support specify partition name if use partition key
dt.deleteMsg.PartitionName = partitionNames[0]
dt.req.PartitionName = partitionNames[0]
assert.Error(t, dt.PreExecute(ctx))
dt.deleteMsg.PartitionName = ""
dt.req.PartitionName = ""
assert.NoError(t, dt.PreExecute(ctx))
assert.NoError(t, dt.Execute(ctx))
assert.NoError(t, dt.PostExecute(ctx))

View File

@ -887,6 +887,18 @@ func passwordVerify(ctx context.Context, username, rawPwd string, globalMetaCach
return true
}
func translatePkOutputFields(schema *schemapb.CollectionSchema) ([]string, []int64) {
pkNames := []string{}
fieldIDs := []int64{}
for _, field := range schema.Fields {
if field.IsPrimaryKey {
pkNames = append(pkNames, field.GetName())
fieldIDs = append(fieldIDs, field.GetFieldID())
}
}
return pkNames, fieldIDs
}
// Support wildcard in output fields:
//
// "*" - all fields

View File

@ -689,6 +689,92 @@ func (_c *MockQueryNodeServer_QuerySegments_Call) RunAndReturn(run func(context.
return _c
}
// QueryStream provides a mock function with given fields: _a0, _a1
func (_m *MockQueryNodeServer) QueryStream(_a0 *querypb.QueryRequest, _a1 querypb.QueryNode_QueryStreamServer) error {
ret := _m.Called(_a0, _a1)
var r0 error
if rf, ok := ret.Get(0).(func(*querypb.QueryRequest, querypb.QueryNode_QueryStreamServer) error); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryNodeServer_QueryStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStream'
type MockQueryNodeServer_QueryStream_Call struct {
*mock.Call
}
// QueryStream is a helper method to define mock.On call
// - _a0 *querypb.QueryRequest
// - _a1 querypb.QueryNode_QueryStreamServer
func (_e *MockQueryNodeServer_Expecter) QueryStream(_a0 interface{}, _a1 interface{}) *MockQueryNodeServer_QueryStream_Call {
return &MockQueryNodeServer_QueryStream_Call{Call: _e.mock.On("QueryStream", _a0, _a1)}
}
func (_c *MockQueryNodeServer_QueryStream_Call) Run(run func(_a0 *querypb.QueryRequest, _a1 querypb.QueryNode_QueryStreamServer)) *MockQueryNodeServer_QueryStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*querypb.QueryRequest), args[1].(querypb.QueryNode_QueryStreamServer))
})
return _c
}
func (_c *MockQueryNodeServer_QueryStream_Call) Return(_a0 error) *MockQueryNodeServer_QueryStream_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryNodeServer_QueryStream_Call) RunAndReturn(run func(*querypb.QueryRequest, querypb.QueryNode_QueryStreamServer) error) *MockQueryNodeServer_QueryStream_Call {
_c.Call.Return(run)
return _c
}
// QueryStreamSegments provides a mock function with given fields: _a0, _a1
func (_m *MockQueryNodeServer) QueryStreamSegments(_a0 *querypb.QueryRequest, _a1 querypb.QueryNode_QueryStreamSegmentsServer) error {
ret := _m.Called(_a0, _a1)
var r0 error
if rf, ok := ret.Get(0).(func(*querypb.QueryRequest, querypb.QueryNode_QueryStreamSegmentsServer) error); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryNodeServer_QueryStreamSegments_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStreamSegments'
type MockQueryNodeServer_QueryStreamSegments_Call struct {
*mock.Call
}
// QueryStreamSegments is a helper method to define mock.On call
// - _a0 *querypb.QueryRequest
// - _a1 querypb.QueryNode_QueryStreamSegmentsServer
func (_e *MockQueryNodeServer_Expecter) QueryStreamSegments(_a0 interface{}, _a1 interface{}) *MockQueryNodeServer_QueryStreamSegments_Call {
return &MockQueryNodeServer_QueryStreamSegments_Call{Call: _e.mock.On("QueryStreamSegments", _a0, _a1)}
}
func (_c *MockQueryNodeServer_QueryStreamSegments_Call) Run(run func(_a0 *querypb.QueryRequest, _a1 querypb.QueryNode_QueryStreamSegmentsServer)) *MockQueryNodeServer_QueryStreamSegments_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*querypb.QueryRequest), args[1].(querypb.QueryNode_QueryStreamSegmentsServer))
})
return _c
}
func (_c *MockQueryNodeServer_QueryStreamSegments_Call) Return(_a0 error) *MockQueryNodeServer_QueryStreamSegments_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryNodeServer_QueryStreamSegments_Call) RunAndReturn(run func(*querypb.QueryRequest, querypb.QueryNode_QueryStreamSegmentsServer) error) *MockQueryNodeServer_QueryStreamSegments_Call {
_c.Call.Return(run)
return _c
}
// ReleaseCollection provides a mock function with given fields: _a0, _a1
func (_m *MockQueryNodeServer) ReleaseCollection(_a0 context.Context, _a1 *querypb.ReleaseCollectionRequest) (*commonpb.Status, error) {
ret := _m.Called(_a0, _a1)

View File

@ -9,6 +9,8 @@ import (
mock "github.com/stretchr/testify/mock"
querypb "github.com/milvus-io/milvus/internal/proto/querypb"
streamrpc "github.com/milvus-io/milvus/internal/util/streamrpc"
)
// MockWorker is an autogenerated mock type for the Worker type
@ -261,6 +263,50 @@ func (_c *MockWorker_QuerySegments_Call) RunAndReturn(run func(context.Context,
return _c
}
// QueryStreamSegments provides a mock function with given fields: ctx, req, srv
func (_m *MockWorker) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
ret := _m.Called(ctx, req, srv)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamServer) error); ok {
r0 = rf(ctx, req, srv)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockWorker_QueryStreamSegments_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStreamSegments'
type MockWorker_QueryStreamSegments_Call struct {
*mock.Call
}
// QueryStreamSegments is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.QueryRequest
// - srv streamrpc.QueryStreamServer
func (_e *MockWorker_Expecter) QueryStreamSegments(ctx interface{}, req interface{}, srv interface{}) *MockWorker_QueryStreamSegments_Call {
return &MockWorker_QueryStreamSegments_Call{Call: _e.mock.On("QueryStreamSegments", ctx, req, srv)}
}
func (_c *MockWorker_QueryStreamSegments_Call) Run(run func(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer)) *MockWorker_QueryStreamSegments_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*querypb.QueryRequest), args[2].(streamrpc.QueryStreamServer))
})
return _c
}
func (_c *MockWorker_QueryStreamSegments_Call) Return(_a0 error) *MockWorker_QueryStreamSegments_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockWorker_QueryStreamSegments_Call) RunAndReturn(run func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamServer) error) *MockWorker_QueryStreamSegments_Call {
_c.Call.Return(run)
return _c
}
// ReleaseSegments provides a mock function with given fields: _a0, _a1
func (_m *MockWorker) ReleaseSegments(_a0 context.Context, _a1 *querypb.ReleaseSegmentsRequest) error {
ret := _m.Called(_a0, _a1)

View File

@ -20,6 +20,7 @@ package cluster
import (
"context"
"fmt"
"io"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
@ -28,6 +29,7 @@ import (
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/util/funcutil"
"github.com/milvus-io/milvus/pkg/util/merr"
@ -40,6 +42,7 @@ type Worker interface {
Delete(ctx context.Context, req *querypb.DeleteRequest) error
SearchSegments(ctx context.Context, req *querypb.SearchRequest) (*internalpb.SearchResults, error)
QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error)
QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error
GetStatistics(ctx context.Context, req *querypb.GetStatisticsRequest) (*internalpb.GetStatisticsResponse, error)
IsHealthy() bool
@ -139,6 +142,39 @@ func (w *remoteWorker) QuerySegments(ctx context.Context, req *querypb.QueryRequ
return ret, err
}
func (w *remoteWorker) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
streamer := streamrpc.NewGrpcQueryStreamer()
err := w.client.QueryStreamSegments(ctx, req, streamer)
if err != nil {
return err
}
client := streamer.AsClient()
for {
result, err := client.Recv()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
err = merr.Error(result.GetStatus())
if err != nil {
return err
}
err = srv.Send(result)
if err != nil {
log.Warn("send stream pks from remote woker failed",
zap.Int64("collectionID", req.Req.GetCollectionID()),
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
)
return err
}
}
}
func (w *remoteWorker) GetStatistics(ctx context.Context, req *querypb.GetStatisticsRequest) (*internalpb.GetStatisticsResponse, error) {
return w.client.GetStatistics(ctx, req)
}

View File

@ -20,6 +20,7 @@ package cluster
import (
context "context"
"io"
"testing"
"github.com/cockroachdb/errors"
@ -27,9 +28,12 @@ import (
"google.golang.org/grpc/status"
commonpb "github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/internal/mocks"
internalpb "github.com/milvus-io/milvus/internal/proto/internalpb"
querypb "github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
@ -332,6 +336,174 @@ func (s *RemoteWorkerSuite) TestQuery() {
})
}
func (s *RemoteWorkerSuite) TestQueryStream() {
s.Run("normal_run", func() {
defer func() { s.mockClient.ExpectedCalls = nil }()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
ids := []int64{10, 11, 12}
s.mockClient.EXPECT().QueryStreamSegments(
mock.Anything,
mock.AnythingOfType("*querypb.QueryRequest"),
mock.AnythingOfType("*streamrpc.GrpcQueryStreamer"),
).Run(func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
streamer.SetClient(client)
server := client.CreateServer()
for _, id := range ids {
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{Data: []int64{id}},
},
},
})
}
server.FinishSend(nil)
}).Return(nil)
go func() {
err := s.worker.QueryStreamSegments(ctx, &querypb.QueryRequest{}, server)
if err != nil {
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(err),
})
}
server.FinishSend(err)
}()
recNum := 0
for {
result, err := client.Recv()
if err == io.EOF {
break
}
s.NoError(err)
err = merr.Error(result.GetStatus())
s.NoError(err)
s.Less(recNum, len(ids))
s.Equal(result.Ids.GetIntId().Data[0], ids[recNum])
recNum++
}
})
s.Run("send msg failed", func() {
defer func() { s.mockClient.ExpectedCalls = nil }()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
clientCtx, clientClose := context.WithCancel(ctx)
client := streamrpc.NewLocalQueryClient(clientCtx)
server := client.CreateServer()
clientClose()
ids := []int64{10, 11, 12}
s.mockClient.EXPECT().QueryStreamSegments(
mock.Anything,
mock.AnythingOfType("*querypb.QueryRequest"),
mock.AnythingOfType("*streamrpc.GrpcQueryStreamer"),
).Run(func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
streamer.SetClient(client)
server := client.CreateServer()
for _, id := range ids {
err := server.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{Data: []int64{id}},
},
},
})
s.NoError(err)
}
server.FinishSend(nil)
}).Return(nil)
err := s.worker.QueryStreamSegments(ctx, &querypb.QueryRequest{}, server)
s.Error(err)
})
s.Run("client_return_error", func() {
defer func() { s.mockClient.ExpectedCalls = nil }()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := streamrpc.NewConcurrentQueryStreamServer(client.CreateServer())
s.mockClient.EXPECT().QueryStreamSegments(
mock.Anything,
mock.AnythingOfType("*querypb.QueryRequest"),
mock.AnythingOfType("*streamrpc.GrpcQueryStreamer"),
).Return(errors.New("mocked error"))
go func() {
err := s.worker.QueryStreamSegments(ctx, &querypb.QueryRequest{}, server)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(err),
})
}()
result, err := client.Recv()
s.NoError(err)
err = merr.Error(result.GetStatus())
// Check result
s.Error(err)
})
s.Run("client_return_fail_status", func() {
defer func() { s.mockClient.ExpectedCalls = nil }()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := streamrpc.NewConcurrentQueryStreamServer(client.CreateServer())
s.mockClient.EXPECT().QueryStreamSegments(
mock.Anything,
mock.AnythingOfType("*querypb.QueryRequest"),
mock.AnythingOfType("*streamrpc.GrpcQueryStreamer"),
).Run(func(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) {
client := streamrpc.NewLocalQueryClient(ctx)
streamer.SetClient(client)
server := client.CreateServer()
server.Send(&internalpb.RetrieveResults{
Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_UnexpectedError},
})
server.FinishSend(nil)
}).Return(nil)
go func() {
err := s.worker.QueryStreamSegments(ctx, &querypb.QueryRequest{}, server)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(err),
})
}()
result, err := client.Recv()
s.NoError(err)
err = merr.Error(result.GetStatus())
// Check result
s.Error(err)
})
}
func (s *RemoteWorkerSuite) TestGetStatistics() {
s.Run("normal_run", func() {
defer func() { s.mockClient.ExpectedCalls = nil }()

View File

@ -37,6 +37,7 @@ import (
"github.com/milvus-io/milvus/internal/querynodev2/pkoracle"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/querynodev2/tsafe"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/metrics"
"github.com/milvus-io/milvus/pkg/mq/msgstream"
@ -57,6 +58,7 @@ type ShardDelegator interface {
SyncDistribution(ctx context.Context, entries ...SegmentEntry)
Search(ctx context.Context, req *querypb.SearchRequest) ([]*internalpb.SearchResults, error)
Query(ctx context.Context, req *querypb.QueryRequest) ([]*internalpb.RetrieveResults, error)
QueryStream(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error
GetStatistics(ctx context.Context, req *querypb.GetStatisticsRequest) ([]*internalpb.GetStatisticsResponse, error)
//data
@ -253,6 +255,68 @@ func (sd *shardDelegator) Search(ctx context.Context, req *querypb.SearchRequest
return results, nil
}
func (sd *shardDelegator) QueryStream(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
log := sd.getLogger(ctx)
if !sd.Serviceable() {
return errors.New("delegator is not serviceable")
}
if !funcutil.SliceContain(req.GetDmlChannels(), sd.vchannelName) {
log.Warn("deletgator received query request not belongs to it",
zap.Strings("reqChannels", req.GetDmlChannels()),
)
return fmt.Errorf("dml channel not match, delegator channel %s, search channels %v", sd.vchannelName, req.GetDmlChannels())
}
partitions := req.GetReq().GetPartitionIDs()
if !sd.collection.ExistPartition(partitions...) {
return merr.WrapErrPartitionNotLoaded(partitions)
}
// wait tsafe
waitTr := timerecord.NewTimeRecorder("wait tSafe")
err := sd.waitTSafe(ctx, req.Req.GuaranteeTimestamp)
if err != nil {
log.Warn("delegator query failed to wait tsafe", zap.Error(err))
return err
}
metrics.QueryNodeSQLatencyWaitTSafe.WithLabelValues(
fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel).
Observe(float64(waitTr.ElapseSpan().Milliseconds()))
sealed, growing, version := sd.distribution.GetSegments(true, req.GetReq().GetPartitionIDs()...)
defer sd.distribution.FinishUsage(version)
existPartitions := sd.collection.GetPartitions()
growing = lo.Filter(growing, func(segment SegmentEntry, _ int) bool {
return funcutil.SliceContain(existPartitions, segment.PartitionID)
})
if req.Req.IgnoreGrowing {
growing = []SegmentEntry{}
}
log.Info("query segments...",
zap.Int("sealedNum", len(sealed)),
zap.Int("growingNum", len(growing)),
)
tasks, err := organizeSubTask(ctx, req, sealed, growing, sd, sd.modifyQueryRequest)
if err != nil {
log.Warn("query organizeSubTask failed", zap.Error(err))
return err
}
_, err = executeSubTasks(ctx, tasks, func(ctx context.Context, req *querypb.QueryRequest, worker cluster.Worker) (*internalpb.RetrieveResults, error) {
return nil, worker.QueryStreamSegments(ctx, req, srv)
}, "Query", log)
if err != nil {
log.Warn("Delegator query failed", zap.Error(err))
return err
}
log.Info("Delegator Query done")
return nil
}
// Query performs query operation on shard.
func (sd *shardDelegator) Query(ctx context.Context, req *querypb.QueryRequest) ([]*internalpb.RetrieveResults, error) {
log := sd.getLogger(ctx)

View File

@ -18,6 +18,7 @@ package delegator
import (
"context"
"io"
"sync"
"testing"
"time"
@ -38,6 +39,7 @@ import (
"github.com/milvus-io/milvus/internal/querynodev2/cluster"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/querynodev2/tsafe"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/mq/msgstream"
"github.com/milvus-io/milvus/pkg/util/commonpbutil"
@ -205,12 +207,10 @@ func (s *DelegatorSuite) TestGetSegmentInfo() {
s.Equal(0, len(growing))
}
func (s *DelegatorSuite) TestSearch() {
s.delegator.Start()
// 1 => sealed segment 1000, 1001
// 1 => growing segment 1004
// 2 => sealed segment 1002, 1003
paramtable.SetNodeID(1)
// nodeID 1 => sealed segment 1000, 1001
// nodeID 1 => growing segment 1004
// nodeID 2 => sealed segment 1002, 1003
func (s *DelegatorSuite) initSegments() {
s.delegator.LoadGrowing(context.Background(), []*querypb.SegmentLoadInfo{
{
SegmentID: 1004,
@ -245,6 +245,12 @@ func (s *DelegatorSuite) TestSearch() {
},
)
s.delegator.SyncTargetVersion(2001, []int64{1004}, []int64{1000, 1001, 1002, 1003}, []int64{})
}
func (s *DelegatorSuite) TestSearch() {
s.delegator.Start()
paramtable.SetNodeID(1)
s.initSegments()
s.Run("normal", func() {
defer func() {
s.workerManager.ExpectedCalls = nil
@ -297,33 +303,19 @@ func (s *DelegatorSuite) TestSearch() {
defer func() {
s.workerManager.ExpectedCalls = nil
}()
workers := make(map[int64]*cluster.MockWorker)
worker1 := &cluster.MockWorker{}
worker2 := &cluster.MockWorker{}
workers[1] = worker1
workers[2] = worker2
worker1.EXPECT().SearchSegments(mock.Anything, mock.AnythingOfType("*querypb.SearchRequest")).
Return(&internalpb.SearchResults{}, nil)
worker2.EXPECT().SearchSegments(mock.Anything, mock.AnythingOfType("*querypb.SearchRequest")).
Return(&internalpb.SearchResults{}, nil)
s.workerManager.EXPECT().GetWorker(mock.Anything, mock.AnythingOfType("int64")).Call.Return(func(_ context.Context, nodeID int64) cluster.Worker {
return workers[nodeID]
}, nil)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err := s.delegator.Search(ctx, &querypb.SearchRequest{
Req: &internalpb.SearchRequest{
Base: commonpbutil.NewMsgBase(),
PartitionIDs: []int64{500},
Base: commonpbutil.NewMsgBase(),
//not load partation -1,will return error
PartitionIDs: []int64{-1},
},
DmlChannels: []string{s.vchannelName},
})
errors.Is(err, merr.ErrPartitionNotLoaded)
s.True(errors.Is(err, merr.ErrPartitionNotLoaded))
})
s.Run("worker_return_error", func() {
@ -460,44 +452,8 @@ func (s *DelegatorSuite) TestSearch() {
func (s *DelegatorSuite) TestQuery() {
s.delegator.Start()
// 1 => sealed segment 1000, 1001
// 1 => growing segment 1004
// 2 => sealed segment 1002, 1003
paramtable.SetNodeID(1)
s.delegator.LoadGrowing(context.Background(), []*querypb.SegmentLoadInfo{
{
SegmentID: 1004,
CollectionID: s.collectionID,
PartitionID: 500,
},
}, 0)
s.delegator.SyncDistribution(context.Background(),
SegmentEntry{
NodeID: 1,
SegmentID: 1000,
PartitionID: 500,
Version: 2001,
},
SegmentEntry{
NodeID: 1,
SegmentID: 1001,
PartitionID: 501,
Version: 2001,
},
SegmentEntry{
NodeID: 2,
SegmentID: 1002,
PartitionID: 500,
Version: 2001,
},
SegmentEntry{
NodeID: 2,
SegmentID: 1003,
PartitionID: 501,
Version: 2001,
},
)
s.delegator.SyncTargetVersion(2001, []int64{1004}, []int64{1000, 1001, 1002, 1003}, []int64{})
s.initSegments()
s.Run("normal", func() {
defer func() {
s.workerManager.ExpectedCalls = nil
@ -550,33 +506,18 @@ func (s *DelegatorSuite) TestQuery() {
defer func() {
s.workerManager.ExpectedCalls = nil
}()
workers := make(map[int64]*cluster.MockWorker)
worker1 := &cluster.MockWorker{}
worker2 := &cluster.MockWorker{}
workers[1] = worker1
workers[2] = worker2
worker1.EXPECT().QuerySegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest")).
Return(&internalpb.RetrieveResults{}, nil)
worker2.EXPECT().QuerySegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest")).
Return(&internalpb.RetrieveResults{}, nil)
s.workerManager.EXPECT().GetWorker(mock.Anything, mock.AnythingOfType("int64")).Call.Return(func(_ context.Context, nodeID int64) cluster.Worker {
return workers[nodeID]
}, nil)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err := s.delegator.Query(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
Base: commonpbutil.NewMsgBase(),
PartitionIDs: []int64{500},
Base: commonpbutil.NewMsgBase(),
//not load partation -1,will return error
PartitionIDs: []int64{-1},
},
DmlChannels: []string{s.vchannelName},
})
errors.Is(err, merr.ErrPartitionNotLoaded)
s.True(errors.Is(err, merr.ErrPartitionNotLoaded))
})
s.Run("worker_return_error", func() {
@ -678,47 +619,280 @@ func (s *DelegatorSuite) TestQuery() {
})
}
func (s *DelegatorSuite) TestQueryStream() {
s.delegator.Start()
paramtable.SetNodeID(1)
s.initSegments()
s.Run("normal", func() {
defer func() {
s.workerManager.AssertExpectations(s.T())
s.workerManager.ExpectedCalls = nil
}()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
workers := make(map[int64]*cluster.MockWorker)
worker1 := &cluster.MockWorker{}
worker2 := &cluster.MockWorker{}
workers[1] = worker1
workers[2] = worker2
s.workerManager.EXPECT().GetWorker(mock.Anything, mock.AnythingOfType("int64")).Call.Return(func(_ context.Context, nodeID int64) cluster.Worker {
return workers[nodeID]
}, nil)
worker1.EXPECT().QueryStreamSegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest"), mock.Anything).
Run(func(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) {
s.EqualValues(1, req.Req.GetBase().GetTargetID())
s.True(req.GetFromShardLeader())
if req.GetScope() == querypb.DataScope_Streaming {
s.EqualValues([]string{s.vchannelName}, req.GetDmlChannels())
s.ElementsMatch([]int64{1004}, req.GetSegmentIDs())
}
if req.GetScope() == querypb.DataScope_Historical {
s.EqualValues([]string{s.vchannelName}, req.GetDmlChannels())
s.ElementsMatch([]int64{1000, 1001}, req.GetSegmentIDs())
}
srv.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{Data: req.GetSegmentIDs()},
},
},
})
}).Return(nil)
worker2.EXPECT().QueryStreamSegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest"), mock.Anything).
Run(func(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) {
s.EqualValues(2, req.Req.GetBase().GetTargetID())
s.True(req.GetFromShardLeader())
s.Equal(querypb.DataScope_Historical, req.GetScope())
s.EqualValues([]string{s.vchannelName}, req.GetDmlChannels())
s.ElementsMatch([]int64{1002, 1003}, req.GetSegmentIDs())
srv.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{Data: req.GetSegmentIDs()},
},
},
})
}).Return(nil)
// run stream function
go func() {
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{Base: commonpbutil.NewMsgBase()},
DmlChannels: []string{s.vchannelName},
}, server)
s.NoError(err)
server.FinishSend(err)
}()
resultIDs := []int64{1000, 1001, 1002, 1003, 1004}
recNum := 0
for {
result, err := client.Recv()
if err == io.EOF {
s.Equal(recNum, len(resultIDs))
break
}
s.NoError(err)
err = merr.Error(result.GetStatus())
s.NoError(err)
for _, segmentID := range result.Ids.GetIntId().Data {
s.Less(recNum, len(resultIDs))
lo.Contains[int64](resultIDs, segmentID)
recNum++
}
}
})
s.Run("partition_not_loaded", func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
Base: commonpbutil.NewMsgBase(),
//not load partation -1,will return error
PartitionIDs: []int64{-1},
},
DmlChannels: []string{s.vchannelName},
}, server)
s.True(errors.Is(err, merr.ErrPartitionNotLoaded))
})
s.Run("tsafe_behind_max_lag", func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
Base: commonpbutil.NewMsgBase(),
GuaranteeTimestamp: uint64(paramtable.Get().QueryNodeCfg.MaxTimestampLag.GetAsDuration(time.Second)),
},
DmlChannels: []string{s.vchannelName},
}, server)
s.Error(err)
})
s.Run("get_worker_failed", func() {
defer func() {
s.workerManager.AssertExpectations(s.T())
s.workerManager.ExpectedCalls = nil
}()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
mockErr := errors.New("mock error")
s.workerManager.EXPECT().GetWorker(mock.Anything, mock.AnythingOfType("int64")).Call.Return(nil, mockErr)
// run stream function
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{Base: commonpbutil.NewMsgBase()},
DmlChannels: []string{s.vchannelName},
}, server)
s.True(errors.Is(err, mockErr))
})
s.Run("worker_return_error", func() {
defer func() {
s.workerManager.AssertExpectations(s.T())
s.workerManager.ExpectedCalls = nil
}()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
workers := make(map[int64]*cluster.MockWorker)
worker1 := &cluster.MockWorker{}
worker2 := &cluster.MockWorker{}
mockErr := errors.New("mock error")
workers[1] = worker1
workers[2] = worker2
s.workerManager.EXPECT().GetWorker(mock.Anything, mock.AnythingOfType("int64")).Call.Return(func(_ context.Context, nodeID int64) cluster.Worker {
return workers[nodeID]
}, nil)
worker1.EXPECT().QueryStreamSegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest"), mock.Anything).
Return(mockErr)
worker2.EXPECT().QueryStreamSegments(mock.Anything, mock.AnythingOfType("*querypb.QueryRequest"), mock.Anything).
Run(func(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) {
s.EqualValues(2, req.Req.GetBase().GetTargetID())
s.True(req.GetFromShardLeader())
s.Equal(querypb.DataScope_Historical, req.GetScope())
s.EqualValues([]string{s.vchannelName}, req.GetDmlChannels())
s.ElementsMatch([]int64{1002, 1003}, req.GetSegmentIDs())
srv.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: &schemapb.IDs{
IdField: &schemapb.IDs_IntId{
IntId: &schemapb.LongArray{Data: req.GetSegmentIDs()},
},
},
})
}).Return(nil)
// run stream function
go func() {
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{Base: commonpbutil.NewMsgBase()},
DmlChannels: []string{s.vchannelName},
}, server)
server.Send(&internalpb.RetrieveResults{
Status: merr.Status(err),
})
}()
resultIDs := []int64{1002, 1003}
recNum := 0
for {
result, err := client.Recv()
s.NoError(err)
err = merr.Error(result.GetStatus())
if err != nil {
s.Equal(recNum, len(resultIDs))
s.Equal(err.Error(), mockErr.Error())
break
}
for _, segmentID := range result.Ids.GetIntId().GetData() {
s.Less(recNum, len(resultIDs))
lo.Contains[int64](resultIDs, segmentID)
recNum++
}
}
})
s.Run("wrong_channel", func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{Base: commonpbutil.NewMsgBase()},
DmlChannels: []string{"non_exist_channel"},
}, server)
s.Error(err)
})
s.Run("cluster_not_serviceable", func() {
s.delegator.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
err := s.delegator.QueryStream(ctx, &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{Base: commonpbutil.NewMsgBase()},
DmlChannels: []string{s.vchannelName},
}, server)
s.Error(err)
})
}
func (s *DelegatorSuite) TestGetStats() {
s.delegator.Start()
// 1 => sealed segment 1000, 1001
// 1 => growing segment 1004
// 2 => sealed segment 1002, 1003
paramtable.SetNodeID(1)
s.delegator.LoadGrowing(context.Background(), []*querypb.SegmentLoadInfo{
{
SegmentID: 1004,
CollectionID: s.collectionID,
PartitionID: 500,
},
}, 0)
s.delegator.SyncDistribution(context.Background(),
SegmentEntry{
NodeID: 1,
SegmentID: 1000,
PartitionID: 500,
Version: 2001,
},
SegmentEntry{
NodeID: 1,
SegmentID: 1001,
PartitionID: 501,
Version: 2001,
},
SegmentEntry{
NodeID: 2,
SegmentID: 1002,
PartitionID: 500,
Version: 2001,
},
SegmentEntry{
NodeID: 2,
SegmentID: 1003,
PartitionID: 501,
Version: 2001,
},
)
s.initSegments()
s.delegator.SyncTargetVersion(2001, []int64{1004}, []int64{1000, 1001, 1002, 1003}, []int64{})
s.Run("normal", func() {
defer func() {
s.workerManager.ExpectedCalls = nil

View File

@ -1,4 +1,4 @@
// Code generated by mockery v2.32.4. DO NOT EDIT.
// Code generated by mockery v2.16.0. DO NOT EDIT.
package delegator
@ -9,6 +9,8 @@ import (
mock "github.com/stretchr/testify/mock"
querypb "github.com/milvus-io/milvus/internal/proto/querypb"
streamrpc "github.com/milvus-io/milvus/internal/util/streamrpc"
)
// MockShardDelegator is an autogenerated mock type for the ShardDelegator type
@ -51,11 +53,6 @@ func (_c *MockShardDelegator_Close_Call) Return() *MockShardDelegator_Close_Call
return _c
}
func (_c *MockShardDelegator_Close_Call) RunAndReturn(run func()) *MockShardDelegator_Close_Call {
_c.Call.Return(run)
return _c
}
// Collection provides a mock function with given fields:
func (_m *MockShardDelegator) Collection() int64 {
ret := _m.Called()
@ -92,20 +89,11 @@ func (_c *MockShardDelegator_Collection_Call) Return(_a0 int64) *MockShardDelega
return _c
}
func (_c *MockShardDelegator_Collection_Call) RunAndReturn(run func() int64) *MockShardDelegator_Collection_Call {
_c.Call.Return(run)
return _c
}
// GetSegmentInfo provides a mock function with given fields: readable
func (_m *MockShardDelegator) GetSegmentInfo(readable bool) ([]SnapshotItem, []SegmentEntry) {
ret := _m.Called(readable)
var r0 []SnapshotItem
var r1 []SegmentEntry
if rf, ok := ret.Get(0).(func(bool) ([]SnapshotItem, []SegmentEntry)); ok {
return rf(readable)
}
if rf, ok := ret.Get(0).(func(bool) []SnapshotItem); ok {
r0 = rf(readable)
} else {
@ -114,6 +102,7 @@ func (_m *MockShardDelegator) GetSegmentInfo(readable bool) ([]SnapshotItem, []S
}
}
var r1 []SegmentEntry
if rf, ok := ret.Get(1).(func(bool) []SegmentEntry); ok {
r1 = rf(readable)
} else {
@ -131,7 +120,7 @@ type MockShardDelegator_GetSegmentInfo_Call struct {
}
// GetSegmentInfo is a helper method to define mock.On call
// - readable bool
// - readable bool
func (_e *MockShardDelegator_Expecter) GetSegmentInfo(readable interface{}) *MockShardDelegator_GetSegmentInfo_Call {
return &MockShardDelegator_GetSegmentInfo_Call{Call: _e.mock.On("GetSegmentInfo", readable)}
}
@ -148,20 +137,11 @@ func (_c *MockShardDelegator_GetSegmentInfo_Call) Return(sealed []SnapshotItem,
return _c
}
func (_c *MockShardDelegator_GetSegmentInfo_Call) RunAndReturn(run func(bool) ([]SnapshotItem, []SegmentEntry)) *MockShardDelegator_GetSegmentInfo_Call {
_c.Call.Return(run)
return _c
}
// GetStatistics provides a mock function with given fields: ctx, req
func (_m *MockShardDelegator) GetStatistics(ctx context.Context, req *querypb.GetStatisticsRequest) ([]*internalpb.GetStatisticsResponse, error) {
ret := _m.Called(ctx, req)
var r0 []*internalpb.GetStatisticsResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.GetStatisticsRequest) ([]*internalpb.GetStatisticsResponse, error)); ok {
return rf(ctx, req)
}
if rf, ok := ret.Get(0).(func(context.Context, *querypb.GetStatisticsRequest) []*internalpb.GetStatisticsResponse); ok {
r0 = rf(ctx, req)
} else {
@ -170,6 +150,7 @@ func (_m *MockShardDelegator) GetStatistics(ctx context.Context, req *querypb.Ge
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *querypb.GetStatisticsRequest) error); ok {
r1 = rf(ctx, req)
} else {
@ -185,8 +166,8 @@ type MockShardDelegator_GetStatistics_Call struct {
}
// GetStatistics is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.GetStatisticsRequest
// - ctx context.Context
// - req *querypb.GetStatisticsRequest
func (_e *MockShardDelegator_Expecter) GetStatistics(ctx interface{}, req interface{}) *MockShardDelegator_GetStatistics_Call {
return &MockShardDelegator_GetStatistics_Call{Call: _e.mock.On("GetStatistics", ctx, req)}
}
@ -203,11 +184,6 @@ func (_c *MockShardDelegator_GetStatistics_Call) Return(_a0 []*internalpb.GetSta
return _c
}
func (_c *MockShardDelegator_GetStatistics_Call) RunAndReturn(run func(context.Context, *querypb.GetStatisticsRequest) ([]*internalpb.GetStatisticsResponse, error)) *MockShardDelegator_GetStatistics_Call {
_c.Call.Return(run)
return _c
}
// GetTargetVersion provides a mock function with given fields:
func (_m *MockShardDelegator) GetTargetVersion() int64 {
ret := _m.Called()
@ -244,11 +220,6 @@ func (_c *MockShardDelegator_GetTargetVersion_Call) Return(_a0 int64) *MockShard
return _c
}
func (_c *MockShardDelegator_GetTargetVersion_Call) RunAndReturn(run func() int64) *MockShardDelegator_GetTargetVersion_Call {
_c.Call.Return(run)
return _c
}
// LoadGrowing provides a mock function with given fields: ctx, infos, version
func (_m *MockShardDelegator) LoadGrowing(ctx context.Context, infos []*querypb.SegmentLoadInfo, version int64) error {
ret := _m.Called(ctx, infos, version)
@ -269,9 +240,9 @@ type MockShardDelegator_LoadGrowing_Call struct {
}
// LoadGrowing is a helper method to define mock.On call
// - ctx context.Context
// - infos []*querypb.SegmentLoadInfo
// - version int64
// - ctx context.Context
// - infos []*querypb.SegmentLoadInfo
// - version int64
func (_e *MockShardDelegator_Expecter) LoadGrowing(ctx interface{}, infos interface{}, version interface{}) *MockShardDelegator_LoadGrowing_Call {
return &MockShardDelegator_LoadGrowing_Call{Call: _e.mock.On("LoadGrowing", ctx, infos, version)}
}
@ -288,11 +259,6 @@ func (_c *MockShardDelegator_LoadGrowing_Call) Return(_a0 error) *MockShardDeleg
return _c
}
func (_c *MockShardDelegator_LoadGrowing_Call) RunAndReturn(run func(context.Context, []*querypb.SegmentLoadInfo, int64) error) *MockShardDelegator_LoadGrowing_Call {
_c.Call.Return(run)
return _c
}
// LoadSegments provides a mock function with given fields: ctx, req
func (_m *MockShardDelegator) LoadSegments(ctx context.Context, req *querypb.LoadSegmentsRequest) error {
ret := _m.Called(ctx, req)
@ -313,8 +279,8 @@ type MockShardDelegator_LoadSegments_Call struct {
}
// LoadSegments is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.LoadSegmentsRequest
// - ctx context.Context
// - req *querypb.LoadSegmentsRequest
func (_e *MockShardDelegator_Expecter) LoadSegments(ctx interface{}, req interface{}) *MockShardDelegator_LoadSegments_Call {
return &MockShardDelegator_LoadSegments_Call{Call: _e.mock.On("LoadSegments", ctx, req)}
}
@ -331,11 +297,6 @@ func (_c *MockShardDelegator_LoadSegments_Call) Return(_a0 error) *MockShardDele
return _c
}
func (_c *MockShardDelegator_LoadSegments_Call) RunAndReturn(run func(context.Context, *querypb.LoadSegmentsRequest) error) *MockShardDelegator_LoadSegments_Call {
_c.Call.Return(run)
return _c
}
// ProcessDelete provides a mock function with given fields: deleteData, ts
func (_m *MockShardDelegator) ProcessDelete(deleteData []*DeleteData, ts uint64) {
_m.Called(deleteData, ts)
@ -347,8 +308,8 @@ type MockShardDelegator_ProcessDelete_Call struct {
}
// ProcessDelete is a helper method to define mock.On call
// - deleteData []*DeleteData
// - ts uint64
// - deleteData []*DeleteData
// - ts uint64
func (_e *MockShardDelegator_Expecter) ProcessDelete(deleteData interface{}, ts interface{}) *MockShardDelegator_ProcessDelete_Call {
return &MockShardDelegator_ProcessDelete_Call{Call: _e.mock.On("ProcessDelete", deleteData, ts)}
}
@ -365,11 +326,6 @@ func (_c *MockShardDelegator_ProcessDelete_Call) Return() *MockShardDelegator_Pr
return _c
}
func (_c *MockShardDelegator_ProcessDelete_Call) RunAndReturn(run func([]*DeleteData, uint64)) *MockShardDelegator_ProcessDelete_Call {
_c.Call.Return(run)
return _c
}
// ProcessInsert provides a mock function with given fields: insertRecords
func (_m *MockShardDelegator) ProcessInsert(insertRecords map[int64]*InsertData) {
_m.Called(insertRecords)
@ -381,7 +337,7 @@ type MockShardDelegator_ProcessInsert_Call struct {
}
// ProcessInsert is a helper method to define mock.On call
// - insertRecords map[int64]*InsertData
// - insertRecords map[int64]*InsertData
func (_e *MockShardDelegator_Expecter) ProcessInsert(insertRecords interface{}) *MockShardDelegator_ProcessInsert_Call {
return &MockShardDelegator_ProcessInsert_Call{Call: _e.mock.On("ProcessInsert", insertRecords)}
}
@ -398,20 +354,11 @@ func (_c *MockShardDelegator_ProcessInsert_Call) Return() *MockShardDelegator_Pr
return _c
}
func (_c *MockShardDelegator_ProcessInsert_Call) RunAndReturn(run func(map[int64]*InsertData)) *MockShardDelegator_ProcessInsert_Call {
_c.Call.Return(run)
return _c
}
// Query provides a mock function with given fields: ctx, req
func (_m *MockShardDelegator) Query(ctx context.Context, req *querypb.QueryRequest) ([]*internalpb.RetrieveResults, error) {
ret := _m.Called(ctx, req)
var r0 []*internalpb.RetrieveResults
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest) ([]*internalpb.RetrieveResults, error)); ok {
return rf(ctx, req)
}
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest) []*internalpb.RetrieveResults); ok {
r0 = rf(ctx, req)
} else {
@ -420,6 +367,7 @@ func (_m *MockShardDelegator) Query(ctx context.Context, req *querypb.QueryReque
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *querypb.QueryRequest) error); ok {
r1 = rf(ctx, req)
} else {
@ -435,8 +383,8 @@ type MockShardDelegator_Query_Call struct {
}
// Query is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.QueryRequest
// - ctx context.Context
// - req *querypb.QueryRequest
func (_e *MockShardDelegator_Expecter) Query(ctx interface{}, req interface{}) *MockShardDelegator_Query_Call {
return &MockShardDelegator_Query_Call{Call: _e.mock.On("Query", ctx, req)}
}
@ -453,8 +401,42 @@ func (_c *MockShardDelegator_Query_Call) Return(_a0 []*internalpb.RetrieveResult
return _c
}
func (_c *MockShardDelegator_Query_Call) RunAndReturn(run func(context.Context, *querypb.QueryRequest) ([]*internalpb.RetrieveResults, error)) *MockShardDelegator_Query_Call {
_c.Call.Return(run)
// QueryStream provides a mock function with given fields: ctx, req, srv
func (_m *MockShardDelegator) QueryStream(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
ret := _m.Called(ctx, req, srv)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.QueryRequest, streamrpc.QueryStreamServer) error); ok {
r0 = rf(ctx, req, srv)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockShardDelegator_QueryStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryStream'
type MockShardDelegator_QueryStream_Call struct {
*mock.Call
}
// QueryStream is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.QueryRequest
// - srv streamrpc.QueryStreamServer
func (_e *MockShardDelegator_Expecter) QueryStream(ctx interface{}, req interface{}, srv interface{}) *MockShardDelegator_QueryStream_Call {
return &MockShardDelegator_QueryStream_Call{Call: _e.mock.On("QueryStream", ctx, req, srv)}
}
func (_c *MockShardDelegator_QueryStream_Call) Run(run func(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer)) *MockShardDelegator_QueryStream_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*querypb.QueryRequest), args[2].(streamrpc.QueryStreamServer))
})
return _c
}
func (_c *MockShardDelegator_QueryStream_Call) Return(_a0 error) *MockShardDelegator_QueryStream_Call {
_c.Call.Return(_a0)
return _c
}
@ -478,9 +460,9 @@ type MockShardDelegator_ReleaseSegments_Call struct {
}
// ReleaseSegments is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.ReleaseSegmentsRequest
// - force bool
// - ctx context.Context
// - req *querypb.ReleaseSegmentsRequest
// - force bool
func (_e *MockShardDelegator_Expecter) ReleaseSegments(ctx interface{}, req interface{}, force interface{}) *MockShardDelegator_ReleaseSegments_Call {
return &MockShardDelegator_ReleaseSegments_Call{Call: _e.mock.On("ReleaseSegments", ctx, req, force)}
}
@ -497,20 +479,11 @@ func (_c *MockShardDelegator_ReleaseSegments_Call) Return(_a0 error) *MockShardD
return _c
}
func (_c *MockShardDelegator_ReleaseSegments_Call) RunAndReturn(run func(context.Context, *querypb.ReleaseSegmentsRequest, bool) error) *MockShardDelegator_ReleaseSegments_Call {
_c.Call.Return(run)
return _c
}
// Search provides a mock function with given fields: ctx, req
func (_m *MockShardDelegator) Search(ctx context.Context, req *querypb.SearchRequest) ([]*internalpb.SearchResults, error) {
ret := _m.Called(ctx, req)
var r0 []*internalpb.SearchResults
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *querypb.SearchRequest) ([]*internalpb.SearchResults, error)); ok {
return rf(ctx, req)
}
if rf, ok := ret.Get(0).(func(context.Context, *querypb.SearchRequest) []*internalpb.SearchResults); ok {
r0 = rf(ctx, req)
} else {
@ -519,6 +492,7 @@ func (_m *MockShardDelegator) Search(ctx context.Context, req *querypb.SearchReq
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *querypb.SearchRequest) error); ok {
r1 = rf(ctx, req)
} else {
@ -534,8 +508,8 @@ type MockShardDelegator_Search_Call struct {
}
// Search is a helper method to define mock.On call
// - ctx context.Context
// - req *querypb.SearchRequest
// - ctx context.Context
// - req *querypb.SearchRequest
func (_e *MockShardDelegator_Expecter) Search(ctx interface{}, req interface{}) *MockShardDelegator_Search_Call {
return &MockShardDelegator_Search_Call{Call: _e.mock.On("Search", ctx, req)}
}
@ -552,11 +526,6 @@ func (_c *MockShardDelegator_Search_Call) Return(_a0 []*internalpb.SearchResults
return _c
}
func (_c *MockShardDelegator_Search_Call) RunAndReturn(run func(context.Context, *querypb.SearchRequest) ([]*internalpb.SearchResults, error)) *MockShardDelegator_Search_Call {
_c.Call.Return(run)
return _c
}
// Serviceable provides a mock function with given fields:
func (_m *MockShardDelegator) Serviceable() bool {
ret := _m.Called()
@ -593,11 +562,6 @@ func (_c *MockShardDelegator_Serviceable_Call) Return(_a0 bool) *MockShardDelega
return _c
}
func (_c *MockShardDelegator_Serviceable_Call) RunAndReturn(run func() bool) *MockShardDelegator_Serviceable_Call {
_c.Call.Return(run)
return _c
}
// Start provides a mock function with given fields:
func (_m *MockShardDelegator) Start() {
_m.Called()
@ -625,11 +589,6 @@ func (_c *MockShardDelegator_Start_Call) Return() *MockShardDelegator_Start_Call
return _c
}
func (_c *MockShardDelegator_Start_Call) RunAndReturn(run func()) *MockShardDelegator_Start_Call {
_c.Call.Return(run)
return _c
}
// SyncDistribution provides a mock function with given fields: ctx, entries
func (_m *MockShardDelegator) SyncDistribution(ctx context.Context, entries ...SegmentEntry) {
_va := make([]interface{}, len(entries))
@ -648,8 +607,8 @@ type MockShardDelegator_SyncDistribution_Call struct {
}
// SyncDistribution is a helper method to define mock.On call
// - ctx context.Context
// - entries ...SegmentEntry
// - ctx context.Context
// - entries ...SegmentEntry
func (_e *MockShardDelegator_Expecter) SyncDistribution(ctx interface{}, entries ...interface{}) *MockShardDelegator_SyncDistribution_Call {
return &MockShardDelegator_SyncDistribution_Call{Call: _e.mock.On("SyncDistribution",
append([]interface{}{ctx}, entries...)...)}

View File

@ -32,7 +32,9 @@ import (
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/querynodev2/delegator"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/querynodev2/tasks"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/metrics"
@ -155,13 +157,6 @@ func (node *QueryNode) queryChannel(ctx context.Context, req *querypb.QueryReque
}
}()
if !node.lifetime.Add(commonpbutil.IsHealthy) {
err := merr.WrapErrServiceUnavailable(fmt.Sprintf("node id: %d is unhealthy", paramtable.GetNodeID()))
failRet.Status = merr.Status(err)
return failRet, nil
}
defer node.lifetime.Done()
log.Debug("start do query with channel",
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
@ -226,6 +221,78 @@ func (node *QueryNode) queryChannel(ctx context.Context, req *querypb.QueryReque
return ret, nil
}
func (node *QueryNode) queryChannelStream(ctx context.Context, req *querypb.QueryRequest, channel string, srv streamrpc.QueryStreamServer) error {
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.TotalLabel, metrics.Leader).Inc()
failRet := WrapRetrieveResult(commonpb.ErrorCode_UnexpectedError, "")
msgID := req.Req.Base.GetMsgID()
log := log.Ctx(ctx).With(
zap.Int64("msgID", msgID),
zap.Int64("collectionID", req.GetReq().GetCollectionID()),
zap.String("channel", channel),
zap.String("scope", req.GetScope().String()),
)
defer func() {
if failRet.Status.ErrorCode != commonpb.ErrorCode_Success {
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.FailLabel, metrics.Leader).Inc()
}
}()
log.Debug("start do streaming query with channel",
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
)
// add cancel when error occurs
queryCtx, cancel := context.WithCancel(ctx)
defer cancel()
// From Proxy
tr := timerecord.NewTimeRecorder("queryDelegator")
// get delegator
sd, ok := node.delegators.Get(channel)
if !ok {
err := merr.WrapErrServiceUnavailable("failed to get query shard delegator")
log.Warn("Query failed, failed to get query shard delegator", zap.Error(err))
return err
}
// do query
err := sd.QueryStream(queryCtx, req, srv)
if err != nil {
return err
}
tr.CtxElapse(ctx, fmt.Sprintf("do query with channel done , vChannel = %s, segmentIDs = %v",
channel,
req.GetSegmentIDs(),
))
return nil
}
func (node *QueryNode) queryStreamSegments(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
collection := node.manager.Collection.Get(req.Req.GetCollectionID())
if collection == nil {
return merr.WrapErrCollectionNotFound(req.Req.GetCollectionID())
}
// Send task to scheduler and wait until it finished.
task := tasks.NewQueryStreamTask(ctx, collection, node.manager, req, srv)
if err := node.scheduler.Add(task); err != nil {
log.Warn("failed to add query task into scheduler", zap.Error(err))
return err
}
err := task.Wait()
if err != nil {
log.Warn("failed to execute task by node scheduler", zap.Error(err))
return err
}
return nil
}
func (node *QueryNode) optimizeSearchParams(ctx context.Context, req *querypb.SearchRequest, deleg delegator.ShardDelegator) (*querypb.SearchRequest, error) {
// no hook applied, just return
if node.queryHook == nil {

View File

@ -25,6 +25,7 @@ import (
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/querynodev2/cluster"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/log"
"github.com/samber/lo"
"go.uber.org/zap"
@ -101,6 +102,10 @@ func (w *LocalWorker) SearchSegments(ctx context.Context, req *querypb.SearchReq
return w.node.SearchSegments(ctx, req)
}
func (w *LocalWorker) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) error {
return w.node.queryStreamSegments(ctx, req, srv)
}
func (w *LocalWorker) QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
return w.node.QuerySegments(ctx, req)
}

View File

@ -22,11 +22,14 @@ import (
"sync"
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/proto/segcorepb"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/metrics"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/milvus-io/milvus/pkg/util/paramtable"
"github.com/milvus-io/milvus/pkg/util/timerecord"
. "github.com/milvus-io/milvus/pkg/util/typeutil"
)
// retrieveOnSegments performs retrieve on listed segments
@ -80,23 +83,97 @@ func retrieveOnSegments(ctx context.Context, segments []Segment, segType Segment
return retrieveResults, nil
}
// retrieveHistorical will retrieve all the target segments in historical
func RetrieveHistorical(ctx context.Context, manager *Manager, plan *RetrievePlan, collID UniqueID, partIDs []UniqueID, segIDs []UniqueID) ([]*segcorepb.RetrieveResults, []Segment, error) {
segments, err := validateOnHistorical(ctx, manager, collID, partIDs, segIDs)
if err != nil {
return nil, nil, err
func retrieveOnSegmentsWithStream(ctx context.Context, segments []Segment, segType SegmentType, plan *RetrievePlan, svr streamrpc.QueryStreamServer) error {
var (
errs = make([]error, len(segments))
wg sync.WaitGroup
)
label := metrics.SealedSegmentLabel
if segType == commonpb.SegmentState_Growing {
label = metrics.GrowingSegmentLabel
}
retrieveResults, err := retrieveOnSegments(ctx, segments, SegmentTypeSealed, plan)
return retrieveResults, segments, err
for i, segment := range segments {
wg.Add(1)
go func(segment Segment, i int) {
defer wg.Done()
seg := segment.(*LocalSegment)
tr := timerecord.NewTimeRecorder("retrieveOnSegmentsWithStream")
result, err := seg.Retrieve(ctx, plan)
if err != nil {
errs[i] = err
return
}
if err = seg.ValidateIndexedFieldsData(ctx, result); err != nil {
errs[i] = err
return
}
if err = svr.Send(&internalpb.RetrieveResults{
Status: merr.Status(nil),
Ids: result.GetIds(),
FieldsData: result.GetFieldsData(),
}); err != nil {
errs[i] = err
}
errs[i] = nil
metrics.QueryNodeSQSegmentLatency.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()),
metrics.QueryLabel, label).Observe(float64(tr.ElapseSpan().Milliseconds()))
}(segment, i)
}
wg.Wait()
return merr.Combine(errs...)
}
// retrieveStreaming will retrieve all the target segments in streaming
func RetrieveStreaming(ctx context.Context, manager *Manager, plan *RetrievePlan, collID UniqueID, partIDs []UniqueID, segIDs []UniqueID) ([]*segcorepb.RetrieveResults, []Segment, error) {
segments, err := validateOnStream(ctx, manager, collID, partIDs, segIDs)
if err != nil {
return nil, nil, err
// retrieve will retrieve all the validate target segments
func Retrieve(ctx context.Context, manager *Manager, plan *RetrievePlan, req *querypb.QueryRequest) ([]*segcorepb.RetrieveResults, []Segment, error) {
var err error
var SegType commonpb.SegmentState
var retrieveResults []*segcorepb.RetrieveResults
var retrieveSegments []Segment
segIDs := req.GetSegmentIDs()
collID := req.Req.GetCollectionID()
if req.GetScope() == querypb.DataScope_Historical {
SegType = SegmentTypeSealed
retrieveSegments, err = validateOnHistorical(ctx, manager, collID, nil, segIDs)
} else {
SegType = SegmentTypeGrowing
retrieveSegments, err = validateOnStream(ctx, manager, collID, nil, segIDs)
}
retrieveResults, err := retrieveOnSegments(ctx, segments, SegmentTypeGrowing, plan)
return retrieveResults, segments, err
if err != nil {
return retrieveResults, retrieveSegments, err
}
retrieveResults, err = retrieveOnSegments(ctx, retrieveSegments, SegType, plan)
return retrieveResults, retrieveSegments, err
}
// retrieveStreaming will retrieve all the validate target segments and return by stream
func RetrieveStream(ctx context.Context, manager *Manager, plan *RetrievePlan, req *querypb.QueryRequest, srv streamrpc.QueryStreamServer) ([]Segment, error) {
var err error
var SegType commonpb.SegmentState
var retrieveSegments []Segment
segIDs := req.GetSegmentIDs()
collID := req.Req.GetCollectionID()
if req.GetScope() == querypb.DataScope_Historical {
SegType = SegmentTypeSealed
retrieveSegments, err = validateOnHistorical(ctx, manager, collID, nil, segIDs)
} else {
SegType = SegmentTypeGrowing
retrieveSegments, err = validateOnStream(ctx, manager, collID, nil, segIDs)
}
if err != nil {
return retrieveSegments, err
}
err = retrieveOnSegmentsWithStream(ctx, retrieveSegments, SegType, plan, srv)
return retrieveSegments, err
}

View File

@ -18,14 +18,17 @@ package segments
import (
"context"
"io"
"testing"
"github.com/stretchr/testify/suite"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/storage"
"github.com/milvus-io/milvus/internal/util/initcore"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/milvus-io/milvus/pkg/util/paramtable"
)
@ -140,10 +143,16 @@ func (suite *RetrieveSuite) TestRetrieveSealed() {
plan, err := genSimpleRetrievePlan(suite.collection)
suite.NoError(err)
res, segments, err := RetrieveHistorical(context.TODO(), suite.manager, plan,
suite.collectionID,
[]int64{suite.partitionID},
[]int64{suite.sealed.ID()})
req := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
CollectionID: suite.collectionID,
PartitionIDs: []int64{suite.partitionID},
},
SegmentIDs: []int64{suite.sealed.ID()},
Scope: querypb.DataScope_Historical,
}
res, segments, err := Retrieve(context.TODO(), suite.manager, plan, req)
suite.NoError(err)
suite.Len(res[0].Offset, 3)
suite.manager.Segment.Unpin(segments)
@ -153,24 +162,80 @@ func (suite *RetrieveSuite) TestRetrieveGrowing() {
plan, err := genSimpleRetrievePlan(suite.collection)
suite.NoError(err)
res, segments, err := RetrieveStreaming(context.TODO(), suite.manager, plan,
suite.collectionID,
[]int64{suite.partitionID},
[]int64{suite.growing.ID()})
req := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
CollectionID: suite.collectionID,
PartitionIDs: []int64{suite.partitionID},
},
SegmentIDs: []int64{suite.growing.ID()},
Scope: querypb.DataScope_Streaming,
}
res, segments, err := Retrieve(context.TODO(), suite.manager, plan, req)
suite.NoError(err)
suite.Len(res[0].Offset, 3)
suite.manager.Segment.Unpin(segments)
}
func (suite *RetrieveSuite) TestRetrieveStreamSealed() {
plan, err := genSimpleRetrievePlan(suite.collection)
suite.NoError(err)
req := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
CollectionID: suite.collectionID,
PartitionIDs: []int64{suite.partitionID},
},
SegmentIDs: []int64{suite.sealed.ID()},
Scope: querypb.DataScope_Historical,
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
go func() {
segments, err := RetrieveStream(ctx, suite.manager, plan, req, server)
suite.NoError(err)
suite.manager.Segment.Unpin(segments)
server.FinishSend(err)
}()
sum := 0
for {
result, err := client.Recv()
if err != nil {
if err == io.EOF {
suite.Equal(3, sum)
break
}
suite.Fail("Retrieve stream fetch error")
}
err = merr.Error(result.GetStatus())
suite.NoError(err)
sum += len(result.Ids.GetIntId().GetData())
}
}
func (suite *RetrieveSuite) TestRetrieveNonExistSegment() {
plan, err := genSimpleRetrievePlan(suite.collection)
suite.NoError(err)
res, segments, err := RetrieveHistorical(context.TODO(), suite.manager, plan,
suite.collectionID,
[]int64{suite.partitionID},
[]int64{999})
suite.ErrorIs(err, merr.ErrSegmentNotLoaded)
req := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
CollectionID: suite.collectionID,
PartitionIDs: []int64{suite.partitionID},
},
SegmentIDs: []int64{999},
Scope: querypb.DataScope_Streaming,
}
res, segments, err := Retrieve(context.TODO(), suite.manager, plan, req)
suite.Error(err)
suite.Len(res, 0)
suite.manager.Segment.Unpin(segments)
}
@ -180,10 +245,16 @@ func (suite *RetrieveSuite) TestRetrieveNilSegment() {
suite.NoError(err)
suite.sealed.Release()
res, segments, err := RetrieveHistorical(context.TODO(), suite.manager, plan,
suite.collectionID,
[]int64{suite.partitionID},
[]int64{suite.sealed.ID()})
req := &querypb.QueryRequest{
Req: &internalpb.RetrieveRequest{
CollectionID: suite.collectionID,
PartitionIDs: []int64{suite.partitionID},
},
SegmentIDs: []int64{suite.sealed.ID()},
Scope: querypb.DataScope_Historical,
}
res, segments, err := Retrieve(context.TODO(), suite.manager, plan, req)
suite.ErrorIs(err, merr.ErrSegmentNotLoaded)
suite.Len(res, 0)
suite.manager.Segment.Unpin(segments)

View File

@ -43,6 +43,7 @@ import (
"github.com/milvus-io/milvus/internal/querynodev2/tasks"
"github.com/milvus-io/milvus/internal/storage"
"github.com/milvus-io/milvus/internal/util"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/metrics"
@ -939,6 +940,63 @@ func (node *QueryNode) QuerySegments(ctx context.Context, req *querypb.QueryRequ
return result, nil
}
func (node *QueryNode) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
failRet := WrapRetrieveResult(commonpb.ErrorCode_UnexpectedError, "")
msgID := req.Req.Base.GetMsgID()
traceID := trace.SpanFromContext(ctx).SpanContext().TraceID()
channel := req.GetDmlChannels()[0]
srv := streamer.AsServer()
log := log.Ctx(ctx).With(
zap.Int64("msgID", msgID),
zap.Int64("collectionID", req.GetReq().GetCollectionID()),
zap.String("channel", channel),
zap.String("scope", req.GetScope().String()),
)
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.TotalLabel, metrics.FromLeader).Inc()
defer func() {
if failRet.Status.ErrorCode != commonpb.ErrorCode_Success {
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.FailLabel, metrics.FromLeader).Inc()
}
}()
if !node.lifetime.Add(commonpbutil.IsHealthy) {
failRet.Status = merr.Status(merr.WrapErrServiceUnavailable(fmt.Sprintf("node id: %d is unhealthy", paramtable.GetNodeID())))
srv.Send(failRet)
return nil
}
defer node.lifetime.Done()
log.Debug("start do query with channel",
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
)
tr := timerecord.NewTimeRecorder("queryChannel")
err := node.queryStreamSegments(ctx, req, srv)
if err != nil {
failRet.Status = merr.Status(err)
srv.Send(failRet)
return nil
}
tr.CtxElapse(ctx, fmt.Sprintf("do query done, traceID = %s, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
traceID,
req.GetFromShardLeader(),
channel,
req.GetSegmentIDs(),
))
failRet.Status.ErrorCode = commonpb.ErrorCode_Success
// TODO QueryNodeSQLatencyInQueue QueryNodeReduceLatency
latency := tr.ElapseSpan()
metrics.QueryNodeSQReqLatency.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.FromLeader).Observe(float64(latency.Milliseconds()))
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(paramtable.GetNodeID()), metrics.QueryLabel, metrics.SuccessLabel, metrics.FromLeader).Inc()
return nil
}
// Query performs replica query tasks.
func (node *QueryNode) Query(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
if req.FromShardLeader {
@ -1030,6 +1088,72 @@ func (node *QueryNode) Query(ctx context.Context, req *querypb.QueryRequest) (*i
return ret, nil
}
// QueryStream
func (node *QueryNode) QueryStream(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
log := log.Ctx(ctx).With(
zap.Int64("collectionID", req.GetReq().GetCollectionID()),
zap.Strings("shards", req.GetDmlChannels()),
)
srv := streamer.AsServer()
log.Debug("received query stream request",
zap.Int64s("outputFields", req.GetReq().GetOutputFieldsId()),
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
zap.Uint64("guaranteeTimestamp", req.GetReq().GetGuaranteeTimestamp()),
zap.Uint64("mvccTimestamp", req.GetReq().GetMvccTimestamp()),
zap.Bool("isCount", req.GetReq().GetIsCount()),
)
if !node.lifetime.Add(commonpbutil.IsHealthy) {
msg := fmt.Sprintf("query node %d is not ready", paramtable.GetNodeID())
err := merr.WrapErrServiceNotReady(msg)
srv.Send(&internalpb.RetrieveResults{Status: merr.Status(err)})
return nil
}
defer node.lifetime.Done()
if !CheckTargetID(req.GetReq()) {
targetID := req.GetReq().GetBase().GetTargetID()
log.Warn("target ID not match",
zap.Int64("targetID", targetID),
zap.Int64("nodeID", paramtable.GetNodeID()),
)
srv.Send(WrapRetrieveResult(commonpb.ErrorCode_NodeIDNotMatch,
common.WrapNodeIDNotMatchMsg(targetID, paramtable.GetNodeID())))
return nil
}
runningGp, runningCtx := errgroup.WithContext(ctx)
for _, ch := range req.GetDmlChannels() {
ch := ch
req := &querypb.QueryRequest{
Req: req.Req,
DmlChannels: []string{ch},
SegmentIDs: req.SegmentIDs,
FromShardLeader: req.FromShardLeader,
Scope: req.Scope,
}
runningGp.Go(func() error {
err := node.queryChannelStream(runningCtx, req, ch, srv)
if err != nil {
return err
}
return nil
})
}
if err := runningGp.Wait(); err != nil {
srv.Send(WrapRetrieveResult(commonpb.ErrorCode_UnexpectedError, "failed to query channel", err))
return nil
}
collector.Rate.Add(metricsinfo.NQPerSecond, 1)
metrics.QueryNodeExecuteCounter.WithLabelValues(strconv.FormatInt(paramtable.GetNodeID(), 10), metrics.QueryLabel).Add(float64(proto.Size(req)))
return nil
}
// SyncReplicaSegments syncs replica node & segments states
func (node *QueryNode) SyncReplicaSegments(ctx context.Context, req *querypb.SyncReplicaSegmentsRequest) (*commonpb.Status, error) {
return util.SuccessStatus(), nil

View File

@ -18,7 +18,9 @@ package querynodev2
import (
"context"
"encoding/json"
"io"
"math/rand"
"sync"
"testing"
"time"
@ -41,6 +43,7 @@ import (
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/storage"
"github.com/milvus-io/milvus/internal/util/dependency"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/milvus-io/milvus/pkg/mq/msgstream"
"github.com/milvus-io/milvus/pkg/util/conc"
"github.com/milvus-io/milvus/pkg/util/etcd"
@ -1316,7 +1319,8 @@ func (suite *ServiceSuite) TestQuery_Normal() {
}
func (suite *ServiceSuite) TestQuery_Failed() {
ctx := context.Background()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// data
schema := segments.GenTestCollectionSchema(suite.collectionName, schemapb.DataType_Int64)
@ -1379,8 +1383,152 @@ func (suite *ServiceSuite) TestQuerySegments_Failed() {
suite.Equal(commonpb.ErrorCode_UnexpectedError, rsp.GetStatus().GetErrorCode())
}
func (suite *ServiceSuite) TestQueryStream_Normal() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// prepare
suite.TestWatchDmChannelsInt64()
suite.TestLoadSegments_Int64()
// data
schema := segments.GenTestCollectionSchema(suite.collectionName, schemapb.DataType_Int64)
creq, err := suite.genCQueryRequest(10, IndexFaissIDMap, schema)
suite.NoError(err)
req := &querypb.QueryRequest{
Req: creq,
FromShardLeader: false,
DmlChannels: []string{suite.vchannel},
}
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
streamer := streamrpc.NewGrpcQueryStreamer()
streamer.SetServer(streamrpc.NewConcurrentQueryStreamServer(server))
go func() {
err := suite.node.QueryStream(ctx, req, streamer)
suite.NoError(err)
server.FinishSend(err)
}()
for {
result, err := client.Recv()
if err == io.EOF {
break
}
suite.NoError(err)
err = merr.Error(result.GetStatus())
suite.NoError(err)
}
}
func (suite *ServiceSuite) TestQueryStream_Failed() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// data
schema := segments.GenTestCollectionSchema(suite.collectionName, schemapb.DataType_Int64)
creq, err := suite.genCQueryRequest(10, IndexFaissIDMap, schema)
suite.NoError(err)
req := &querypb.QueryRequest{
Req: creq,
FromShardLeader: false,
DmlChannels: []string{suite.vchannel},
}
queryFunc := func(wg *sync.WaitGroup, req *querypb.QueryRequest, client *streamrpc.LocalQueryClient) {
server := client.CreateServer()
streamer := streamrpc.NewGrpcQueryStreamer()
streamer.SetServer(streamrpc.NewConcurrentQueryStreamServer(server))
defer wg.Done()
err := suite.node.QueryStream(ctx, req, streamer)
suite.NoError(err)
server.FinishSend(err)
}
// Delegator not found
suite.Run("delegator not found", func() {
client := streamrpc.NewLocalQueryClient(ctx)
wg := &sync.WaitGroup{}
wg.Add(1)
go queryFunc(wg, req, client)
for {
result, err := client.Recv()
if err == io.EOF {
break
}
suite.NoError(err)
err = merr.Error(result.GetStatus())
// Check result
if err != nil {
suite.Equal(commonpb.ErrorCode_UnexpectedError, result.GetStatus().GetErrorCode())
suite.Contains(err.Error(), merr.ErrServiceUnavailable.Error())
}
}
wg.Wait()
})
// prepare
suite.TestWatchDmChannelsInt64()
suite.TestLoadSegments_Int64()
// target not match
suite.Run("target not match", func() {
client := streamrpc.NewLocalQueryClient(ctx)
wg := &sync.WaitGroup{}
wg.Add(1)
go queryFunc(wg, req, client)
for {
result, err := client.Recv()
if err == io.EOF {
break
}
suite.NoError(err)
err = merr.Error(result.GetStatus())
if err != nil {
suite.Equal(commonpb.ErrorCode_NodeIDNotMatch, result.GetStatus().GetErrorCode())
}
}
wg.Wait()
})
// node not healthy
suite.Run("node not healthy", func() {
suite.node.UpdateStateCode(commonpb.StateCode_Abnormal)
client := streamrpc.NewLocalQueryClient(ctx)
wg := &sync.WaitGroup{}
wg.Add(1)
go queryFunc(wg, req, client)
for {
result, err := client.Recv()
if err == io.EOF {
break
}
suite.NoError(err)
err = merr.Error(result.GetStatus())
if err != nil {
suite.True(errors.Is(err, merr.ErrServiceNotReady))
}
}
wg.Wait()
})
}
func (suite *ServiceSuite) TestQuerySegments_Normal() {
ctx := context.Background()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// pre
suite.TestWatchDmChannelsInt64()
suite.TestLoadSegments_Int64()
@ -1400,6 +1548,52 @@ func (suite *ServiceSuite) TestQuerySegments_Normal() {
suite.Equal(commonpb.ErrorCode_Success, rsp.GetStatus().GetErrorCode())
}
func (suite *ServiceSuite) TestQueryStreamSegments_Normal() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// pre
suite.TestWatchDmChannelsInt64()
suite.TestLoadSegments_Int64()
// data
schema := segments.GenTestCollectionSchema(suite.collectionName, schemapb.DataType_Int64)
creq, err := suite.genCQueryRequest(10, IndexFaissIDMap, schema)
suite.NoError(err)
req := &querypb.QueryRequest{
Req: creq,
FromShardLeader: true,
DmlChannels: []string{suite.vchannel},
}
client := streamrpc.NewLocalQueryClient(ctx)
server := client.CreateServer()
streamer := streamrpc.NewGrpcQueryStreamer()
streamer.SetServer(streamrpc.NewConcurrentQueryStreamServer(server))
go func() {
err := suite.node.QueryStreamSegments(ctx, req, streamer)
suite.NoError(err)
server.FinishSend(err)
}()
for {
result, err := client.Recv()
if err == io.EOF {
break
}
suite.NoError(err)
err = merr.Error(result.GetStatus())
suite.NoError(err)
// Check result
if !errors.Is(err, nil) {
suite.NoError(err)
break
}
}
}
func (suite *ServiceSuite) TestSyncReplicaSegments_Normal() {
ctx := context.Background()
req := &querypb.SyncReplicaSegmentsRequest{}

View File

@ -0,0 +1,83 @@
package tasks
import (
"context"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/internal/util/streamrpc"
)
var _ Task = &QueryStreamTask{}
func NewQueryStreamTask(ctx context.Context,
collection *segments.Collection,
manager *segments.Manager,
req *querypb.QueryRequest,
srv streamrpc.QueryStreamServer,
) *QueryStreamTask {
return &QueryStreamTask{
ctx: ctx,
collection: collection,
segmentManager: manager,
req: req,
srv: srv,
notifier: make(chan error, 1),
}
}
type QueryStreamTask struct {
ctx context.Context
collection *segments.Collection
segmentManager *segments.Manager
req *querypb.QueryRequest
srv streamrpc.QueryStreamServer
notifier chan error
}
// Return the username which task is belong to.
// Return "" if the task do not contain any user info.
func (t *QueryStreamTask) Username() string {
return t.req.Req.GetUsername()
}
// PreExecute the task, only call once.
func (t *QueryStreamTask) PreExecute() error {
return nil
}
func (t *QueryStreamTask) Execute() error {
retrievePlan, err := segments.NewRetrievePlan(
t.collection,
t.req.Req.GetSerializedExprPlan(),
t.req.Req.GetMvccTimestamp(),
t.req.Req.Base.GetMsgID(),
)
if err != nil {
return err
}
defer retrievePlan.Delete()
segments, err := segments.RetrieveStream(t.ctx, t.segmentManager, retrievePlan, t.req, t.srv)
defer t.segmentManager.Segment.Unpin(segments)
if err != nil {
return err
}
return nil
}
func (t *QueryStreamTask) Done(err error) {
t.notifier <- err
}
func (t *QueryStreamTask) Canceled() error {
return t.ctx.Err()
}
func (t *QueryStreamTask) Wait() error {
return <-t.notifier
}
func (t *QueryStreamTask) NQ() int64 {
return 1
}

View File

@ -7,7 +7,6 @@ import (
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/proto/segcorepb"
"github.com/milvus-io/milvus/internal/querynodev2/collector"
"github.com/milvus-io/milvus/internal/querynodev2/segments"
"github.com/milvus-io/milvus/pkg/metrics"
@ -89,29 +88,7 @@ func (t *QueryTask) Execute() error {
}
defer retrievePlan.Delete()
var (
results []*segcorepb.RetrieveResults
searchedSegments []segments.Segment
)
if t.req.GetScope() == querypb.DataScope_Historical {
results, searchedSegments, err = segments.RetrieveHistorical(
t.ctx,
t.segmentManager,
retrievePlan,
t.req.Req.CollectionID,
nil,
t.req.GetSegmentIDs(),
)
} else {
results, searchedSegments, err = segments.RetrieveStreaming(
t.ctx,
t.segmentManager,
retrievePlan,
t.req.Req.CollectionID,
nil,
t.req.GetSegmentIDs(),
)
}
results, searchedSegments, err := segments.Retrieve(t.ctx, t.segmentManager, retrievePlan, t.req)
defer t.segmentManager.Segment.Unpin(searchedSegments)
if err != nil {
return err

View File

@ -19,7 +19,9 @@ package types
import (
"context"
"github.com/milvus-io/milvus/internal/util/streamrpc"
"github.com/tikv/client-go/v2/txnkv"
clientv3 "go.etcd.io/etcd/client/v3"
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
@ -1455,7 +1457,9 @@ type QueryNode interface {
Search(ctx context.Context, req *querypb.SearchRequest) (*internalpb.SearchResults, error)
SearchSegments(ctx context.Context, req *querypb.SearchRequest) (*internalpb.SearchResults, error)
Query(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error)
QueryStream(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error
QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error)
QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error
SyncReplicaSegments(ctx context.Context, req *querypb.SyncReplicaSegmentsRequest) (*commonpb.Status, error)
ShowConfigurations(ctx context.Context, req *internalpb.ShowConfigurationsRequest) (*internalpb.ShowConfigurationsResponse, error)

View File

@ -89,10 +89,18 @@ func (m *GrpcQueryNodeClient) Query(ctx context.Context, in *querypb.QueryReques
return &internalpb.RetrieveResults{}, m.Err
}
func (m *GrpcQueryNodeClient) QueryStream(ctx context.Context, in *querypb.QueryRequest, opts ...grpc.CallOption) (querypb.QueryNode_QueryStreamClient, error) {
return &GrpcQueryStreamClient{}, m.Err
}
func (m *GrpcQueryNodeClient) QuerySegments(ctx context.Context, in *querypb.QueryRequest, opts ...grpc.CallOption) (*internalpb.RetrieveResults, error) {
return &internalpb.RetrieveResults{}, m.Err
}
func (m *GrpcQueryNodeClient) QueryStreamSegments(ctx context.Context, in *querypb.QueryRequest, opts ...grpc.CallOption) (querypb.QueryNode_QueryStreamSegmentsClient, error) {
return &GrpcQueryStreamSegmentsClient{}, m.Err
}
func (m *GrpcQueryNodeClient) SyncReplicaSegments(ctx context.Context, in *querypb.SyncReplicaSegmentsRequest, opts ...grpc.CallOption) (*commonpb.Status, error) {
return &commonpb.Status{}, m.Err
}

View File

@ -0,0 +1,74 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package mock
import (
"context"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
var _ grpc.ClientStream = &MockClientStream{}
type MockClientStream struct{}
func (s *MockClientStream) Header() (metadata.MD, error) {
return nil, nil
}
func (s *MockClientStream) Trailer() metadata.MD {
return nil
}
func (s *MockClientStream) CloseSend() error {
return nil
}
func (s *MockClientStream) Context() context.Context {
return nil
}
func (s *MockClientStream) SendMsg(m interface{}) error {
return nil
}
func (s *MockClientStream) RecvMsg(m interface{}) error {
return nil
}
var _ querypb.QueryNode_QueryStreamClient = &GrpcQueryStreamClient{}
type GrpcQueryStreamClient struct {
MockClientStream
}
func (c *GrpcQueryStreamClient) Recv() (*internalpb.RetrieveResults, error) {
return &internalpb.RetrieveResults{}, nil
}
var _ querypb.QueryNode_QueryStreamSegmentsClient = &GrpcQueryStreamSegmentsClient{}
type GrpcQueryStreamSegmentsClient struct {
MockClientStream
}
func (c *GrpcQueryStreamSegmentsClient) Recv() (*internalpb.RetrieveResults, error) {
return &internalpb.RetrieveResults{}, nil
}

View File

@ -24,6 +24,7 @@ import (
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/streamrpc"
)
var _ types.QueryNode = &QueryNodeClient{}
@ -105,10 +106,30 @@ func (q QueryNodeClient) Query(ctx context.Context, req *querypb.QueryRequest) (
return q.grpcClient.Query(ctx, req)
}
func (q QueryNodeClient) QueryStream(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
cli, err := q.grpcClient.QueryStream(ctx, req)
if err != nil {
return err
}
// streamer
streamer.SetClient(cli)
return nil
}
func (q QueryNodeClient) QuerySegments(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
return q.grpcClient.Query(ctx, req)
}
func (q QueryNodeClient) QueryStreamSegments(ctx context.Context, req *querypb.QueryRequest, streamer streamrpc.QueryStreamer) error {
cli, err := q.grpcClient.QueryStreamSegments(ctx, req)
if err != nil {
return err
}
// streamer
streamer.SetClient(cli)
return nil
}
func (q QueryNodeClient) SyncReplicaSegments(ctx context.Context, req *querypb.SyncReplicaSegmentsRequest) (*commonpb.Status, error) {
return q.grpcClient.SyncReplicaSegments(ctx, req)
}

View File

@ -0,0 +1,325 @@
// Code generated by mockery v2.32.4. DO NOT EDIT.
package mocks
import (
context "context"
internalpb "github.com/milvus-io/milvus/internal/proto/internalpb"
metadata "google.golang.org/grpc/metadata"
mock "github.com/stretchr/testify/mock"
)
// MockQueryStreamSegmentsServer is an autogenerated mock type for the QueryNode_QueryStreamSegmentsServer type
type MockQueryStreamSegmentsServer struct {
mock.Mock
}
type MockQueryStreamSegmentsServer_Expecter struct {
mock *mock.Mock
}
func (_m *MockQueryStreamSegmentsServer) EXPECT() *MockQueryStreamSegmentsServer_Expecter {
return &MockQueryStreamSegmentsServer_Expecter{mock: &_m.Mock}
}
// Context provides a mock function with given fields:
func (_m *MockQueryStreamSegmentsServer) Context() context.Context {
ret := _m.Called()
var r0 context.Context
if rf, ok := ret.Get(0).(func() context.Context); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(context.Context)
}
}
return r0
}
// MockQueryStreamSegmentsServer_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context'
type MockQueryStreamSegmentsServer_Context_Call struct {
*mock.Call
}
// Context is a helper method to define mock.On call
func (_e *MockQueryStreamSegmentsServer_Expecter) Context() *MockQueryStreamSegmentsServer_Context_Call {
return &MockQueryStreamSegmentsServer_Context_Call{Call: _e.mock.On("Context")}
}
func (_c *MockQueryStreamSegmentsServer_Context_Call) Run(run func()) *MockQueryStreamSegmentsServer_Context_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_Context_Call) Return(_a0 context.Context) *MockQueryStreamSegmentsServer_Context_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_Context_Call) RunAndReturn(run func() context.Context) *MockQueryStreamSegmentsServer_Context_Call {
_c.Call.Return(run)
return _c
}
// RecvMsg provides a mock function with given fields: m
func (_m *MockQueryStreamSegmentsServer) RecvMsg(m interface{}) error {
ret := _m.Called(m)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(m)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamSegmentsServer_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg'
type MockQueryStreamSegmentsServer_RecvMsg_Call struct {
*mock.Call
}
// RecvMsg is a helper method to define mock.On call
// - m interface{}
func (_e *MockQueryStreamSegmentsServer_Expecter) RecvMsg(m interface{}) *MockQueryStreamSegmentsServer_RecvMsg_Call {
return &MockQueryStreamSegmentsServer_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)}
}
func (_c *MockQueryStreamSegmentsServer_RecvMsg_Call) Run(run func(m interface{})) *MockQueryStreamSegmentsServer_RecvMsg_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(interface{}))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_RecvMsg_Call) Return(_a0 error) *MockQueryStreamSegmentsServer_RecvMsg_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *MockQueryStreamSegmentsServer_RecvMsg_Call {
_c.Call.Return(run)
return _c
}
// Send provides a mock function with given fields: _a0
func (_m *MockQueryStreamSegmentsServer) Send(_a0 *internalpb.RetrieveResults) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(*internalpb.RetrieveResults) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamSegmentsServer_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send'
type MockQueryStreamSegmentsServer_Send_Call struct {
*mock.Call
}
// Send is a helper method to define mock.On call
// - _a0 *internalpb.RetrieveResults
func (_e *MockQueryStreamSegmentsServer_Expecter) Send(_a0 interface{}) *MockQueryStreamSegmentsServer_Send_Call {
return &MockQueryStreamSegmentsServer_Send_Call{Call: _e.mock.On("Send", _a0)}
}
func (_c *MockQueryStreamSegmentsServer_Send_Call) Run(run func(_a0 *internalpb.RetrieveResults)) *MockQueryStreamSegmentsServer_Send_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*internalpb.RetrieveResults))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_Send_Call) Return(_a0 error) *MockQueryStreamSegmentsServer_Send_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_Send_Call) RunAndReturn(run func(*internalpb.RetrieveResults) error) *MockQueryStreamSegmentsServer_Send_Call {
_c.Call.Return(run)
return _c
}
// SendHeader provides a mock function with given fields: _a0
func (_m *MockQueryStreamSegmentsServer) SendHeader(_a0 metadata.MD) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamSegmentsServer_SendHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendHeader'
type MockQueryStreamSegmentsServer_SendHeader_Call struct {
*mock.Call
}
// SendHeader is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamSegmentsServer_Expecter) SendHeader(_a0 interface{}) *MockQueryStreamSegmentsServer_SendHeader_Call {
return &MockQueryStreamSegmentsServer_SendHeader_Call{Call: _e.mock.On("SendHeader", _a0)}
}
func (_c *MockQueryStreamSegmentsServer_SendHeader_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamSegmentsServer_SendHeader_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_SendHeader_Call) Return(_a0 error) *MockQueryStreamSegmentsServer_SendHeader_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_SendHeader_Call) RunAndReturn(run func(metadata.MD) error) *MockQueryStreamSegmentsServer_SendHeader_Call {
_c.Call.Return(run)
return _c
}
// SendMsg provides a mock function with given fields: m
func (_m *MockQueryStreamSegmentsServer) SendMsg(m interface{}) error {
ret := _m.Called(m)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(m)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamSegmentsServer_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg'
type MockQueryStreamSegmentsServer_SendMsg_Call struct {
*mock.Call
}
// SendMsg is a helper method to define mock.On call
// - m interface{}
func (_e *MockQueryStreamSegmentsServer_Expecter) SendMsg(m interface{}) *MockQueryStreamSegmentsServer_SendMsg_Call {
return &MockQueryStreamSegmentsServer_SendMsg_Call{Call: _e.mock.On("SendMsg", m)}
}
func (_c *MockQueryStreamSegmentsServer_SendMsg_Call) Run(run func(m interface{})) *MockQueryStreamSegmentsServer_SendMsg_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(interface{}))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_SendMsg_Call) Return(_a0 error) *MockQueryStreamSegmentsServer_SendMsg_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_SendMsg_Call) RunAndReturn(run func(interface{}) error) *MockQueryStreamSegmentsServer_SendMsg_Call {
_c.Call.Return(run)
return _c
}
// SetHeader provides a mock function with given fields: _a0
func (_m *MockQueryStreamSegmentsServer) SetHeader(_a0 metadata.MD) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamSegmentsServer_SetHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetHeader'
type MockQueryStreamSegmentsServer_SetHeader_Call struct {
*mock.Call
}
// SetHeader is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamSegmentsServer_Expecter) SetHeader(_a0 interface{}) *MockQueryStreamSegmentsServer_SetHeader_Call {
return &MockQueryStreamSegmentsServer_SetHeader_Call{Call: _e.mock.On("SetHeader", _a0)}
}
func (_c *MockQueryStreamSegmentsServer_SetHeader_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamSegmentsServer_SetHeader_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_SetHeader_Call) Return(_a0 error) *MockQueryStreamSegmentsServer_SetHeader_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamSegmentsServer_SetHeader_Call) RunAndReturn(run func(metadata.MD) error) *MockQueryStreamSegmentsServer_SetHeader_Call {
_c.Call.Return(run)
return _c
}
// SetTrailer provides a mock function with given fields: _a0
func (_m *MockQueryStreamSegmentsServer) SetTrailer(_a0 metadata.MD) {
_m.Called(_a0)
}
// MockQueryStreamSegmentsServer_SetTrailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrailer'
type MockQueryStreamSegmentsServer_SetTrailer_Call struct {
*mock.Call
}
// SetTrailer is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamSegmentsServer_Expecter) SetTrailer(_a0 interface{}) *MockQueryStreamSegmentsServer_SetTrailer_Call {
return &MockQueryStreamSegmentsServer_SetTrailer_Call{Call: _e.mock.On("SetTrailer", _a0)}
}
func (_c *MockQueryStreamSegmentsServer_SetTrailer_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamSegmentsServer_SetTrailer_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamSegmentsServer_SetTrailer_Call) Return() *MockQueryStreamSegmentsServer_SetTrailer_Call {
_c.Call.Return()
return _c
}
func (_c *MockQueryStreamSegmentsServer_SetTrailer_Call) RunAndReturn(run func(metadata.MD)) *MockQueryStreamSegmentsServer_SetTrailer_Call {
_c.Call.Return(run)
return _c
}
// NewMockQueryStreamSegmentsServer creates a new instance of MockQueryStreamSegmentsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockQueryStreamSegmentsServer(t interface {
mock.TestingT
Cleanup(func())
}) *MockQueryStreamSegmentsServer {
mock := &MockQueryStreamSegmentsServer{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -0,0 +1,325 @@
// Code generated by mockery v2.32.4. DO NOT EDIT.
package mocks
import (
context "context"
internalpb "github.com/milvus-io/milvus/internal/proto/internalpb"
metadata "google.golang.org/grpc/metadata"
mock "github.com/stretchr/testify/mock"
)
// MockQueryStreamServer is an autogenerated mock type for the QueryNode_QueryStreamServer type
type MockQueryStreamServer struct {
mock.Mock
}
type MockQueryStreamServer_Expecter struct {
mock *mock.Mock
}
func (_m *MockQueryStreamServer) EXPECT() *MockQueryStreamServer_Expecter {
return &MockQueryStreamServer_Expecter{mock: &_m.Mock}
}
// Context provides a mock function with given fields:
func (_m *MockQueryStreamServer) Context() context.Context {
ret := _m.Called()
var r0 context.Context
if rf, ok := ret.Get(0).(func() context.Context); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(context.Context)
}
}
return r0
}
// MockQueryStreamServer_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context'
type MockQueryStreamServer_Context_Call struct {
*mock.Call
}
// Context is a helper method to define mock.On call
func (_e *MockQueryStreamServer_Expecter) Context() *MockQueryStreamServer_Context_Call {
return &MockQueryStreamServer_Context_Call{Call: _e.mock.On("Context")}
}
func (_c *MockQueryStreamServer_Context_Call) Run(run func()) *MockQueryStreamServer_Context_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockQueryStreamServer_Context_Call) Return(_a0 context.Context) *MockQueryStreamServer_Context_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_Context_Call) RunAndReturn(run func() context.Context) *MockQueryStreamServer_Context_Call {
_c.Call.Return(run)
return _c
}
// RecvMsg provides a mock function with given fields: m
func (_m *MockQueryStreamServer) RecvMsg(m interface{}) error {
ret := _m.Called(m)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(m)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamServer_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg'
type MockQueryStreamServer_RecvMsg_Call struct {
*mock.Call
}
// RecvMsg is a helper method to define mock.On call
// - m interface{}
func (_e *MockQueryStreamServer_Expecter) RecvMsg(m interface{}) *MockQueryStreamServer_RecvMsg_Call {
return &MockQueryStreamServer_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)}
}
func (_c *MockQueryStreamServer_RecvMsg_Call) Run(run func(m interface{})) *MockQueryStreamServer_RecvMsg_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(interface{}))
})
return _c
}
func (_c *MockQueryStreamServer_RecvMsg_Call) Return(_a0 error) *MockQueryStreamServer_RecvMsg_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *MockQueryStreamServer_RecvMsg_Call {
_c.Call.Return(run)
return _c
}
// Send provides a mock function with given fields: _a0
func (_m *MockQueryStreamServer) Send(_a0 *internalpb.RetrieveResults) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(*internalpb.RetrieveResults) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamServer_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send'
type MockQueryStreamServer_Send_Call struct {
*mock.Call
}
// Send is a helper method to define mock.On call
// - _a0 *internalpb.RetrieveResults
func (_e *MockQueryStreamServer_Expecter) Send(_a0 interface{}) *MockQueryStreamServer_Send_Call {
return &MockQueryStreamServer_Send_Call{Call: _e.mock.On("Send", _a0)}
}
func (_c *MockQueryStreamServer_Send_Call) Run(run func(_a0 *internalpb.RetrieveResults)) *MockQueryStreamServer_Send_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*internalpb.RetrieveResults))
})
return _c
}
func (_c *MockQueryStreamServer_Send_Call) Return(_a0 error) *MockQueryStreamServer_Send_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_Send_Call) RunAndReturn(run func(*internalpb.RetrieveResults) error) *MockQueryStreamServer_Send_Call {
_c.Call.Return(run)
return _c
}
// SendHeader provides a mock function with given fields: _a0
func (_m *MockQueryStreamServer) SendHeader(_a0 metadata.MD) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamServer_SendHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendHeader'
type MockQueryStreamServer_SendHeader_Call struct {
*mock.Call
}
// SendHeader is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamServer_Expecter) SendHeader(_a0 interface{}) *MockQueryStreamServer_SendHeader_Call {
return &MockQueryStreamServer_SendHeader_Call{Call: _e.mock.On("SendHeader", _a0)}
}
func (_c *MockQueryStreamServer_SendHeader_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamServer_SendHeader_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamServer_SendHeader_Call) Return(_a0 error) *MockQueryStreamServer_SendHeader_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_SendHeader_Call) RunAndReturn(run func(metadata.MD) error) *MockQueryStreamServer_SendHeader_Call {
_c.Call.Return(run)
return _c
}
// SendMsg provides a mock function with given fields: m
func (_m *MockQueryStreamServer) SendMsg(m interface{}) error {
ret := _m.Called(m)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(m)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamServer_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg'
type MockQueryStreamServer_SendMsg_Call struct {
*mock.Call
}
// SendMsg is a helper method to define mock.On call
// - m interface{}
func (_e *MockQueryStreamServer_Expecter) SendMsg(m interface{}) *MockQueryStreamServer_SendMsg_Call {
return &MockQueryStreamServer_SendMsg_Call{Call: _e.mock.On("SendMsg", m)}
}
func (_c *MockQueryStreamServer_SendMsg_Call) Run(run func(m interface{})) *MockQueryStreamServer_SendMsg_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(interface{}))
})
return _c
}
func (_c *MockQueryStreamServer_SendMsg_Call) Return(_a0 error) *MockQueryStreamServer_SendMsg_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_SendMsg_Call) RunAndReturn(run func(interface{}) error) *MockQueryStreamServer_SendMsg_Call {
_c.Call.Return(run)
return _c
}
// SetHeader provides a mock function with given fields: _a0
func (_m *MockQueryStreamServer) SetHeader(_a0 metadata.MD) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockQueryStreamServer_SetHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetHeader'
type MockQueryStreamServer_SetHeader_Call struct {
*mock.Call
}
// SetHeader is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamServer_Expecter) SetHeader(_a0 interface{}) *MockQueryStreamServer_SetHeader_Call {
return &MockQueryStreamServer_SetHeader_Call{Call: _e.mock.On("SetHeader", _a0)}
}
func (_c *MockQueryStreamServer_SetHeader_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamServer_SetHeader_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamServer_SetHeader_Call) Return(_a0 error) *MockQueryStreamServer_SetHeader_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockQueryStreamServer_SetHeader_Call) RunAndReturn(run func(metadata.MD) error) *MockQueryStreamServer_SetHeader_Call {
_c.Call.Return(run)
return _c
}
// SetTrailer provides a mock function with given fields: _a0
func (_m *MockQueryStreamServer) SetTrailer(_a0 metadata.MD) {
_m.Called(_a0)
}
// MockQueryStreamServer_SetTrailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrailer'
type MockQueryStreamServer_SetTrailer_Call struct {
*mock.Call
}
// SetTrailer is a helper method to define mock.On call
// - _a0 metadata.MD
func (_e *MockQueryStreamServer_Expecter) SetTrailer(_a0 interface{}) *MockQueryStreamServer_SetTrailer_Call {
return &MockQueryStreamServer_SetTrailer_Call{Call: _e.mock.On("SetTrailer", _a0)}
}
func (_c *MockQueryStreamServer_SetTrailer_Call) Run(run func(_a0 metadata.MD)) *MockQueryStreamServer_SetTrailer_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(metadata.MD))
})
return _c
}
func (_c *MockQueryStreamServer_SetTrailer_Call) Return() *MockQueryStreamServer_SetTrailer_Call {
_c.Call.Return()
return _c
}
func (_c *MockQueryStreamServer_SetTrailer_Call) RunAndReturn(run func(metadata.MD)) *MockQueryStreamServer_SetTrailer_Call {
_c.Call.Return(run)
return _c
}
// NewMockQueryStreamServer creates a new instance of MockQueryStreamServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockQueryStreamServer(t interface {
mock.TestingT
Cleanup(func())
}) *MockQueryStreamServer {
mock := &MockQueryStreamServer{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -0,0 +1,164 @@
package streamrpc
import (
"context"
"io"
"sync"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
)
type QueryStreamServer interface {
Send(*internalpb.RetrieveResults) error
Context() context.Context
}
type QueryStreamClient interface {
Recv() (*internalpb.RetrieveResults, error)
Context() context.Context
CloseSend() error
}
type QueryFunc func(ctx context.Context, req *querypb.QueryRequest) (QueryStreamClient, error)
type QueryStreamer interface {
AsServer() QueryStreamServer
SetServer(svr QueryStreamServer)
AsClient() QueryStreamClient
SetClient(cli QueryStreamClient)
}
type ConcurrentQueryStreamServer struct {
server QueryStreamServer
mu sync.Mutex
}
func (s *ConcurrentQueryStreamServer) Send(result *internalpb.RetrieveResults) error {
s.mu.Lock()
defer s.mu.Unlock()
return s.server.Send(result)
}
func (s *ConcurrentQueryStreamServer) Context() context.Context {
return s.server.Context()
}
func NewConcurrentQueryStreamServer(srv QueryStreamServer) *ConcurrentQueryStreamServer {
return &ConcurrentQueryStreamServer{
server: srv,
mu: sync.Mutex{},
}
}
// for streaming query rpc
type GrpcQueryStreamer struct {
server QueryStreamServer
client QueryStreamClient
}
func (c *GrpcQueryStreamer) AsServer() QueryStreamServer {
return c.server
}
func (c *GrpcQueryStreamer) AsClient() QueryStreamClient {
return c.client
}
func (c *GrpcQueryStreamer) SetClient(cli QueryStreamClient) {
c.client = cli
}
func (c *GrpcQueryStreamer) SetServer(svr QueryStreamServer) {
c.server = svr
}
func NewGrpcQueryStreamer() QueryStreamer {
return &GrpcQueryStreamer{}
}
// TODO LOCAL SERVER AND CLIENT FOR STANDALONE
// ONLY FOR TEST
type LocalQueryServer struct {
resultCh chan *internalpb.RetrieveResults
ctx context.Context
finishOnce sync.Once
errCh chan error
mu sync.Mutex
}
func (s *LocalQueryServer) Send(result *internalpb.RetrieveResults) error {
select {
case <-s.ctx.Done():
return s.ctx.Err()
default:
s.resultCh <- result
return nil
}
}
func (s *LocalQueryServer) FinishError() error {
return <-s.errCh
}
func (s *LocalQueryServer) Context() context.Context {
return s.ctx
}
func (s *LocalQueryServer) FinishSend(err error) error {
s.finishOnce.Do(func() {
close(s.resultCh)
if err != nil {
s.errCh <- err
} else {
s.errCh <- io.EOF
}
})
return nil
}
type LocalQueryClient struct {
server *LocalQueryServer
resultCh chan *internalpb.RetrieveResults
ctx context.Context
}
func (s *LocalQueryClient) Recv() (*internalpb.RetrieveResults, error) {
select {
case <-s.ctx.Done():
return nil, s.ctx.Err()
default:
result, ok := <-s.resultCh
if !ok {
return nil, s.server.FinishError()
}
return result, nil
}
}
func (s *LocalQueryClient) Context() context.Context {
return s.ctx
}
func (s *LocalQueryClient) CloseSend() error {
return nil
}
func (s *LocalQueryClient) CreateServer() *LocalQueryServer {
s.server = &LocalQueryServer{
resultCh: s.resultCh,
ctx: s.ctx,
mu: sync.Mutex{},
errCh: make(chan error, 1),
}
return s.server
}
func NewLocalQueryClient(ctx context.Context) *LocalQueryClient {
return &LocalQueryClient{
resultCh: make(chan *internalpb.RetrieveResults, 64),
ctx: ctx,
}
}

View File

@ -55,6 +55,30 @@ class TestDeleteParams(TestcaseBase):
# query with deleted ids
collection_w.query(expr, check_task=CheckTasks.check_query_empty)
@pytest.mark.tags(CaseLabel.L0)
@pytest.mark.parametrize('is_binary', [False, True])
def test_delete_entities_with_range(self, is_binary):
"""
target: test delete data from collection
method: 1.create and insert nb with flush
2.load collection
3.delete half of nb
4.query with deleted ids
expected: Query result is empty
"""
# init collection with default_nb default data
collection_w, _, _, ids = self.init_collection_general(prefix, insert_data=True, auto_id=True, is_binary=is_binary)[0:4]
expr = f'{ct.default_int64_field_name} < {ids[half_nb]}'
# delete half of data
del_res = collection_w.delete(expr)[0]
assert del_res.delete_count == half_nb
# This flush will not persist the deleted ids, just delay the time to ensure that queryNode consumes deleteMsg
collection_w.num_entities
# query with deleted ids
collection_w.query(expr, check_task=CheckTasks.check_query_empty)
@pytest.mark.tags(CaseLabel.L2)
def test_delete_without_connection(self):
"""
@ -159,32 +183,18 @@ class TestDeleteParams(TestcaseBase):
collection_w.query(expr, check_task=CheckTasks.check_query_empty)
@pytest.mark.tags(CaseLabel.L1)
def test_delete_expr_non_primary_key(self):
def test_delete_expr_with_vector(self):
"""
target: test delete with non-pk field
method: delete with expr field not pk
target: test delete with vector field
method: delete with expr vector field
expected: raise exception
"""
collection_w = self.init_collection_general(prefix, nb=tmp_nb, insert_data=True, is_all_data_type=True, is_index=True)[0]
exprs = [
f"{ct.default_int32_field_name} in [1]",
f"{ct.default_int16_field_name} in [1]",
f"{ct.default_int8_field_name} in [1]",
f"{ct.default_bool_field_name} in [True]",
f"{ct.default_float_field_name} in [1.0]",
f"{ct.default_double_field_name} in [1.0]",
f"{ct.default_string_field_name} in [ \"0\"]",
f"{ct.default_float_vec_field_name} in [[0.1]]"
]
expr = f"{ct.default_float_vec_field_name} in [[0.1]]"
error = {ct.err_code: 1,
ct.err_msg: f"invalid expression, we only support to delete by pk"}
for expr in exprs:
collection_w.delete(expr, check_task=CheckTasks.err_res, check_items=error)
ct.err_msg: f"failed to create expr plan, expr = {expr}"}
# query
_query_res_tmp_expr = [{ct.default_int64_field_name: 0, ct.default_string_field_name: '0'}]
collection_w.query(tmp_expr, output_fields=[ct.default_string_field_name], check_task=CheckTasks.check_query_results,
check_items={exp_res: _query_res_tmp_expr})
collection_w.delete(expr, check_task=CheckTasks.err_res, check_items=error)
@pytest.mark.tags(CaseLabel.L2)
def test_delete_not_existed_values(self):