From 1dcd9eeb792af819f121fd8b22df7e1b63cab0bc Mon Sep 17 00:00:00 2001 From: jaime Date: Thu, 19 Jan 2023 14:13:43 +0800 Subject: [PATCH] Support rename collection (#21693) Signed-off-by: jaime --- go.mod | 2 +- go.sum | 4 +- internal/core/src/pb/common.pb.cc | 158 ++++++------ internal/core/src/pb/common.pb.h | 1 + internal/datacoord/mock_test.go | 5 + internal/distributed/proxy/service.go | 4 + internal/distributed/proxy/service_test.go | 15 +- .../distributed/rootcoord/client/client.go | 18 ++ internal/distributed/rootcoord/service.go | 4 + .../distributed/rootcoord/service_test.go | 20 +- internal/mocks/mock_rootcoord.go | 47 ++++ internal/proto/root_coord.proto | 2 + internal/proto/rootcoordpb/root_coord.pb.go | 235 ++++++++++-------- internal/proxy/impl.go | 45 +++- internal/proxy/impl_test.go | 58 ++++- internal/proxy/proxy_test.go | 4 + internal/proxy/rootcoord_mock_test.go | 4 + .../rootcoord/drop_collection_task_test.go | 8 +- internal/rootcoord/meta_table.go | 60 ++++- internal/rootcoord/meta_table_test.go | 140 ++++++++++- internal/rootcoord/mock_test.go | 5 + internal/rootcoord/mocks/meta_table.go | 204 +++++++++------ internal/rootcoord/rename_collection_task.go | 27 ++ .../rootcoord/rename_collection_task_test.go | 74 ++++++ internal/rootcoord/root_coord.go | 38 +++ internal/rootcoord/root_coord_test.go | 40 +++ internal/types/types.go | 5 + internal/util/mock/grpc_rootcoord_client.go | 4 + 28 files changed, 937 insertions(+), 294 deletions(-) create mode 100644 internal/rootcoord/rename_collection_task.go create mode 100644 internal/rootcoord/rename_collection_task_test.go diff --git a/go.mod b/go.mod index 6f0fa19913..9825b7e5c8 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/klauspost/compress v1.14.4 github.com/lingdor/stackerror v0.0.0-20191119040541-976d8885ed76 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d - github.com/milvus-io/milvus-proto/go-api v0.0.0-20230110094734-99d76998b0b9 + github.com/milvus-io/milvus-proto/go-api v0.0.0-20230112125535-5f87a812202c github.com/minio/minio-go/v7 v7.0.17 github.com/panjf2000/ants/v2 v2.4.8 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 3aa544eb3c..3300fbe4a8 100644 --- a/go.sum +++ b/go.sum @@ -491,8 +491,8 @@ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyex github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8= github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4= -github.com/milvus-io/milvus-proto/go-api v0.0.0-20230110094734-99d76998b0b9 h1:I7O1+IqGXhFDnzGzh+62/VJOTfLdX7UuM5OteylxOoM= -github.com/milvus-io/milvus-proto/go-api v0.0.0-20230110094734-99d76998b0b9/go.mod h1:148qnlmZ0Fdm1Fq+Mj/OW2uDoEP25g3mjh0vMGtkgmk= +github.com/milvus-io/milvus-proto/go-api v0.0.0-20230112125535-5f87a812202c h1:74uRPm5WWagMe8bItOQ8QFuXcrUIWuWGAQ1GrwVM4J4= +github.com/milvus-io/milvus-proto/go-api v0.0.0-20230112125535-5f87a812202c/go.mod h1:148qnlmZ0Fdm1Fq+Mj/OW2uDoEP25g3mjh0vMGtkgmk= github.com/milvus-io/pulsar-client-go v0.6.10 h1:eqpJjU+/QX0iIhEo3nhOqMNXL+TyInAs1IAHZCrCM/A= github.com/milvus-io/pulsar-client-go v0.6.10/go.mod h1:lQqCkgwDF8YFYjKA+zOheTk1tev2B+bKj5j7+nm8M1w= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= diff --git a/internal/core/src/pb/common.pb.cc b/internal/core/src/pb/common.pb.cc index acdfaf6ac6..8da8ef9393 100644 --- a/internal/core/src/pb/common.pb.cc +++ b/internal/core/src/pb/common.pb.cc @@ -372,96 +372,97 @@ const char descriptor_table_protodef_common_2eproto[] PROTOBUF_SECTION_VARIABLE( "\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*>\n\017Placeholde" "rType\022\010\n\004None\020\000\022\020\n\014BinaryVector\020d\022\017\n\013Flo" - "atVector\020e*\251\016\n\007MsgType\022\r\n\tUndefined\020\000\022\024\n" + "atVector\020e*\277\016\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\022DescribeCollection" "\020g\022\023\n\017ShowCollections\020h\022\024\n\020GetSystemConf" "igs\020i\022\022\n\016LoadCollection\020j\022\025\n\021ReleaseColl" "ection\020k\022\017\n\013CreateAlias\020l\022\r\n\tDropAlias\020m" "\022\016\n\nAlterAlias\020n\022\023\n\017AlterCollection\020o\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\016ShowPartitions\020\314\001\022\023\n\016LoadPartition" - "s\020\315\001\022\026\n\021ReleasePartitions\020\316\001\022\021\n\014ShowSegm" - "ents\020\372\001\022\024\n\017DescribeSegment\020\373\001\022\021\n\014LoadSeg" - "ments\020\374\001\022\024\n\017ReleaseSegments\020\375\001\022\024\n\017Handof" - "fSegments\020\376\001\022\030\n\023LoadBalanceSegments\020\377\001\022\025" - "\n\020DescribeSegments\020\200\002\022\020\n\013CreateIndex\020\254\002\022" - "\022\n\rDescribeIndex\020\255\002\022\016\n\tDropIndex\020\256\002\022\013\n\006I" - "nsert\020\220\003\022\013\n\006Delete\020\221\003\022\n\n\005Flush\020\222\003\022\027\n\022Res" - "endSegmentStats\020\223\003\022\013\n\006Upsert\020\224\003\022\013\n\006Searc" - "h\020\364\003\022\021\n\014SearchResult\020\365\003\022\022\n\rGetIndexState" - "\020\366\003\022\032\n\025GetIndexBuildProgress\020\367\003\022\034\n\027GetCo" - "llectionStatistics\020\370\003\022\033\n\026GetPartitionSta" - "tistics\020\371\003\022\r\n\010Retrieve\020\372\003\022\023\n\016RetrieveRes" - "ult\020\373\003\022\024\n\017WatchDmChannels\020\374\003\022\025\n\020RemoveDm" - "Channels\020\375\003\022\027\n\022WatchQueryChannels\020\376\003\022\030\n\023" - "RemoveQueryChannels\020\377\003\022\035\n\030SealedSegments" - "ChangeInfo\020\200\004\022\027\n\022WatchDeltaChannels\020\201\004\022\024" - "\n\017GetShardLeaders\020\202\004\022\020\n\013GetReplicas\020\203\004\022\023" - "\n\016UnsubDmChannel\020\204\004\022\024\n\017GetDistribution\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\017GetRecoveryInfo\020\332" - "\004\022\024\n\017GetSegmentState\020\333\004\022\r\n\010TimeTick\020\260\t\022\023" - "\n\016QueryNodeStats\020\261\t\022\016\n\tLoadIndex\020\262\t\022\016\n\tR" - "equestID\020\263\t\022\017\n\nRequestTSO\020\264\t\022\024\n\017Allocate" - "Segment\020\265\t\022\026\n\021SegmentStatistics\020\266\t\022\025\n\020Se" - "gmentFlushDone\020\267\t\022\017\n\nDataNodeTt\020\270\t\022\025\n\020Cr" - "eateCredential\020\334\013\022\022\n\rGetCredential\020\335\013\022\025\n" - "\020DeleteCredential\020\336\013\022\025\n\020UpdateCredential" - "\020\337\013\022\026\n\021ListCredUsernames\020\340\013\022\017\n\nCreateRol" - "e\020\300\014\022\r\n\010DropRole\020\301\014\022\024\n\017OperateUserRole\020\302" - "\014\022\017\n\nSelectRole\020\303\014\022\017\n\nSelectUser\020\304\014\022\023\n\016S" - "electResource\020\305\014\022\025\n\020OperatePrivilege\020\306\014\022" - "\020\n\013SelectGrant\020\307\014\022\033\n\026RefreshPolicyInfoCa" - "che\020\310\014\022\017\n\nListPolicy\020\311\014\022\030\n\023CreateResourc" - "eGroup\020\244\r\022\026\n\021DropResourceGroup\020\245\r\022\026\n\021Lis" - "tResourceGroup\020\246\r\022\032\n\025DescribeResourceGro" - "up\020\247\r\022\021\n\014TransferNode\020\250\r\022\024\n\017TransferRepl" - "ica\020\251\r*\"\n\007DslType\022\007\n\003Dsl\020\000\022\016\n\nBoolExprV1" - "\020\001*B\n\017CompactionState\022\021\n\rUndefiedState\020\000" - "\022\r\n\tExecuting\020\001\022\r\n\tCompleted\020\002*X\n\020Consis" - "tencyLevel\022\n\n\006Strong\020\000\022\013\n\007Session\020\001\022\013\n\007B" - "ounded\020\002\022\016\n\nEventually\020\003\022\016\n\nCustomized\020\004" - "*\236\001\n\013ImportState\022\021\n\rImportPending\020\000\022\020\n\014I" - "mportFailed\020\001\022\021\n\rImportStarted\020\002\022\023\n\017Impo" - "rtPersisted\020\005\022\021\n\rImportFlushed\020\010\022\023\n\017Impo" - "rtCompleted\020\006\022\032\n\026ImportFailedAndCleaned\020" - "\007*2\n\nObjectType\022\016\n\nCollection\020\000\022\n\n\006Globa" - "l\020\001\022\010\n\004User\020\002*\233\005\n\017ObjectPrivilege\022\020\n\014Pri" - "vilegeAll\020\000\022\035\n\031PrivilegeCreateCollection" - "\020\001\022\033\n\027PrivilegeDropCollection\020\002\022\037\n\033Privi" - "legeDescribeCollection\020\003\022\034\n\030PrivilegeSho" - "wCollections\020\004\022\021\n\rPrivilegeLoad\020\005\022\024\n\020Pri" - "vilegeRelease\020\006\022\027\n\023PrivilegeCompaction\020\007" - "\022\023\n\017PrivilegeInsert\020\010\022\023\n\017PrivilegeDelete" - "\020\t\022\032\n\026PrivilegeGetStatistics\020\n\022\030\n\024Privil" - "egeCreateIndex\020\013\022\030\n\024PrivilegeIndexDetail" - "\020\014\022\026\n\022PrivilegeDropIndex\020\r\022\023\n\017PrivilegeS" - "earch\020\016\022\022\n\016PrivilegeFlush\020\017\022\022\n\016Privilege" - "Query\020\020\022\030\n\024PrivilegeLoadBalance\020\021\022\023\n\017Pri" - "vilegeImport\020\022\022\034\n\030PrivilegeCreateOwnersh" - "ip\020\023\022\027\n\023PrivilegeUpdateUser\020\024\022\032\n\026Privile" - "geDropOwnership\020\025\022\034\n\030PrivilegeSelectOwne" - "rship\020\026\022\034\n\030PrivilegeManageOwnership\020\027\022\027\n" - "\023PrivilegeSelectUser\020\030\022\023\n\017PrivilegeUpser" - "t\020\031*S\n\tStateCode\022\020\n\014Initializing\020\000\022\013\n\007He" - "althy\020\001\022\014\n\010Abnormal\020\002\022\013\n\007StandBy\020\003\022\014\n\010St" - "opping\020\004*c\n\tLoadState\022\025\n\021LoadStateNotExi" - "st\020\000\022\024\n\020LoadStateNotLoad\020\001\022\024\n\020LoadStateL" - "oading\020\002\022\023\n\017LoadStateLoaded\020\003:^\n\021privile" - "ge_ext_obj\022\037.google.protobuf.MessageOpti" - "ons\030\351\007 \001(\0132!.milvus.proto.common.Privile" - "geExtBf\n\016io.milvus.grpcB\013CommonProtoP\001Z1" - "github.com/milvus-io/milvus-proto/go-api" - "/commonpb\240\001\001\252\002\016IO.Milvus.Grpcb\006proto3" + "\020RenameCollection\020p\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\016ShowPartitio" + "ns\020\314\001\022\023\n\016LoadPartitions\020\315\001\022\026\n\021ReleasePar" + "titions\020\316\001\022\021\n\014ShowSegments\020\372\001\022\024\n\017Describ" + "eSegment\020\373\001\022\021\n\014LoadSegments\020\374\001\022\024\n\017Releas" + "eSegments\020\375\001\022\024\n\017HandoffSegments\020\376\001\022\030\n\023Lo" + "adBalanceSegments\020\377\001\022\025\n\020DescribeSegments" + "\020\200\002\022\020\n\013CreateIndex\020\254\002\022\022\n\rDescribeIndex\020\255" + "\002\022\016\n\tDropIndex\020\256\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\022ResendSegmentStats\020\223\003" + "\022\013\n\006Upsert\020\224\003\022\013\n\006Search\020\364\003\022\021\n\014SearchResu" + "lt\020\365\003\022\022\n\rGetIndexState\020\366\003\022\032\n\025GetIndexBui" + "ldProgress\020\367\003\022\034\n\027GetCollectionStatistics" + "\020\370\003\022\033\n\026GetPartitionStatistics\020\371\003\022\r\n\010Retr" + "ieve\020\372\003\022\023\n\016RetrieveResult\020\373\003\022\024\n\017WatchDmC" + "hannels\020\374\003\022\025\n\020RemoveDmChannels\020\375\003\022\027\n\022Wat" + "chQueryChannels\020\376\003\022\030\n\023RemoveQueryChannel" + "s\020\377\003\022\035\n\030SealedSegmentsChangeInfo\020\200\004\022\027\n\022W" + "atchDeltaChannels\020\201\004\022\024\n\017GetShardLeaders\020" + "\202\004\022\020\n\013GetReplicas\020\203\004\022\023\n\016UnsubDmChannel\020\204" + "\004\022\024\n\017GetDistribution\020\205\004\022\025\n\020SyncDistribut" + "ion\020\206\004\022\020\n\013SegmentInfo\020\330\004\022\017\n\nSystemInfo\020\331" + "\004\022\024\n\017GetRecoveryInfo\020\332\004\022\024\n\017GetSegmentSta" + "te\020\333\004\022\r\n\010TimeTick\020\260\t\022\023\n\016QueryNodeStats\020\261" + "\t\022\016\n\tLoadIndex\020\262\t\022\016\n\tRequestID\020\263\t\022\017\n\nReq" + "uestTSO\020\264\t\022\024\n\017AllocateSegment\020\265\t\022\026\n\021Segm" + "entStatistics\020\266\t\022\025\n\020SegmentFlushDone\020\267\t\022" + "\017\n\nDataNodeTt\020\270\t\022\025\n\020CreateCredential\020\334\013\022" + "\022\n\rGetCredential\020\335\013\022\025\n\020DeleteCredential\020" + "\336\013\022\025\n\020UpdateCredential\020\337\013\022\026\n\021ListCredUse" + "rnames\020\340\013\022\017\n\nCreateRole\020\300\014\022\r\n\010DropRole\020\301" + "\014\022\024\n\017OperateUserRole\020\302\014\022\017\n\nSelectRole\020\303\014" + "\022\017\n\nSelectUser\020\304\014\022\023\n\016SelectResource\020\305\014\022\025" + "\n\020OperatePrivilege\020\306\014\022\020\n\013SelectGrant\020\307\014\022" + "\033\n\026RefreshPolicyInfoCache\020\310\014\022\017\n\nListPoli" + "cy\020\311\014\022\030\n\023CreateResourceGroup\020\244\r\022\026\n\021DropR" + "esourceGroup\020\245\r\022\026\n\021ListResourceGroup\020\246\r\022" + "\032\n\025DescribeResourceGroup\020\247\r\022\021\n\014TransferN" + "ode\020\250\r\022\024\n\017TransferReplica\020\251\r*\"\n\007DslType\022" + "\007\n\003Dsl\020\000\022\016\n\nBoolExprV1\020\001*B\n\017CompactionSt" + "ate\022\021\n\rUndefiedState\020\000\022\r\n\tExecuting\020\001\022\r\n" + "\tCompleted\020\002*X\n\020ConsistencyLevel\022\n\n\006Stro" + "ng\020\000\022\013\n\007Session\020\001\022\013\n\007Bounded\020\002\022\016\n\nEventu" + "ally\020\003\022\016\n\nCustomized\020\004*\236\001\n\013ImportState\022\021" + "\n\rImportPending\020\000\022\020\n\014ImportFailed\020\001\022\021\n\rI" + "mportStarted\020\002\022\023\n\017ImportPersisted\020\005\022\021\n\rI" + "mportFlushed\020\010\022\023\n\017ImportCompleted\020\006\022\032\n\026I" + "mportFailedAndCleaned\020\007*2\n\nObjectType\022\016\n" + "\nCollection\020\000\022\n\n\006Global\020\001\022\010\n\004User\020\002*\233\005\n\017" + "ObjectPrivilege\022\020\n\014PrivilegeAll\020\000\022\035\n\031Pri" + "vilegeCreateCollection\020\001\022\033\n\027PrivilegeDro" + "pCollection\020\002\022\037\n\033PrivilegeDescribeCollec" + "tion\020\003\022\034\n\030PrivilegeShowCollections\020\004\022\021\n\r" + "PrivilegeLoad\020\005\022\024\n\020PrivilegeRelease\020\006\022\027\n" + "\023PrivilegeCompaction\020\007\022\023\n\017PrivilegeInser" + "t\020\010\022\023\n\017PrivilegeDelete\020\t\022\032\n\026PrivilegeGet" + "Statistics\020\n\022\030\n\024PrivilegeCreateIndex\020\013\022\030" + "\n\024PrivilegeIndexDetail\020\014\022\026\n\022PrivilegeDro" + "pIndex\020\r\022\023\n\017PrivilegeSearch\020\016\022\022\n\016Privile" + "geFlush\020\017\022\022\n\016PrivilegeQuery\020\020\022\030\n\024Privile" + "geLoadBalance\020\021\022\023\n\017PrivilegeImport\020\022\022\034\n\030" + "PrivilegeCreateOwnership\020\023\022\027\n\023PrivilegeU" + "pdateUser\020\024\022\032\n\026PrivilegeDropOwnership\020\025\022" + "\034\n\030PrivilegeSelectOwnership\020\026\022\034\n\030Privile" + "geManageOwnership\020\027\022\027\n\023PrivilegeSelectUs" + "er\020\030\022\023\n\017PrivilegeUpsert\020\031*S\n\tStateCode\022\020" + "\n\014Initializing\020\000\022\013\n\007Healthy\020\001\022\014\n\010Abnorma" + "l\020\002\022\013\n\007StandBy\020\003\022\014\n\010Stopping\020\004*c\n\tLoadSt" + "ate\022\025\n\021LoadStateNotExist\020\000\022\024\n\020LoadStateN" + "otLoad\020\001\022\024\n\020LoadStateLoading\020\002\022\023\n\017LoadSt" + "ateLoaded\020\003:^\n\021privilege_ext_obj\022\037.googl" + "e.protobuf.MessageOptions\030\351\007 \001(\0132!.milvu" + "s.proto.common.PrivilegeExtBf\n\016io.milvus" + ".grpcB\013CommonProtoP\001Z1github.com/milvus-" + "io/milvus-proto/go-api/commonpb\240\001\001\252\002\016IO." + "Milvus.Grpcb\006proto3" ; 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, 5837, descriptor_table_protodef_common_2eproto, + false, false, 5859, descriptor_table_protodef_common_2eproto, "common.proto", &descriptor_table_common_2eproto_once, descriptor_table_common_2eproto_deps, 1, 11, schemas, file_default_instances, TableStruct_common_2eproto::offsets, @@ -618,6 +619,7 @@ bool MsgType_IsValid(int value) { case 109: case 110: case 111: + case 112: case 200: case 201: case 202: diff --git a/internal/core/src/pb/common.pb.h b/internal/core/src/pb/common.pb.h index e6fb0e1122..2aba9850c4 100644 --- a/internal/core/src/pb/common.pb.h +++ b/internal/core/src/pb/common.pb.h @@ -282,6 +282,7 @@ enum MsgType : int { DropAlias = 109, AlterAlias = 110, AlterCollection = 111, + RenameCollection = 112, CreatePartition = 200, DropPartition = 201, HasPartition = 202, diff --git a/internal/datacoord/mock_test.go b/internal/datacoord/mock_test.go index 8049fc8539..4e3052fd99 100644 --- a/internal/datacoord/mock_test.go +++ b/internal/datacoord/mock_test.go @@ -368,6 +368,11 @@ type mockRootCoordService struct { cnt int64 } +func (m *mockRootCoordService) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + //TODO implement me + panic("implement me") +} + func (m *mockRootCoordService) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) { panic("implement me") } diff --git a/internal/distributed/proxy/service.go b/internal/distributed/proxy/service.go index d169d8afcc..7de66fd887 100644 --- a/internal/distributed/proxy/service.go +++ b/internal/distributed/proxy/service.go @@ -864,6 +864,10 @@ func (s *Server) CheckHealth(ctx context.Context, request *milvuspb.CheckHealthR return s.proxy.CheckHealth(ctx, request) } +func (s *Server) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return s.proxy.RenameCollection(ctx, req) +} + func (s *Server) CreateResourceGroup(ctx context.Context, req *milvuspb.CreateResourceGroupRequest) (*commonpb.Status, error) { return nil, nil } diff --git a/internal/distributed/proxy/service_test.go b/internal/distributed/proxy/service_test.go index cdf5878229..574d96d8c6 100644 --- a/internal/distributed/proxy/service_test.go +++ b/internal/distributed/proxy/service_test.go @@ -289,7 +289,11 @@ func (m *MockRootCoord) CheckHealth(ctx context.Context, req *milvuspb.CheckHeal }, nil } -// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +func (m *MockRootCoord) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return nil, nil +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type MockQueryCoord struct { MockBase initErr error @@ -935,6 +939,10 @@ func (m *MockProxy) ListResourceGroup(ctx context.Context, req *milvuspb.ListRes return nil, nil } +func (m *MockProxy) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return nil, nil +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type WaitOption struct { @@ -1367,6 +1375,11 @@ func Test_NewServer(t *testing.T) { assert.Nil(t, err) }) + t.Run("RenameCollection", func(t *testing.T) { + _, err := server.RenameCollection(ctx, nil) + assert.Nil(t, err) + }) + err = server.Stop() assert.Nil(t, err) diff --git a/internal/distributed/rootcoord/client/client.go b/internal/distributed/rootcoord/client/client.go index 2781df6ec3..3433133c08 100644 --- a/internal/distributed/rootcoord/client/client.go +++ b/internal/distributed/rootcoord/client/client.go @@ -894,3 +894,21 @@ func (c *Client) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthReque } return ret.(*milvuspb.CheckHealthResponse), err } + +func (c *Client) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + req = typeutil.Clone(req) + commonpbutil.UpdateMsgBase( + req.GetBase(), + commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.sess.ServerID)), + ) + ret, err := c.grpcClient.ReCall(ctx, func(client rootcoordpb.RootCoordClient) (any, error) { + if !funcutil.CheckCtxValid(ctx) { + return nil, ctx.Err() + } + return client.RenameCollection(ctx, req) + }) + if err != nil { + return nil, err + } + return ret.(*commonpb.Status), err +} diff --git a/internal/distributed/rootcoord/service.go b/internal/distributed/rootcoord/service.go index cbe083f2bb..869786b841 100644 --- a/internal/distributed/rootcoord/service.go +++ b/internal/distributed/rootcoord/service.go @@ -480,3 +480,7 @@ func (s *Server) ListPolicy(ctx context.Context, request *internalpb.ListPolicyR func (s *Server) AlterCollection(ctx context.Context, request *milvuspb.AlterCollectionRequest) (*commonpb.Status, error) { return s.rootCoord.AlterCollection(ctx, request) } + +func (s *Server) RenameCollection(ctx context.Context, request *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return s.rootCoord.RenameCollection(ctx, request) +} diff --git a/internal/distributed/rootcoord/service_test.go b/internal/distributed/rootcoord/service_test.go index 9751c58d5c..68dd1c1398 100644 --- a/internal/distributed/rootcoord/service_test.go +++ b/internal/distributed/rootcoord/service_test.go @@ -31,7 +31,6 @@ import ( "github.com/milvus-io/milvus-proto/go-api/commonpb" "github.com/milvus-io/milvus-proto/go-api/milvuspb" - "github.com/milvus-io/milvus/internal/proto/proxypb" "github.com/milvus-io/milvus/internal/rootcoord" "github.com/milvus-io/milvus/internal/types" "github.com/milvus-io/milvus/internal/util/etcd" @@ -39,19 +38,14 @@ import ( "github.com/milvus-io/milvus/internal/util/sessionutil" ) -type proxyMock struct { - types.Proxy - invalidateCollectionMetaCache func(ctx context.Context, request *proxypb.InvalidateCollMetaCacheRequest) (*commonpb.Status, error) -} - -func (p *proxyMock) InvalidateCollectionMetaCache(ctx context.Context, request *proxypb.InvalidateCollMetaCacheRequest) (*commonpb.Status, error) { - return p.invalidateCollectionMetaCache(ctx, request) -} - type mockCore struct { types.RootCoordComponent } +func (m *mockCore) RenameCollection(ctx context.Context, request *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}, nil +} + func (m *mockCore) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) { return &milvuspb.CheckHealthResponse{ IsHealthy: true, @@ -194,9 +188,13 @@ func TestRun(t *testing.T) { assert.Equal(t, true, ret.IsHealthy) }) + t.Run("RenameCollection", func(t *testing.T) { + _, err := svr.RenameCollection(ctx, nil) + assert.Nil(t, err) + }) + err = svr.Stop() assert.Nil(t, err) - } func TestServerRun_DataCoordClientInitErr(t *testing.T) { diff --git a/internal/mocks/mock_rootcoord.go b/internal/mocks/mock_rootcoord.go index 8a4e0dcb0f..a7869a9576 100644 --- a/internal/mocks/mock_rootcoord.go +++ b/internal/mocks/mock_rootcoord.go @@ -1604,6 +1604,53 @@ func (_c *RootCoord_Register_Call) Return(_a0 error) *RootCoord_Register_Call { return _c } +// RenameCollection provides a mock function with given fields: ctx, req +func (_m *RootCoord) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + ret := _m.Called(ctx, req) + + var r0 *commonpb.Status + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.RenameCollectionRequest) *commonpb.Status); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*commonpb.Status) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.RenameCollectionRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RootCoord_RenameCollection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenameCollection' +type RootCoord_RenameCollection_Call struct { + *mock.Call +} + +// RenameCollection is a helper method to define mock.On call +// - ctx context.Context +// - req *milvuspb.RenameCollectionRequest +func (_e *RootCoord_Expecter) RenameCollection(ctx interface{}, req interface{}) *RootCoord_RenameCollection_Call { + return &RootCoord_RenameCollection_Call{Call: _e.mock.On("RenameCollection", ctx, req)} +} + +func (_c *RootCoord_RenameCollection_Call) Run(run func(ctx context.Context, req *milvuspb.RenameCollectionRequest)) *RootCoord_RenameCollection_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*milvuspb.RenameCollectionRequest)) + }) + return _c +} + +func (_c *RootCoord_RenameCollection_Call) Return(_a0 *commonpb.Status, _a1 error) *RootCoord_RenameCollection_Call { + _c.Call.Return(_a0, _a1) + return _c +} + // ReportImport provides a mock function with given fields: ctx, req func (_m *RootCoord) ReportImport(ctx context.Context, req *rootcoordpb.ImportResult) (*commonpb.Status, error) { ret := _m.Called(ctx, req) diff --git a/internal/proto/root_coord.proto b/internal/proto/root_coord.proto index 3d59617611..8783c007da 100644 --- a/internal/proto/root_coord.proto +++ b/internal/proto/root_coord.proto @@ -139,6 +139,8 @@ service RootCoord { rpc ListPolicy(internal.ListPolicyRequest) returns (internal.ListPolicyResponse) {} rpc CheckHealth(milvus.CheckHealthRequest) returns (milvus.CheckHealthResponse) {} + + rpc RenameCollection(milvus.RenameCollectionRequest) returns (common.Status) {} } message AllocTimestampRequest { diff --git a/internal/proto/rootcoordpb/root_coord.pb.go b/internal/proto/rootcoordpb/root_coord.pb.go index 9546a8674b..6b4ba381bb 100644 --- a/internal/proto/rootcoordpb/root_coord.pb.go +++ b/internal/proto/rootcoordpb/root_coord.pb.go @@ -674,105 +674,106 @@ func init() { func init() { proto.RegisterFile("root_coord.proto", fileDescriptor_4513485a144f6b06) } var fileDescriptor_4513485a144f6b06 = []byte{ - // 1557 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5b, 0x93, 0xda, 0x36, - 0x14, 0x0e, 0x90, 0xbd, 0x1d, 0x58, 0xd8, 0x68, 0x72, 0xa1, 0x24, 0x6d, 0x09, 0x49, 0x1b, 0x72, - 0x63, 0xd3, 0xcd, 0x4c, 0x9a, 0xe6, 0x2d, 0x0b, 0x99, 0x0d, 0xd3, 0xee, 0x64, 0x6b, 0x92, 0x4e, - 0x7a, 0xd9, 0xa1, 0xc2, 0x56, 0xc0, 0xb3, 0xc6, 0x22, 0x92, 0xd8, 0xcb, 0xf4, 0xa1, 0xd3, 0x99, - 0xbe, 0xf7, 0x3f, 0xb5, 0x3f, 0xa5, 0xbf, 0xa1, 0xef, 0x1d, 0x59, 0xb6, 0xb0, 0x8d, 0xcd, 0x7a, - 0x93, 0xb4, 0x6f, 0x48, 0xfa, 0xfc, 0x7d, 0x47, 0xe7, 0x22, 0x1d, 0x01, 0x1b, 0x8c, 0x52, 0xd1, - 0x37, 0x29, 0x65, 0x56, 0x6b, 0xc2, 0xa8, 0xa0, 0xe8, 0xf2, 0xd8, 0x76, 0x0e, 0xa7, 0x5c, 0x8d, - 0x5a, 0x72, 0xd9, 0x5b, 0xad, 0x95, 0x4c, 0x3a, 0x1e, 0x53, 0x57, 0xcd, 0xd7, 0x4a, 0x61, 0x54, - 0xad, 0x6c, 0xbb, 0x82, 0x30, 0x17, 0x3b, 0xfe, 0xb8, 0x38, 0x61, 0xf4, 0xf8, 0xc4, 0x1f, 0x54, - 0x88, 0x30, 0xad, 0xfe, 0x98, 0x08, 0xac, 0x26, 0x1a, 0x7d, 0xb8, 0xf4, 0xd4, 0x71, 0xa8, 0xf9, - 0xd2, 0x1e, 0x13, 0x2e, 0xf0, 0x78, 0x62, 0x90, 0xb7, 0x53, 0xc2, 0x05, 0x7a, 0x00, 0xe7, 0x07, - 0x98, 0x93, 0x6a, 0xae, 0x9e, 0x6b, 0x16, 0xb7, 0xae, 0xb5, 0x22, 0x96, 0xf8, 0xf2, 0xbb, 0x7c, - 0xb8, 0x8d, 0x39, 0x31, 0x3c, 0x24, 0xba, 0x08, 0x4b, 0x26, 0x9d, 0xba, 0xa2, 0x5a, 0xa8, 0xe7, - 0x9a, 0xeb, 0x86, 0x1a, 0x34, 0x7e, 0xcb, 0xc1, 0xe5, 0xb8, 0x02, 0x9f, 0x50, 0x97, 0x13, 0xf4, - 0x10, 0x96, 0xb9, 0xc0, 0x62, 0xca, 0x7d, 0x91, 0xab, 0x89, 0x22, 0x3d, 0x0f, 0x62, 0xf8, 0x50, - 0x74, 0x0d, 0xd6, 0x44, 0xc0, 0x54, 0xcd, 0xd7, 0x73, 0xcd, 0xf3, 0xc6, 0x6c, 0x22, 0xc5, 0x86, - 0xd7, 0x50, 0xf6, 0x4c, 0xe8, 0x76, 0x3e, 0xc0, 0xee, 0xf2, 0x61, 0x66, 0x07, 0x2a, 0x9a, 0xf9, - 0x7d, 0x76, 0x55, 0x86, 0x7c, 0xb7, 0xe3, 0x51, 0x17, 0x8c, 0x7c, 0xb7, 0x93, 0xb2, 0x8f, 0x3f, - 0xf3, 0x50, 0xea, 0x8e, 0x27, 0x94, 0x09, 0x83, 0xf0, 0xa9, 0x23, 0xde, 0x4d, 0xeb, 0x0a, 0xac, - 0x08, 0xcc, 0x0f, 0xfa, 0xb6, 0xe5, 0x0b, 0x2e, 0xcb, 0x61, 0xd7, 0x42, 0x9f, 0x42, 0xd1, 0xc2, - 0x02, 0xbb, 0xd4, 0x22, 0x72, 0xb1, 0xe0, 0x2d, 0x42, 0x30, 0xd5, 0xb5, 0xd0, 0x23, 0x58, 0x92, - 0x1c, 0xa4, 0x7a, 0xbe, 0x9e, 0x6b, 0x96, 0xb7, 0xea, 0x89, 0x6a, 0xca, 0x40, 0xa9, 0x49, 0x0c, - 0x05, 0x47, 0x35, 0x58, 0xe5, 0x64, 0x38, 0x26, 0xae, 0xe0, 0xd5, 0xa5, 0x7a, 0xa1, 0x59, 0x30, - 0xf4, 0x18, 0x7d, 0x04, 0xab, 0x78, 0x2a, 0x68, 0xdf, 0xb6, 0x78, 0x75, 0xd9, 0x5b, 0x5b, 0x91, - 0xe3, 0xae, 0xc5, 0xd1, 0x55, 0x58, 0x63, 0xf4, 0xa8, 0xaf, 0x1c, 0xb1, 0xe2, 0x59, 0xb3, 0xca, - 0xe8, 0x51, 0x5b, 0x8e, 0xd1, 0x97, 0xb0, 0x64, 0xbb, 0x6f, 0x28, 0xaf, 0xae, 0xd6, 0x0b, 0xcd, - 0xe2, 0xd6, 0xf5, 0x44, 0x5b, 0xbe, 0x26, 0x27, 0xdf, 0x61, 0x67, 0x4a, 0xf6, 0xb0, 0xcd, 0x0c, - 0x85, 0x6f, 0xfc, 0x91, 0x83, 0x2b, 0x1d, 0xc2, 0x4d, 0x66, 0x0f, 0x48, 0xcf, 0xb7, 0xe2, 0xdd, - 0xd3, 0xa2, 0x01, 0x25, 0x93, 0x3a, 0x0e, 0x31, 0x85, 0x4d, 0x5d, 0x1d, 0xc2, 0xc8, 0x1c, 0xfa, - 0x04, 0xc0, 0xdf, 0x6e, 0xb7, 0xc3, 0xab, 0x05, 0x6f, 0x93, 0xa1, 0x99, 0xc6, 0x14, 0x2a, 0xbe, - 0x21, 0x92, 0xb8, 0xeb, 0xbe, 0xa1, 0x73, 0xb4, 0xb9, 0x04, 0xda, 0x3a, 0x14, 0x27, 0x98, 0x09, - 0x3b, 0xa2, 0x1c, 0x9e, 0x92, 0xb5, 0xa2, 0x65, 0xfc, 0x70, 0xce, 0x26, 0x1a, 0x7f, 0xe7, 0xa1, - 0xe4, 0xeb, 0x4a, 0x4d, 0x8e, 0x3a, 0xb0, 0x26, 0xf7, 0xd4, 0x97, 0x7e, 0xf2, 0x5d, 0x70, 0xab, - 0x95, 0x7c, 0x02, 0xb5, 0x62, 0x06, 0x1b, 0xab, 0x83, 0xc0, 0xf4, 0x0e, 0x14, 0x6d, 0xd7, 0x22, - 0xc7, 0x7d, 0x15, 0x9e, 0xbc, 0x17, 0x9e, 0x1b, 0x51, 0x1e, 0x79, 0x0a, 0xb5, 0xb4, 0xb6, 0x45, - 0x8e, 0x3d, 0x0e, 0xb0, 0x83, 0x9f, 0x1c, 0x11, 0xb8, 0x40, 0x8e, 0x05, 0xc3, 0xfd, 0x30, 0x57, - 0xc1, 0xe3, 0xfa, 0xea, 0x14, 0x9b, 0x3c, 0x82, 0xd6, 0x33, 0xf9, 0xb5, 0xe6, 0xe6, 0xcf, 0x5c, - 0xc1, 0x4e, 0x8c, 0x0a, 0x89, 0xce, 0xd6, 0x7e, 0x86, 0x8b, 0x49, 0x40, 0xb4, 0x01, 0x85, 0x03, - 0x72, 0xe2, 0xbb, 0x5d, 0xfe, 0x44, 0x5b, 0xb0, 0x74, 0x28, 0x53, 0xc9, 0xf3, 0xf3, 0x5c, 0x6e, - 0x78, 0x1b, 0x9a, 0xed, 0x44, 0x41, 0x9f, 0xe4, 0x1f, 0xe7, 0x1a, 0x7f, 0xe5, 0xa1, 0x3a, 0x9f, - 0x6e, 0xef, 0x73, 0x56, 0x64, 0x49, 0xb9, 0x21, 0xac, 0xfb, 0x81, 0x8e, 0xb8, 0x6e, 0x3b, 0xcd, - 0x75, 0x69, 0x16, 0x46, 0x7c, 0xaa, 0x7c, 0x58, 0xe2, 0xa1, 0xa9, 0x1a, 0x81, 0x0b, 0x73, 0x90, - 0x04, 0xef, 0x3d, 0x89, 0x7a, 0xef, 0x66, 0x96, 0x10, 0x86, 0xbd, 0x68, 0xc1, 0xc5, 0x1d, 0x22, - 0xda, 0x8c, 0x58, 0xc4, 0x15, 0x36, 0x76, 0xde, 0xbd, 0x60, 0x6b, 0xb0, 0x3a, 0xe5, 0xf2, 0x7e, - 0x1c, 0x2b, 0x63, 0xd6, 0x0c, 0x3d, 0x6e, 0xfc, 0x9e, 0x83, 0x4b, 0x31, 0x99, 0xf7, 0x09, 0xd4, - 0x02, 0x29, 0xb9, 0x36, 0xc1, 0x9c, 0x1f, 0x51, 0xa6, 0x0e, 0xda, 0x35, 0x43, 0x8f, 0xb7, 0xfe, - 0xb9, 0x0e, 0x6b, 0x06, 0xa5, 0xa2, 0x2d, 0x5d, 0x82, 0x1c, 0x40, 0xd2, 0x26, 0x3a, 0x9e, 0x50, - 0x97, 0xb8, 0xea, 0x60, 0xe5, 0xa8, 0x15, 0x35, 0xc0, 0x1f, 0xcc, 0x03, 0x7d, 0x47, 0xd5, 0x6e, - 0x26, 0xe2, 0x63, 0xe0, 0xc6, 0x39, 0x34, 0xf6, 0xd4, 0xe4, 0x5d, 0xfd, 0xd2, 0x36, 0x0f, 0xda, - 0x23, 0xec, 0xba, 0xc4, 0x41, 0x0f, 0xa2, 0x5f, 0xeb, 0x0e, 0x63, 0x1e, 0x1a, 0xe8, 0xdd, 0x48, - 0xd4, 0xeb, 0x09, 0x66, 0xbb, 0xc3, 0xc0, 0xab, 0x8d, 0x73, 0xe8, 0xad, 0x17, 0x57, 0xa9, 0x6e, - 0x73, 0x61, 0x9b, 0x3c, 0x10, 0xdc, 0x4a, 0x17, 0x9c, 0x03, 0x9f, 0x51, 0xb2, 0x0f, 0x1b, 0x6d, - 0x46, 0xb0, 0x20, 0x6d, 0x5d, 0x30, 0xe8, 0x5e, 0xb2, 0x77, 0x62, 0xb0, 0x40, 0x68, 0x51, 0xf0, - 0x1b, 0xe7, 0xd0, 0x8f, 0x50, 0xee, 0x30, 0x3a, 0x09, 0xd1, 0xdf, 0x49, 0xa4, 0x8f, 0x82, 0x32, - 0x92, 0xf7, 0x61, 0xfd, 0x39, 0xe6, 0x21, 0xee, 0xdb, 0x89, 0xdc, 0x11, 0x4c, 0x40, 0x7d, 0x3d, - 0x11, 0xba, 0x4d, 0xa9, 0x13, 0x72, 0xcf, 0x11, 0xa0, 0xe0, 0x30, 0x08, 0xa9, 0x24, 0xa7, 0xdb, - 0x3c, 0x30, 0x90, 0xda, 0xcc, 0x8c, 0xd7, 0xc2, 0xbf, 0x42, 0x6d, 0x7e, 0xbd, 0xeb, 0x07, 0xfe, - 0xff, 0x30, 0xe0, 0x15, 0x14, 0x55, 0xc4, 0x9f, 0x3a, 0x36, 0xe6, 0xe8, 0xd6, 0x82, 0x9c, 0xf0, - 0x10, 0x19, 0x23, 0xf6, 0x2d, 0xac, 0xc9, 0x48, 0x2b, 0xd2, 0xcf, 0x52, 0x33, 0xe1, 0x2c, 0x94, - 0x3d, 0x80, 0xa7, 0x8e, 0x20, 0x4c, 0x71, 0x7e, 0x9e, 0xc8, 0x39, 0x03, 0x64, 0x24, 0x75, 0xa1, - 0xd2, 0x1b, 0xc9, 0xee, 0x2a, 0x70, 0x0d, 0x47, 0x77, 0x93, 0x2b, 0x2a, 0x8a, 0x0a, 0xe8, 0xef, - 0x65, 0x03, 0x6b, 0x77, 0xef, 0xcb, 0xd6, 0x59, 0x10, 0x16, 0xca, 0xb2, 0xbb, 0xe9, 0x3b, 0x39, - 0x73, 0xa1, 0xec, 0x43, 0x45, 0xc5, 0x6a, 0x2f, 0x68, 0x88, 0x52, 0xe8, 0x63, 0xa8, 0x8c, 0xf4, - 0xdf, 0xc3, 0xba, 0x8c, 0xda, 0x8c, 0xfc, 0x76, 0x6a, 0x64, 0xcf, 0x4a, 0xbd, 0x0f, 0xa5, 0xe7, - 0x98, 0xcf, 0x98, 0x9b, 0x69, 0x15, 0x3e, 0x47, 0x9c, 0xa9, 0xc0, 0x0f, 0xa0, 0x2c, 0x83, 0xa2, - 0x3f, 0xe6, 0x29, 0xc7, 0x53, 0x14, 0x14, 0x48, 0xdc, 0xcd, 0x84, 0xd5, 0x62, 0x1c, 0x2e, 0x47, - 0xd7, 0x74, 0x41, 0xff, 0x87, 0xa2, 0x04, 0x4a, 0x72, 0x2d, 0xe8, 0x65, 0x52, 0x1c, 0x18, 0x86, - 0x04, 0x42, 0xb7, 0x33, 0x20, 0x43, 0x77, 0x57, 0x39, 0xfa, 0xb0, 0x45, 0xf7, 0xd3, 0xda, 0x9a, - 0xc4, 0x27, 0x76, 0xad, 0x95, 0x15, 0xae, 0x25, 0x7f, 0x82, 0x15, 0xff, 0xb9, 0x19, 0xaf, 0xfa, - 0xd8, 0xc7, 0xfa, 0xa5, 0x5b, 0xbb, 0x75, 0x2a, 0x4e, 0xb3, 0x63, 0xb8, 0xf4, 0x6a, 0x62, 0xc9, - 0x2b, 0x4f, 0x5d, 0xac, 0xc1, 0xd5, 0x1e, 0xcf, 0x6d, 0x7d, 0x1b, 0xc7, 0x70, 0xbb, 0x7c, 0x78, - 0x5a, 0x6e, 0x33, 0xf8, 0xb8, 0xeb, 0x1e, 0x62, 0xc7, 0xb6, 0x22, 0x37, 0xeb, 0x2e, 0x11, 0xb8, - 0x8d, 0xcd, 0x11, 0x89, 0x5f, 0xfc, 0xea, 0xbf, 0x8b, 0xe8, 0x27, 0x1a, 0x9c, 0xb1, 0x9e, 0x7e, - 0x01, 0xa4, 0x4e, 0x21, 0xf7, 0x8d, 0x3d, 0x9c, 0x32, 0xac, 0x92, 0x3e, 0xad, 0xa5, 0x99, 0x87, - 0x06, 0x32, 0x5f, 0x9c, 0xe1, 0x8b, 0x50, 0xb7, 0x01, 0x3b, 0x44, 0xec, 0x12, 0xc1, 0x6c, 0x33, - 0xed, 0xa8, 0x9e, 0x01, 0x52, 0x82, 0x96, 0x80, 0xd3, 0x02, 0x3d, 0x58, 0x56, 0x2f, 0x6e, 0xd4, - 0x48, 0xfc, 0x28, 0xf8, 0xbf, 0x60, 0x51, 0x8f, 0xa4, 0xff, 0x53, 0x08, 0x9d, 0x11, 0x3b, 0x44, - 0x84, 0x5e, 0xf2, 0x29, 0xe5, 0x1a, 0x05, 0x2d, 0x2e, 0xd7, 0x38, 0x56, 0x8b, 0xb9, 0x50, 0xf9, - 0xc6, 0xe6, 0xfe, 0xe2, 0x4b, 0xcc, 0x0f, 0xd2, 0x2e, 0x9e, 0x18, 0x6a, 0xf1, 0xc5, 0x33, 0x07, - 0x0e, 0x79, 0xac, 0x64, 0x10, 0xb9, 0xe0, 0xfb, 0x2d, 0xf5, 0x31, 0x12, 0xfe, 0xab, 0xe5, 0xb4, - 0x24, 0x7b, 0xad, 0xbb, 0x4a, 0xfd, 0x78, 0x88, 0x5f, 0xf6, 0xb3, 0xb2, 0xd1, 0x10, 0xf9, 0xce, - 0xc9, 0xc0, 0xec, 0x57, 0xe5, 0x87, 0x66, 0xee, 0xc3, 0x46, 0x87, 0x38, 0x24, 0xc2, 0x7c, 0x2f, - 0xa5, 0x6f, 0x8a, 0xc2, 0x32, 0x56, 0xde, 0x08, 0xd6, 0x65, 0x18, 0xe4, 0x77, 0xaf, 0x38, 0x61, - 0x3c, 0xe5, 0x92, 0x8c, 0x60, 0x02, 0xea, 0x3b, 0x59, 0xa0, 0xa1, 0x1c, 0x5a, 0x8f, 0x3c, 0xdc, - 0xe2, 0xfb, 0x98, 0x05, 0x35, 0xe9, 0x19, 0x59, 0xbb, 0x9f, 0x11, 0x1d, 0xca, 0x21, 0x50, 0xe1, - 0x36, 0xa8, 0x43, 0x52, 0xca, 0x7a, 0x06, 0xc8, 0xe8, 0xae, 0x17, 0xb0, 0x2a, 0xfb, 0x05, 0x8f, - 0xf2, 0x66, 0x6a, 0x3b, 0x71, 0x06, 0xc2, 0x7d, 0xa8, 0xbc, 0x98, 0x10, 0x86, 0x05, 0x91, 0xfe, - 0xf2, 0x78, 0x93, 0x2b, 0x2b, 0x86, 0xca, 0xfc, 0x16, 0x81, 0x1e, 0x91, 0x27, 0xf8, 0x02, 0x27, - 0xcc, 0x00, 0x8b, 0xcf, 0xb6, 0x30, 0x2e, 0x7c, 0x78, 0xaa, 0x79, 0x69, 0xd8, 0x42, 0x01, 0xcf, - 0xf2, 0x0c, 0x02, 0x0a, 0x17, 0x7e, 0x0b, 0xfa, 0x5b, 0xdf, 0x63, 0xf6, 0xa1, 0xed, 0x90, 0x21, - 0x49, 0xa9, 0x80, 0x38, 0x2c, 0xa3, 0x8b, 0x06, 0x50, 0x54, 0xc2, 0x3b, 0x0c, 0xbb, 0x02, 0x2d, - 0x32, 0xcd, 0x43, 0x04, 0xb4, 0xcd, 0xd3, 0x81, 0x7a, 0x13, 0x26, 0x80, 0x2c, 0x8b, 0x3d, 0xea, - 0xd8, 0xe6, 0x49, 0xbc, 0xd9, 0xd1, 0x47, 0xc3, 0x0c, 0x92, 0xd2, 0xec, 0x24, 0x22, 0xb5, 0xc8, - 0x00, 0x8a, 0xed, 0x11, 0x31, 0x0f, 0x9e, 0x13, 0xec, 0x88, 0x51, 0xda, 0xe3, 0x68, 0x86, 0x58, - 0xbc, 0x91, 0x08, 0x30, 0xd0, 0xd8, 0x7e, 0xfc, 0xc3, 0xa3, 0xa1, 0x2d, 0x46, 0xd3, 0x81, 0x74, - 0xe3, 0xa6, 0x82, 0xde, 0xb7, 0xa9, 0xff, 0x6b, 0x33, 0x30, 0x70, 0xd3, 0xa3, 0xda, 0xd4, 0x45, - 0x3a, 0x19, 0x0c, 0x96, 0xbd, 0xa9, 0x87, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x68, 0x68, 0x82, - 0xf8, 0x42, 0x19, 0x00, 0x00, + // 1570 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xeb, 0x92, 0xd3, 0x36, + 0x14, 0x26, 0x09, 0x7b, 0x3b, 0xc9, 0x26, 0x8b, 0x86, 0x4b, 0x1a, 0x68, 0x1b, 0x02, 0x2d, 0xe1, + 0x96, 0xa5, 0xcb, 0x0c, 0xa5, 0xfc, 0x63, 0x13, 0x66, 0xc9, 0xb4, 0x3b, 0x6c, 0x1d, 0xe8, 0xd0, + 0xcb, 0x4e, 0xaa, 0xd8, 0x87, 0xc4, 0xb3, 0x8e, 0x15, 0x2c, 0x65, 0x2f, 0xd3, 0x1f, 0x9d, 0xce, + 0xf4, 0x7f, 0xdf, 0xa9, 0x7d, 0x87, 0xbe, 0x40, 0x5f, 0xa4, 0x23, 0x5f, 0x14, 0xdb, 0xb1, 0xb3, + 0x5e, 0xa0, 0xfd, 0x67, 0x49, 0x9f, 0xbe, 0xef, 0xe8, 0x1c, 0x1d, 0x49, 0xc7, 0xb0, 0xe1, 0x30, + 0x26, 0xfa, 0x3a, 0x63, 0x8e, 0xd1, 0x9a, 0x38, 0x4c, 0x30, 0x72, 0x79, 0x6c, 0x5a, 0x87, 0x53, + 0xee, 0xb5, 0x5a, 0x72, 0xd8, 0x1d, 0xad, 0x95, 0x74, 0x36, 0x1e, 0x33, 0xdb, 0xeb, 0xaf, 0x95, + 0xc2, 0xa8, 0x5a, 0xd9, 0xb4, 0x05, 0x3a, 0x36, 0xb5, 0xfc, 0x76, 0x71, 0xe2, 0xb0, 0xe3, 0x13, + 0xbf, 0x51, 0x41, 0xa1, 0x1b, 0xfd, 0x31, 0x0a, 0xea, 0x75, 0x34, 0xfa, 0x70, 0xe9, 0xa9, 0x65, + 0x31, 0xfd, 0xa5, 0x39, 0x46, 0x2e, 0xe8, 0x78, 0xa2, 0xe1, 0xdb, 0x29, 0x72, 0x41, 0x1e, 0xc0, + 0xf9, 0x01, 0xe5, 0x58, 0xcd, 0xd5, 0x73, 0xcd, 0xe2, 0xd6, 0xb5, 0x56, 0xc4, 0x12, 0x5f, 0x7e, + 0x97, 0x0f, 0xb7, 0x29, 0x47, 0xcd, 0x45, 0x92, 0x8b, 0xb0, 0xa4, 0xb3, 0xa9, 0x2d, 0xaa, 0x85, + 0x7a, 0xae, 0xb9, 0xae, 0x79, 0x8d, 0xc6, 0x6f, 0x39, 0xb8, 0x1c, 0x57, 0xe0, 0x13, 0x66, 0x73, + 0x24, 0x0f, 0x61, 0x99, 0x0b, 0x2a, 0xa6, 0xdc, 0x17, 0xb9, 0x9a, 0x28, 0xd2, 0x73, 0x21, 0x9a, + 0x0f, 0x25, 0xd7, 0x60, 0x4d, 0x04, 0x4c, 0xd5, 0x7c, 0x3d, 0xd7, 0x3c, 0xaf, 0xcd, 0x3a, 0x52, + 0x6c, 0x78, 0x0d, 0x65, 0xd7, 0x84, 0x6e, 0xe7, 0x03, 0xac, 0x2e, 0x1f, 0x66, 0xb6, 0xa0, 0xa2, + 0x98, 0xdf, 0x67, 0x55, 0x65, 0xc8, 0x77, 0x3b, 0x2e, 0x75, 0x41, 0xcb, 0x77, 0x3b, 0x29, 0xeb, + 0xf8, 0x33, 0x0f, 0xa5, 0xee, 0x78, 0xc2, 0x1c, 0xa1, 0x21, 0x9f, 0x5a, 0xe2, 0xdd, 0xb4, 0xae, + 0xc0, 0x8a, 0xa0, 0xfc, 0xa0, 0x6f, 0x1a, 0xbe, 0xe0, 0xb2, 0x6c, 0x76, 0x0d, 0xf2, 0x29, 0x14, + 0x0d, 0x2a, 0xa8, 0xcd, 0x0c, 0x94, 0x83, 0x05, 0x77, 0x10, 0x82, 0xae, 0xae, 0x41, 0x1e, 0xc1, + 0x92, 0xe4, 0xc0, 0xea, 0xf9, 0x7a, 0xae, 0x59, 0xde, 0xaa, 0x27, 0xaa, 0x79, 0x06, 0x4a, 0x4d, + 0xd4, 0x3c, 0x38, 0xa9, 0xc1, 0x2a, 0xc7, 0xe1, 0x18, 0x6d, 0xc1, 0xab, 0x4b, 0xf5, 0x42, 0xb3, + 0xa0, 0xa9, 0x36, 0xf9, 0x08, 0x56, 0xe9, 0x54, 0xb0, 0xbe, 0x69, 0xf0, 0xea, 0xb2, 0x3b, 0xb6, + 0x22, 0xdb, 0x5d, 0x83, 0x93, 0xab, 0xb0, 0xe6, 0xb0, 0xa3, 0xbe, 0xe7, 0x88, 0x15, 0xd7, 0x9a, + 0x55, 0x87, 0x1d, 0xb5, 0x65, 0x9b, 0x7c, 0x09, 0x4b, 0xa6, 0xfd, 0x86, 0xf1, 0xea, 0x6a, 0xbd, + 0xd0, 0x2c, 0x6e, 0x5d, 0x4f, 0xb4, 0xe5, 0x6b, 0x3c, 0xf9, 0x8e, 0x5a, 0x53, 0xdc, 0xa3, 0xa6, + 0xa3, 0x79, 0xf8, 0xc6, 0x1f, 0x39, 0xb8, 0xd2, 0x41, 0xae, 0x3b, 0xe6, 0x00, 0x7b, 0xbe, 0x15, + 0xef, 0xbe, 0x2d, 0x1a, 0x50, 0xd2, 0x99, 0x65, 0xa1, 0x2e, 0x4c, 0x66, 0xab, 0x10, 0x46, 0xfa, + 0xc8, 0x27, 0x00, 0xfe, 0x72, 0xbb, 0x1d, 0x5e, 0x2d, 0xb8, 0x8b, 0x0c, 0xf5, 0x34, 0xa6, 0x50, + 0xf1, 0x0d, 0x91, 0xc4, 0x5d, 0xfb, 0x0d, 0x9b, 0xa3, 0xcd, 0x25, 0xd0, 0xd6, 0xa1, 0x38, 0xa1, + 0x8e, 0x30, 0x23, 0xca, 0xe1, 0x2e, 0x99, 0x2b, 0x4a, 0xc6, 0x0f, 0xe7, 0xac, 0xa3, 0xf1, 0x4f, + 0x1e, 0x4a, 0xbe, 0xae, 0xd4, 0xe4, 0xa4, 0x03, 0x6b, 0x72, 0x4d, 0x7d, 0xe9, 0x27, 0xdf, 0x05, + 0xb7, 0x5a, 0xc9, 0x27, 0x50, 0x2b, 0x66, 0xb0, 0xb6, 0x3a, 0x08, 0x4c, 0xef, 0x40, 0xd1, 0xb4, + 0x0d, 0x3c, 0xee, 0x7b, 0xe1, 0xc9, 0xbb, 0xe1, 0xb9, 0x11, 0xe5, 0x91, 0xa7, 0x50, 0x4b, 0x69, + 0x1b, 0x78, 0xec, 0x72, 0x80, 0x19, 0x7c, 0x72, 0x82, 0x70, 0x01, 0x8f, 0x85, 0x43, 0xfb, 0x61, + 0xae, 0x82, 0xcb, 0xf5, 0xd5, 0x29, 0x36, 0xb9, 0x04, 0xad, 0x67, 0x72, 0xb6, 0xe2, 0xe6, 0xcf, + 0x6c, 0xe1, 0x9c, 0x68, 0x15, 0x8c, 0xf6, 0xd6, 0x7e, 0x86, 0x8b, 0x49, 0x40, 0xb2, 0x01, 0x85, + 0x03, 0x3c, 0xf1, 0xdd, 0x2e, 0x3f, 0xc9, 0x16, 0x2c, 0x1d, 0xca, 0xad, 0xe4, 0xfa, 0x79, 0x6e, + 0x6f, 0xb8, 0x0b, 0x9a, 0xad, 0xc4, 0x83, 0x3e, 0xc9, 0x3f, 0xce, 0x35, 0xfe, 0xca, 0x43, 0x75, + 0x7e, 0xbb, 0xbd, 0xcf, 0x59, 0x91, 0x65, 0xcb, 0x0d, 0x61, 0xdd, 0x0f, 0x74, 0xc4, 0x75, 0xdb, + 0x69, 0xae, 0x4b, 0xb3, 0x30, 0xe2, 0x53, 0xcf, 0x87, 0x25, 0x1e, 0xea, 0xaa, 0x21, 0x5c, 0x98, + 0x83, 0x24, 0x78, 0xef, 0x49, 0xd4, 0x7b, 0x37, 0xb3, 0x84, 0x30, 0xec, 0x45, 0x03, 0x2e, 0xee, + 0xa0, 0x68, 0x3b, 0x68, 0xa0, 0x2d, 0x4c, 0x6a, 0xbd, 0x7b, 0xc2, 0xd6, 0x60, 0x75, 0xca, 0xe5, + 0xfd, 0x38, 0xf6, 0x8c, 0x59, 0xd3, 0x54, 0xbb, 0xf1, 0x7b, 0x0e, 0x2e, 0xc5, 0x64, 0xde, 0x27, + 0x50, 0x0b, 0xa4, 0xe4, 0xd8, 0x84, 0x72, 0x7e, 0xc4, 0x1c, 0xef, 0xa0, 0x5d, 0xd3, 0x54, 0x7b, + 0xeb, 0xef, 0x06, 0xac, 0x69, 0x8c, 0x89, 0xb6, 0x74, 0x09, 0xb1, 0x80, 0x48, 0x9b, 0xd8, 0x78, + 0xc2, 0x6c, 0xb4, 0xbd, 0x83, 0x95, 0x93, 0x56, 0xd4, 0x00, 0xbf, 0x31, 0x0f, 0xf4, 0x1d, 0x55, + 0xbb, 0x99, 0x88, 0x8f, 0x81, 0x1b, 0xe7, 0xc8, 0xd8, 0x55, 0x93, 0x77, 0xf5, 0x4b, 0x53, 0x3f, + 0x68, 0x8f, 0xa8, 0x6d, 0xa3, 0x45, 0x1e, 0x44, 0x67, 0xab, 0x17, 0xc6, 0x3c, 0x34, 0xd0, 0xbb, + 0x91, 0xa8, 0xd7, 0x13, 0x8e, 0x69, 0x0f, 0x03, 0xaf, 0x36, 0xce, 0x91, 0xb7, 0x6e, 0x5c, 0xa5, + 0xba, 0xc9, 0x85, 0xa9, 0xf3, 0x40, 0x70, 0x2b, 0x5d, 0x70, 0x0e, 0x7c, 0x46, 0xc9, 0x3e, 0x6c, + 0xb4, 0x1d, 0xa4, 0x02, 0xdb, 0x2a, 0x61, 0xc8, 0xbd, 0x64, 0xef, 0xc4, 0x60, 0x81, 0xd0, 0xa2, + 0xe0, 0x37, 0xce, 0x91, 0x1f, 0xa1, 0xdc, 0x71, 0xd8, 0x24, 0x44, 0x7f, 0x27, 0x91, 0x3e, 0x0a, + 0xca, 0x48, 0xde, 0x87, 0xf5, 0xe7, 0x94, 0x87, 0xb8, 0x6f, 0x27, 0x72, 0x47, 0x30, 0x01, 0xf5, + 0xf5, 0x44, 0xe8, 0x36, 0x63, 0x56, 0xc8, 0x3d, 0x47, 0x40, 0x82, 0xc3, 0x20, 0xa4, 0x92, 0xbc, + 0xdd, 0xe6, 0x81, 0x81, 0xd4, 0x66, 0x66, 0xbc, 0x12, 0xfe, 0x15, 0x6a, 0xf3, 0xe3, 0x5d, 0x3f, + 0xf0, 0xff, 0x87, 0x01, 0xaf, 0xa0, 0xe8, 0x45, 0xfc, 0xa9, 0x65, 0x52, 0x4e, 0x6e, 0x2d, 0xd8, + 0x13, 0x2e, 0x22, 0x63, 0xc4, 0xbe, 0x85, 0x35, 0x19, 0x69, 0x8f, 0xf4, 0xb3, 0xd4, 0x9d, 0x70, + 0x16, 0xca, 0x1e, 0xc0, 0x53, 0x4b, 0xa0, 0xe3, 0x71, 0x7e, 0x9e, 0xc8, 0x39, 0x03, 0x64, 0x24, + 0xb5, 0xa1, 0xd2, 0x1b, 0xc9, 0xd7, 0x55, 0xe0, 0x1a, 0x4e, 0xee, 0x26, 0x67, 0x54, 0x14, 0x15, + 0xd0, 0xdf, 0xcb, 0x06, 0x56, 0xee, 0xde, 0x97, 0x4f, 0x67, 0x81, 0x4e, 0x68, 0x97, 0xdd, 0x4d, + 0x5f, 0xc9, 0x99, 0x13, 0x65, 0x1f, 0x2a, 0x5e, 0xac, 0xf6, 0x82, 0x07, 0x51, 0x0a, 0x7d, 0x0c, + 0x95, 0x91, 0xfe, 0x7b, 0x58, 0x97, 0x51, 0x9b, 0x91, 0xdf, 0x4e, 0x8d, 0xec, 0x59, 0xa9, 0xf7, + 0xa1, 0xf4, 0x9c, 0xf2, 0x19, 0x73, 0x33, 0x2d, 0xc3, 0xe7, 0x88, 0x33, 0x25, 0xf8, 0x01, 0x94, + 0x65, 0x50, 0xd4, 0x64, 0x9e, 0x72, 0x3c, 0x45, 0x41, 0x81, 0xc4, 0xdd, 0x4c, 0x58, 0x25, 0xc6, + 0xe1, 0x72, 0x74, 0x4c, 0x25, 0xf4, 0x7f, 0x28, 0x8a, 0x50, 0x92, 0x63, 0xc1, 0x5b, 0x26, 0xc5, + 0x81, 0x61, 0x48, 0x20, 0x74, 0x3b, 0x03, 0x32, 0x74, 0x77, 0x95, 0xa3, 0x85, 0x2d, 0xb9, 0x9f, + 0xf6, 0xac, 0x49, 0x2c, 0xb1, 0x6b, 0xad, 0xac, 0x70, 0x25, 0xf9, 0x13, 0xac, 0xf8, 0xe5, 0x66, + 0x3c, 0xeb, 0x63, 0x93, 0x55, 0xa5, 0x5b, 0xbb, 0x75, 0x2a, 0x4e, 0xb1, 0x53, 0xb8, 0xf4, 0x6a, + 0x62, 0xc8, 0x2b, 0xcf, 0xbb, 0x58, 0x83, 0xab, 0x3d, 0xbe, 0xb7, 0xd5, 0x6d, 0x1c, 0xc3, 0xed, + 0xf2, 0xe1, 0x69, 0x7b, 0xdb, 0x81, 0x8f, 0xbb, 0xf6, 0x21, 0xb5, 0x4c, 0x23, 0x72, 0xb3, 0xee, + 0xa2, 0xa0, 0x6d, 0xaa, 0x8f, 0x30, 0x7e, 0xf1, 0x7b, 0xff, 0x2e, 0xa2, 0x53, 0x14, 0x38, 0x63, + 0x3e, 0xfd, 0x02, 0xc4, 0x3b, 0x85, 0xec, 0x37, 0xe6, 0x70, 0xea, 0x50, 0x6f, 0xd3, 0xa7, 0x3d, + 0x69, 0xe6, 0xa1, 0x81, 0xcc, 0x17, 0x67, 0x98, 0x11, 0x7a, 0x6d, 0xc0, 0x0e, 0x8a, 0x5d, 0x14, + 0x8e, 0xa9, 0xa7, 0x1d, 0xd5, 0x33, 0x40, 0x4a, 0xd0, 0x12, 0x70, 0x4a, 0xa0, 0x07, 0xcb, 0x5e, + 0xc5, 0x4d, 0x1a, 0x89, 0x93, 0x82, 0xff, 0x05, 0x8b, 0xde, 0x48, 0xea, 0x9f, 0x42, 0xe8, 0x8c, + 0xd8, 0x41, 0x11, 0xaa, 0xe4, 0x53, 0xd2, 0x35, 0x0a, 0x5a, 0x9c, 0xae, 0x71, 0xac, 0x12, 0xb3, + 0xa1, 0xf2, 0x8d, 0xc9, 0xfd, 0xc1, 0x97, 0x94, 0x1f, 0xa4, 0x5d, 0x3c, 0x31, 0xd4, 0xe2, 0x8b, + 0x67, 0x0e, 0x1c, 0xf2, 0x58, 0x49, 0x43, 0x39, 0xe0, 0xfb, 0x2d, 0xb5, 0x18, 0x09, 0xff, 0x6a, + 0x39, 0x6d, 0x93, 0xbd, 0x56, 0xaf, 0x4a, 0x55, 0x3c, 0xc4, 0x2f, 0xfb, 0x59, 0xda, 0x28, 0x88, + 0xac, 0x73, 0x32, 0x30, 0xfb, 0x59, 0xf9, 0xa1, 0x99, 0xfb, 0xb0, 0xd1, 0x41, 0x0b, 0x23, 0xcc, + 0xf7, 0x52, 0xde, 0x4d, 0x51, 0x58, 0xc6, 0xcc, 0x1b, 0xc1, 0xba, 0x0c, 0x83, 0x9c, 0xf7, 0x8a, + 0xa3, 0xc3, 0x53, 0x2e, 0xc9, 0x08, 0x26, 0xa0, 0xbe, 0x93, 0x05, 0x1a, 0xda, 0x43, 0xeb, 0x91, + 0xc2, 0x2d, 0xbe, 0x8e, 0x59, 0x50, 0x93, 0xca, 0xc8, 0xda, 0xfd, 0x8c, 0xe8, 0xd0, 0x1e, 0x02, + 0x2f, 0xdc, 0x1a, 0xb3, 0x30, 0x25, 0xad, 0x67, 0x80, 0x8c, 0xee, 0x7a, 0x01, 0xab, 0xf2, 0xbd, + 0xe0, 0x52, 0xde, 0x4c, 0x7d, 0x4e, 0x9c, 0x81, 0x70, 0x1f, 0x2a, 0x2f, 0x26, 0xe8, 0x50, 0x81, + 0xd2, 0x5f, 0x2e, 0x6f, 0x72, 0x66, 0xc5, 0x50, 0x99, 0x6b, 0x11, 0xe8, 0xa1, 0x3c, 0xc1, 0x17, + 0x38, 0x61, 0x06, 0x58, 0x7c, 0xb6, 0x85, 0x71, 0xe1, 0xc3, 0xd3, 0xeb, 0x97, 0x86, 0x2d, 0x14, + 0x70, 0x2d, 0xcf, 0x20, 0xe0, 0xe1, 0xc2, 0xb5, 0xa0, 0xbf, 0xf4, 0x3d, 0xc7, 0x3c, 0x34, 0x2d, + 0x1c, 0x62, 0x4a, 0x06, 0xc4, 0x61, 0x19, 0x5d, 0x34, 0x80, 0xa2, 0x27, 0xbc, 0xe3, 0x50, 0x5b, + 0x90, 0x45, 0xa6, 0xb9, 0x88, 0x80, 0xb6, 0x79, 0x3a, 0x50, 0x2d, 0x42, 0x07, 0x90, 0x69, 0xb1, + 0xc7, 0x2c, 0x53, 0x3f, 0x89, 0x3f, 0x76, 0xd4, 0xd1, 0x30, 0x83, 0xa4, 0x3c, 0x76, 0x12, 0x91, + 0x4a, 0x64, 0x00, 0xc5, 0xf6, 0x08, 0xf5, 0x83, 0xe7, 0x48, 0x2d, 0x31, 0x4a, 0x2b, 0x8e, 0x66, + 0x88, 0xc5, 0x0b, 0x89, 0x00, 0xc3, 0xd1, 0xd0, 0xd0, 0xa6, 0xe3, 0xd3, 0x2b, 0xf3, 0x38, 0x2c, + 0x5b, 0x34, 0xb6, 0x1f, 0xff, 0xf0, 0x68, 0x68, 0x8a, 0xd1, 0x74, 0x20, 0x47, 0x36, 0x3d, 0xe8, + 0x7d, 0x93, 0xf9, 0x5f, 0x9b, 0x81, 0x07, 0x36, 0xdd, 0xd9, 0x9b, 0xea, 0x14, 0x98, 0x0c, 0x06, + 0xcb, 0x6e, 0xd7, 0xc3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x8d, 0x70, 0xb9, 0xa3, 0x19, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -882,6 +883,7 @@ type RootCoordClient interface { SelectGrant(ctx context.Context, in *milvuspb.SelectGrantRequest, opts ...grpc.CallOption) (*milvuspb.SelectGrantResponse, error) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest, opts ...grpc.CallOption) (*internalpb.ListPolicyResponse, error) CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest, opts ...grpc.CallOption) (*milvuspb.CheckHealthResponse, error) + RenameCollection(ctx context.Context, in *milvuspb.RenameCollectionRequest, opts ...grpc.CallOption) (*commonpb.Status, error) } type rootCoordClient struct { @@ -1279,6 +1281,15 @@ func (c *rootCoordClient) CheckHealth(ctx context.Context, in *milvuspb.CheckHea return out, nil } +func (c *rootCoordClient) RenameCollection(ctx context.Context, in *milvuspb.RenameCollectionRequest, opts ...grpc.CallOption) (*commonpb.Status, error) { + out := new(commonpb.Status) + err := c.cc.Invoke(ctx, "/milvus.proto.rootcoord.RootCoord/RenameCollection", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // RootCoordServer is the server API for RootCoord service. type RootCoordServer interface { GetComponentStates(context.Context, *milvuspb.GetComponentStatesRequest) (*milvuspb.ComponentStates, error) @@ -1376,6 +1387,7 @@ type RootCoordServer interface { SelectGrant(context.Context, *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) ListPolicy(context.Context, *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) CheckHealth(context.Context, *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) + RenameCollection(context.Context, *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) } // UnimplementedRootCoordServer can be embedded to have forward compatible implementations. @@ -1511,6 +1523,9 @@ func (*UnimplementedRootCoordServer) ListPolicy(ctx context.Context, req *intern func (*UnimplementedRootCoordServer) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CheckHealth not implemented") } +func (*UnimplementedRootCoordServer) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return nil, status.Errorf(codes.Unimplemented, "method RenameCollection not implemented") +} func RegisterRootCoordServer(s *grpc.Server, srv RootCoordServer) { s.RegisterService(&_RootCoord_serviceDesc, srv) @@ -2290,6 +2305,24 @@ func _RootCoord_CheckHealth_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _RootCoord_RenameCollection_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(milvuspb.RenameCollectionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RootCoordServer).RenameCollection(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/milvus.proto.rootcoord.RootCoord/RenameCollection", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RootCoordServer).RenameCollection(ctx, req.(*milvuspb.RenameCollectionRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _RootCoord_serviceDesc = grpc.ServiceDesc{ ServiceName: "milvus.proto.rootcoord.RootCoord", HandlerType: (*RootCoordServer)(nil), @@ -2466,6 +2499,10 @@ var _RootCoord_serviceDesc = grpc.ServiceDesc{ MethodName: "CheckHealth", Handler: _RootCoord_CheckHealth_Handler, }, + { + MethodName: "RenameCollection", + Handler: _RootCoord_RenameCollection_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "root_coord.proto", diff --git a/internal/proxy/impl.go b/internal/proxy/impl.go index 8e7af4430e..b4498120f1 100644 --- a/internal/proxy/impl.go +++ b/internal/proxy/impl.go @@ -24,10 +24,11 @@ import ( "strconv" "sync" + "github.com/golang/protobuf/proto" "go.opentelemetry.io/otel" + "go.uber.org/zap" "golang.org/x/sync/errgroup" - "github.com/golang/protobuf/proto" "github.com/milvus-io/milvus-proto/go-api/commonpb" "github.com/milvus-io/milvus-proto/go-api/milvuspb" "github.com/milvus-io/milvus-proto/go-api/schemapb" @@ -49,7 +50,6 @@ import ( "github.com/milvus-io/milvus/internal/util/paramtable" "github.com/milvus-io/milvus/internal/util/timerecord" "github.com/milvus-io/milvus/internal/util/typeutil" - "go.uber.org/zap" ) const moduleName = "Proxy" @@ -4407,6 +4407,47 @@ func (node *Proxy) CheckHealth(ctx context.Context, request *milvuspb.CheckHealt }, nil } +func (node *Proxy) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-RefreshPolicyInfoCache") + defer sp.End() + + log := log.Ctx(ctx).With( + zap.String("role", typeutil.ProxyRole), + zap.String("oldName", req.GetOldName()), + zap.String("newName", req.GetNewName())) + + log.Info("received rename collection request") + var err error + + if !node.checkHealthy() { + return unhealthyStatus(), nil + } + + if err := validateCollectionName(req.GetNewName()); err != nil { + log.Warn("validate new collection name fail", zap.Error(err)) + return &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_IllegalCollectionName, + Reason: err.Error(), + }, err + } + + req.Base = commonpbutil.NewMsgBase( + commonpbutil.WithMsgType(commonpb.MsgType_RenameCollection), + commonpbutil.WithMsgID(0), + commonpbutil.WithSourceID(paramtable.GetNodeID()), + ) + resp, err := node.rootCoord.RenameCollection(ctx, req) + if err != nil { + log.Warn("failed to rename collection", zap.Error(err)) + return &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_UnexpectedError, + Reason: err.Error(), + }, err + } + + return resp, nil +} + func (node *Proxy) CreateResourceGroup(ctx context.Context, request *milvuspb.CreateResourceGroupRequest) (*commonpb.Status, error) { return &commonpb.Status{ ErrorCode: commonpb.ErrorCode_Success, diff --git a/internal/proxy/impl_test.go b/internal/proxy/impl_test.go index 826098fe00..096bba2105 100644 --- a/internal/proxy/impl_test.go +++ b/internal/proxy/impl_test.go @@ -21,14 +21,16 @@ import ( "testing" "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/milvus-io/milvus-proto/go-api/commonpb" "github.com/milvus-io/milvus-proto/go-api/milvuspb" "github.com/milvus-io/milvus/internal/log" + "github.com/milvus-io/milvus/internal/mocks" "github.com/milvus-io/milvus/internal/proto/proxypb" "github.com/milvus-io/milvus/internal/util/paramtable" "github.com/milvus-io/milvus/internal/util/sessionutil" - "github.com/stretchr/testify/assert" ) func TestProxy_InvalidateCollectionMetaCache_remove_stream(t *testing.T) { @@ -142,3 +144,57 @@ func TestProxy_CheckHealth(t *testing.T) { assert.Equal(t, 2, len(resp.GetReasons())) }) } + +func TestProxyRenameCollection(t *testing.T) { + t.Run("not healthy", func(t *testing.T) { + node := &Proxy{session: &sessionutil.Session{ServerID: 1}} + node.stateCode.Store(commonpb.StateCode_Abnormal) + ctx := context.Background() + resp, err := node.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_UnexpectedError, resp.GetErrorCode()) + }) + + t.Run("rename with illegal new collection name", func(t *testing.T) { + node := &Proxy{session: &sessionutil.Session{ServerID: 1}} + node.stateCode.Store(commonpb.StateCode_Healthy) + ctx := context.Background() + resp, err := node.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{NewName: "$#^%#&#$*!)#@!"}) + assert.Error(t, err) + assert.Equal(t, commonpb.ErrorCode_IllegalCollectionName, resp.GetErrorCode()) + }) + + t.Run("rename fail", func(t *testing.T) { + rc := mocks.NewRootCoord(t) + rc.On("RenameCollection", mock.Anything, mock.Anything). + Return(nil, errors.New("fail")) + node := &Proxy{ + session: &sessionutil.Session{ServerID: 1}, + rootCoord: rc, + } + node.stateCode.Store(commonpb.StateCode_Healthy) + ctx := context.Background() + + resp, err := node.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{NewName: "new"}) + assert.Error(t, err) + assert.Equal(t, commonpb.ErrorCode_UnexpectedError, resp.GetErrorCode()) + }) + + t.Run("rename ok", func(t *testing.T) { + rc := mocks.NewRootCoord(t) + rc.On("RenameCollection", mock.Anything, mock.Anything). + Return(&commonpb.Status{ + ErrorCode: commonpb.ErrorCode_Success, + }, nil) + node := &Proxy{ + session: &sessionutil.Session{ServerID: 1}, + rootCoord: rc, + } + node.stateCode.Store(commonpb.StateCode_Healthy) + ctx := context.Background() + + resp, err := node.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{NewName: "new"}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetErrorCode()) + }) +} diff --git a/internal/proxy/proxy_test.go b/internal/proxy/proxy_test.go index 58444fc641..a24e0a73f1 100644 --- a/internal/proxy/proxy_test.go +++ b/internal/proxy/proxy_test.go @@ -292,6 +292,10 @@ func (s *proxyTestServer) GetVersion(ctx context.Context, request *milvuspb.GetV }, nil } +func (s *proxyTestServer) RenameCollection(ctx context.Context, request *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return s.Proxy.RenameCollection(ctx, request) +} + func (s *proxyTestServer) GetComponentStates(ctx context.Context, request *milvuspb.GetComponentStatesRequest) (*milvuspb.ComponentStates, error) { return s.Proxy.GetComponentStates(ctx) } diff --git a/internal/proxy/rootcoord_mock_test.go b/internal/proxy/rootcoord_mock_test.go index 5fde1a3cc9..728c91d68c 100644 --- a/internal/proxy/rootcoord_mock_test.go +++ b/internal/proxy/rootcoord_mock_test.go @@ -1140,6 +1140,10 @@ func (coord *RootCoordMock) CheckHealth(ctx context.Context, req *milvuspb.Check return &milvuspb.CheckHealthResponse{IsHealthy: true}, nil } +func (coord *RootCoordMock) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + return &commonpb.Status{}, nil +} + type DescribeCollectionFunc func(ctx context.Context, request *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error) type ShowPartitionsFunc func(ctx context.Context, request *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error) type ShowSegmentsFunc func(ctx context.Context, request *milvuspb.ShowSegmentsRequest) (*milvuspb.ShowSegmentsResponse, error) diff --git a/internal/rootcoord/drop_collection_task_test.go b/internal/rootcoord/drop_collection_task_test.go index e05afd0a39..6aa724ffdf 100644 --- a/internal/rootcoord/drop_collection_task_test.go +++ b/internal/rootcoord/drop_collection_task_test.go @@ -72,8 +72,8 @@ func Test_dropCollectionTask_Execute(t *testing.T) { meta := mockrootcoord.NewIMetaTable(t) meta.On("GetCollectionByName", mock.Anything, // context.Context. - mock.AnythingOfType("string"), - mock.AnythingOfType("uint64"), + mock.Anything, + mock.Anything, ).Return(nil, func(ctx context.Context, name string, ts Timestamp) error { if collectionName == name { return common.NewCollectionNotExistError("collection not exist") @@ -102,8 +102,8 @@ func Test_dropCollectionTask_Execute(t *testing.T) { meta := mockrootcoord.NewIMetaTable(t) meta.On("GetCollectionByName", mock.Anything, // context.Context - mock.AnythingOfType("string"), - mock.AnythingOfType("uint64"), + mock.Anything, + mock.Anything, ).Return(coll.Clone(), nil) meta.On("ListAliasesByID", mock.AnythingOfType("int64"), diff --git a/internal/rootcoord/meta_table.go b/internal/rootcoord/meta_table.go index d6b91beccf..59b666d9ec 100644 --- a/internal/rootcoord/meta_table.go +++ b/internal/rootcoord/meta_table.go @@ -22,27 +22,23 @@ import ( "fmt" "sync" - "github.com/milvus-io/milvus/internal/metrics" - - "github.com/milvus-io/milvus/internal/util/timerecord" - - "github.com/milvus-io/milvus/internal/common" - - pb "github.com/milvus-io/milvus/internal/proto/etcdpb" - "go.uber.org/zap" "github.com/milvus-io/milvus-proto/go-api/milvuspb" + "github.com/milvus-io/milvus/internal/common" "github.com/milvus-io/milvus/internal/log" "github.com/milvus-io/milvus/internal/metastore" "github.com/milvus-io/milvus/internal/metastore/model" + "github.com/milvus-io/milvus/internal/metrics" + pb "github.com/milvus-io/milvus/internal/proto/etcdpb" "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/util/contextutil" "github.com/milvus-io/milvus/internal/util/funcutil" + "github.com/milvus-io/milvus/internal/util/timerecord" "github.com/milvus-io/milvus/internal/util/typeutil" ) -//go:generate mockery --name=IMetaTable --outpkg=mockrootcoord +//go:generate mockery --name=IMetaTable --outpkg=mockrootcoord --filename=meta_table.go --with-expecter type IMetaTable interface { AddCollection(ctx context.Context, coll *model.Collection) error ChangeCollectionState(ctx context.Context, collectionID UniqueID, state pb.CollectionState, ts Timestamp) error @@ -60,6 +56,7 @@ type IMetaTable interface { DropAlias(ctx context.Context, alias string, ts Timestamp) error AlterAlias(ctx context.Context, alias string, collectionName string, ts Timestamp) error AlterCollection(ctx context.Context, oldColl *model.Collection, newColl *model.Collection, ts Timestamp) error + RenameCollection(ctx context.Context, oldName string, newName string, ts Timestamp) error // TODO: it'll be a big cost if we handle the time travel logic, since we should always list all aliases in catalog. IsAlias(name string) bool @@ -356,6 +353,7 @@ func (mt *MetaTable) GetCollectionByName(ctx context.Context, collectionName str if err != nil { return nil, err } + if coll == nil || !coll.Available() { return nil, common.NewCollectionNotExistError(fmt.Sprintf("can't find collection: %s", collectionName)) } @@ -448,6 +446,50 @@ func (mt *MetaTable) AlterCollection(ctx context.Context, oldColl *model.Collect return nil } +func (mt *MetaTable) RenameCollection(ctx context.Context, oldName string, newName string, ts Timestamp) error { + mt.ddLock.RLock() + defer mt.ddLock.RUnlock() + ctx = contextutil.WithTenantID(ctx, Params.CommonCfg.ClusterName.GetValue()) + + log := log.Ctx(ctx).With(zap.String("oldName", oldName), zap.String("newName", newName)) + + //old collection should not be an alias + _, ok := mt.collAlias2ID[oldName] + if ok { + log.Warn("unsupported use a alias to rename collection") + return fmt.Errorf("unsupported use an alias to rename collection, alias:%s", oldName) + } + + // check new collection already exists + newColl, err := mt.GetCollectionByName(ctx, newName, ts) + if newColl != nil { + return fmt.Errorf("duplicated new collection name :%s with other collection name or alias", newName) + } + if err != nil && !common.IsCollectionNotExistErrorV2(err) { + log.Warn("check new collection name fail") + return err + } + + // get old collection meta + oldColl, err := mt.GetCollectionByName(ctx, oldName, ts) + if err != nil { + return err + } + + newColl = oldColl.Clone() + newColl.Name = newName + if err := mt.catalog.AlterCollection(ctx, oldColl, newColl, metastore.MODIFY, ts); err != nil { + return err + } + + mt.collName2ID[newName] = oldColl.CollectionID + delete(mt.collName2ID, oldName) + mt.collID2Meta[oldColl.CollectionID] = newColl + + log.Info("rename collection finished") + return nil +} + // GetCollectionVirtualChannels returns virtual channels of a given collection. func (mt *MetaTable) GetCollectionVirtualChannels(colID int64) []string { mt.ddLock.RLock() diff --git a/internal/rootcoord/meta_table_test.go b/internal/rootcoord/meta_table_test.go index 808799e08c..c62ff6e822 100644 --- a/internal/rootcoord/meta_table_test.go +++ b/internal/rootcoord/meta_table_test.go @@ -22,17 +22,16 @@ import ( "math/rand" "testing" - "github.com/milvus-io/milvus-proto/go-api/milvuspb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/milvus-io/milvus-proto/go-api/milvuspb" + "github.com/milvus-io/milvus/internal/common" + memkv "github.com/milvus-io/milvus/internal/kv/mem" "github.com/milvus-io/milvus/internal/metastore/kv/rootcoord" "github.com/milvus-io/milvus/internal/metastore/mocks" "github.com/milvus-io/milvus/internal/metastore/model" - - "github.com/milvus-io/milvus/internal/common" - memkv "github.com/milvus-io/milvus/internal/kv/mem" pb "github.com/milvus-io/milvus/internal/proto/etcdpb" "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/util" @@ -914,6 +913,139 @@ func TestMetaTable_AddPartition(t *testing.T) { }) } +func TestMetaTable_RenameCollection(t *testing.T) { + t.Run("unsupported use a alias to rename collection", func(t *testing.T) { + meta := &MetaTable{ + collAlias2ID: map[string]typeutil.UniqueID{ + "alias": 1, + }, + } + err := meta.RenameCollection(context.TODO(), "alias", "new", typeutil.MaxTimestamp) + assert.Error(t, err) + }) + + t.Run("collection name not exist", func(t *testing.T) { + meta := &MetaTable{} + err := meta.RenameCollection(context.TODO(), "non-exists", "new", typeutil.MaxTimestamp) + assert.Error(t, err) + }) + + t.Run("collection id not exist", func(t *testing.T) { + meta := &MetaTable{ + collName2ID: map[string]typeutil.UniqueID{ + "old": 1, + }, + } + err := meta.RenameCollection(context.TODO(), "old", "new", typeutil.MaxTimestamp) + assert.Error(t, err) + }) + + t.Run("new collection name already exist-1", func(t *testing.T) { + meta := &MetaTable{ + collName2ID: map[string]typeutil.UniqueID{ + "old": 1, + "new": 2, + }, + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + 2: { + CollectionID: 1, + Name: "old", + State: pb.CollectionState_CollectionCreated, + }, + }, + } + err := meta.RenameCollection(context.TODO(), "old", "new", 1000) + assert.Error(t, err) + }) + + t.Run("new collection name already exist-2", func(t *testing.T) { + catalog := mocks.NewRootCoordCatalog(t) + catalog.On("GetCollectionByID", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil, errors.New("error mock GetCollectionByID")) + meta := &MetaTable{ + catalog: catalog, + collName2ID: map[string]typeutil.UniqueID{ + "old": 1, + "new": 2, + }, + } + err := meta.RenameCollection(context.TODO(), "old", "new", 1000) + assert.Error(t, err) + }) + + t.Run("alter collection fail", func(t *testing.T) { + catalog := mocks.NewRootCoordCatalog(t) + catalog.On("AlterCollection", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(errors.New("fail")) + catalog.On("GetCollectionByName", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil, common.NewCollectionNotExistError("error")) + + meta := &MetaTable{ + catalog: catalog, + collName2ID: map[string]typeutil.UniqueID{ + "old": 1, + }, + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + 1: { + CollectionID: 1, + Name: "old", + }, + }, + } + err := meta.RenameCollection(context.TODO(), "old", "new", 1000) + assert.Error(t, err) + }) + + t.Run("alter collection ok", func(t *testing.T) { + catalog := mocks.NewRootCoordCatalog(t) + catalog.On("AlterCollection", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil) + catalog.On("GetCollectionByName", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil, common.NewCollectionNotExistError("error")) + meta := &MetaTable{ + catalog: catalog, + collName2ID: map[string]typeutil.UniqueID{ + "old": 1, + }, + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + 1: { + CollectionID: 1, + Name: "old", + }, + }, + } + err := meta.RenameCollection(context.TODO(), "old", "new", 1000) + assert.NoError(t, err) + + id, ok := meta.collName2ID["new"] + assert.True(t, ok) + assert.Equal(t, int64(1), id) + + coll, ok := meta.collID2Meta[1] + assert.True(t, ok) + assert.Equal(t, "new", coll.Name) + }) +} + func TestMetaTable_ChangePartitionState(t *testing.T) { t.Run("collection not exist", func(t *testing.T) { meta := &MetaTable{} diff --git a/internal/rootcoord/mock_test.go b/internal/rootcoord/mock_test.go index dce97fb9cc..582131ac7c 100644 --- a/internal/rootcoord/mock_test.go +++ b/internal/rootcoord/mock_test.go @@ -54,6 +54,7 @@ type mockMetaTable struct { GetPartitionByNameFunc func(collID UniqueID, partitionName string, ts Timestamp) (UniqueID, error) GetCollectionVirtualChannelsFunc func(colID int64) []string AlterCollectionFunc func(ctx context.Context, oldColl *model.Collection, newColl *model.Collection, ts Timestamp) error + RenameCollectionFunc func(ctx context.Context, oldName string, newName string, ts Timestamp) error } func (m mockMetaTable) ListCollections(ctx context.Context, ts Timestamp) ([]*model.Collection, error) { @@ -116,6 +117,10 @@ func (m mockMetaTable) AlterCollection(ctx context.Context, oldColl *model.Colle return m.AlterCollectionFunc(ctx, oldColl, newColl, ts) } +func (m *mockMetaTable) RenameCollection(ctx context.Context, oldName string, newName string, ts Timestamp) error { + return m.RenameCollectionFunc(ctx, oldName, newName, ts) +} + func (m mockMetaTable) GetCollectionIDByName(name string) (UniqueID, error) { return m.GetCollectionIDByNameFunc(name) } diff --git a/internal/rootcoord/mocks/meta_table.go b/internal/rootcoord/mocks/meta_table.go index 8d7d35da04..e443e47f6f 100644 --- a/internal/rootcoord/mocks/meta_table.go +++ b/internal/rootcoord/mocks/meta_table.go @@ -48,8 +48,8 @@ type IMetaTable_AddCollection_Call struct { } // AddCollection is a helper method to define mock.On call -// - ctx context.Context -// - coll *model.Collection +// - ctx context.Context +// - coll *model.Collection func (_e *IMetaTable_Expecter) AddCollection(ctx interface{}, coll interface{}) *IMetaTable_AddCollection_Call { return &IMetaTable_AddCollection_Call{Call: _e.mock.On("AddCollection", ctx, coll)} } @@ -86,7 +86,7 @@ type IMetaTable_AddCredential_Call struct { } // AddCredential is a helper method to define mock.On call -// - credInfo *internalpb.CredentialInfo +// - credInfo *internalpb.CredentialInfo func (_e *IMetaTable_Expecter) AddCredential(credInfo interface{}) *IMetaTable_AddCredential_Call { return &IMetaTable_AddCredential_Call{Call: _e.mock.On("AddCredential", credInfo)} } @@ -123,8 +123,8 @@ type IMetaTable_AddPartition_Call struct { } // AddPartition is a helper method to define mock.On call -// - ctx context.Context -// - partition *model.Partition +// - ctx context.Context +// - partition *model.Partition func (_e *IMetaTable_Expecter) AddPartition(ctx interface{}, partition interface{}) *IMetaTable_AddPartition_Call { return &IMetaTable_AddPartition_Call{Call: _e.mock.On("AddPartition", ctx, partition)} } @@ -161,10 +161,10 @@ type IMetaTable_AlterAlias_Call struct { } // AlterAlias is a helper method to define mock.On call -// - ctx context.Context -// - alias string -// - collectionName string -// - ts uint64 +// - ctx context.Context +// - alias string +// - collectionName string +// - ts uint64 func (_e *IMetaTable_Expecter) AlterAlias(ctx interface{}, alias interface{}, collectionName interface{}, ts interface{}) *IMetaTable_AlterAlias_Call { return &IMetaTable_AlterAlias_Call{Call: _e.mock.On("AlterAlias", ctx, alias, collectionName, ts)} } @@ -201,10 +201,10 @@ type IMetaTable_AlterCollection_Call struct { } // AlterCollection is a helper method to define mock.On call -// - ctx context.Context -// - oldColl *model.Collection -// - newColl *model.Collection -// - ts uint64 +// - ctx context.Context +// - oldColl *model.Collection +// - newColl *model.Collection +// - ts uint64 func (_e *IMetaTable_Expecter) AlterCollection(ctx interface{}, oldColl interface{}, newColl interface{}, ts interface{}) *IMetaTable_AlterCollection_Call { return &IMetaTable_AlterCollection_Call{Call: _e.mock.On("AlterCollection", ctx, oldColl, newColl, ts)} } @@ -241,7 +241,7 @@ type IMetaTable_AlterCredential_Call struct { } // AlterCredential is a helper method to define mock.On call -// - credInfo *internalpb.CredentialInfo +// - credInfo *internalpb.CredentialInfo func (_e *IMetaTable_Expecter) AlterCredential(credInfo interface{}) *IMetaTable_AlterCredential_Call { return &IMetaTable_AlterCredential_Call{Call: _e.mock.On("AlterCredential", credInfo)} } @@ -278,10 +278,10 @@ type IMetaTable_ChangeCollectionState_Call struct { } // ChangeCollectionState is a helper method to define mock.On call -// - ctx context.Context -// - collectionID int64 -// - state etcdpb.CollectionState -// - ts uint64 +// - ctx context.Context +// - collectionID int64 +// - state etcdpb.CollectionState +// - ts uint64 func (_e *IMetaTable_Expecter) ChangeCollectionState(ctx interface{}, collectionID interface{}, state interface{}, ts interface{}) *IMetaTable_ChangeCollectionState_Call { return &IMetaTable_ChangeCollectionState_Call{Call: _e.mock.On("ChangeCollectionState", ctx, collectionID, state, ts)} } @@ -318,11 +318,11 @@ type IMetaTable_ChangePartitionState_Call struct { } // ChangePartitionState is a helper method to define mock.On call -// - ctx context.Context -// - collectionID int64 -// - partitionID int64 -// - state etcdpb.PartitionState -// - ts uint64 +// - ctx context.Context +// - collectionID int64 +// - partitionID int64 +// - state etcdpb.PartitionState +// - ts uint64 func (_e *IMetaTable_Expecter) ChangePartitionState(ctx interface{}, collectionID interface{}, partitionID interface{}, state interface{}, ts interface{}) *IMetaTable_ChangePartitionState_Call { return &IMetaTable_ChangePartitionState_Call{Call: _e.mock.On("ChangePartitionState", ctx, collectionID, partitionID, state, ts)} } @@ -359,10 +359,10 @@ type IMetaTable_CreateAlias_Call struct { } // CreateAlias is a helper method to define mock.On call -// - ctx context.Context -// - alias string -// - collectionName string -// - ts uint64 +// - ctx context.Context +// - alias string +// - collectionName string +// - ts uint64 func (_e *IMetaTable_Expecter) CreateAlias(ctx interface{}, alias interface{}, collectionName interface{}, ts interface{}) *IMetaTable_CreateAlias_Call { return &IMetaTable_CreateAlias_Call{Call: _e.mock.On("CreateAlias", ctx, alias, collectionName, ts)} } @@ -399,8 +399,8 @@ type IMetaTable_CreateRole_Call struct { } // CreateRole is a helper method to define mock.On call -// - tenant string -// - entity *milvuspb.RoleEntity +// - tenant string +// - entity *milvuspb.RoleEntity func (_e *IMetaTable_Expecter) CreateRole(tenant interface{}, entity interface{}) *IMetaTable_CreateRole_Call { return &IMetaTable_CreateRole_Call{Call: _e.mock.On("CreateRole", tenant, entity)} } @@ -437,7 +437,7 @@ type IMetaTable_DeleteCredential_Call struct { } // DeleteCredential is a helper method to define mock.On call -// - username string +// - username string func (_e *IMetaTable_Expecter) DeleteCredential(username interface{}) *IMetaTable_DeleteCredential_Call { return &IMetaTable_DeleteCredential_Call{Call: _e.mock.On("DeleteCredential", username)} } @@ -474,9 +474,9 @@ type IMetaTable_DropAlias_Call struct { } // DropAlias is a helper method to define mock.On call -// - ctx context.Context -// - alias string -// - ts uint64 +// - ctx context.Context +// - alias string +// - ts uint64 func (_e *IMetaTable_Expecter) DropAlias(ctx interface{}, alias interface{}, ts interface{}) *IMetaTable_DropAlias_Call { return &IMetaTable_DropAlias_Call{Call: _e.mock.On("DropAlias", ctx, alias, ts)} } @@ -513,8 +513,8 @@ type IMetaTable_DropGrant_Call struct { } // DropGrant is a helper method to define mock.On call -// - tenant string -// - role *milvuspb.RoleEntity +// - tenant string +// - role *milvuspb.RoleEntity func (_e *IMetaTable_Expecter) DropGrant(tenant interface{}, role interface{}) *IMetaTable_DropGrant_Call { return &IMetaTable_DropGrant_Call{Call: _e.mock.On("DropGrant", tenant, role)} } @@ -551,8 +551,8 @@ type IMetaTable_DropRole_Call struct { } // DropRole is a helper method to define mock.On call -// - tenant string -// - roleName string +// - tenant string +// - roleName string func (_e *IMetaTable_Expecter) DropRole(tenant interface{}, roleName interface{}) *IMetaTable_DropRole_Call { return &IMetaTable_DropRole_Call{Call: _e.mock.On("DropRole", tenant, roleName)} } @@ -598,10 +598,10 @@ type IMetaTable_GetCollectionByID_Call struct { } // GetCollectionByID is a helper method to define mock.On call -// - ctx context.Context -// - collectionID int64 -// - ts uint64 -// - allowUnavailable bool +// - ctx context.Context +// - collectionID int64 +// - ts uint64 +// - allowUnavailable bool func (_e *IMetaTable_Expecter) GetCollectionByID(ctx interface{}, collectionID interface{}, ts interface{}, allowUnavailable interface{}) *IMetaTable_GetCollectionByID_Call { return &IMetaTable_GetCollectionByID_Call{Call: _e.mock.On("GetCollectionByID", ctx, collectionID, ts, allowUnavailable)} } @@ -647,9 +647,9 @@ type IMetaTable_GetCollectionByName_Call struct { } // GetCollectionByName is a helper method to define mock.On call -// - ctx context.Context -// - collectionName string -// - ts uint64 +// - ctx context.Context +// - collectionName string +// - ts uint64 func (_e *IMetaTable_Expecter) GetCollectionByName(ctx interface{}, collectionName interface{}, ts interface{}) *IMetaTable_GetCollectionByName_Call { return &IMetaTable_GetCollectionByName_Call{Call: _e.mock.On("GetCollectionByName", ctx, collectionName, ts)} } @@ -688,7 +688,7 @@ type IMetaTable_GetCollectionVirtualChannels_Call struct { } // GetCollectionVirtualChannels is a helper method to define mock.On call -// - colID int64 +// - colID int64 func (_e *IMetaTable_Expecter) GetCollectionVirtualChannels(colID interface{}) *IMetaTable_GetCollectionVirtualChannels_Call { return &IMetaTable_GetCollectionVirtualChannels_Call{Call: _e.mock.On("GetCollectionVirtualChannels", colID)} } @@ -734,7 +734,7 @@ type IMetaTable_GetCredential_Call struct { } // GetCredential is a helper method to define mock.On call -// - username string +// - username string func (_e *IMetaTable_Expecter) GetCredential(username interface{}) *IMetaTable_GetCredential_Call { return &IMetaTable_GetCredential_Call{Call: _e.mock.On("GetCredential", username)} } @@ -778,9 +778,9 @@ type IMetaTable_GetPartitionByName_Call struct { } // GetPartitionByName is a helper method to define mock.On call -// - collID int64 -// - partitionName string -// - ts uint64 +// - collID int64 +// - partitionName string +// - ts uint64 func (_e *IMetaTable_Expecter) GetPartitionByName(collID interface{}, partitionName interface{}, ts interface{}) *IMetaTable_GetPartitionByName_Call { return &IMetaTable_GetPartitionByName_Call{Call: _e.mock.On("GetPartitionByName", collID, partitionName, ts)} } @@ -824,9 +824,9 @@ type IMetaTable_GetPartitionNameByID_Call struct { } // GetPartitionNameByID is a helper method to define mock.On call -// - collID int64 -// - partitionID int64 -// - ts uint64 +// - collID int64 +// - partitionID int64 +// - ts uint64 func (_e *IMetaTable_Expecter) GetPartitionNameByID(collID interface{}, partitionID interface{}, ts interface{}) *IMetaTable_GetPartitionNameByID_Call { return &IMetaTable_GetPartitionNameByID_Call{Call: _e.mock.On("GetPartitionNameByID", collID, partitionID, ts)} } @@ -863,7 +863,7 @@ type IMetaTable_IsAlias_Call struct { } // IsAlias is a helper method to define mock.On call -// - name string +// - name string func (_e *IMetaTable_Expecter) IsAlias(name interface{}) *IMetaTable_IsAlias_Call { return &IMetaTable_IsAlias_Call{Call: _e.mock.On("IsAlias", name)} } @@ -909,8 +909,8 @@ type IMetaTable_ListAbnormalCollections_Call struct { } // ListAbnormalCollections is a helper method to define mock.On call -// - ctx context.Context -// - ts uint64 +// - ctx context.Context +// - ts uint64 func (_e *IMetaTable_Expecter) ListAbnormalCollections(ctx interface{}, ts interface{}) *IMetaTable_ListAbnormalCollections_Call { return &IMetaTable_ListAbnormalCollections_Call{Call: _e.mock.On("ListAbnormalCollections", ctx, ts)} } @@ -949,7 +949,7 @@ type IMetaTable_ListAliasesByID_Call struct { } // ListAliasesByID is a helper method to define mock.On call -// - collID int64 +// - collID int64 func (_e *IMetaTable_Expecter) ListAliasesByID(collID interface{}) *IMetaTable_ListAliasesByID_Call { return &IMetaTable_ListAliasesByID_Call{Call: _e.mock.On("ListAliasesByID", collID)} } @@ -1033,8 +1033,8 @@ type IMetaTable_ListCollections_Call struct { } // ListCollections is a helper method to define mock.On call -// - ctx context.Context -// - ts uint64 +// - ctx context.Context +// - ts uint64 func (_e *IMetaTable_Expecter) ListCollections(ctx interface{}, ts interface{}) *IMetaTable_ListCollections_Call { return &IMetaTable_ListCollections_Call{Call: _e.mock.On("ListCollections", ctx, ts)} } @@ -1125,7 +1125,7 @@ type IMetaTable_ListPolicy_Call struct { } // ListPolicy is a helper method to define mock.On call -// - tenant string +// - tenant string func (_e *IMetaTable_Expecter) ListPolicy(tenant interface{}) *IMetaTable_ListPolicy_Call { return &IMetaTable_ListPolicy_Call{Call: _e.mock.On("ListPolicy", tenant)} } @@ -1171,7 +1171,7 @@ type IMetaTable_ListUserRole_Call struct { } // ListUserRole is a helper method to define mock.On call -// - tenant string +// - tenant string func (_e *IMetaTable_Expecter) ListUserRole(tenant interface{}) *IMetaTable_ListUserRole_Call { return &IMetaTable_ListUserRole_Call{Call: _e.mock.On("ListUserRole", tenant)} } @@ -1208,9 +1208,9 @@ type IMetaTable_OperatePrivilege_Call struct { } // OperatePrivilege is a helper method to define mock.On call -// - tenant string -// - entity *milvuspb.GrantEntity -// - operateType milvuspb.OperatePrivilegeType +// - tenant string +// - entity *milvuspb.GrantEntity +// - operateType milvuspb.OperatePrivilegeType func (_e *IMetaTable_Expecter) OperatePrivilege(tenant interface{}, entity interface{}, operateType interface{}) *IMetaTable_OperatePrivilege_Call { return &IMetaTable_OperatePrivilege_Call{Call: _e.mock.On("OperatePrivilege", tenant, entity, operateType)} } @@ -1247,10 +1247,10 @@ type IMetaTable_OperateUserRole_Call struct { } // OperateUserRole is a helper method to define mock.On call -// - tenant string -// - userEntity *milvuspb.UserEntity -// - roleEntity *milvuspb.RoleEntity -// - operateType milvuspb.OperateUserRoleType +// - tenant string +// - userEntity *milvuspb.UserEntity +// - roleEntity *milvuspb.RoleEntity +// - operateType milvuspb.OperateUserRoleType func (_e *IMetaTable_Expecter) OperateUserRole(tenant interface{}, userEntity interface{}, roleEntity interface{}, operateType interface{}) *IMetaTable_OperateUserRole_Call { return &IMetaTable_OperateUserRole_Call{Call: _e.mock.On("OperateUserRole", tenant, userEntity, roleEntity, operateType)} } @@ -1287,9 +1287,9 @@ type IMetaTable_RemoveCollection_Call struct { } // RemoveCollection is a helper method to define mock.On call -// - ctx context.Context -// - collectionID int64 -// - ts uint64 +// - ctx context.Context +// - collectionID int64 +// - ts uint64 func (_e *IMetaTable_Expecter) RemoveCollection(ctx interface{}, collectionID interface{}, ts interface{}) *IMetaTable_RemoveCollection_Call { return &IMetaTable_RemoveCollection_Call{Call: _e.mock.On("RemoveCollection", ctx, collectionID, ts)} } @@ -1326,10 +1326,10 @@ type IMetaTable_RemovePartition_Call struct { } // RemovePartition is a helper method to define mock.On call -// - ctx context.Context -// - collectionID int64 -// - partitionID int64 -// - ts uint64 +// - ctx context.Context +// - collectionID int64 +// - partitionID int64 +// - ts uint64 func (_e *IMetaTable_Expecter) RemovePartition(ctx interface{}, collectionID interface{}, partitionID interface{}, ts interface{}) *IMetaTable_RemovePartition_Call { return &IMetaTable_RemovePartition_Call{Call: _e.mock.On("RemovePartition", ctx, collectionID, partitionID, ts)} } @@ -1346,6 +1346,46 @@ func (_c *IMetaTable_RemovePartition_Call) Return(_a0 error) *IMetaTable_RemoveP return _c } +// RenameCollection provides a mock function with given fields: ctx, oldName, newName, ts +func (_m *IMetaTable) RenameCollection(ctx context.Context, oldName string, newName string, ts uint64) error { + ret := _m.Called(ctx, oldName, newName, ts) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, uint64) error); ok { + r0 = rf(ctx, oldName, newName, ts) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// IMetaTable_RenameCollection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenameCollection' +type IMetaTable_RenameCollection_Call struct { + *mock.Call +} + +// RenameCollection is a helper method to define mock.On call +// - ctx context.Context +// - oldName string +// - newName string +// - ts uint64 +func (_e *IMetaTable_Expecter) RenameCollection(ctx interface{}, oldName interface{}, newName interface{}, ts interface{}) *IMetaTable_RenameCollection_Call { + return &IMetaTable_RenameCollection_Call{Call: _e.mock.On("RenameCollection", ctx, oldName, newName, ts)} +} + +func (_c *IMetaTable_RenameCollection_Call) Run(run func(ctx context.Context, oldName string, newName string, ts uint64)) *IMetaTable_RenameCollection_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(uint64)) + }) + return _c +} + +func (_c *IMetaTable_RenameCollection_Call) Return(_a0 error) *IMetaTable_RenameCollection_Call { + _c.Call.Return(_a0) + return _c +} + // SelectGrant provides a mock function with given fields: tenant, entity func (_m *IMetaTable) SelectGrant(tenant string, entity *milvuspb.GrantEntity) ([]*milvuspb.GrantEntity, error) { ret := _m.Called(tenant, entity) @@ -1375,8 +1415,8 @@ type IMetaTable_SelectGrant_Call struct { } // SelectGrant is a helper method to define mock.On call -// - tenant string -// - entity *milvuspb.GrantEntity +// - tenant string +// - entity *milvuspb.GrantEntity func (_e *IMetaTable_Expecter) SelectGrant(tenant interface{}, entity interface{}) *IMetaTable_SelectGrant_Call { return &IMetaTable_SelectGrant_Call{Call: _e.mock.On("SelectGrant", tenant, entity)} } @@ -1422,9 +1462,9 @@ type IMetaTable_SelectRole_Call struct { } // SelectRole is a helper method to define mock.On call -// - tenant string -// - entity *milvuspb.RoleEntity -// - includeUserInfo bool +// - tenant string +// - entity *milvuspb.RoleEntity +// - includeUserInfo bool func (_e *IMetaTable_Expecter) SelectRole(tenant interface{}, entity interface{}, includeUserInfo interface{}) *IMetaTable_SelectRole_Call { return &IMetaTable_SelectRole_Call{Call: _e.mock.On("SelectRole", tenant, entity, includeUserInfo)} } @@ -1470,9 +1510,9 @@ type IMetaTable_SelectUser_Call struct { } // SelectUser is a helper method to define mock.On call -// - tenant string -// - entity *milvuspb.UserEntity -// - includeRoleInfo bool +// - tenant string +// - entity *milvuspb.UserEntity +// - includeRoleInfo bool func (_e *IMetaTable_Expecter) SelectUser(tenant interface{}, entity interface{}, includeRoleInfo interface{}) *IMetaTable_SelectUser_Call { return &IMetaTable_SelectUser_Call{Call: _e.mock.On("SelectUser", tenant, entity, includeRoleInfo)} } diff --git a/internal/rootcoord/rename_collection_task.go b/internal/rootcoord/rename_collection_task.go new file mode 100644 index 0000000000..e36fa4b55c --- /dev/null +++ b/internal/rootcoord/rename_collection_task.go @@ -0,0 +1,27 @@ +package rootcoord + +import ( + "context" + + "github.com/milvus-io/milvus-proto/go-api/commonpb" + "github.com/milvus-io/milvus-proto/go-api/milvuspb" +) + +type renameCollectionTask struct { + baseTask + Req *milvuspb.RenameCollectionRequest +} + +func (t *renameCollectionTask) Prepare(ctx context.Context) error { + if err := CheckMsgType(t.Req.GetBase().GetMsgType(), commonpb.MsgType_RenameCollection); err != nil { + return err + } + return nil +} + +func (t *renameCollectionTask) Execute(ctx context.Context) error { + if err := t.core.ExpireMetaCache(ctx, []string{t.Req.GetOldName()}, InvalidCollectionID, t.GetTs()); err != nil { + return err + } + return t.core.meta.RenameCollection(ctx, t.Req.GetOldName(), t.Req.GetNewName(), t.GetTs()) +} diff --git a/internal/rootcoord/rename_collection_task_test.go b/internal/rootcoord/rename_collection_task_test.go new file mode 100644 index 0000000000..dcb6dc9398 --- /dev/null +++ b/internal/rootcoord/rename_collection_task_test.go @@ -0,0 +1,74 @@ +package rootcoord + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/milvus-io/milvus-proto/go-api/commonpb" + + "github.com/milvus-io/milvus-proto/go-api/milvuspb" +) + +func Test_renameCollectionTask_Prepare(t *testing.T) { + t.Run("invalid msg type", func(t *testing.T) { + task := &renameCollectionTask{ + Req: &milvuspb.RenameCollectionRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_Undefined, + }, + }, + } + err := task.Prepare(context.Background()) + assert.Error(t, err) + }) + + t.Run("ok", func(t *testing.T) { + task := &renameCollectionTask{ + Req: &milvuspb.RenameCollectionRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_RenameCollection, + }, + }, + } + err := task.Prepare(context.Background()) + assert.NoError(t, err) + }) +} + +func Test_renameCollectionTask_Execute(t *testing.T) { + t.Run("failed to expire cache", func(t *testing.T) { + core := newTestCore(withInvalidProxyManager()) + task := &renameCollectionTask{ + baseTask: baseTask{core: core}, + Req: &milvuspb.RenameCollectionRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_RenameCollection, + }, + }, + } + err := task.Execute(context.Background()) + assert.Error(t, err) + }) + + t.Run("failed to rename collection", func(t *testing.T) { + meta := newMockMetaTable() + meta.RenameCollectionFunc = func(ctx context.Context, oldName string, newName string, ts Timestamp) error { + return errors.New("fail") + } + + core := newTestCore(withValidProxyManager(), withMeta(meta)) + task := &renameCollectionTask{ + baseTask: baseTask{core: core}, + Req: &milvuspb.RenameCollectionRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_RenameCollection, + }, + }, + } + err := task.Execute(context.Background()) + assert.Error(t, err) + }) +} diff --git a/internal/rootcoord/root_coord.go b/internal/rootcoord/root_coord.go index bdc98551ad..f9319676bf 100644 --- a/internal/rootcoord/root_coord.go +++ b/internal/rootcoord/root_coord.go @@ -2497,6 +2497,44 @@ func (c *Core) ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) }, nil } +func (c *Core) RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { + if code, ok := c.checkHealthy(); !ok { + return failStatus(commonpb.ErrorCode_UnexpectedError, "StateCode="+commonpb.StateCode_name[int32(code)]), nil + } + + log := log.Ctx(ctx).With(zap.String("oldCollectionName", req.GetOldName()), zap.String("newCollectionName", req.GetNewName())) + log.Info("received request to rename collection") + + metrics.RootCoordDDLReqCounter.WithLabelValues("RenameCollection", metrics.TotalLabel).Inc() + tr := timerecord.NewTimeRecorder("RenameCollection") + t := &renameCollectionTask{ + baseTask: baseTask{ + ctx: ctx, + core: c, + done: make(chan error, 1), + }, + Req: req, + } + + if err := c.scheduler.AddTask(t); err != nil { + log.Warn("failed to enqueue request to rename collection", zap.Error(err)) + metrics.RootCoordDDLReqCounter.WithLabelValues("RenameCollection", metrics.FailLabel).Inc() + return failStatus(commonpb.ErrorCode_UnexpectedError, err.Error()), nil + } + + if err := t.WaitToFinish(); err != nil { + log.Warn("failed to rename collection", zap.Uint64("ts", t.GetTs()), zap.Error(err)) + metrics.RootCoordDDLReqCounter.WithLabelValues("RenameCollection", metrics.FailLabel).Inc() + return failStatus(commonpb.ErrorCode_UnexpectedError, err.Error()), nil + } + + metrics.RootCoordDDLReqCounter.WithLabelValues("RenameCollection", metrics.SuccessLabel).Inc() + metrics.RootCoordDDLReqLatency.WithLabelValues("RenameCollection").Observe(float64(tr.ElapseSpan().Milliseconds())) + + log.Info("done to rename collection", zap.Uint64("ts", t.GetTs())) + return succStatus(), nil +} + func (c *Core) CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) { if _, ok := c.checkHealthy(); !ok { reason := errorutil.UnHealthReason("rootcoord", c.session.ServerID, "rootcoord is unhealthy") diff --git a/internal/rootcoord/root_coord_test.go b/internal/rootcoord/root_coord_test.go index a3bb21551a..f407d086bc 100644 --- a/internal/rootcoord/root_coord_test.go +++ b/internal/rootcoord/root_coord_test.go @@ -704,6 +704,46 @@ func TestRootCoord_InvalidateCollectionMetaCache(t *testing.T) { }) } +func TestRootCoord_RenameCollection(t *testing.T) { + t.Run("not healthy", func(t *testing.T) { + ctx := context.Background() + c := newTestCore(withAbnormalCode()) + resp, err := c.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetErrorCode()) + }) + + t.Run("add task failed", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withInvalidScheduler()) + + ctx := context.Background() + resp, err := c.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetErrorCode()) + }) + + t.Run("execute task failed", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withTaskFailScheduler()) + + ctx := context.Background() + resp, err := c.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetErrorCode()) + }) + + t.Run("run ok", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withValidScheduler()) + + ctx := context.Background() + resp, err := c.RenameCollection(ctx, &milvuspb.RenameCollectionRequest{}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetErrorCode()) + }) +} + func TestRootCoord_ShowConfigurations(t *testing.T) { t.Run("not healthy", func(t *testing.T) { ctx := context.Background() diff --git a/internal/types/types.go b/internal/types/types.go index 5e52ab78ed..94b4d92509 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -757,6 +757,8 @@ type RootCoord interface { ListPolicy(ctx context.Context, in *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) + + RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) } // RootCoordComponent is used by grpc server of RootCoord @@ -1299,6 +1301,9 @@ type ProxyComponent interface { SelectGrant(ctx context.Context, req *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) + + // RenameCollection rename collection from old name to new name + RenameCollection(ctx context.Context, req *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) } // QueryNode is the interface `querynode` package implements diff --git a/internal/util/mock/grpc_rootcoord_client.go b/internal/util/mock/grpc_rootcoord_client.go index 1d56496f25..f53aeed7f0 100644 --- a/internal/util/mock/grpc_rootcoord_client.go +++ b/internal/util/mock/grpc_rootcoord_client.go @@ -35,6 +35,10 @@ type GrpcRootCoordClient struct { Err error } +func (m *GrpcRootCoordClient) RenameCollection(ctx context.Context, in *milvuspb.RenameCollectionRequest, opts ...grpc.CallOption) (*commonpb.Status, error) { + return &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}, nil +} + func (m *GrpcRootCoordClient) CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest, opts ...grpc.CallOption) (*milvuspb.CheckHealthResponse, error) { return &milvuspb.CheckHealthResponse{}, m.Err }