diff --git a/README.md b/README.md index 0f08800d..fb40ef58 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ cargo build --release --features vector | command | description | |---------|-------------| | `VADD key element f32 [f32 ...] [METRIC COSINE\|L2\|IP] [QUANT F32\|F16\|Q8] [M n] [EF n]` | add a vector to the set | +| `VADD_BATCH key DIM n elem1 f32... elem2 f32... [METRIC\|QUANT\|M\|EF]` | add multiple vectors in one command | | `VSIM key f32 [f32 ...] COUNT k [EF n] [WITHSCORES]` | k nearest neighbors | | `VREM key element` | remove a vector | | `VGET key element` | retrieve stored vector values | @@ -303,7 +304,7 @@ contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). | 4 | clustering (raft, gossip, slots, migration) | ✅ complete | | 5 | developer experience (observability, CLI, clients) | 🚧 in progress | -**current**: 106 commands, 796+ tests, ~31k lines of code (excluding tests) +**current**: 107 commands, 796+ tests, ~31k lines of code (excluding tests) ## security diff --git a/bench/README.md b/bench/README.md index e376e813..b5031eef 100644 --- a/bench/README.md +++ b/bench/README.md @@ -52,7 +52,7 @@ tested on GCP c2-standard-8 (8 vCPU Intel Xeon @ 3.10GHz), Ubuntu 22.04. dragonfly in particular offers features ember simply doesn't have: -- full Redis API compatibility (200+ commands vs ember's ~106) +- full Redis API compatibility (200+ commands vs ember's ~107) - sophisticated memory management (dashtable for ~25% of Redis memory usage) - transactional semantics (MULTI/EXEC, Lua scripting) - fork-free snapshotting @@ -121,13 +121,13 @@ HNSW index: M=16, ef_construction=64 for all systems. tested on GCP c2-standard- | metric | ember (RESP) | ember (gRPC) | chromadb | pgvector | qdrant | |--------|-------------|-------------|----------|----------|--------| -| insert (vectors/sec) | 963 | 1,009 | **3,891** | 1,617 | **7,747** | -| query (queries/sec) | 1,264 | **1,462** | 390 | 831 | 596 | -| query p50 (ms) | 0.79ms | **0.68ms** | 2.56ms | 1.18ms | 1.67ms | -| query p99 (ms) | 0.93ms | **0.83ms** | 2.76ms | 1.56ms | 1.88ms | -| memory (MB) | **36 MB** | — | 122 MB | 179 MB | 121 MB | +| insert (vectors/sec) | 1,483 | 2,374 | 3,679 | 1,513 | **7,382** | +| query (queries/sec) | 1,212 | **1,452** | 383 | 843 | 589 | +| query p50 (ms) | 0.82ms | **0.68ms** | 2.60ms | 1.16ms | 1.69ms | +| query p99 (ms) | 1.00ms | **0.86ms** | 2.82ms | 1.61ms | 1.93ms | +| memory (MB) | **38 MB** | — | 123 MB | 179 MB | 122 MB | -ember's query throughput is 3.2x chromadb, 1.5x pgvector, and 2.1x qdrant, with 3-5x lower memory usage. gRPC queries are 16% faster than RESP due to lower serialization overhead. insert throughput is lower due to per-vector protocol overhead — qdrant's batch API gives it a significant edge on ingestion. +ember's query throughput is 3.2x chromadb, 1.4x pgvector, and 2.1x qdrant, with 3-5x lower memory usage. gRPC queries are 20% faster than RESP due to lower serialization overhead. insert throughput uses VADD_BATCH (batches of 500 vectors per command) — the gRPC path benefits most since packed floats avoid string parsing entirely. #### SIFT1M recall accuracy (128-dim, 1M vectors, 10k queries) diff --git a/bench/bench-memory.sh b/bench/bench-memory.sh index c1292d38..f9509c14 100755 --- a/bench/bench-memory.sh +++ b/bench/bench-memory.sh @@ -326,18 +326,22 @@ dim = int(sys.argv[3]) r = redis.Redis(host="127.0.0.1", port=port, decode_responses=True) -for i in range(count): - vec = [random.gauss(0, 1) for _ in range(dim)] - norm = sum(v * v for v in vec) ** 0.5 - vec = [v / norm for v in vec] - - args = ["VADD", "vectors", f"v{i}"] + [str(v) for v in vec] - if i == 0: +batch_size = 500 +for start in range(0, count, batch_size): + end = min(start + batch_size, count) + args = ["vectors", "DIM", str(dim)] + for i in range(start, end): + vec = [random.gauss(0, 1) for _ in range(dim)] + norm = sum(v * v for v in vec) ** 0.5 + vec = [v / norm for v in vec] + args.append(f"v{i}") + args.extend(str(v) for v in vec) + if start == 0: args += ["METRIC", "COSINE"] - r.execute_command(*args) + r.execute_command("VADD_BATCH", *args) - if (i + 1) % 10000 == 0: - print(f" inserted {i + 1}/{count} vectors", file=sys.stderr) + if end % 10000 == 0 or end == count: + print(f" inserted {end}/{count} vectors", file=sys.stderr) PYEOF # vector requires sharded mode diff --git a/bench/bench-vector.py b/bench/bench-vector.py index fbf13ede..53984a37 100755 --- a/bench/bench-vector.py +++ b/bench/bench-vector.py @@ -75,14 +75,13 @@ def setup(self, dim: int, metric: str = "cosine"): self.conn.delete(self.key) def insert_batch(self, ids: list, vectors: np.ndarray): - pipe = self.conn.pipeline(transaction=False) + dim = vectors.shape[1] + args = [self.key, "DIM", str(dim)] for i, vid in enumerate(ids): - vec = vectors[i] - # VADD key element v1 v2 ... METRIC COSINE M 16 EF 64 - args = [self.key, vid] + [str(float(v)) for v in vec] - args += ["METRIC", "COSINE", "M", "16", "EF", "64"] - pipe.execute_command("VADD", *args) - pipe.execute() + args.append(vid) + args.extend(str(float(v)) for v in vectors[i]) + args += ["METRIC", "COSINE", "M", "16", "EF", "64"] + self.conn.execute_command("VADD_BATCH", *args) def query(self, vector: np.ndarray, k: int) -> list: args = [self.key] + [str(float(v)) for v in vector] @@ -116,9 +115,8 @@ def setup(self, dim: int, metric: str = "cosine"): self.client.flushdb() def insert_batch(self, ids: list, vectors: np.ndarray): - for i, vid in enumerate(ids): - vec = vectors[i].tolist() - self.client.vadd(self.key, vid, vec, metric="cosine", m=16, ef=64) + entries = [(vid, vectors[i].tolist()) for i, vid in enumerate(ids)] + self.client.vadd_batch(self.key, entries, metric="cosine", m=16, ef=64) def query(self, vector: np.ndarray, k: int) -> list: results = self.client.vsim(self.key, vector.tolist(), count=k) diff --git a/bench/bench-vector.sh b/bench/bench-vector.sh index 69f65140..a96d3a6d 100755 --- a/bench/bench-vector.sh +++ b/bench/bench-vector.sh @@ -242,10 +242,10 @@ elif [[ "$QDRANT" == "true" ]] && ! python3 -c "import qdrant_client" 2>/dev/nul pip install --quiet $REQUIRED_DEPS fi -# install ember-py for gRPC benchmarks +# install ember-py for gRPC benchmarks (also install base deps into venv) if [[ "$EMBER_GRPC" == "true" ]]; then ensure_venv - pip install --quiet ./clients/ember-py + pip install --quiet $REQUIRED_DEPS ./clients/ember-py fi # build ember if needed diff --git a/clients/ember-go/proto/ember/v1/ember.pb.go b/clients/ember-go/proto/ember/v1/ember.pb.go index 823da814..56795d6f 100644 --- a/clients/ember-go/proto/ember/v1/ember.pb.go +++ b/clients/ember-go/proto/ember/v1/ember.pb.go @@ -3743,6 +3743,142 @@ func (x *VAddRequest) GetEfConstruction() uint32 { return 0 } +type VAddBatchEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Element string `protobuf:"bytes,1,opt,name=element,proto3" json:"element,omitempty"` + Vector []float32 `protobuf:"fixed32,2,rep,packed,name=vector,proto3" json:"vector,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VAddBatchEntry) Reset() { + *x = VAddBatchEntry{} + mi := &file_ember_v1_ember_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VAddBatchEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VAddBatchEntry) ProtoMessage() {} + +func (x *VAddBatchEntry) ProtoReflect() protoreflect.Message { + mi := &file_ember_v1_ember_proto_msgTypes[72] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VAddBatchEntry.ProtoReflect.Descriptor instead. +func (*VAddBatchEntry) Descriptor() ([]byte, []int) { + return file_ember_v1_ember_proto_rawDescGZIP(), []int{72} +} + +func (x *VAddBatchEntry) GetElement() string { + if x != nil { + return x.Element + } + return "" +} + +func (x *VAddBatchEntry) GetVector() []float32 { + if x != nil { + return x.Vector + } + return nil +} + +type VAddBatchRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Entries []*VAddBatchEntry `protobuf:"bytes,2,rep,name=entries,proto3" json:"entries,omitempty"` + Metric VectorMetric `protobuf:"varint,3,opt,name=metric,proto3,enum=ember.v1.VectorMetric" json:"metric,omitempty"` + Quantization VectorQuantization `protobuf:"varint,4,opt,name=quantization,proto3,enum=ember.v1.VectorQuantization" json:"quantization,omitempty"` + Connectivity *uint32 `protobuf:"varint,5,opt,name=connectivity,proto3,oneof" json:"connectivity,omitempty"` + EfConstruction *uint32 `protobuf:"varint,6,opt,name=ef_construction,json=efConstruction,proto3,oneof" json:"ef_construction,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VAddBatchRequest) Reset() { + *x = VAddBatchRequest{} + mi := &file_ember_v1_ember_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VAddBatchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VAddBatchRequest) ProtoMessage() {} + +func (x *VAddBatchRequest) ProtoReflect() protoreflect.Message { + mi := &file_ember_v1_ember_proto_msgTypes[73] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VAddBatchRequest.ProtoReflect.Descriptor instead. +func (*VAddBatchRequest) Descriptor() ([]byte, []int) { + return file_ember_v1_ember_proto_rawDescGZIP(), []int{73} +} + +func (x *VAddBatchRequest) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *VAddBatchRequest) GetEntries() []*VAddBatchEntry { + if x != nil { + return x.Entries + } + return nil +} + +func (x *VAddBatchRequest) GetMetric() VectorMetric { + if x != nil { + return x.Metric + } + return VectorMetric_VECTOR_METRIC_COSINE +} + +func (x *VAddBatchRequest) GetQuantization() VectorQuantization { + if x != nil { + return x.Quantization + } + return VectorQuantization_VECTOR_QUANTIZATION_NONE +} + +func (x *VAddBatchRequest) GetConnectivity() uint32 { + if x != nil && x.Connectivity != nil { + return *x.Connectivity + } + return 0 +} + +func (x *VAddBatchRequest) GetEfConstruction() uint32 { + if x != nil && x.EfConstruction != nil { + return *x.EfConstruction + } + return 0 +} + type VSimRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` @@ -3755,7 +3891,7 @@ type VSimRequest struct { func (x *VSimRequest) Reset() { *x = VSimRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[72] + mi := &file_ember_v1_ember_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3767,7 +3903,7 @@ func (x *VSimRequest) String() string { func (*VSimRequest) ProtoMessage() {} func (x *VSimRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[72] + mi := &file_ember_v1_ember_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3780,7 +3916,7 @@ func (x *VSimRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VSimRequest.ProtoReflect.Descriptor instead. func (*VSimRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{72} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{74} } func (x *VSimRequest) GetKey() string { @@ -3820,7 +3956,7 @@ type VSimResponse struct { func (x *VSimResponse) Reset() { *x = VSimResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[73] + mi := &file_ember_v1_ember_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3832,7 +3968,7 @@ func (x *VSimResponse) String() string { func (*VSimResponse) ProtoMessage() {} func (x *VSimResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[73] + mi := &file_ember_v1_ember_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3845,7 +3981,7 @@ func (x *VSimResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VSimResponse.ProtoReflect.Descriptor instead. func (*VSimResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{73} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{75} } func (x *VSimResponse) GetResults() []*VSimResult { @@ -3865,7 +4001,7 @@ type VSimResult struct { func (x *VSimResult) Reset() { *x = VSimResult{} - mi := &file_ember_v1_ember_proto_msgTypes[74] + mi := &file_ember_v1_ember_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3877,7 +4013,7 @@ func (x *VSimResult) String() string { func (*VSimResult) ProtoMessage() {} func (x *VSimResult) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[74] + mi := &file_ember_v1_ember_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3890,7 +4026,7 @@ func (x *VSimResult) ProtoReflect() protoreflect.Message { // Deprecated: Use VSimResult.ProtoReflect.Descriptor instead. func (*VSimResult) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{74} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{76} } func (x *VSimResult) GetElement() string { @@ -3917,7 +4053,7 @@ type VRemRequest struct { func (x *VRemRequest) Reset() { *x = VRemRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[75] + mi := &file_ember_v1_ember_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3929,7 +4065,7 @@ func (x *VRemRequest) String() string { func (*VRemRequest) ProtoMessage() {} func (x *VRemRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[75] + mi := &file_ember_v1_ember_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3942,7 +4078,7 @@ func (x *VRemRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VRemRequest.ProtoReflect.Descriptor instead. func (*VRemRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{75} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{77} } func (x *VRemRequest) GetKey() string { @@ -3969,7 +4105,7 @@ type VGetRequest struct { func (x *VGetRequest) Reset() { *x = VGetRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[76] + mi := &file_ember_v1_ember_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3981,7 +4117,7 @@ func (x *VGetRequest) String() string { func (*VGetRequest) ProtoMessage() {} func (x *VGetRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[76] + mi := &file_ember_v1_ember_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3994,7 +4130,7 @@ func (x *VGetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VGetRequest.ProtoReflect.Descriptor instead. func (*VGetRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{76} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{78} } func (x *VGetRequest) GetKey() string { @@ -4021,7 +4157,7 @@ type VGetResponse struct { func (x *VGetResponse) Reset() { *x = VGetResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[77] + mi := &file_ember_v1_ember_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4033,7 +4169,7 @@ func (x *VGetResponse) String() string { func (*VGetResponse) ProtoMessage() {} func (x *VGetResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[77] + mi := &file_ember_v1_ember_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4046,7 +4182,7 @@ func (x *VGetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VGetResponse.ProtoReflect.Descriptor instead. func (*VGetResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{77} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{79} } func (x *VGetResponse) GetExists() bool { @@ -4072,7 +4208,7 @@ type VCardRequest struct { func (x *VCardRequest) Reset() { *x = VCardRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[78] + mi := &file_ember_v1_ember_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4084,7 +4220,7 @@ func (x *VCardRequest) String() string { func (*VCardRequest) ProtoMessage() {} func (x *VCardRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[78] + mi := &file_ember_v1_ember_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4097,7 +4233,7 @@ func (x *VCardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VCardRequest.ProtoReflect.Descriptor instead. func (*VCardRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{78} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{80} } func (x *VCardRequest) GetKey() string { @@ -4116,7 +4252,7 @@ type VDimRequest struct { func (x *VDimRequest) Reset() { *x = VDimRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[79] + mi := &file_ember_v1_ember_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4128,7 +4264,7 @@ func (x *VDimRequest) String() string { func (*VDimRequest) ProtoMessage() {} func (x *VDimRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[79] + mi := &file_ember_v1_ember_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4141,7 +4277,7 @@ func (x *VDimRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VDimRequest.ProtoReflect.Descriptor instead. func (*VDimRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{79} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{81} } func (x *VDimRequest) GetKey() string { @@ -4160,7 +4296,7 @@ type VInfoRequest struct { func (x *VInfoRequest) Reset() { *x = VInfoRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[80] + mi := &file_ember_v1_ember_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4172,7 +4308,7 @@ func (x *VInfoRequest) String() string { func (*VInfoRequest) ProtoMessage() {} func (x *VInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[80] + mi := &file_ember_v1_ember_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4185,7 +4321,7 @@ func (x *VInfoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VInfoRequest.ProtoReflect.Descriptor instead. func (*VInfoRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{80} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{82} } func (x *VInfoRequest) GetKey() string { @@ -4205,7 +4341,7 @@ type VInfoResponse struct { func (x *VInfoResponse) Reset() { *x = VInfoResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[81] + mi := &file_ember_v1_ember_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4217,7 +4353,7 @@ func (x *VInfoResponse) String() string { func (*VInfoResponse) ProtoMessage() {} func (x *VInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[81] + mi := &file_ember_v1_ember_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4230,7 +4366,7 @@ func (x *VInfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VInfoResponse.ProtoReflect.Descriptor instead. func (*VInfoResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{81} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{83} } func (x *VInfoResponse) GetExists() bool { @@ -4256,7 +4392,7 @@ type PingRequest struct { func (x *PingRequest) Reset() { *x = PingRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[82] + mi := &file_ember_v1_ember_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4268,7 +4404,7 @@ func (x *PingRequest) String() string { func (*PingRequest) ProtoMessage() {} func (x *PingRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[82] + mi := &file_ember_v1_ember_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4281,7 +4417,7 @@ func (x *PingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. func (*PingRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{82} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{84} } func (x *PingRequest) GetMessage() string { @@ -4300,7 +4436,7 @@ type PingResponse struct { func (x *PingResponse) Reset() { *x = PingResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[83] + mi := &file_ember_v1_ember_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4312,7 +4448,7 @@ func (x *PingResponse) String() string { func (*PingResponse) ProtoMessage() {} func (x *PingResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[83] + mi := &file_ember_v1_ember_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4325,7 +4461,7 @@ func (x *PingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. func (*PingResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{83} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{85} } func (x *PingResponse) GetMessage() string { @@ -4344,7 +4480,7 @@ type FlushDbRequest struct { func (x *FlushDbRequest) Reset() { *x = FlushDbRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[84] + mi := &file_ember_v1_ember_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4356,7 +4492,7 @@ func (x *FlushDbRequest) String() string { func (*FlushDbRequest) ProtoMessage() {} func (x *FlushDbRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[84] + mi := &file_ember_v1_ember_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4369,7 +4505,7 @@ func (x *FlushDbRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FlushDbRequest.ProtoReflect.Descriptor instead. func (*FlushDbRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{84} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{86} } func (x *FlushDbRequest) GetAsync() bool { @@ -4387,7 +4523,7 @@ type DbSizeRequest struct { func (x *DbSizeRequest) Reset() { *x = DbSizeRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[85] + mi := &file_ember_v1_ember_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4399,7 +4535,7 @@ func (x *DbSizeRequest) String() string { func (*DbSizeRequest) ProtoMessage() {} func (x *DbSizeRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[85] + mi := &file_ember_v1_ember_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4412,7 +4548,7 @@ func (x *DbSizeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DbSizeRequest.ProtoReflect.Descriptor instead. func (*DbSizeRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{85} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{87} } type InfoRequest struct { @@ -4424,7 +4560,7 @@ type InfoRequest struct { func (x *InfoRequest) Reset() { *x = InfoRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[86] + mi := &file_ember_v1_ember_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4436,7 +4572,7 @@ func (x *InfoRequest) String() string { func (*InfoRequest) ProtoMessage() {} func (x *InfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[86] + mi := &file_ember_v1_ember_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4449,7 +4585,7 @@ func (x *InfoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InfoRequest.ProtoReflect.Descriptor instead. func (*InfoRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{86} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{88} } func (x *InfoRequest) GetSection() string { @@ -4468,7 +4604,7 @@ type InfoResponse struct { func (x *InfoResponse) Reset() { *x = InfoResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[87] + mi := &file_ember_v1_ember_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4480,7 +4616,7 @@ func (x *InfoResponse) String() string { func (*InfoResponse) ProtoMessage() {} func (x *InfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[87] + mi := &file_ember_v1_ember_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4493,7 +4629,7 @@ func (x *InfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead. func (*InfoResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{87} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{89} } func (x *InfoResponse) GetInfo() string { @@ -4512,7 +4648,7 @@ type EchoRequest struct { func (x *EchoRequest) Reset() { *x = EchoRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[88] + mi := &file_ember_v1_ember_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4524,7 +4660,7 @@ func (x *EchoRequest) String() string { func (*EchoRequest) ProtoMessage() {} func (x *EchoRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[88] + mi := &file_ember_v1_ember_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4537,7 +4673,7 @@ func (x *EchoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EchoRequest.ProtoReflect.Descriptor instead. func (*EchoRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{88} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{90} } func (x *EchoRequest) GetMessage() string { @@ -4556,7 +4692,7 @@ type EchoResponse struct { func (x *EchoResponse) Reset() { *x = EchoResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[89] + mi := &file_ember_v1_ember_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4568,7 +4704,7 @@ func (x *EchoResponse) String() string { func (*EchoResponse) ProtoMessage() {} func (x *EchoResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[89] + mi := &file_ember_v1_ember_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4581,7 +4717,7 @@ func (x *EchoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EchoResponse.ProtoReflect.Descriptor instead. func (*EchoResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{89} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{91} } func (x *EchoResponse) GetMessage() string { @@ -4600,7 +4736,7 @@ type DecrRequest struct { func (x *DecrRequest) Reset() { *x = DecrRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[90] + mi := &file_ember_v1_ember_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4612,7 +4748,7 @@ func (x *DecrRequest) String() string { func (*DecrRequest) ProtoMessage() {} func (x *DecrRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[90] + mi := &file_ember_v1_ember_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4625,7 +4761,7 @@ func (x *DecrRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DecrRequest.ProtoReflect.Descriptor instead. func (*DecrRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{90} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{92} } func (x *DecrRequest) GetKey() string { @@ -4644,7 +4780,7 @@ type UnlinkRequest struct { func (x *UnlinkRequest) Reset() { *x = UnlinkRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[91] + mi := &file_ember_v1_ember_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4656,7 +4792,7 @@ func (x *UnlinkRequest) String() string { func (*UnlinkRequest) ProtoMessage() {} func (x *UnlinkRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[91] + mi := &file_ember_v1_ember_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4669,7 +4805,7 @@ func (x *UnlinkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnlinkRequest.ProtoReflect.Descriptor instead. func (*UnlinkRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{91} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{93} } func (x *UnlinkRequest) GetKeys() []string { @@ -4687,7 +4823,7 @@ type BgSaveRequest struct { func (x *BgSaveRequest) Reset() { *x = BgSaveRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[92] + mi := &file_ember_v1_ember_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4699,7 +4835,7 @@ func (x *BgSaveRequest) String() string { func (*BgSaveRequest) ProtoMessage() {} func (x *BgSaveRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[92] + mi := &file_ember_v1_ember_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4712,7 +4848,7 @@ func (x *BgSaveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BgSaveRequest.ProtoReflect.Descriptor instead. func (*BgSaveRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{92} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{94} } type BgRewriteAofRequest struct { @@ -4723,7 +4859,7 @@ type BgRewriteAofRequest struct { func (x *BgRewriteAofRequest) Reset() { *x = BgRewriteAofRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[93] + mi := &file_ember_v1_ember_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4735,7 +4871,7 @@ func (x *BgRewriteAofRequest) String() string { func (*BgRewriteAofRequest) ProtoMessage() {} func (x *BgRewriteAofRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[93] + mi := &file_ember_v1_ember_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4748,7 +4884,7 @@ func (x *BgRewriteAofRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BgRewriteAofRequest.ProtoReflect.Descriptor instead. func (*BgRewriteAofRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{93} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{95} } type SlowLogGetRequest struct { @@ -4760,7 +4896,7 @@ type SlowLogGetRequest struct { func (x *SlowLogGetRequest) Reset() { *x = SlowLogGetRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[94] + mi := &file_ember_v1_ember_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4772,7 +4908,7 @@ func (x *SlowLogGetRequest) String() string { func (*SlowLogGetRequest) ProtoMessage() {} func (x *SlowLogGetRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[94] + mi := &file_ember_v1_ember_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4785,7 +4921,7 @@ func (x *SlowLogGetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SlowLogGetRequest.ProtoReflect.Descriptor instead. func (*SlowLogGetRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{94} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{96} } func (x *SlowLogGetRequest) GetCount() uint32 { @@ -4804,7 +4940,7 @@ type SlowLogGetResponse struct { func (x *SlowLogGetResponse) Reset() { *x = SlowLogGetResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[95] + mi := &file_ember_v1_ember_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4816,7 +4952,7 @@ func (x *SlowLogGetResponse) String() string { func (*SlowLogGetResponse) ProtoMessage() {} func (x *SlowLogGetResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[95] + mi := &file_ember_v1_ember_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4829,7 +4965,7 @@ func (x *SlowLogGetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SlowLogGetResponse.ProtoReflect.Descriptor instead. func (*SlowLogGetResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{95} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{97} } func (x *SlowLogGetResponse) GetEntries() []*SlowLogEntry { @@ -4851,7 +4987,7 @@ type SlowLogEntry struct { func (x *SlowLogEntry) Reset() { *x = SlowLogEntry{} - mi := &file_ember_v1_ember_proto_msgTypes[96] + mi := &file_ember_v1_ember_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4863,7 +4999,7 @@ func (x *SlowLogEntry) String() string { func (*SlowLogEntry) ProtoMessage() {} func (x *SlowLogEntry) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[96] + mi := &file_ember_v1_ember_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4876,7 +5012,7 @@ func (x *SlowLogEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use SlowLogEntry.ProtoReflect.Descriptor instead. func (*SlowLogEntry) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{96} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{98} } func (x *SlowLogEntry) GetId() uint64 { @@ -4915,7 +5051,7 @@ type SlowLogLenRequest struct { func (x *SlowLogLenRequest) Reset() { *x = SlowLogLenRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[97] + mi := &file_ember_v1_ember_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4927,7 +5063,7 @@ func (x *SlowLogLenRequest) String() string { func (*SlowLogLenRequest) ProtoMessage() {} func (x *SlowLogLenRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[97] + mi := &file_ember_v1_ember_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4940,7 +5076,7 @@ func (x *SlowLogLenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SlowLogLenRequest.ProtoReflect.Descriptor instead. func (*SlowLogLenRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{97} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{99} } type SlowLogResetRequest struct { @@ -4951,7 +5087,7 @@ type SlowLogResetRequest struct { func (x *SlowLogResetRequest) Reset() { *x = SlowLogResetRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[98] + mi := &file_ember_v1_ember_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4963,7 +5099,7 @@ func (x *SlowLogResetRequest) String() string { func (*SlowLogResetRequest) ProtoMessage() {} func (x *SlowLogResetRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[98] + mi := &file_ember_v1_ember_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4976,7 +5112,7 @@ func (x *SlowLogResetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SlowLogResetRequest.ProtoReflect.Descriptor instead. func (*SlowLogResetRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{98} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{100} } type PublishRequest struct { @@ -4989,7 +5125,7 @@ type PublishRequest struct { func (x *PublishRequest) Reset() { *x = PublishRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[99] + mi := &file_ember_v1_ember_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5001,7 +5137,7 @@ func (x *PublishRequest) String() string { func (*PublishRequest) ProtoMessage() {} func (x *PublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[99] + mi := &file_ember_v1_ember_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5014,7 +5150,7 @@ func (x *PublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. func (*PublishRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{99} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{101} } func (x *PublishRequest) GetChannel() string { @@ -5041,7 +5177,7 @@ type SubscribeRequest struct { func (x *SubscribeRequest) Reset() { *x = SubscribeRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[100] + mi := &file_ember_v1_ember_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5053,7 +5189,7 @@ func (x *SubscribeRequest) String() string { func (*SubscribeRequest) ProtoMessage() {} func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[100] + mi := &file_ember_v1_ember_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5066,7 +5202,7 @@ func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubscribeRequest.ProtoReflect.Descriptor instead. func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{100} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{102} } func (x *SubscribeRequest) GetChannels() []string { @@ -5097,7 +5233,7 @@ type SubscribeEvent struct { func (x *SubscribeEvent) Reset() { *x = SubscribeEvent{} - mi := &file_ember_v1_ember_proto_msgTypes[101] + mi := &file_ember_v1_ember_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5109,7 +5245,7 @@ func (x *SubscribeEvent) String() string { func (*SubscribeEvent) ProtoMessage() {} func (x *SubscribeEvent) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[101] + mi := &file_ember_v1_ember_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5122,7 +5258,7 @@ func (x *SubscribeEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use SubscribeEvent.ProtoReflect.Descriptor instead. func (*SubscribeEvent) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{101} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{103} } func (x *SubscribeEvent) GetKind() string { @@ -5162,7 +5298,7 @@ type PubSubChannelsRequest struct { func (x *PubSubChannelsRequest) Reset() { *x = PubSubChannelsRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[102] + mi := &file_ember_v1_ember_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5174,7 +5310,7 @@ func (x *PubSubChannelsRequest) String() string { func (*PubSubChannelsRequest) ProtoMessage() {} func (x *PubSubChannelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[102] + mi := &file_ember_v1_ember_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5187,7 +5323,7 @@ func (x *PubSubChannelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PubSubChannelsRequest.ProtoReflect.Descriptor instead. func (*PubSubChannelsRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{102} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{104} } func (x *PubSubChannelsRequest) GetPattern() string { @@ -5206,7 +5342,7 @@ type PubSubNumSubRequest struct { func (x *PubSubNumSubRequest) Reset() { *x = PubSubNumSubRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[103] + mi := &file_ember_v1_ember_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5218,7 +5354,7 @@ func (x *PubSubNumSubRequest) String() string { func (*PubSubNumSubRequest) ProtoMessage() {} func (x *PubSubNumSubRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[103] + mi := &file_ember_v1_ember_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5231,7 +5367,7 @@ func (x *PubSubNumSubRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PubSubNumSubRequest.ProtoReflect.Descriptor instead. func (*PubSubNumSubRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{103} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{105} } func (x *PubSubNumSubRequest) GetChannels() []string { @@ -5250,7 +5386,7 @@ type PubSubNumSubResponse struct { func (x *PubSubNumSubResponse) Reset() { *x = PubSubNumSubResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[104] + mi := &file_ember_v1_ember_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5262,7 +5398,7 @@ func (x *PubSubNumSubResponse) String() string { func (*PubSubNumSubResponse) ProtoMessage() {} func (x *PubSubNumSubResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[104] + mi := &file_ember_v1_ember_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5275,7 +5411,7 @@ func (x *PubSubNumSubResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PubSubNumSubResponse.ProtoReflect.Descriptor instead. func (*PubSubNumSubResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{104} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{106} } func (x *PubSubNumSubResponse) GetCounts() []*ChannelCount { @@ -5293,7 +5429,7 @@ type PubSubNumPatRequest struct { func (x *PubSubNumPatRequest) Reset() { *x = PubSubNumPatRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[105] + mi := &file_ember_v1_ember_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5305,7 +5441,7 @@ func (x *PubSubNumPatRequest) String() string { func (*PubSubNumPatRequest) ProtoMessage() {} func (x *PubSubNumPatRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[105] + mi := &file_ember_v1_ember_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5318,7 +5454,7 @@ func (x *PubSubNumPatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PubSubNumPatRequest.ProtoReflect.Descriptor instead. func (*PubSubNumPatRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{105} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{107} } type ChannelCount struct { @@ -5331,7 +5467,7 @@ type ChannelCount struct { func (x *ChannelCount) Reset() { *x = ChannelCount{} - mi := &file_ember_v1_ember_proto_msgTypes[106] + mi := &file_ember_v1_ember_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5343,7 +5479,7 @@ func (x *ChannelCount) String() string { func (*ChannelCount) ProtoMessage() {} func (x *ChannelCount) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[106] + mi := &file_ember_v1_ember_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5356,7 +5492,7 @@ func (x *ChannelCount) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelCount.ProtoReflect.Descriptor instead. func (*ChannelCount) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{106} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{108} } func (x *ChannelCount) GetChannel() string { @@ -5448,6 +5584,7 @@ type PipelineRequest struct { // *PipelineRequest_PubsubChannels // *PipelineRequest_PubsubNumsub // *PipelineRequest_PubsubNumpat + // *PipelineRequest_VaddBatch Command isPipelineRequest_Command `protobuf_oneof:"command"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -5455,7 +5592,7 @@ type PipelineRequest struct { func (x *PipelineRequest) Reset() { *x = PipelineRequest{} - mi := &file_ember_v1_ember_proto_msgTypes[107] + mi := &file_ember_v1_ember_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5467,7 +5604,7 @@ func (x *PipelineRequest) String() string { func (*PipelineRequest) ProtoMessage() {} func (x *PipelineRequest) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[107] + mi := &file_ember_v1_ember_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5480,7 +5617,7 @@ func (x *PipelineRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PipelineRequest.ProtoReflect.Descriptor instead. func (*PipelineRequest) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{107} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{109} } func (x *PipelineRequest) GetId() uint64 { @@ -6127,6 +6264,15 @@ func (x *PipelineRequest) GetPubsubNumpat() *PubSubNumPatRequest { return nil } +func (x *PipelineRequest) GetVaddBatch() *VAddBatchRequest { + if x != nil { + if x, ok := x.Command.(*PipelineRequest_VaddBatch); ok { + return x.VaddBatch + } + } + return nil +} + type isPipelineRequest_Command interface { isPipelineRequest_Command() } @@ -6411,6 +6557,10 @@ type PipelineRequest_PubsubNumpat struct { PubsubNumpat *PubSubNumPatRequest `protobuf:"bytes,71,opt,name=pubsub_numpat,json=pubsubNumpat,proto3,oneof"` } +type PipelineRequest_VaddBatch struct { + VaddBatch *VAddBatchRequest `protobuf:"bytes,72,opt,name=vadd_batch,json=vaddBatch,proto3,oneof"` +} + func (*PipelineRequest_Get) isPipelineRequest_Command() {} func (*PipelineRequest_Set) isPipelineRequest_Command() {} @@ -6551,6 +6701,8 @@ func (*PipelineRequest_PubsubNumsub) isPipelineRequest_Command() {} func (*PipelineRequest_PubsubNumpat) isPipelineRequest_Command() {} +func (*PipelineRequest_VaddBatch) isPipelineRequest_Command() {} + type PipelineResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` @@ -6591,7 +6743,7 @@ type PipelineResponse struct { func (x *PipelineResponse) Reset() { *x = PipelineResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[108] + mi := &file_ember_v1_ember_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6603,7 +6755,7 @@ func (x *PipelineResponse) String() string { func (*PipelineResponse) ProtoMessage() {} func (x *PipelineResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[108] + mi := &file_ember_v1_ember_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6616,7 +6768,7 @@ func (x *PipelineResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PipelineResponse.ProtoReflect.Descriptor instead. func (*PipelineResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{108} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{110} } func (x *PipelineResponse) GetId() uint64 { @@ -7067,7 +7219,7 @@ type ErrorResponse struct { func (x *ErrorResponse) Reset() { *x = ErrorResponse{} - mi := &file_ember_v1_ember_proto_msgTypes[109] + mi := &file_ember_v1_ember_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7079,7 +7231,7 @@ func (x *ErrorResponse) String() string { func (*ErrorResponse) ProtoMessage() {} func (x *ErrorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ember_v1_ember_proto_msgTypes[109] + mi := &file_ember_v1_ember_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7092,7 +7244,7 @@ func (x *ErrorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. func (*ErrorResponse) Descriptor() ([]byte, []int) { - return file_ember_v1_ember_proto_rawDescGZIP(), []int{109} + return file_ember_v1_ember_proto_rawDescGZIP(), []int{111} } func (x *ErrorResponse) GetMessage() string { @@ -7320,6 +7472,18 @@ const file_ember_v1_ember_proto_rawDesc = "" + "\fconnectivity\x18\x06 \x01(\rH\x00R\fconnectivity\x88\x01\x01\x12,\n" + "\x0fef_construction\x18\a \x01(\rH\x01R\x0eefConstruction\x88\x01\x01B\x0f\n" + "\r_connectivityB\x12\n" + + "\x10_ef_construction\"F\n" + + "\x0eVAddBatchEntry\x12\x18\n" + + "\aelement\x18\x01 \x01(\tR\aelement\x12\x1a\n" + + "\x06vector\x18\x02 \x03(\x02B\x02\x10\x01R\x06vector\"\xc6\x02\n" + + "\x10VAddBatchRequest\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x122\n" + + "\aentries\x18\x02 \x03(\v2\x18.ember.v1.VAddBatchEntryR\aentries\x12.\n" + + "\x06metric\x18\x03 \x01(\x0e2\x16.ember.v1.VectorMetricR\x06metric\x12@\n" + + "\fquantization\x18\x04 \x01(\x0e2\x1c.ember.v1.VectorQuantizationR\fquantization\x12'\n" + + "\fconnectivity\x18\x05 \x01(\rH\x00R\fconnectivity\x88\x01\x01\x12,\n" + + "\x0fef_construction\x18\x06 \x01(\rH\x01R\x0eefConstruction\x88\x01\x01B\x0f\n" + + "\r_connectivityB\x12\n" + "\x10_ef_construction\"\x7f\n" + "\vVSimRequest\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x18\n" + @@ -7414,7 +7578,7 @@ const file_ember_v1_ember_proto_rawDesc = "" + "\x13PubSubNumPatRequest\">\n" + "\fChannelCount\x12\x18\n" + "\achannel\x18\x01 \x01(\tR\achannel\x12\x14\n" + - "\x05count\x18\x02 \x01(\x03R\x05count\"\xf6\x1b\n" + + "\x05count\x18\x02 \x01(\x03R\x05count\"\xb3\x1c\n" + "\x0fPipelineRequest\x12\x0e\n" + "\x02id\x18\x01 \x01(\x04R\x02id\x12(\n" + "\x03get\x18\x02 \x01(\v2\x14.ember.v1.GetRequestH\x00R\x03get\x12(\n" + @@ -7489,7 +7653,9 @@ const file_ember_v1_ember_proto_rawDesc = "" + "\apublish\x18D \x01(\v2\x18.ember.v1.PublishRequestH\x00R\apublish\x12J\n" + "\x0fpubsub_channels\x18E \x01(\v2\x1f.ember.v1.PubSubChannelsRequestH\x00R\x0epubsubChannels\x12D\n" + "\rpubsub_numsub\x18F \x01(\v2\x1d.ember.v1.PubSubNumSubRequestH\x00R\fpubsubNumsub\x12D\n" + - "\rpubsub_numpat\x18G \x01(\v2\x1d.ember.v1.PubSubNumPatRequestH\x00R\fpubsubNumpatB\t\n" + + "\rpubsub_numpat\x18G \x01(\v2\x1d.ember.v1.PubSubNumPatRequestH\x00R\fpubsubNumpat\x12;\n" + + "\n" + + "vadd_batch\x18H \x01(\v2\x1a.ember.v1.VAddBatchRequestH\x00R\tvaddBatchB\t\n" + "\acommand\"\xcc\v\n" + "\x10PipelineResponse\x12\x0e\n" + "\x02id\x18\x01 \x01(\x04R\x02id\x12)\n" + @@ -7540,7 +7706,7 @@ const file_ember_v1_ember_proto_rawDesc = "" + "\x15ERROR_KIND_WRONG_TYPE\x10\x01\x12\x1c\n" + "\x18ERROR_KIND_OUT_OF_MEMORY\x10\x02\x12\x17\n" + "\x13ERROR_KIND_INTERNAL\x10\x03\x12\x1f\n" + - "\x1bERROR_KIND_INVALID_ARGUMENT\x10\x042\xe3!\n" + + "\x1bERROR_KIND_INVALID_ARGUMENT\x10\x042\xa3\"\n" + "\n" + "EmberCache\x122\n" + "\x03Get\x12\x14.ember.v1.GetRequest\x1a\x15.ember.v1.GetResponse\x122\n" + @@ -7591,7 +7757,8 @@ const file_ember_v1_ember_proto_rawDesc = "" + "\x05ZRank\x12\x16.ember.v1.ZRankRequest\x1a\x1d.ember.v1.OptionalIntResponse\x126\n" + "\x05ZCard\x12\x16.ember.v1.ZCardRequest\x1a\x15.ember.v1.IntResponse\x12;\n" + "\x06ZRange\x12\x17.ember.v1.ZRangeRequest\x1a\x18.ember.v1.ZRangeResponse\x125\n" + - "\x04VAdd\x12\x15.ember.v1.VAddRequest\x1a\x16.ember.v1.BoolResponse\x125\n" + + "\x04VAdd\x12\x15.ember.v1.VAddRequest\x1a\x16.ember.v1.BoolResponse\x12>\n" + + "\tVAddBatch\x12\x1a.ember.v1.VAddBatchRequest\x1a\x15.ember.v1.IntResponse\x125\n" + "\x04VSim\x12\x15.ember.v1.VSimRequest\x1a\x16.ember.v1.VSimResponse\x125\n" + "\x04VRem\x12\x15.ember.v1.VRemRequest\x1a\x16.ember.v1.BoolResponse\x125\n" + "\x04VGet\x12\x15.ember.v1.VGetRequest\x1a\x16.ember.v1.VGetResponse\x126\n" + @@ -7632,7 +7799,7 @@ func file_ember_v1_ember_proto_rawDescGZIP() []byte { } var file_ember_v1_ember_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_ember_v1_ember_proto_msgTypes = make([]protoimpl.MessageInfo, 110) +var file_ember_v1_ember_proto_msgTypes = make([]protoimpl.MessageInfo, 112) var file_ember_v1_ember_proto_goTypes = []any{ (VectorMetric)(0), // 0: ember.v1.VectorMetric (VectorQuantization)(0), // 1: ember.v1.VectorQuantization @@ -7709,44 +7876,46 @@ var file_ember_v1_ember_proto_goTypes = []any{ (*ZRangeRequest)(nil), // 72: ember.v1.ZRangeRequest (*ZRangeResponse)(nil), // 73: ember.v1.ZRangeResponse (*VAddRequest)(nil), // 74: ember.v1.VAddRequest - (*VSimRequest)(nil), // 75: ember.v1.VSimRequest - (*VSimResponse)(nil), // 76: ember.v1.VSimResponse - (*VSimResult)(nil), // 77: ember.v1.VSimResult - (*VRemRequest)(nil), // 78: ember.v1.VRemRequest - (*VGetRequest)(nil), // 79: ember.v1.VGetRequest - (*VGetResponse)(nil), // 80: ember.v1.VGetResponse - (*VCardRequest)(nil), // 81: ember.v1.VCardRequest - (*VDimRequest)(nil), // 82: ember.v1.VDimRequest - (*VInfoRequest)(nil), // 83: ember.v1.VInfoRequest - (*VInfoResponse)(nil), // 84: ember.v1.VInfoResponse - (*PingRequest)(nil), // 85: ember.v1.PingRequest - (*PingResponse)(nil), // 86: ember.v1.PingResponse - (*FlushDbRequest)(nil), // 87: ember.v1.FlushDbRequest - (*DbSizeRequest)(nil), // 88: ember.v1.DbSizeRequest - (*InfoRequest)(nil), // 89: ember.v1.InfoRequest - (*InfoResponse)(nil), // 90: ember.v1.InfoResponse - (*EchoRequest)(nil), // 91: ember.v1.EchoRequest - (*EchoResponse)(nil), // 92: ember.v1.EchoResponse - (*DecrRequest)(nil), // 93: ember.v1.DecrRequest - (*UnlinkRequest)(nil), // 94: ember.v1.UnlinkRequest - (*BgSaveRequest)(nil), // 95: ember.v1.BgSaveRequest - (*BgRewriteAofRequest)(nil), // 96: ember.v1.BgRewriteAofRequest - (*SlowLogGetRequest)(nil), // 97: ember.v1.SlowLogGetRequest - (*SlowLogGetResponse)(nil), // 98: ember.v1.SlowLogGetResponse - (*SlowLogEntry)(nil), // 99: ember.v1.SlowLogEntry - (*SlowLogLenRequest)(nil), // 100: ember.v1.SlowLogLenRequest - (*SlowLogResetRequest)(nil), // 101: ember.v1.SlowLogResetRequest - (*PublishRequest)(nil), // 102: ember.v1.PublishRequest - (*SubscribeRequest)(nil), // 103: ember.v1.SubscribeRequest - (*SubscribeEvent)(nil), // 104: ember.v1.SubscribeEvent - (*PubSubChannelsRequest)(nil), // 105: ember.v1.PubSubChannelsRequest - (*PubSubNumSubRequest)(nil), // 106: ember.v1.PubSubNumSubRequest - (*PubSubNumSubResponse)(nil), // 107: ember.v1.PubSubNumSubResponse - (*PubSubNumPatRequest)(nil), // 108: ember.v1.PubSubNumPatRequest - (*ChannelCount)(nil), // 109: ember.v1.ChannelCount - (*PipelineRequest)(nil), // 110: ember.v1.PipelineRequest - (*PipelineResponse)(nil), // 111: ember.v1.PipelineResponse - (*ErrorResponse)(nil), // 112: ember.v1.ErrorResponse + (*VAddBatchEntry)(nil), // 75: ember.v1.VAddBatchEntry + (*VAddBatchRequest)(nil), // 76: ember.v1.VAddBatchRequest + (*VSimRequest)(nil), // 77: ember.v1.VSimRequest + (*VSimResponse)(nil), // 78: ember.v1.VSimResponse + (*VSimResult)(nil), // 79: ember.v1.VSimResult + (*VRemRequest)(nil), // 80: ember.v1.VRemRequest + (*VGetRequest)(nil), // 81: ember.v1.VGetRequest + (*VGetResponse)(nil), // 82: ember.v1.VGetResponse + (*VCardRequest)(nil), // 83: ember.v1.VCardRequest + (*VDimRequest)(nil), // 84: ember.v1.VDimRequest + (*VInfoRequest)(nil), // 85: ember.v1.VInfoRequest + (*VInfoResponse)(nil), // 86: ember.v1.VInfoResponse + (*PingRequest)(nil), // 87: ember.v1.PingRequest + (*PingResponse)(nil), // 88: ember.v1.PingResponse + (*FlushDbRequest)(nil), // 89: ember.v1.FlushDbRequest + (*DbSizeRequest)(nil), // 90: ember.v1.DbSizeRequest + (*InfoRequest)(nil), // 91: ember.v1.InfoRequest + (*InfoResponse)(nil), // 92: ember.v1.InfoResponse + (*EchoRequest)(nil), // 93: ember.v1.EchoRequest + (*EchoResponse)(nil), // 94: ember.v1.EchoResponse + (*DecrRequest)(nil), // 95: ember.v1.DecrRequest + (*UnlinkRequest)(nil), // 96: ember.v1.UnlinkRequest + (*BgSaveRequest)(nil), // 97: ember.v1.BgSaveRequest + (*BgRewriteAofRequest)(nil), // 98: ember.v1.BgRewriteAofRequest + (*SlowLogGetRequest)(nil), // 99: ember.v1.SlowLogGetRequest + (*SlowLogGetResponse)(nil), // 100: ember.v1.SlowLogGetResponse + (*SlowLogEntry)(nil), // 101: ember.v1.SlowLogEntry + (*SlowLogLenRequest)(nil), // 102: ember.v1.SlowLogLenRequest + (*SlowLogResetRequest)(nil), // 103: ember.v1.SlowLogResetRequest + (*PublishRequest)(nil), // 104: ember.v1.PublishRequest + (*SubscribeRequest)(nil), // 105: ember.v1.SubscribeRequest + (*SubscribeEvent)(nil), // 106: ember.v1.SubscribeEvent + (*PubSubChannelsRequest)(nil), // 107: ember.v1.PubSubChannelsRequest + (*PubSubNumSubRequest)(nil), // 108: ember.v1.PubSubNumSubRequest + (*PubSubNumSubResponse)(nil), // 109: ember.v1.PubSubNumSubResponse + (*PubSubNumPatRequest)(nil), // 110: ember.v1.PubSubNumPatRequest + (*ChannelCount)(nil), // 111: ember.v1.ChannelCount + (*PipelineRequest)(nil), // 112: ember.v1.PipelineRequest + (*PipelineResponse)(nil), // 113: ember.v1.PipelineResponse + (*ErrorResponse)(nil), // 114: ember.v1.ErrorResponse } var file_ember_v1_ember_proto_depIdxs = []int32{ 15, // 0: ember.v1.MGetResponse.values:type_name -> ember.v1.OptionalValue @@ -7758,260 +7927,266 @@ var file_ember_v1_ember_proto_depIdxs = []int32{ 65, // 6: ember.v1.ZRangeResponse.members:type_name -> ember.v1.ScoreMember 0, // 7: ember.v1.VAddRequest.metric:type_name -> ember.v1.VectorMetric 1, // 8: ember.v1.VAddRequest.quantization:type_name -> ember.v1.VectorQuantization - 77, // 9: ember.v1.VSimResponse.results:type_name -> ember.v1.VSimResult - 47, // 10: ember.v1.VInfoResponse.info:type_name -> ember.v1.FieldValue - 99, // 11: ember.v1.SlowLogGetResponse.entries:type_name -> ember.v1.SlowLogEntry - 109, // 12: ember.v1.PubSubNumSubResponse.counts:type_name -> ember.v1.ChannelCount - 7, // 13: ember.v1.PipelineRequest.get:type_name -> ember.v1.GetRequest - 9, // 14: ember.v1.PipelineRequest.set:type_name -> ember.v1.SetRequest - 11, // 15: ember.v1.PipelineRequest.del:type_name -> ember.v1.DelRequest - 25, // 16: ember.v1.PipelineRequest.exists:type_name -> ember.v1.ExistsRequest - 19, // 17: ember.v1.PipelineRequest.incr:type_name -> ember.v1.IncrRequest - 20, // 18: ember.v1.PipelineRequest.incr_by:type_name -> ember.v1.IncrByRequest - 21, // 19: ember.v1.PipelineRequest.decr_by:type_name -> ember.v1.DecrByRequest - 22, // 20: ember.v1.PipelineRequest.incr_by_float:type_name -> ember.v1.IncrByFloatRequest - 23, // 21: ember.v1.PipelineRequest.append:type_name -> ember.v1.AppendRequest - 24, // 22: ember.v1.PipelineRequest.strlen:type_name -> ember.v1.StrlenRequest - 26, // 23: ember.v1.PipelineRequest.expire:type_name -> ember.v1.ExpireRequest - 27, // 24: ember.v1.PipelineRequest.pexpire:type_name -> ember.v1.PExpireRequest - 28, // 25: ember.v1.PipelineRequest.persist:type_name -> ember.v1.PersistRequest - 29, // 26: ember.v1.PipelineRequest.ttl:type_name -> ember.v1.TtlRequest - 30, // 27: ember.v1.PipelineRequest.pttl:type_name -> ember.v1.PTtlRequest - 32, // 28: ember.v1.PipelineRequest.type:type_name -> ember.v1.TypeRequest - 39, // 29: ember.v1.PipelineRequest.lpush:type_name -> ember.v1.LPushRequest - 40, // 30: ember.v1.PipelineRequest.rpush:type_name -> ember.v1.RPushRequest - 41, // 31: ember.v1.PipelineRequest.lpop:type_name -> ember.v1.LPopRequest - 42, // 32: ember.v1.PipelineRequest.rpop:type_name -> ember.v1.RPopRequest - 43, // 33: ember.v1.PipelineRequest.lrange:type_name -> ember.v1.LRangeRequest - 45, // 34: ember.v1.PipelineRequest.llen:type_name -> ember.v1.LLenRequest - 46, // 35: ember.v1.PipelineRequest.hset:type_name -> ember.v1.HSetRequest - 48, // 36: ember.v1.PipelineRequest.hget:type_name -> ember.v1.HGetRequest - 49, // 37: ember.v1.PipelineRequest.hgetall:type_name -> ember.v1.HGetAllRequest - 51, // 38: ember.v1.PipelineRequest.hdel:type_name -> ember.v1.HDelRequest - 52, // 39: ember.v1.PipelineRequest.hexists:type_name -> ember.v1.HExistsRequest - 53, // 40: ember.v1.PipelineRequest.hlen:type_name -> ember.v1.HLenRequest - 54, // 41: ember.v1.PipelineRequest.hincr_by:type_name -> ember.v1.HIncrByRequest - 55, // 42: ember.v1.PipelineRequest.hkeys:type_name -> ember.v1.HKeysRequest - 56, // 43: ember.v1.PipelineRequest.hvals:type_name -> ember.v1.HValsRequest - 57, // 44: ember.v1.PipelineRequest.hmget:type_name -> ember.v1.HMGetRequest - 59, // 45: ember.v1.PipelineRequest.sadd:type_name -> ember.v1.SAddRequest - 60, // 46: ember.v1.PipelineRequest.srem:type_name -> ember.v1.SRemRequest - 61, // 47: ember.v1.PipelineRequest.smembers:type_name -> ember.v1.SMembersRequest - 62, // 48: ember.v1.PipelineRequest.sismember:type_name -> ember.v1.SIsMemberRequest - 63, // 49: ember.v1.PipelineRequest.scard:type_name -> ember.v1.SCardRequest - 64, // 50: ember.v1.PipelineRequest.zadd:type_name -> ember.v1.ZAddRequest - 66, // 51: ember.v1.PipelineRequest.zrem:type_name -> ember.v1.ZRemRequest - 67, // 52: ember.v1.PipelineRequest.zscore:type_name -> ember.v1.ZScoreRequest - 69, // 53: ember.v1.PipelineRequest.zrank:type_name -> ember.v1.ZRankRequest - 71, // 54: ember.v1.PipelineRequest.zcard:type_name -> ember.v1.ZCardRequest - 72, // 55: ember.v1.PipelineRequest.zrange:type_name -> ember.v1.ZRangeRequest - 74, // 56: ember.v1.PipelineRequest.vadd:type_name -> ember.v1.VAddRequest - 75, // 57: ember.v1.PipelineRequest.vsim:type_name -> ember.v1.VSimRequest - 78, // 58: ember.v1.PipelineRequest.vrem:type_name -> ember.v1.VRemRequest - 79, // 59: ember.v1.PipelineRequest.vget:type_name -> ember.v1.VGetRequest - 81, // 60: ember.v1.PipelineRequest.vcard:type_name -> ember.v1.VCardRequest - 82, // 61: ember.v1.PipelineRequest.vdim:type_name -> ember.v1.VDimRequest - 83, // 62: ember.v1.PipelineRequest.vinfo:type_name -> ember.v1.VInfoRequest - 85, // 63: ember.v1.PipelineRequest.ping:type_name -> ember.v1.PingRequest - 87, // 64: ember.v1.PipelineRequest.flushdb:type_name -> ember.v1.FlushDbRequest - 88, // 65: ember.v1.PipelineRequest.dbsize:type_name -> ember.v1.DbSizeRequest - 13, // 66: ember.v1.PipelineRequest.mget:type_name -> ember.v1.MGetRequest - 16, // 67: ember.v1.PipelineRequest.mset:type_name -> ember.v1.MSetRequest - 34, // 68: ember.v1.PipelineRequest.keys:type_name -> ember.v1.KeysRequest - 36, // 69: ember.v1.PipelineRequest.rename:type_name -> ember.v1.RenameRequest - 37, // 70: ember.v1.PipelineRequest.scan:type_name -> ember.v1.ScanRequest - 91, // 71: ember.v1.PipelineRequest.echo:type_name -> ember.v1.EchoRequest - 93, // 72: ember.v1.PipelineRequest.decr:type_name -> ember.v1.DecrRequest - 94, // 73: ember.v1.PipelineRequest.unlink:type_name -> ember.v1.UnlinkRequest - 95, // 74: ember.v1.PipelineRequest.bgsave:type_name -> ember.v1.BgSaveRequest - 96, // 75: ember.v1.PipelineRequest.bgrewriteaof:type_name -> ember.v1.BgRewriteAofRequest - 97, // 76: ember.v1.PipelineRequest.slowlog_get:type_name -> ember.v1.SlowLogGetRequest - 100, // 77: ember.v1.PipelineRequest.slowlog_len:type_name -> ember.v1.SlowLogLenRequest - 101, // 78: ember.v1.PipelineRequest.slowlog_reset:type_name -> ember.v1.SlowLogResetRequest - 102, // 79: ember.v1.PipelineRequest.publish:type_name -> ember.v1.PublishRequest - 105, // 80: ember.v1.PipelineRequest.pubsub_channels:type_name -> ember.v1.PubSubChannelsRequest - 106, // 81: ember.v1.PipelineRequest.pubsub_numsub:type_name -> ember.v1.PubSubNumSubRequest - 108, // 82: ember.v1.PipelineRequest.pubsub_numpat:type_name -> ember.v1.PubSubNumPatRequest - 8, // 83: ember.v1.PipelineResponse.get:type_name -> ember.v1.GetResponse - 10, // 84: ember.v1.PipelineResponse.set:type_name -> ember.v1.SetResponse - 12, // 85: ember.v1.PipelineResponse.del:type_name -> ember.v1.DelResponse - 3, // 86: ember.v1.PipelineResponse.int_val:type_name -> ember.v1.IntResponse - 4, // 87: ember.v1.PipelineResponse.bool_val:type_name -> ember.v1.BoolResponse - 5, // 88: ember.v1.PipelineResponse.float_val:type_name -> ember.v1.FloatResponse - 6, // 89: ember.v1.PipelineResponse.status:type_name -> ember.v1.StatusResponse - 31, // 90: ember.v1.PipelineResponse.ttl:type_name -> ember.v1.TtlResponse - 33, // 91: ember.v1.PipelineResponse.type:type_name -> ember.v1.TypeResponse - 44, // 92: ember.v1.PipelineResponse.array:type_name -> ember.v1.ArrayResponse - 50, // 93: ember.v1.PipelineResponse.hash:type_name -> ember.v1.HashResponse - 58, // 94: ember.v1.PipelineResponse.optional_array:type_name -> ember.v1.OptionalArrayResponse - 35, // 95: ember.v1.PipelineResponse.keys:type_name -> ember.v1.KeysResponse - 38, // 96: ember.v1.PipelineResponse.scan:type_name -> ember.v1.ScanResponse - 68, // 97: ember.v1.PipelineResponse.optional_float:type_name -> ember.v1.OptionalFloatResponse - 70, // 98: ember.v1.PipelineResponse.optional_int:type_name -> ember.v1.OptionalIntResponse - 73, // 99: ember.v1.PipelineResponse.zrange:type_name -> ember.v1.ZRangeResponse - 76, // 100: ember.v1.PipelineResponse.vsim:type_name -> ember.v1.VSimResponse - 80, // 101: ember.v1.PipelineResponse.vget:type_name -> ember.v1.VGetResponse - 84, // 102: ember.v1.PipelineResponse.vinfo:type_name -> ember.v1.VInfoResponse - 14, // 103: ember.v1.PipelineResponse.mget:type_name -> ember.v1.MGetResponse - 18, // 104: ember.v1.PipelineResponse.mset:type_name -> ember.v1.MSetResponse - 86, // 105: ember.v1.PipelineResponse.ping:type_name -> ember.v1.PingResponse - 112, // 106: ember.v1.PipelineResponse.error:type_name -> ember.v1.ErrorResponse - 90, // 107: ember.v1.PipelineResponse.info:type_name -> ember.v1.InfoResponse - 92, // 108: ember.v1.PipelineResponse.echo:type_name -> ember.v1.EchoResponse - 98, // 109: ember.v1.PipelineResponse.slowlog_get:type_name -> ember.v1.SlowLogGetResponse - 107, // 110: ember.v1.PipelineResponse.pubsub_numsub:type_name -> ember.v1.PubSubNumSubResponse - 2, // 111: ember.v1.ErrorResponse.kind:type_name -> ember.v1.ErrorKind - 7, // 112: ember.v1.EmberCache.Get:input_type -> ember.v1.GetRequest - 9, // 113: ember.v1.EmberCache.Set:input_type -> ember.v1.SetRequest - 11, // 114: ember.v1.EmberCache.Del:input_type -> ember.v1.DelRequest - 13, // 115: ember.v1.EmberCache.MGet:input_type -> ember.v1.MGetRequest - 16, // 116: ember.v1.EmberCache.MSet:input_type -> ember.v1.MSetRequest - 19, // 117: ember.v1.EmberCache.Incr:input_type -> ember.v1.IncrRequest - 20, // 118: ember.v1.EmberCache.IncrBy:input_type -> ember.v1.IncrByRequest - 21, // 119: ember.v1.EmberCache.DecrBy:input_type -> ember.v1.DecrByRequest - 22, // 120: ember.v1.EmberCache.IncrByFloat:input_type -> ember.v1.IncrByFloatRequest - 23, // 121: ember.v1.EmberCache.Append:input_type -> ember.v1.AppendRequest - 24, // 122: ember.v1.EmberCache.Strlen:input_type -> ember.v1.StrlenRequest - 25, // 123: ember.v1.EmberCache.Exists:input_type -> ember.v1.ExistsRequest - 26, // 124: ember.v1.EmberCache.Expire:input_type -> ember.v1.ExpireRequest - 27, // 125: ember.v1.EmberCache.PExpire:input_type -> ember.v1.PExpireRequest - 28, // 126: ember.v1.EmberCache.Persist:input_type -> ember.v1.PersistRequest - 29, // 127: ember.v1.EmberCache.Ttl:input_type -> ember.v1.TtlRequest - 30, // 128: ember.v1.EmberCache.PTtl:input_type -> ember.v1.PTtlRequest - 32, // 129: ember.v1.EmberCache.Type:input_type -> ember.v1.TypeRequest - 34, // 130: ember.v1.EmberCache.Keys:input_type -> ember.v1.KeysRequest - 36, // 131: ember.v1.EmberCache.Rename:input_type -> ember.v1.RenameRequest - 37, // 132: ember.v1.EmberCache.Scan:input_type -> ember.v1.ScanRequest - 39, // 133: ember.v1.EmberCache.LPush:input_type -> ember.v1.LPushRequest - 40, // 134: ember.v1.EmberCache.RPush:input_type -> ember.v1.RPushRequest - 41, // 135: ember.v1.EmberCache.LPop:input_type -> ember.v1.LPopRequest - 42, // 136: ember.v1.EmberCache.RPop:input_type -> ember.v1.RPopRequest - 43, // 137: ember.v1.EmberCache.LRange:input_type -> ember.v1.LRangeRequest - 45, // 138: ember.v1.EmberCache.LLen:input_type -> ember.v1.LLenRequest - 46, // 139: ember.v1.EmberCache.HSet:input_type -> ember.v1.HSetRequest - 48, // 140: ember.v1.EmberCache.HGet:input_type -> ember.v1.HGetRequest - 49, // 141: ember.v1.EmberCache.HGetAll:input_type -> ember.v1.HGetAllRequest - 51, // 142: ember.v1.EmberCache.HDel:input_type -> ember.v1.HDelRequest - 52, // 143: ember.v1.EmberCache.HExists:input_type -> ember.v1.HExistsRequest - 53, // 144: ember.v1.EmberCache.HLen:input_type -> ember.v1.HLenRequest - 54, // 145: ember.v1.EmberCache.HIncrBy:input_type -> ember.v1.HIncrByRequest - 55, // 146: ember.v1.EmberCache.HKeys:input_type -> ember.v1.HKeysRequest - 56, // 147: ember.v1.EmberCache.HVals:input_type -> ember.v1.HValsRequest - 57, // 148: ember.v1.EmberCache.HMGet:input_type -> ember.v1.HMGetRequest - 59, // 149: ember.v1.EmberCache.SAdd:input_type -> ember.v1.SAddRequest - 60, // 150: ember.v1.EmberCache.SRem:input_type -> ember.v1.SRemRequest - 61, // 151: ember.v1.EmberCache.SMembers:input_type -> ember.v1.SMembersRequest - 62, // 152: ember.v1.EmberCache.SIsMember:input_type -> ember.v1.SIsMemberRequest - 63, // 153: ember.v1.EmberCache.SCard:input_type -> ember.v1.SCardRequest - 64, // 154: ember.v1.EmberCache.ZAdd:input_type -> ember.v1.ZAddRequest - 66, // 155: ember.v1.EmberCache.ZRem:input_type -> ember.v1.ZRemRequest - 67, // 156: ember.v1.EmberCache.ZScore:input_type -> ember.v1.ZScoreRequest - 69, // 157: ember.v1.EmberCache.ZRank:input_type -> ember.v1.ZRankRequest - 71, // 158: ember.v1.EmberCache.ZCard:input_type -> ember.v1.ZCardRequest - 72, // 159: ember.v1.EmberCache.ZRange:input_type -> ember.v1.ZRangeRequest - 74, // 160: ember.v1.EmberCache.VAdd:input_type -> ember.v1.VAddRequest - 75, // 161: ember.v1.EmberCache.VSim:input_type -> ember.v1.VSimRequest - 78, // 162: ember.v1.EmberCache.VRem:input_type -> ember.v1.VRemRequest - 79, // 163: ember.v1.EmberCache.VGet:input_type -> ember.v1.VGetRequest - 81, // 164: ember.v1.EmberCache.VCard:input_type -> ember.v1.VCardRequest - 82, // 165: ember.v1.EmberCache.VDim:input_type -> ember.v1.VDimRequest - 83, // 166: ember.v1.EmberCache.VInfo:input_type -> ember.v1.VInfoRequest - 85, // 167: ember.v1.EmberCache.Ping:input_type -> ember.v1.PingRequest - 91, // 168: ember.v1.EmberCache.Echo:input_type -> ember.v1.EchoRequest - 93, // 169: ember.v1.EmberCache.Decr:input_type -> ember.v1.DecrRequest - 94, // 170: ember.v1.EmberCache.Unlink:input_type -> ember.v1.UnlinkRequest - 87, // 171: ember.v1.EmberCache.FlushDb:input_type -> ember.v1.FlushDbRequest - 88, // 172: ember.v1.EmberCache.DbSize:input_type -> ember.v1.DbSizeRequest - 89, // 173: ember.v1.EmberCache.Info:input_type -> ember.v1.InfoRequest - 95, // 174: ember.v1.EmberCache.BgSave:input_type -> ember.v1.BgSaveRequest - 96, // 175: ember.v1.EmberCache.BgRewriteAof:input_type -> ember.v1.BgRewriteAofRequest - 97, // 176: ember.v1.EmberCache.SlowLogGet:input_type -> ember.v1.SlowLogGetRequest - 100, // 177: ember.v1.EmberCache.SlowLogLen:input_type -> ember.v1.SlowLogLenRequest - 101, // 178: ember.v1.EmberCache.SlowLogReset:input_type -> ember.v1.SlowLogResetRequest - 102, // 179: ember.v1.EmberCache.Publish:input_type -> ember.v1.PublishRequest - 103, // 180: ember.v1.EmberCache.Subscribe:input_type -> ember.v1.SubscribeRequest - 105, // 181: ember.v1.EmberCache.PubSubChannels:input_type -> ember.v1.PubSubChannelsRequest - 106, // 182: ember.v1.EmberCache.PubSubNumSub:input_type -> ember.v1.PubSubNumSubRequest - 108, // 183: ember.v1.EmberCache.PubSubNumPat:input_type -> ember.v1.PubSubNumPatRequest - 110, // 184: ember.v1.EmberCache.Pipeline:input_type -> ember.v1.PipelineRequest - 8, // 185: ember.v1.EmberCache.Get:output_type -> ember.v1.GetResponse - 10, // 186: ember.v1.EmberCache.Set:output_type -> ember.v1.SetResponse - 12, // 187: ember.v1.EmberCache.Del:output_type -> ember.v1.DelResponse - 14, // 188: ember.v1.EmberCache.MGet:output_type -> ember.v1.MGetResponse - 18, // 189: ember.v1.EmberCache.MSet:output_type -> ember.v1.MSetResponse - 3, // 190: ember.v1.EmberCache.Incr:output_type -> ember.v1.IntResponse - 3, // 191: ember.v1.EmberCache.IncrBy:output_type -> ember.v1.IntResponse - 3, // 192: ember.v1.EmberCache.DecrBy:output_type -> ember.v1.IntResponse - 5, // 193: ember.v1.EmberCache.IncrByFloat:output_type -> ember.v1.FloatResponse - 3, // 194: ember.v1.EmberCache.Append:output_type -> ember.v1.IntResponse - 3, // 195: ember.v1.EmberCache.Strlen:output_type -> ember.v1.IntResponse - 3, // 196: ember.v1.EmberCache.Exists:output_type -> ember.v1.IntResponse - 4, // 197: ember.v1.EmberCache.Expire:output_type -> ember.v1.BoolResponse - 4, // 198: ember.v1.EmberCache.PExpire:output_type -> ember.v1.BoolResponse - 4, // 199: ember.v1.EmberCache.Persist:output_type -> ember.v1.BoolResponse - 31, // 200: ember.v1.EmberCache.Ttl:output_type -> ember.v1.TtlResponse - 31, // 201: ember.v1.EmberCache.PTtl:output_type -> ember.v1.TtlResponse - 33, // 202: ember.v1.EmberCache.Type:output_type -> ember.v1.TypeResponse - 35, // 203: ember.v1.EmberCache.Keys:output_type -> ember.v1.KeysResponse - 6, // 204: ember.v1.EmberCache.Rename:output_type -> ember.v1.StatusResponse - 38, // 205: ember.v1.EmberCache.Scan:output_type -> ember.v1.ScanResponse - 3, // 206: ember.v1.EmberCache.LPush:output_type -> ember.v1.IntResponse - 3, // 207: ember.v1.EmberCache.RPush:output_type -> ember.v1.IntResponse - 8, // 208: ember.v1.EmberCache.LPop:output_type -> ember.v1.GetResponse - 8, // 209: ember.v1.EmberCache.RPop:output_type -> ember.v1.GetResponse - 44, // 210: ember.v1.EmberCache.LRange:output_type -> ember.v1.ArrayResponse - 3, // 211: ember.v1.EmberCache.LLen:output_type -> ember.v1.IntResponse - 3, // 212: ember.v1.EmberCache.HSet:output_type -> ember.v1.IntResponse - 8, // 213: ember.v1.EmberCache.HGet:output_type -> ember.v1.GetResponse - 50, // 214: ember.v1.EmberCache.HGetAll:output_type -> ember.v1.HashResponse - 3, // 215: ember.v1.EmberCache.HDel:output_type -> ember.v1.IntResponse - 4, // 216: ember.v1.EmberCache.HExists:output_type -> ember.v1.BoolResponse - 3, // 217: ember.v1.EmberCache.HLen:output_type -> ember.v1.IntResponse - 3, // 218: ember.v1.EmberCache.HIncrBy:output_type -> ember.v1.IntResponse - 35, // 219: ember.v1.EmberCache.HKeys:output_type -> ember.v1.KeysResponse - 44, // 220: ember.v1.EmberCache.HVals:output_type -> ember.v1.ArrayResponse - 58, // 221: ember.v1.EmberCache.HMGet:output_type -> ember.v1.OptionalArrayResponse - 3, // 222: ember.v1.EmberCache.SAdd:output_type -> ember.v1.IntResponse - 3, // 223: ember.v1.EmberCache.SRem:output_type -> ember.v1.IntResponse - 35, // 224: ember.v1.EmberCache.SMembers:output_type -> ember.v1.KeysResponse - 4, // 225: ember.v1.EmberCache.SIsMember:output_type -> ember.v1.BoolResponse - 3, // 226: ember.v1.EmberCache.SCard:output_type -> ember.v1.IntResponse - 3, // 227: ember.v1.EmberCache.ZAdd:output_type -> ember.v1.IntResponse - 3, // 228: ember.v1.EmberCache.ZRem:output_type -> ember.v1.IntResponse - 68, // 229: ember.v1.EmberCache.ZScore:output_type -> ember.v1.OptionalFloatResponse - 70, // 230: ember.v1.EmberCache.ZRank:output_type -> ember.v1.OptionalIntResponse - 3, // 231: ember.v1.EmberCache.ZCard:output_type -> ember.v1.IntResponse - 73, // 232: ember.v1.EmberCache.ZRange:output_type -> ember.v1.ZRangeResponse - 4, // 233: ember.v1.EmberCache.VAdd:output_type -> ember.v1.BoolResponse - 76, // 234: ember.v1.EmberCache.VSim:output_type -> ember.v1.VSimResponse - 4, // 235: ember.v1.EmberCache.VRem:output_type -> ember.v1.BoolResponse - 80, // 236: ember.v1.EmberCache.VGet:output_type -> ember.v1.VGetResponse - 3, // 237: ember.v1.EmberCache.VCard:output_type -> ember.v1.IntResponse - 3, // 238: ember.v1.EmberCache.VDim:output_type -> ember.v1.IntResponse - 84, // 239: ember.v1.EmberCache.VInfo:output_type -> ember.v1.VInfoResponse - 86, // 240: ember.v1.EmberCache.Ping:output_type -> ember.v1.PingResponse - 92, // 241: ember.v1.EmberCache.Echo:output_type -> ember.v1.EchoResponse - 3, // 242: ember.v1.EmberCache.Decr:output_type -> ember.v1.IntResponse - 12, // 243: ember.v1.EmberCache.Unlink:output_type -> ember.v1.DelResponse - 6, // 244: ember.v1.EmberCache.FlushDb:output_type -> ember.v1.StatusResponse - 3, // 245: ember.v1.EmberCache.DbSize:output_type -> ember.v1.IntResponse - 90, // 246: ember.v1.EmberCache.Info:output_type -> ember.v1.InfoResponse - 6, // 247: ember.v1.EmberCache.BgSave:output_type -> ember.v1.StatusResponse - 6, // 248: ember.v1.EmberCache.BgRewriteAof:output_type -> ember.v1.StatusResponse - 98, // 249: ember.v1.EmberCache.SlowLogGet:output_type -> ember.v1.SlowLogGetResponse - 3, // 250: ember.v1.EmberCache.SlowLogLen:output_type -> ember.v1.IntResponse - 6, // 251: ember.v1.EmberCache.SlowLogReset:output_type -> ember.v1.StatusResponse - 3, // 252: ember.v1.EmberCache.Publish:output_type -> ember.v1.IntResponse - 104, // 253: ember.v1.EmberCache.Subscribe:output_type -> ember.v1.SubscribeEvent - 35, // 254: ember.v1.EmberCache.PubSubChannels:output_type -> ember.v1.KeysResponse - 107, // 255: ember.v1.EmberCache.PubSubNumSub:output_type -> ember.v1.PubSubNumSubResponse - 3, // 256: ember.v1.EmberCache.PubSubNumPat:output_type -> ember.v1.IntResponse - 111, // 257: ember.v1.EmberCache.Pipeline:output_type -> ember.v1.PipelineResponse - 185, // [185:258] is the sub-list for method output_type - 112, // [112:185] is the sub-list for method input_type - 112, // [112:112] is the sub-list for extension type_name - 112, // [112:112] is the sub-list for extension extendee - 0, // [0:112] is the sub-list for field type_name + 75, // 9: ember.v1.VAddBatchRequest.entries:type_name -> ember.v1.VAddBatchEntry + 0, // 10: ember.v1.VAddBatchRequest.metric:type_name -> ember.v1.VectorMetric + 1, // 11: ember.v1.VAddBatchRequest.quantization:type_name -> ember.v1.VectorQuantization + 79, // 12: ember.v1.VSimResponse.results:type_name -> ember.v1.VSimResult + 47, // 13: ember.v1.VInfoResponse.info:type_name -> ember.v1.FieldValue + 101, // 14: ember.v1.SlowLogGetResponse.entries:type_name -> ember.v1.SlowLogEntry + 111, // 15: ember.v1.PubSubNumSubResponse.counts:type_name -> ember.v1.ChannelCount + 7, // 16: ember.v1.PipelineRequest.get:type_name -> ember.v1.GetRequest + 9, // 17: ember.v1.PipelineRequest.set:type_name -> ember.v1.SetRequest + 11, // 18: ember.v1.PipelineRequest.del:type_name -> ember.v1.DelRequest + 25, // 19: ember.v1.PipelineRequest.exists:type_name -> ember.v1.ExistsRequest + 19, // 20: ember.v1.PipelineRequest.incr:type_name -> ember.v1.IncrRequest + 20, // 21: ember.v1.PipelineRequest.incr_by:type_name -> ember.v1.IncrByRequest + 21, // 22: ember.v1.PipelineRequest.decr_by:type_name -> ember.v1.DecrByRequest + 22, // 23: ember.v1.PipelineRequest.incr_by_float:type_name -> ember.v1.IncrByFloatRequest + 23, // 24: ember.v1.PipelineRequest.append:type_name -> ember.v1.AppendRequest + 24, // 25: ember.v1.PipelineRequest.strlen:type_name -> ember.v1.StrlenRequest + 26, // 26: ember.v1.PipelineRequest.expire:type_name -> ember.v1.ExpireRequest + 27, // 27: ember.v1.PipelineRequest.pexpire:type_name -> ember.v1.PExpireRequest + 28, // 28: ember.v1.PipelineRequest.persist:type_name -> ember.v1.PersistRequest + 29, // 29: ember.v1.PipelineRequest.ttl:type_name -> ember.v1.TtlRequest + 30, // 30: ember.v1.PipelineRequest.pttl:type_name -> ember.v1.PTtlRequest + 32, // 31: ember.v1.PipelineRequest.type:type_name -> ember.v1.TypeRequest + 39, // 32: ember.v1.PipelineRequest.lpush:type_name -> ember.v1.LPushRequest + 40, // 33: ember.v1.PipelineRequest.rpush:type_name -> ember.v1.RPushRequest + 41, // 34: ember.v1.PipelineRequest.lpop:type_name -> ember.v1.LPopRequest + 42, // 35: ember.v1.PipelineRequest.rpop:type_name -> ember.v1.RPopRequest + 43, // 36: ember.v1.PipelineRequest.lrange:type_name -> ember.v1.LRangeRequest + 45, // 37: ember.v1.PipelineRequest.llen:type_name -> ember.v1.LLenRequest + 46, // 38: ember.v1.PipelineRequest.hset:type_name -> ember.v1.HSetRequest + 48, // 39: ember.v1.PipelineRequest.hget:type_name -> ember.v1.HGetRequest + 49, // 40: ember.v1.PipelineRequest.hgetall:type_name -> ember.v1.HGetAllRequest + 51, // 41: ember.v1.PipelineRequest.hdel:type_name -> ember.v1.HDelRequest + 52, // 42: ember.v1.PipelineRequest.hexists:type_name -> ember.v1.HExistsRequest + 53, // 43: ember.v1.PipelineRequest.hlen:type_name -> ember.v1.HLenRequest + 54, // 44: ember.v1.PipelineRequest.hincr_by:type_name -> ember.v1.HIncrByRequest + 55, // 45: ember.v1.PipelineRequest.hkeys:type_name -> ember.v1.HKeysRequest + 56, // 46: ember.v1.PipelineRequest.hvals:type_name -> ember.v1.HValsRequest + 57, // 47: ember.v1.PipelineRequest.hmget:type_name -> ember.v1.HMGetRequest + 59, // 48: ember.v1.PipelineRequest.sadd:type_name -> ember.v1.SAddRequest + 60, // 49: ember.v1.PipelineRequest.srem:type_name -> ember.v1.SRemRequest + 61, // 50: ember.v1.PipelineRequest.smembers:type_name -> ember.v1.SMembersRequest + 62, // 51: ember.v1.PipelineRequest.sismember:type_name -> ember.v1.SIsMemberRequest + 63, // 52: ember.v1.PipelineRequest.scard:type_name -> ember.v1.SCardRequest + 64, // 53: ember.v1.PipelineRequest.zadd:type_name -> ember.v1.ZAddRequest + 66, // 54: ember.v1.PipelineRequest.zrem:type_name -> ember.v1.ZRemRequest + 67, // 55: ember.v1.PipelineRequest.zscore:type_name -> ember.v1.ZScoreRequest + 69, // 56: ember.v1.PipelineRequest.zrank:type_name -> ember.v1.ZRankRequest + 71, // 57: ember.v1.PipelineRequest.zcard:type_name -> ember.v1.ZCardRequest + 72, // 58: ember.v1.PipelineRequest.zrange:type_name -> ember.v1.ZRangeRequest + 74, // 59: ember.v1.PipelineRequest.vadd:type_name -> ember.v1.VAddRequest + 77, // 60: ember.v1.PipelineRequest.vsim:type_name -> ember.v1.VSimRequest + 80, // 61: ember.v1.PipelineRequest.vrem:type_name -> ember.v1.VRemRequest + 81, // 62: ember.v1.PipelineRequest.vget:type_name -> ember.v1.VGetRequest + 83, // 63: ember.v1.PipelineRequest.vcard:type_name -> ember.v1.VCardRequest + 84, // 64: ember.v1.PipelineRequest.vdim:type_name -> ember.v1.VDimRequest + 85, // 65: ember.v1.PipelineRequest.vinfo:type_name -> ember.v1.VInfoRequest + 87, // 66: ember.v1.PipelineRequest.ping:type_name -> ember.v1.PingRequest + 89, // 67: ember.v1.PipelineRequest.flushdb:type_name -> ember.v1.FlushDbRequest + 90, // 68: ember.v1.PipelineRequest.dbsize:type_name -> ember.v1.DbSizeRequest + 13, // 69: ember.v1.PipelineRequest.mget:type_name -> ember.v1.MGetRequest + 16, // 70: ember.v1.PipelineRequest.mset:type_name -> ember.v1.MSetRequest + 34, // 71: ember.v1.PipelineRequest.keys:type_name -> ember.v1.KeysRequest + 36, // 72: ember.v1.PipelineRequest.rename:type_name -> ember.v1.RenameRequest + 37, // 73: ember.v1.PipelineRequest.scan:type_name -> ember.v1.ScanRequest + 93, // 74: ember.v1.PipelineRequest.echo:type_name -> ember.v1.EchoRequest + 95, // 75: ember.v1.PipelineRequest.decr:type_name -> ember.v1.DecrRequest + 96, // 76: ember.v1.PipelineRequest.unlink:type_name -> ember.v1.UnlinkRequest + 97, // 77: ember.v1.PipelineRequest.bgsave:type_name -> ember.v1.BgSaveRequest + 98, // 78: ember.v1.PipelineRequest.bgrewriteaof:type_name -> ember.v1.BgRewriteAofRequest + 99, // 79: ember.v1.PipelineRequest.slowlog_get:type_name -> ember.v1.SlowLogGetRequest + 102, // 80: ember.v1.PipelineRequest.slowlog_len:type_name -> ember.v1.SlowLogLenRequest + 103, // 81: ember.v1.PipelineRequest.slowlog_reset:type_name -> ember.v1.SlowLogResetRequest + 104, // 82: ember.v1.PipelineRequest.publish:type_name -> ember.v1.PublishRequest + 107, // 83: ember.v1.PipelineRequest.pubsub_channels:type_name -> ember.v1.PubSubChannelsRequest + 108, // 84: ember.v1.PipelineRequest.pubsub_numsub:type_name -> ember.v1.PubSubNumSubRequest + 110, // 85: ember.v1.PipelineRequest.pubsub_numpat:type_name -> ember.v1.PubSubNumPatRequest + 76, // 86: ember.v1.PipelineRequest.vadd_batch:type_name -> ember.v1.VAddBatchRequest + 8, // 87: ember.v1.PipelineResponse.get:type_name -> ember.v1.GetResponse + 10, // 88: ember.v1.PipelineResponse.set:type_name -> ember.v1.SetResponse + 12, // 89: ember.v1.PipelineResponse.del:type_name -> ember.v1.DelResponse + 3, // 90: ember.v1.PipelineResponse.int_val:type_name -> ember.v1.IntResponse + 4, // 91: ember.v1.PipelineResponse.bool_val:type_name -> ember.v1.BoolResponse + 5, // 92: ember.v1.PipelineResponse.float_val:type_name -> ember.v1.FloatResponse + 6, // 93: ember.v1.PipelineResponse.status:type_name -> ember.v1.StatusResponse + 31, // 94: ember.v1.PipelineResponse.ttl:type_name -> ember.v1.TtlResponse + 33, // 95: ember.v1.PipelineResponse.type:type_name -> ember.v1.TypeResponse + 44, // 96: ember.v1.PipelineResponse.array:type_name -> ember.v1.ArrayResponse + 50, // 97: ember.v1.PipelineResponse.hash:type_name -> ember.v1.HashResponse + 58, // 98: ember.v1.PipelineResponse.optional_array:type_name -> ember.v1.OptionalArrayResponse + 35, // 99: ember.v1.PipelineResponse.keys:type_name -> ember.v1.KeysResponse + 38, // 100: ember.v1.PipelineResponse.scan:type_name -> ember.v1.ScanResponse + 68, // 101: ember.v1.PipelineResponse.optional_float:type_name -> ember.v1.OptionalFloatResponse + 70, // 102: ember.v1.PipelineResponse.optional_int:type_name -> ember.v1.OptionalIntResponse + 73, // 103: ember.v1.PipelineResponse.zrange:type_name -> ember.v1.ZRangeResponse + 78, // 104: ember.v1.PipelineResponse.vsim:type_name -> ember.v1.VSimResponse + 82, // 105: ember.v1.PipelineResponse.vget:type_name -> ember.v1.VGetResponse + 86, // 106: ember.v1.PipelineResponse.vinfo:type_name -> ember.v1.VInfoResponse + 14, // 107: ember.v1.PipelineResponse.mget:type_name -> ember.v1.MGetResponse + 18, // 108: ember.v1.PipelineResponse.mset:type_name -> ember.v1.MSetResponse + 88, // 109: ember.v1.PipelineResponse.ping:type_name -> ember.v1.PingResponse + 114, // 110: ember.v1.PipelineResponse.error:type_name -> ember.v1.ErrorResponse + 92, // 111: ember.v1.PipelineResponse.info:type_name -> ember.v1.InfoResponse + 94, // 112: ember.v1.PipelineResponse.echo:type_name -> ember.v1.EchoResponse + 100, // 113: ember.v1.PipelineResponse.slowlog_get:type_name -> ember.v1.SlowLogGetResponse + 109, // 114: ember.v1.PipelineResponse.pubsub_numsub:type_name -> ember.v1.PubSubNumSubResponse + 2, // 115: ember.v1.ErrorResponse.kind:type_name -> ember.v1.ErrorKind + 7, // 116: ember.v1.EmberCache.Get:input_type -> ember.v1.GetRequest + 9, // 117: ember.v1.EmberCache.Set:input_type -> ember.v1.SetRequest + 11, // 118: ember.v1.EmberCache.Del:input_type -> ember.v1.DelRequest + 13, // 119: ember.v1.EmberCache.MGet:input_type -> ember.v1.MGetRequest + 16, // 120: ember.v1.EmberCache.MSet:input_type -> ember.v1.MSetRequest + 19, // 121: ember.v1.EmberCache.Incr:input_type -> ember.v1.IncrRequest + 20, // 122: ember.v1.EmberCache.IncrBy:input_type -> ember.v1.IncrByRequest + 21, // 123: ember.v1.EmberCache.DecrBy:input_type -> ember.v1.DecrByRequest + 22, // 124: ember.v1.EmberCache.IncrByFloat:input_type -> ember.v1.IncrByFloatRequest + 23, // 125: ember.v1.EmberCache.Append:input_type -> ember.v1.AppendRequest + 24, // 126: ember.v1.EmberCache.Strlen:input_type -> ember.v1.StrlenRequest + 25, // 127: ember.v1.EmberCache.Exists:input_type -> ember.v1.ExistsRequest + 26, // 128: ember.v1.EmberCache.Expire:input_type -> ember.v1.ExpireRequest + 27, // 129: ember.v1.EmberCache.PExpire:input_type -> ember.v1.PExpireRequest + 28, // 130: ember.v1.EmberCache.Persist:input_type -> ember.v1.PersistRequest + 29, // 131: ember.v1.EmberCache.Ttl:input_type -> ember.v1.TtlRequest + 30, // 132: ember.v1.EmberCache.PTtl:input_type -> ember.v1.PTtlRequest + 32, // 133: ember.v1.EmberCache.Type:input_type -> ember.v1.TypeRequest + 34, // 134: ember.v1.EmberCache.Keys:input_type -> ember.v1.KeysRequest + 36, // 135: ember.v1.EmberCache.Rename:input_type -> ember.v1.RenameRequest + 37, // 136: ember.v1.EmberCache.Scan:input_type -> ember.v1.ScanRequest + 39, // 137: ember.v1.EmberCache.LPush:input_type -> ember.v1.LPushRequest + 40, // 138: ember.v1.EmberCache.RPush:input_type -> ember.v1.RPushRequest + 41, // 139: ember.v1.EmberCache.LPop:input_type -> ember.v1.LPopRequest + 42, // 140: ember.v1.EmberCache.RPop:input_type -> ember.v1.RPopRequest + 43, // 141: ember.v1.EmberCache.LRange:input_type -> ember.v1.LRangeRequest + 45, // 142: ember.v1.EmberCache.LLen:input_type -> ember.v1.LLenRequest + 46, // 143: ember.v1.EmberCache.HSet:input_type -> ember.v1.HSetRequest + 48, // 144: ember.v1.EmberCache.HGet:input_type -> ember.v1.HGetRequest + 49, // 145: ember.v1.EmberCache.HGetAll:input_type -> ember.v1.HGetAllRequest + 51, // 146: ember.v1.EmberCache.HDel:input_type -> ember.v1.HDelRequest + 52, // 147: ember.v1.EmberCache.HExists:input_type -> ember.v1.HExistsRequest + 53, // 148: ember.v1.EmberCache.HLen:input_type -> ember.v1.HLenRequest + 54, // 149: ember.v1.EmberCache.HIncrBy:input_type -> ember.v1.HIncrByRequest + 55, // 150: ember.v1.EmberCache.HKeys:input_type -> ember.v1.HKeysRequest + 56, // 151: ember.v1.EmberCache.HVals:input_type -> ember.v1.HValsRequest + 57, // 152: ember.v1.EmberCache.HMGet:input_type -> ember.v1.HMGetRequest + 59, // 153: ember.v1.EmberCache.SAdd:input_type -> ember.v1.SAddRequest + 60, // 154: ember.v1.EmberCache.SRem:input_type -> ember.v1.SRemRequest + 61, // 155: ember.v1.EmberCache.SMembers:input_type -> ember.v1.SMembersRequest + 62, // 156: ember.v1.EmberCache.SIsMember:input_type -> ember.v1.SIsMemberRequest + 63, // 157: ember.v1.EmberCache.SCard:input_type -> ember.v1.SCardRequest + 64, // 158: ember.v1.EmberCache.ZAdd:input_type -> ember.v1.ZAddRequest + 66, // 159: ember.v1.EmberCache.ZRem:input_type -> ember.v1.ZRemRequest + 67, // 160: ember.v1.EmberCache.ZScore:input_type -> ember.v1.ZScoreRequest + 69, // 161: ember.v1.EmberCache.ZRank:input_type -> ember.v1.ZRankRequest + 71, // 162: ember.v1.EmberCache.ZCard:input_type -> ember.v1.ZCardRequest + 72, // 163: ember.v1.EmberCache.ZRange:input_type -> ember.v1.ZRangeRequest + 74, // 164: ember.v1.EmberCache.VAdd:input_type -> ember.v1.VAddRequest + 76, // 165: ember.v1.EmberCache.VAddBatch:input_type -> ember.v1.VAddBatchRequest + 77, // 166: ember.v1.EmberCache.VSim:input_type -> ember.v1.VSimRequest + 80, // 167: ember.v1.EmberCache.VRem:input_type -> ember.v1.VRemRequest + 81, // 168: ember.v1.EmberCache.VGet:input_type -> ember.v1.VGetRequest + 83, // 169: ember.v1.EmberCache.VCard:input_type -> ember.v1.VCardRequest + 84, // 170: ember.v1.EmberCache.VDim:input_type -> ember.v1.VDimRequest + 85, // 171: ember.v1.EmberCache.VInfo:input_type -> ember.v1.VInfoRequest + 87, // 172: ember.v1.EmberCache.Ping:input_type -> ember.v1.PingRequest + 93, // 173: ember.v1.EmberCache.Echo:input_type -> ember.v1.EchoRequest + 95, // 174: ember.v1.EmberCache.Decr:input_type -> ember.v1.DecrRequest + 96, // 175: ember.v1.EmberCache.Unlink:input_type -> ember.v1.UnlinkRequest + 89, // 176: ember.v1.EmberCache.FlushDb:input_type -> ember.v1.FlushDbRequest + 90, // 177: ember.v1.EmberCache.DbSize:input_type -> ember.v1.DbSizeRequest + 91, // 178: ember.v1.EmberCache.Info:input_type -> ember.v1.InfoRequest + 97, // 179: ember.v1.EmberCache.BgSave:input_type -> ember.v1.BgSaveRequest + 98, // 180: ember.v1.EmberCache.BgRewriteAof:input_type -> ember.v1.BgRewriteAofRequest + 99, // 181: ember.v1.EmberCache.SlowLogGet:input_type -> ember.v1.SlowLogGetRequest + 102, // 182: ember.v1.EmberCache.SlowLogLen:input_type -> ember.v1.SlowLogLenRequest + 103, // 183: ember.v1.EmberCache.SlowLogReset:input_type -> ember.v1.SlowLogResetRequest + 104, // 184: ember.v1.EmberCache.Publish:input_type -> ember.v1.PublishRequest + 105, // 185: ember.v1.EmberCache.Subscribe:input_type -> ember.v1.SubscribeRequest + 107, // 186: ember.v1.EmberCache.PubSubChannels:input_type -> ember.v1.PubSubChannelsRequest + 108, // 187: ember.v1.EmberCache.PubSubNumSub:input_type -> ember.v1.PubSubNumSubRequest + 110, // 188: ember.v1.EmberCache.PubSubNumPat:input_type -> ember.v1.PubSubNumPatRequest + 112, // 189: ember.v1.EmberCache.Pipeline:input_type -> ember.v1.PipelineRequest + 8, // 190: ember.v1.EmberCache.Get:output_type -> ember.v1.GetResponse + 10, // 191: ember.v1.EmberCache.Set:output_type -> ember.v1.SetResponse + 12, // 192: ember.v1.EmberCache.Del:output_type -> ember.v1.DelResponse + 14, // 193: ember.v1.EmberCache.MGet:output_type -> ember.v1.MGetResponse + 18, // 194: ember.v1.EmberCache.MSet:output_type -> ember.v1.MSetResponse + 3, // 195: ember.v1.EmberCache.Incr:output_type -> ember.v1.IntResponse + 3, // 196: ember.v1.EmberCache.IncrBy:output_type -> ember.v1.IntResponse + 3, // 197: ember.v1.EmberCache.DecrBy:output_type -> ember.v1.IntResponse + 5, // 198: ember.v1.EmberCache.IncrByFloat:output_type -> ember.v1.FloatResponse + 3, // 199: ember.v1.EmberCache.Append:output_type -> ember.v1.IntResponse + 3, // 200: ember.v1.EmberCache.Strlen:output_type -> ember.v1.IntResponse + 3, // 201: ember.v1.EmberCache.Exists:output_type -> ember.v1.IntResponse + 4, // 202: ember.v1.EmberCache.Expire:output_type -> ember.v1.BoolResponse + 4, // 203: ember.v1.EmberCache.PExpire:output_type -> ember.v1.BoolResponse + 4, // 204: ember.v1.EmberCache.Persist:output_type -> ember.v1.BoolResponse + 31, // 205: ember.v1.EmberCache.Ttl:output_type -> ember.v1.TtlResponse + 31, // 206: ember.v1.EmberCache.PTtl:output_type -> ember.v1.TtlResponse + 33, // 207: ember.v1.EmberCache.Type:output_type -> ember.v1.TypeResponse + 35, // 208: ember.v1.EmberCache.Keys:output_type -> ember.v1.KeysResponse + 6, // 209: ember.v1.EmberCache.Rename:output_type -> ember.v1.StatusResponse + 38, // 210: ember.v1.EmberCache.Scan:output_type -> ember.v1.ScanResponse + 3, // 211: ember.v1.EmberCache.LPush:output_type -> ember.v1.IntResponse + 3, // 212: ember.v1.EmberCache.RPush:output_type -> ember.v1.IntResponse + 8, // 213: ember.v1.EmberCache.LPop:output_type -> ember.v1.GetResponse + 8, // 214: ember.v1.EmberCache.RPop:output_type -> ember.v1.GetResponse + 44, // 215: ember.v1.EmberCache.LRange:output_type -> ember.v1.ArrayResponse + 3, // 216: ember.v1.EmberCache.LLen:output_type -> ember.v1.IntResponse + 3, // 217: ember.v1.EmberCache.HSet:output_type -> ember.v1.IntResponse + 8, // 218: ember.v1.EmberCache.HGet:output_type -> ember.v1.GetResponse + 50, // 219: ember.v1.EmberCache.HGetAll:output_type -> ember.v1.HashResponse + 3, // 220: ember.v1.EmberCache.HDel:output_type -> ember.v1.IntResponse + 4, // 221: ember.v1.EmberCache.HExists:output_type -> ember.v1.BoolResponse + 3, // 222: ember.v1.EmberCache.HLen:output_type -> ember.v1.IntResponse + 3, // 223: ember.v1.EmberCache.HIncrBy:output_type -> ember.v1.IntResponse + 35, // 224: ember.v1.EmberCache.HKeys:output_type -> ember.v1.KeysResponse + 44, // 225: ember.v1.EmberCache.HVals:output_type -> ember.v1.ArrayResponse + 58, // 226: ember.v1.EmberCache.HMGet:output_type -> ember.v1.OptionalArrayResponse + 3, // 227: ember.v1.EmberCache.SAdd:output_type -> ember.v1.IntResponse + 3, // 228: ember.v1.EmberCache.SRem:output_type -> ember.v1.IntResponse + 35, // 229: ember.v1.EmberCache.SMembers:output_type -> ember.v1.KeysResponse + 4, // 230: ember.v1.EmberCache.SIsMember:output_type -> ember.v1.BoolResponse + 3, // 231: ember.v1.EmberCache.SCard:output_type -> ember.v1.IntResponse + 3, // 232: ember.v1.EmberCache.ZAdd:output_type -> ember.v1.IntResponse + 3, // 233: ember.v1.EmberCache.ZRem:output_type -> ember.v1.IntResponse + 68, // 234: ember.v1.EmberCache.ZScore:output_type -> ember.v1.OptionalFloatResponse + 70, // 235: ember.v1.EmberCache.ZRank:output_type -> ember.v1.OptionalIntResponse + 3, // 236: ember.v1.EmberCache.ZCard:output_type -> ember.v1.IntResponse + 73, // 237: ember.v1.EmberCache.ZRange:output_type -> ember.v1.ZRangeResponse + 4, // 238: ember.v1.EmberCache.VAdd:output_type -> ember.v1.BoolResponse + 3, // 239: ember.v1.EmberCache.VAddBatch:output_type -> ember.v1.IntResponse + 78, // 240: ember.v1.EmberCache.VSim:output_type -> ember.v1.VSimResponse + 4, // 241: ember.v1.EmberCache.VRem:output_type -> ember.v1.BoolResponse + 82, // 242: ember.v1.EmberCache.VGet:output_type -> ember.v1.VGetResponse + 3, // 243: ember.v1.EmberCache.VCard:output_type -> ember.v1.IntResponse + 3, // 244: ember.v1.EmberCache.VDim:output_type -> ember.v1.IntResponse + 86, // 245: ember.v1.EmberCache.VInfo:output_type -> ember.v1.VInfoResponse + 88, // 246: ember.v1.EmberCache.Ping:output_type -> ember.v1.PingResponse + 94, // 247: ember.v1.EmberCache.Echo:output_type -> ember.v1.EchoResponse + 3, // 248: ember.v1.EmberCache.Decr:output_type -> ember.v1.IntResponse + 12, // 249: ember.v1.EmberCache.Unlink:output_type -> ember.v1.DelResponse + 6, // 250: ember.v1.EmberCache.FlushDb:output_type -> ember.v1.StatusResponse + 3, // 251: ember.v1.EmberCache.DbSize:output_type -> ember.v1.IntResponse + 92, // 252: ember.v1.EmberCache.Info:output_type -> ember.v1.InfoResponse + 6, // 253: ember.v1.EmberCache.BgSave:output_type -> ember.v1.StatusResponse + 6, // 254: ember.v1.EmberCache.BgRewriteAof:output_type -> ember.v1.StatusResponse + 100, // 255: ember.v1.EmberCache.SlowLogGet:output_type -> ember.v1.SlowLogGetResponse + 3, // 256: ember.v1.EmberCache.SlowLogLen:output_type -> ember.v1.IntResponse + 6, // 257: ember.v1.EmberCache.SlowLogReset:output_type -> ember.v1.StatusResponse + 3, // 258: ember.v1.EmberCache.Publish:output_type -> ember.v1.IntResponse + 106, // 259: ember.v1.EmberCache.Subscribe:output_type -> ember.v1.SubscribeEvent + 35, // 260: ember.v1.EmberCache.PubSubChannels:output_type -> ember.v1.KeysResponse + 109, // 261: ember.v1.EmberCache.PubSubNumSub:output_type -> ember.v1.PubSubNumSubResponse + 3, // 262: ember.v1.EmberCache.PubSubNumPat:output_type -> ember.v1.IntResponse + 113, // 263: ember.v1.EmberCache.Pipeline:output_type -> ember.v1.PipelineResponse + 190, // [190:264] is the sub-list for method output_type + 116, // [116:190] is the sub-list for method input_type + 116, // [116:116] is the sub-list for extension type_name + 116, // [116:116] is the sub-list for extension extendee + 0, // [0:116] is the sub-list for field type_name } func init() { file_ember_v1_ember_proto_init() } @@ -8025,14 +8200,15 @@ func file_ember_v1_ember_proto_init() { file_ember_v1_ember_proto_msgTypes[65].OneofWrappers = []any{} file_ember_v1_ember_proto_msgTypes[67].OneofWrappers = []any{} file_ember_v1_ember_proto_msgTypes[71].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[72].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[77].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[82].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[86].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[94].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[101].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[102].OneofWrappers = []any{} - file_ember_v1_ember_proto_msgTypes[107].OneofWrappers = []any{ + file_ember_v1_ember_proto_msgTypes[73].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[74].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[79].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[84].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[88].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[96].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[103].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[104].OneofWrappers = []any{} + file_ember_v1_ember_proto_msgTypes[109].OneofWrappers = []any{ (*PipelineRequest_Get)(nil), (*PipelineRequest_Set)(nil), (*PipelineRequest_Del)(nil), @@ -8103,8 +8279,9 @@ func file_ember_v1_ember_proto_init() { (*PipelineRequest_PubsubChannels)(nil), (*PipelineRequest_PubsubNumsub)(nil), (*PipelineRequest_PubsubNumpat)(nil), + (*PipelineRequest_VaddBatch)(nil), } - file_ember_v1_ember_proto_msgTypes[108].OneofWrappers = []any{ + file_ember_v1_ember_proto_msgTypes[110].OneofWrappers = []any{ (*PipelineResponse_Get)(nil), (*PipelineResponse_Set)(nil), (*PipelineResponse_Del)(nil), @@ -8140,7 +8317,7 @@ func file_ember_v1_ember_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_ember_v1_ember_proto_rawDesc), len(file_ember_v1_ember_proto_rawDesc)), NumEnums: 3, - NumMessages: 110, + NumMessages: 112, NumExtensions: 0, NumServices: 1, }, diff --git a/clients/ember-go/proto/ember/v1/ember_grpc.pb.go b/clients/ember-go/proto/ember/v1/ember_grpc.pb.go index b1da762c..c16b6ff6 100644 --- a/clients/ember-go/proto/ember/v1/ember_grpc.pb.go +++ b/clients/ember-go/proto/ember/v1/ember_grpc.pb.go @@ -68,6 +68,7 @@ const ( EmberCache_ZCard_FullMethodName = "/ember.v1.EmberCache/ZCard" EmberCache_ZRange_FullMethodName = "/ember.v1.EmberCache/ZRange" EmberCache_VAdd_FullMethodName = "/ember.v1.EmberCache/VAdd" + EmberCache_VAddBatch_FullMethodName = "/ember.v1.EmberCache/VAddBatch" EmberCache_VSim_FullMethodName = "/ember.v1.EmberCache/VSim" EmberCache_VRem_FullMethodName = "/ember.v1.EmberCache/VRem" EmberCache_VGet_FullMethodName = "/ember.v1.EmberCache/VGet" @@ -151,6 +152,7 @@ type EmberCacheClient interface { ZCard(ctx context.Context, in *ZCardRequest, opts ...grpc.CallOption) (*IntResponse, error) ZRange(ctx context.Context, in *ZRangeRequest, opts ...grpc.CallOption) (*ZRangeResponse, error) VAdd(ctx context.Context, in *VAddRequest, opts ...grpc.CallOption) (*BoolResponse, error) + VAddBatch(ctx context.Context, in *VAddBatchRequest, opts ...grpc.CallOption) (*IntResponse, error) VSim(ctx context.Context, in *VSimRequest, opts ...grpc.CallOption) (*VSimResponse, error) VRem(ctx context.Context, in *VRemRequest, opts ...grpc.CallOption) (*BoolResponse, error) VGet(ctx context.Context, in *VGetRequest, opts ...grpc.CallOption) (*VGetResponse, error) @@ -675,6 +677,16 @@ func (c *emberCacheClient) VAdd(ctx context.Context, in *VAddRequest, opts ...gr return out, nil } +func (c *emberCacheClient) VAddBatch(ctx context.Context, in *VAddBatchRequest, opts ...grpc.CallOption) (*IntResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(IntResponse) + err := c.cc.Invoke(ctx, EmberCache_VAddBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *emberCacheClient) VSim(ctx context.Context, in *VSimRequest, opts ...grpc.CallOption) (*VSimResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(VSimResponse) @@ -984,6 +996,7 @@ type EmberCacheServer interface { ZCard(context.Context, *ZCardRequest) (*IntResponse, error) ZRange(context.Context, *ZRangeRequest) (*ZRangeResponse, error) VAdd(context.Context, *VAddRequest) (*BoolResponse, error) + VAddBatch(context.Context, *VAddBatchRequest) (*IntResponse, error) VSim(context.Context, *VSimRequest) (*VSimResponse, error) VRem(context.Context, *VRemRequest) (*BoolResponse, error) VGet(context.Context, *VGetRequest) (*VGetResponse, error) @@ -1165,6 +1178,9 @@ func (UnimplementedEmberCacheServer) ZRange(context.Context, *ZRangeRequest) (*Z func (UnimplementedEmberCacheServer) VAdd(context.Context, *VAddRequest) (*BoolResponse, error) { return nil, status.Error(codes.Unimplemented, "method VAdd not implemented") } +func (UnimplementedEmberCacheServer) VAddBatch(context.Context, *VAddBatchRequest) (*IntResponse, error) { + return nil, status.Error(codes.Unimplemented, "method VAddBatch not implemented") +} func (UnimplementedEmberCacheServer) VSim(context.Context, *VSimRequest) (*VSimResponse, error) { return nil, status.Error(codes.Unimplemented, "method VSim not implemented") } @@ -2140,6 +2156,24 @@ func _EmberCache_VAdd_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _EmberCache_VAddBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VAddBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EmberCacheServer).VAddBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EmberCache_VAddBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EmberCacheServer).VAddBatch(ctx, req.(*VAddBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _EmberCache_VSim_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(VSimRequest) if err := dec(in); err != nil { @@ -2757,6 +2791,10 @@ var EmberCache_ServiceDesc = grpc.ServiceDesc{ MethodName: "VAdd", Handler: _EmberCache_VAdd_Handler, }, + { + MethodName: "VAddBatch", + Handler: _EmberCache_VAddBatch_Handler, + }, { MethodName: "VSim", Handler: _EmberCache_VSim_Handler, diff --git a/clients/ember-py/ember/client.py b/clients/ember-py/ember/client.py index 9352e086..f84d65d1 100644 --- a/clients/ember-py/ember/client.py +++ b/clients/ember-py/ember/client.py @@ -302,6 +302,40 @@ def vadd( ) return resp.value + def vadd_batch( + self, + key: str, + entries: list[tuple[str, list[float]]], + metric: str = "cosine", + m: int = 16, + ef: int = 64, + ) -> int: + """Add multiple vectors to a vector set. Returns count of newly added elements. + + entries: list of (element, vector) tuples. All vectors must have the + same dimensionality. + """ + metric_map = { + "cosine": ember_pb2.VECTOR_METRIC_COSINE, + "euclidean": ember_pb2.VECTOR_METRIC_EUCLIDEAN, + "ip": ember_pb2.VECTOR_METRIC_INNER_PRODUCT, + } + batch_entries = [ + ember_pb2.VAddBatchEntry(element=elem, vector=vec) + for elem, vec in entries + ] + resp = self._stub.VAddBatch( + ember_pb2.VAddBatchRequest( + key=key, + entries=batch_entries, + metric=metric_map.get(metric, ember_pb2.VECTOR_METRIC_COSINE), + connectivity=m, + ef_construction=ef, + ), + metadata=self._metadata(), + ) + return resp.value + def vsim( self, key: str, diff --git a/clients/ember-py/ember/proto/ember/v1/ember_pb2.py b/clients/ember-py/ember/proto/ember/v1/ember_pb2.py index 36e05b09..305bd287 100644 --- a/clients/ember-py/ember/proto/ember/v1/ember_pb2.py +++ b/clients/ember-py/ember/proto/ember/v1/ember_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x65mber/v1/ember.proto\x12\x08\x65mber.v1\"\x1c\n\x0bIntResponse\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1d\n\x0c\x42oolResponse\x12\r\n\x05value\x18\x01 \x01(\x08\"\x1e\n\rFloatResponse\x12\r\n\x05value\x18\x01 \x01(\t\" \n\x0eStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\"\x19\n\nGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\x0bGetResponse\x12\x12\n\x05value\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x08\n\x06_value\"o\n\nSetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65xpire_seconds\x18\x03 \x01(\x04\x12\x15\n\rexpire_millis\x18\x04 \x01(\x04\x12\n\n\x02nx\x18\x05 \x01(\x08\x12\n\n\x02xx\x18\x06 \x01(\x08\"\x19\n\x0bSetResponse\x12\n\n\x02ok\x18\x01 \x01(\x08\"\x1a\n\nDelRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"\x1e\n\x0b\x44\x65lResponse\x12\x0f\n\x07\x64\x65leted\x18\x01 \x01(\x03\"\x1b\n\x0bMGetRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"7\n\x0cMGetResponse\x12\'\n\x06values\x18\x01 \x03(\x0b\x32\x17.ember.v1.OptionalValue\"-\n\rOptionalValue\x12\x12\n\x05value\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x08\n\x06_value\"0\n\x0bMSetRequest\x12!\n\x05pairs\x18\x01 \x03(\x0b\x32\x12.ember.v1.KeyValue\"&\n\x08KeyValue\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x0e\n\x0cMSetResponse\"\x1a\n\x0bIncrRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\rIncrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x03\"+\n\rDecrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x03\"0\n\x12IncrByFloatRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x01\"+\n\rAppendRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1c\n\rStrlenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1d\n\rExistsRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"-\n\rExpireRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07seconds\x18\x02 \x01(\x04\"3\n\x0ePExpireRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x14\n\x0cmilliseconds\x18\x02 \x01(\x04\"\x1d\n\x0ePersistRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x19\n\nTtlRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bPTtlRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1c\n\x0bTtlResponse\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1a\n\x0bTypeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"!\n\x0cTypeResponse\x12\x11\n\ttype_name\x18\x01 \x01(\t\"\x1e\n\x0bKeysRequest\x12\x0f\n\x07pattern\x18\x01 \x01(\t\"\x1c\n\x0cKeysResponse\x12\x0c\n\x04keys\x18\x01 \x03(\t\"-\n\rRenameRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07new_key\x18\x02 \x01(\t\"N\n\x0bScanRequest\x12\x0e\n\x06\x63ursor\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x14\n\x07pattern\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\",\n\x0cScanResponse\x12\x0e\n\x06\x63ursor\x18\x01 \x01(\x04\x12\x0c\n\x04keys\x18\x02 \x03(\t\"+\n\x0cLPushRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06values\x18\x02 \x03(\x0c\"+\n\x0cRPushRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06values\x18\x02 \x03(\x0c\"\x1a\n\x0bLPopRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bRPopRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"9\n\rLRangeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05start\x18\x02 \x01(\x03\x12\x0c\n\x04stop\x18\x03 \x01(\x03\"\x1f\n\rArrayResponse\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1a\n\x0bLLenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"@\n\x0bHSetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x14.ember.v1.FieldValue\"*\n\nFieldValue\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\")\n\x0bHGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\x1d\n\x0eHGetAllRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"4\n\x0cHashResponse\x12$\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x14.ember.v1.FieldValue\"*\n\x0bHDelRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06\x66ields\x18\x02 \x03(\t\",\n\x0eHExistsRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\x1a\n\x0bHLenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\";\n\x0eHIncrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x03 \x01(\x03\"\x1b\n\x0cHKeysRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1b\n\x0cHValsRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\x0cHMGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06\x66ields\x18\x02 \x03(\t\"@\n\x15OptionalArrayResponse\x12\'\n\x06values\x18\x01 \x03(\x0b\x32\x17.ember.v1.OptionalValue\"+\n\x0bSAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\"+\n\x0bSRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\"\x1e\n\x0fSMembersRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"/\n\x10SIsMemberRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"\x1b\n\x0cSCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"~\n\x0bZAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x07members\x18\x02 \x03(\x0b\x32\x15.ember.v1.ScoreMember\x12\n\n\x02nx\x18\x03 \x01(\x08\x12\n\n\x02xx\x18\x04 \x01(\x08\x12\n\n\x02gt\x18\x05 \x01(\x08\x12\n\n\x02lt\x18\x06 \x01(\x08\x12\n\n\x02\x63h\x18\x07 \x01(\x08\",\n\x0bScoreMember\x12\r\n\x05score\x18\x01 \x01(\x01\x12\x0e\n\x06member\x18\x02 \x01(\t\"+\n\x0bZRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\",\n\rZScoreRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"5\n\x15OptionalFloatResponse\x12\x12\n\x05value\x18\x01 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value\"+\n\x0cZRankRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"3\n\x13OptionalIntResponse\x12\x12\n\x05value\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x08\n\x06_value\"\x1b\n\x0cZCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"N\n\rZRangeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05start\x18\x02 \x01(\x03\x12\x0c\n\x04stop\x18\x03 \x01(\x03\x12\x13\n\x0bwith_scores\x18\x04 \x01(\x08\"8\n\x0eZRangeResponse\x12&\n\x07members\x18\x01 \x03(\x0b\x32\x15.ember.v1.ScoreMember\"\xf9\x01\n\x0bVAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\x12\x12\n\x06vector\x18\x03 \x03(\x02\x42\x02\x10\x01\x12&\n\x06metric\x18\x04 \x01(\x0e\x32\x16.ember.v1.VectorMetric\x12\x32\n\x0cquantization\x18\x05 \x01(\x0e\x32\x1c.ember.v1.VectorQuantization\x12\x19\n\x0c\x63onnectivity\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0f\x65\x66_construction\x18\x07 \x01(\rH\x01\x88\x01\x01\x42\x0f\n\r_connectivityB\x12\n\x10_ef_construction\"b\n\x0bVSimRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x11\n\x05query\x18\x02 \x03(\x02\x42\x02\x10\x01\x12\r\n\x05\x63ount\x18\x03 \x01(\r\x12\x16\n\tef_search\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x0c\n\n_ef_search\"5\n\x0cVSimResponse\x12%\n\x07results\x18\x01 \x03(\x0b\x32\x14.ember.v1.VSimResult\"/\n\nVSimResult\x12\x0f\n\x07\x65lement\x18\x01 \x01(\t\x12\x10\n\x08\x64istance\x18\x02 \x01(\x02\"+\n\x0bVRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\"+\n\x0bVGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\"B\n\x0cVGetResponse\x12\x13\n\x06\x65xists\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x12\n\x06vector\x18\x02 \x03(\x02\x42\x02\x10\x01\x42\t\n\x07_exists\"\x1b\n\x0cVCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bVDimRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1b\n\x0cVInfoRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"C\n\rVInfoResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\x12\"\n\x04info\x18\x02 \x03(\x0b\x32\x14.ember.v1.FieldValue\"/\n\x0bPingRequest\x12\x14\n\x07message\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_message\"\x1f\n\x0cPingResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1f\n\x0e\x46lushDbRequest\x12\r\n\x05\x61sync\x18\x01 \x01(\x08\"\x0f\n\rDbSizeRequest\"/\n\x0bInfoRequest\x12\x14\n\x07section\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_section\"\x1c\n\x0cInfoResponse\x12\x0c\n\x04info\x18\x01 \x01(\t\"\x1e\n\x0b\x45\x63hoRequest\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1f\n\x0c\x45\x63hoResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1a\n\x0b\x44\x65\x63rRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1d\n\rUnlinkRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"\x0f\n\rBgSaveRequest\"\x15\n\x13\x42gRewriteAofRequest\"1\n\x11SlowLogGetRequest\x12\x12\n\x05\x63ount\x18\x01 \x01(\rH\x00\x88\x01\x01\x42\x08\n\x06_count\"=\n\x12SlowLogGetResponse\x12\'\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x16.ember.v1.SlowLogEntry\"\\\n\x0cSlowLogEntry\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x16\n\x0etimestamp_unix\x18\x02 \x01(\x04\x12\x17\n\x0f\x64uration_micros\x18\x03 \x01(\x04\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\"\x13\n\x11SlowLogLenRequest\"\x15\n\x13SlowLogResetRequest\"2\n\x0ePublishRequest\x12\x0f\n\x07\x63hannel\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\x0c\"6\n\x10SubscribeRequest\x12\x10\n\x08\x63hannels\x18\x01 \x03(\t\x12\x10\n\x08patterns\x18\x02 \x03(\t\"_\n\x0eSubscribeEvent\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x14\n\x07pattern\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\"9\n\x15PubSubChannelsRequest\x12\x14\n\x07pattern\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\"\'\n\x13PubSubNumSubRequest\x12\x10\n\x08\x63hannels\x18\x01 \x03(\t\">\n\x14PubSubNumSubResponse\x12&\n\x06\x63ounts\x18\x01 \x03(\x0b\x32\x16.ember.v1.ChannelCount\"\x15\n\x13PubSubNumPatRequest\".\n\x0c\x43hannelCount\x12\x0f\n\x07\x63hannel\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\"\xd3\x17\n\x0fPipelineRequest\x12\n\n\x02id\x18\x01 \x01(\x04\x12#\n\x03get\x18\x02 \x01(\x0b\x32\x14.ember.v1.GetRequestH\x00\x12#\n\x03set\x18\x03 \x01(\x0b\x32\x14.ember.v1.SetRequestH\x00\x12#\n\x03\x64\x65l\x18\x04 \x01(\x0b\x32\x14.ember.v1.DelRequestH\x00\x12)\n\x06\x65xists\x18\x05 \x01(\x0b\x32\x17.ember.v1.ExistsRequestH\x00\x12%\n\x04incr\x18\x06 \x01(\x0b\x32\x15.ember.v1.IncrRequestH\x00\x12*\n\x07incr_by\x18\x07 \x01(\x0b\x32\x17.ember.v1.IncrByRequestH\x00\x12*\n\x07\x64\x65\x63r_by\x18\x08 \x01(\x0b\x32\x17.ember.v1.DecrByRequestH\x00\x12\x35\n\rincr_by_float\x18\t \x01(\x0b\x32\x1c.ember.v1.IncrByFloatRequestH\x00\x12)\n\x06\x61ppend\x18\n \x01(\x0b\x32\x17.ember.v1.AppendRequestH\x00\x12)\n\x06strlen\x18\x0b \x01(\x0b\x32\x17.ember.v1.StrlenRequestH\x00\x12)\n\x06\x65xpire\x18\x0c \x01(\x0b\x32\x17.ember.v1.ExpireRequestH\x00\x12+\n\x07pexpire\x18\r \x01(\x0b\x32\x18.ember.v1.PExpireRequestH\x00\x12+\n\x07persist\x18\x0e \x01(\x0b\x32\x18.ember.v1.PersistRequestH\x00\x12#\n\x03ttl\x18\x0f \x01(\x0b\x32\x14.ember.v1.TtlRequestH\x00\x12%\n\x04pttl\x18\x10 \x01(\x0b\x32\x15.ember.v1.PTtlRequestH\x00\x12%\n\x04type\x18\x11 \x01(\x0b\x32\x15.ember.v1.TypeRequestH\x00\x12\'\n\x05lpush\x18\x12 \x01(\x0b\x32\x16.ember.v1.LPushRequestH\x00\x12\'\n\x05rpush\x18\x13 \x01(\x0b\x32\x16.ember.v1.RPushRequestH\x00\x12%\n\x04lpop\x18\x14 \x01(\x0b\x32\x15.ember.v1.LPopRequestH\x00\x12%\n\x04rpop\x18\x15 \x01(\x0b\x32\x15.ember.v1.RPopRequestH\x00\x12)\n\x06lrange\x18\x16 \x01(\x0b\x32\x17.ember.v1.LRangeRequestH\x00\x12%\n\x04llen\x18\x17 \x01(\x0b\x32\x15.ember.v1.LLenRequestH\x00\x12%\n\x04hset\x18\x18 \x01(\x0b\x32\x15.ember.v1.HSetRequestH\x00\x12%\n\x04hget\x18\x19 \x01(\x0b\x32\x15.ember.v1.HGetRequestH\x00\x12+\n\x07hgetall\x18\x1a \x01(\x0b\x32\x18.ember.v1.HGetAllRequestH\x00\x12%\n\x04hdel\x18\x1b \x01(\x0b\x32\x15.ember.v1.HDelRequestH\x00\x12+\n\x07hexists\x18\x1c \x01(\x0b\x32\x18.ember.v1.HExistsRequestH\x00\x12%\n\x04hlen\x18\x1d \x01(\x0b\x32\x15.ember.v1.HLenRequestH\x00\x12,\n\x08hincr_by\x18\x1e \x01(\x0b\x32\x18.ember.v1.HIncrByRequestH\x00\x12\'\n\x05hkeys\x18\x1f \x01(\x0b\x32\x16.ember.v1.HKeysRequestH\x00\x12\'\n\x05hvals\x18 \x01(\x0b\x32\x16.ember.v1.HValsRequestH\x00\x12\'\n\x05hmget\x18! \x01(\x0b\x32\x16.ember.v1.HMGetRequestH\x00\x12%\n\x04sadd\x18\" \x01(\x0b\x32\x15.ember.v1.SAddRequestH\x00\x12%\n\x04srem\x18# \x01(\x0b\x32\x15.ember.v1.SRemRequestH\x00\x12-\n\x08smembers\x18$ \x01(\x0b\x32\x19.ember.v1.SMembersRequestH\x00\x12/\n\tsismember\x18% \x01(\x0b\x32\x1a.ember.v1.SIsMemberRequestH\x00\x12\'\n\x05scard\x18& \x01(\x0b\x32\x16.ember.v1.SCardRequestH\x00\x12%\n\x04zadd\x18\' \x01(\x0b\x32\x15.ember.v1.ZAddRequestH\x00\x12%\n\x04zrem\x18( \x01(\x0b\x32\x15.ember.v1.ZRemRequestH\x00\x12)\n\x06zscore\x18) \x01(\x0b\x32\x17.ember.v1.ZScoreRequestH\x00\x12\'\n\x05zrank\x18* \x01(\x0b\x32\x16.ember.v1.ZRankRequestH\x00\x12\'\n\x05zcard\x18+ \x01(\x0b\x32\x16.ember.v1.ZCardRequestH\x00\x12)\n\x06zrange\x18, \x01(\x0b\x32\x17.ember.v1.ZRangeRequestH\x00\x12%\n\x04vadd\x18- \x01(\x0b\x32\x15.ember.v1.VAddRequestH\x00\x12%\n\x04vsim\x18. \x01(\x0b\x32\x15.ember.v1.VSimRequestH\x00\x12%\n\x04vrem\x18/ \x01(\x0b\x32\x15.ember.v1.VRemRequestH\x00\x12%\n\x04vget\x18\x30 \x01(\x0b\x32\x15.ember.v1.VGetRequestH\x00\x12\'\n\x05vcard\x18\x31 \x01(\x0b\x32\x16.ember.v1.VCardRequestH\x00\x12%\n\x04vdim\x18\x32 \x01(\x0b\x32\x15.ember.v1.VDimRequestH\x00\x12\'\n\x05vinfo\x18\x33 \x01(\x0b\x32\x16.ember.v1.VInfoRequestH\x00\x12%\n\x04ping\x18\x34 \x01(\x0b\x32\x15.ember.v1.PingRequestH\x00\x12+\n\x07\x66lushdb\x18\x35 \x01(\x0b\x32\x18.ember.v1.FlushDbRequestH\x00\x12)\n\x06\x64\x62size\x18\x36 \x01(\x0b\x32\x17.ember.v1.DbSizeRequestH\x00\x12%\n\x04mget\x18\x37 \x01(\x0b\x32\x15.ember.v1.MGetRequestH\x00\x12%\n\x04mset\x18\x38 \x01(\x0b\x32\x15.ember.v1.MSetRequestH\x00\x12%\n\x04keys\x18\x39 \x01(\x0b\x32\x15.ember.v1.KeysRequestH\x00\x12)\n\x06rename\x18: \x01(\x0b\x32\x17.ember.v1.RenameRequestH\x00\x12%\n\x04scan\x18; \x01(\x0b\x32\x15.ember.v1.ScanRequestH\x00\x12%\n\x04\x65\x63ho\x18< \x01(\x0b\x32\x15.ember.v1.EchoRequestH\x00\x12%\n\x04\x64\x65\x63r\x18= \x01(\x0b\x32\x15.ember.v1.DecrRequestH\x00\x12)\n\x06unlink\x18> \x01(\x0b\x32\x17.ember.v1.UnlinkRequestH\x00\x12)\n\x06\x62gsave\x18? \x01(\x0b\x32\x17.ember.v1.BgSaveRequestH\x00\x12\x35\n\x0c\x62grewriteaof\x18@ \x01(\x0b\x32\x1d.ember.v1.BgRewriteAofRequestH\x00\x12\x32\n\x0bslowlog_get\x18\x41 \x01(\x0b\x32\x1b.ember.v1.SlowLogGetRequestH\x00\x12\x32\n\x0bslowlog_len\x18\x42 \x01(\x0b\x32\x1b.ember.v1.SlowLogLenRequestH\x00\x12\x36\n\rslowlog_reset\x18\x43 \x01(\x0b\x32\x1d.ember.v1.SlowLogResetRequestH\x00\x12+\n\x07publish\x18\x44 \x01(\x0b\x32\x18.ember.v1.PublishRequestH\x00\x12:\n\x0fpubsub_channels\x18\x45 \x01(\x0b\x32\x1f.ember.v1.PubSubChannelsRequestH\x00\x12\x36\n\rpubsub_numsub\x18\x46 \x01(\x0b\x32\x1d.ember.v1.PubSubNumSubRequestH\x00\x12\x36\n\rpubsub_numpat\x18G \x01(\x0b\x32\x1d.ember.v1.PubSubNumPatRequestH\x00\x42\t\n\x07\x63ommand\"\xed\t\n\x10PipelineResponse\x12\n\n\x02id\x18\x01 \x01(\x04\x12$\n\x03get\x18\x02 \x01(\x0b\x32\x15.ember.v1.GetResponseH\x00\x12$\n\x03set\x18\x03 \x01(\x0b\x32\x15.ember.v1.SetResponseH\x00\x12$\n\x03\x64\x65l\x18\x04 \x01(\x0b\x32\x15.ember.v1.DelResponseH\x00\x12(\n\x07int_val\x18\x05 \x01(\x0b\x32\x15.ember.v1.IntResponseH\x00\x12*\n\x08\x62ool_val\x18\x06 \x01(\x0b\x32\x16.ember.v1.BoolResponseH\x00\x12,\n\tfloat_val\x18\x07 \x01(\x0b\x32\x17.ember.v1.FloatResponseH\x00\x12*\n\x06status\x18\x08 \x01(\x0b\x32\x18.ember.v1.StatusResponseH\x00\x12$\n\x03ttl\x18\t \x01(\x0b\x32\x15.ember.v1.TtlResponseH\x00\x12&\n\x04type\x18\n \x01(\x0b\x32\x16.ember.v1.TypeResponseH\x00\x12(\n\x05\x61rray\x18\x0b \x01(\x0b\x32\x17.ember.v1.ArrayResponseH\x00\x12&\n\x04hash\x18\x0c \x01(\x0b\x32\x16.ember.v1.HashResponseH\x00\x12\x39\n\x0eoptional_array\x18\r \x01(\x0b\x32\x1f.ember.v1.OptionalArrayResponseH\x00\x12&\n\x04keys\x18\x0e \x01(\x0b\x32\x16.ember.v1.KeysResponseH\x00\x12&\n\x04scan\x18\x0f \x01(\x0b\x32\x16.ember.v1.ScanResponseH\x00\x12\x39\n\x0eoptional_float\x18\x10 \x01(\x0b\x32\x1f.ember.v1.OptionalFloatResponseH\x00\x12\x35\n\x0coptional_int\x18\x11 \x01(\x0b\x32\x1d.ember.v1.OptionalIntResponseH\x00\x12*\n\x06zrange\x18\x12 \x01(\x0b\x32\x18.ember.v1.ZRangeResponseH\x00\x12&\n\x04vsim\x18\x13 \x01(\x0b\x32\x16.ember.v1.VSimResponseH\x00\x12&\n\x04vget\x18\x14 \x01(\x0b\x32\x16.ember.v1.VGetResponseH\x00\x12(\n\x05vinfo\x18\x15 \x01(\x0b\x32\x17.ember.v1.VInfoResponseH\x00\x12&\n\x04mget\x18\x16 \x01(\x0b\x32\x16.ember.v1.MGetResponseH\x00\x12&\n\x04mset\x18\x17 \x01(\x0b\x32\x16.ember.v1.MSetResponseH\x00\x12&\n\x04ping\x18\x18 \x01(\x0b\x32\x16.ember.v1.PingResponseH\x00\x12(\n\x05\x65rror\x18\x19 \x01(\x0b\x32\x17.ember.v1.ErrorResponseH\x00\x12&\n\x04info\x18\x1a \x01(\x0b\x32\x16.ember.v1.InfoResponseH\x00\x12&\n\x04\x65\x63ho\x18\x1b \x01(\x0b\x32\x16.ember.v1.EchoResponseH\x00\x12\x33\n\x0bslowlog_get\x18\x1c \x01(\x0b\x32\x1c.ember.v1.SlowLogGetResponseH\x00\x12\x37\n\rpubsub_numsub\x18\x1d \x01(\x0b\x32\x1e.ember.v1.PubSubNumSubResponseH\x00\x42\x08\n\x06result\"C\n\rErrorResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\x12!\n\x04kind\x18\x02 \x01(\x0e\x32\x13.ember.v1.ErrorKind*f\n\x0cVectorMetric\x12\x18\n\x14VECTOR_METRIC_COSINE\x10\x00\x12\x1b\n\x17VECTOR_METRIC_EUCLIDEAN\x10\x01\x12\x1f\n\x1bVECTOR_METRIC_INNER_PRODUCT\x10\x02*k\n\x12VectorQuantization\x12\x1c\n\x18VECTOR_QUANTIZATION_NONE\x10\x00\x12\x1b\n\x17VECTOR_QUANTIZATION_F16\x10\x01\x12\x1a\n\x16VECTOR_QUANTIZATION_I8\x10\x02*\x9a\x01\n\tErrorKind\x12\x1a\n\x16\x45RROR_KIND_UNSPECIFIED\x10\x00\x12\x19\n\x15\x45RROR_KIND_WRONG_TYPE\x10\x01\x12\x1c\n\x18\x45RROR_KIND_OUT_OF_MEMORY\x10\x02\x12\x17\n\x13\x45RROR_KIND_INTERNAL\x10\x03\x12\x1f\n\x1b\x45RROR_KIND_INVALID_ARGUMENT\x10\x04\x32\xe3!\n\nEmberCache\x12\x32\n\x03Get\x12\x14.ember.v1.GetRequest\x1a\x15.ember.v1.GetResponse\x12\x32\n\x03Set\x12\x14.ember.v1.SetRequest\x1a\x15.ember.v1.SetResponse\x12\x32\n\x03\x44\x65l\x12\x14.ember.v1.DelRequest\x1a\x15.ember.v1.DelResponse\x12\x35\n\x04MGet\x12\x15.ember.v1.MGetRequest\x1a\x16.ember.v1.MGetResponse\x12\x35\n\x04MSet\x12\x15.ember.v1.MSetRequest\x1a\x16.ember.v1.MSetResponse\x12\x34\n\x04Incr\x12\x15.ember.v1.IncrRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06IncrBy\x12\x17.ember.v1.IncrByRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06\x44\x65\x63rBy\x12\x17.ember.v1.DecrByRequest\x1a\x15.ember.v1.IntResponse\x12\x44\n\x0bIncrByFloat\x12\x1c.ember.v1.IncrByFloatRequest\x1a\x17.ember.v1.FloatResponse\x12\x38\n\x06\x41ppend\x12\x17.ember.v1.AppendRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06Strlen\x12\x17.ember.v1.StrlenRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06\x45xists\x12\x17.ember.v1.ExistsRequest\x1a\x15.ember.v1.IntResponse\x12\x39\n\x06\x45xpire\x12\x17.ember.v1.ExpireRequest\x1a\x16.ember.v1.BoolResponse\x12;\n\x07PExpire\x12\x18.ember.v1.PExpireRequest\x1a\x16.ember.v1.BoolResponse\x12;\n\x07Persist\x12\x18.ember.v1.PersistRequest\x1a\x16.ember.v1.BoolResponse\x12\x32\n\x03Ttl\x12\x14.ember.v1.TtlRequest\x1a\x15.ember.v1.TtlResponse\x12\x34\n\x04PTtl\x12\x15.ember.v1.PTtlRequest\x1a\x15.ember.v1.TtlResponse\x12\x35\n\x04Type\x12\x15.ember.v1.TypeRequest\x1a\x16.ember.v1.TypeResponse\x12\x35\n\x04Keys\x12\x15.ember.v1.KeysRequest\x1a\x16.ember.v1.KeysResponse\x12;\n\x06Rename\x12\x17.ember.v1.RenameRequest\x1a\x18.ember.v1.StatusResponse\x12\x35\n\x04Scan\x12\x15.ember.v1.ScanRequest\x1a\x16.ember.v1.ScanResponse\x12\x36\n\x05LPush\x12\x16.ember.v1.LPushRequest\x1a\x15.ember.v1.IntResponse\x12\x36\n\x05RPush\x12\x16.ember.v1.RPushRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04LPop\x12\x15.ember.v1.LPopRequest\x1a\x15.ember.v1.GetResponse\x12\x34\n\x04RPop\x12\x15.ember.v1.RPopRequest\x1a\x15.ember.v1.GetResponse\x12:\n\x06LRange\x12\x17.ember.v1.LRangeRequest\x1a\x17.ember.v1.ArrayResponse\x12\x34\n\x04LLen\x12\x15.ember.v1.LLenRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04HSet\x12\x15.ember.v1.HSetRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04HGet\x12\x15.ember.v1.HGetRequest\x1a\x15.ember.v1.GetResponse\x12;\n\x07HGetAll\x12\x18.ember.v1.HGetAllRequest\x1a\x16.ember.v1.HashResponse\x12\x34\n\x04HDel\x12\x15.ember.v1.HDelRequest\x1a\x15.ember.v1.IntResponse\x12;\n\x07HExists\x12\x18.ember.v1.HExistsRequest\x1a\x16.ember.v1.BoolResponse\x12\x34\n\x04HLen\x12\x15.ember.v1.HLenRequest\x1a\x15.ember.v1.IntResponse\x12:\n\x07HIncrBy\x12\x18.ember.v1.HIncrByRequest\x1a\x15.ember.v1.IntResponse\x12\x37\n\x05HKeys\x12\x16.ember.v1.HKeysRequest\x1a\x16.ember.v1.KeysResponse\x12\x38\n\x05HVals\x12\x16.ember.v1.HValsRequest\x1a\x17.ember.v1.ArrayResponse\x12@\n\x05HMGet\x12\x16.ember.v1.HMGetRequest\x1a\x1f.ember.v1.OptionalArrayResponse\x12\x34\n\x04SAdd\x12\x15.ember.v1.SAddRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04SRem\x12\x15.ember.v1.SRemRequest\x1a\x15.ember.v1.IntResponse\x12=\n\x08SMembers\x12\x19.ember.v1.SMembersRequest\x1a\x16.ember.v1.KeysResponse\x12?\n\tSIsMember\x12\x1a.ember.v1.SIsMemberRequest\x1a\x16.ember.v1.BoolResponse\x12\x36\n\x05SCard\x12\x16.ember.v1.SCardRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04ZAdd\x12\x15.ember.v1.ZAddRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04ZRem\x12\x15.ember.v1.ZRemRequest\x1a\x15.ember.v1.IntResponse\x12\x42\n\x06ZScore\x12\x17.ember.v1.ZScoreRequest\x1a\x1f.ember.v1.OptionalFloatResponse\x12>\n\x05ZRank\x12\x16.ember.v1.ZRankRequest\x1a\x1d.ember.v1.OptionalIntResponse\x12\x36\n\x05ZCard\x12\x16.ember.v1.ZCardRequest\x1a\x15.ember.v1.IntResponse\x12;\n\x06ZRange\x12\x17.ember.v1.ZRangeRequest\x1a\x18.ember.v1.ZRangeResponse\x12\x35\n\x04VAdd\x12\x15.ember.v1.VAddRequest\x1a\x16.ember.v1.BoolResponse\x12\x35\n\x04VSim\x12\x15.ember.v1.VSimRequest\x1a\x16.ember.v1.VSimResponse\x12\x35\n\x04VRem\x12\x15.ember.v1.VRemRequest\x1a\x16.ember.v1.BoolResponse\x12\x35\n\x04VGet\x12\x15.ember.v1.VGetRequest\x1a\x16.ember.v1.VGetResponse\x12\x36\n\x05VCard\x12\x16.ember.v1.VCardRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04VDim\x12\x15.ember.v1.VDimRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x05VInfo\x12\x16.ember.v1.VInfoRequest\x1a\x17.ember.v1.VInfoResponse\x12\x35\n\x04Ping\x12\x15.ember.v1.PingRequest\x1a\x16.ember.v1.PingResponse\x12\x35\n\x04\x45\x63ho\x12\x15.ember.v1.EchoRequest\x1a\x16.ember.v1.EchoResponse\x12\x34\n\x04\x44\x65\x63r\x12\x15.ember.v1.DecrRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06Unlink\x12\x17.ember.v1.UnlinkRequest\x1a\x15.ember.v1.DelResponse\x12=\n\x07\x46lushDb\x12\x18.ember.v1.FlushDbRequest\x1a\x18.ember.v1.StatusResponse\x12\x38\n\x06\x44\x62Size\x12\x17.ember.v1.DbSizeRequest\x1a\x15.ember.v1.IntResponse\x12\x35\n\x04Info\x12\x15.ember.v1.InfoRequest\x1a\x16.ember.v1.InfoResponse\x12;\n\x06\x42gSave\x12\x17.ember.v1.BgSaveRequest\x1a\x18.ember.v1.StatusResponse\x12G\n\x0c\x42gRewriteAof\x12\x1d.ember.v1.BgRewriteAofRequest\x1a\x18.ember.v1.StatusResponse\x12G\n\nSlowLogGet\x12\x1b.ember.v1.SlowLogGetRequest\x1a\x1c.ember.v1.SlowLogGetResponse\x12@\n\nSlowLogLen\x12\x1b.ember.v1.SlowLogLenRequest\x1a\x15.ember.v1.IntResponse\x12G\n\x0cSlowLogReset\x12\x1d.ember.v1.SlowLogResetRequest\x1a\x18.ember.v1.StatusResponse\x12:\n\x07Publish\x12\x18.ember.v1.PublishRequest\x1a\x15.ember.v1.IntResponse\x12\x43\n\tSubscribe\x12\x1a.ember.v1.SubscribeRequest\x1a\x18.ember.v1.SubscribeEvent0\x01\x12I\n\x0ePubSubChannels\x12\x1f.ember.v1.PubSubChannelsRequest\x1a\x16.ember.v1.KeysResponse\x12M\n\x0cPubSubNumSub\x12\x1d.ember.v1.PubSubNumSubRequest\x1a\x1e.ember.v1.PubSubNumSubResponse\x12\x44\n\x0cPubSubNumPat\x12\x1d.ember.v1.PubSubNumPatRequest\x1a\x15.ember.v1.IntResponse\x12\x45\n\x08Pipeline\x12\x19.ember.v1.PipelineRequest\x1a\x1a.ember.v1.PipelineResponse(\x01\x30\x01\x42\x31Z/github.com/kacy/ember-go/proto/ember/v1;emberv1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x65mber/v1/ember.proto\x12\x08\x65mber.v1\"\x1c\n\x0bIntResponse\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1d\n\x0c\x42oolResponse\x12\r\n\x05value\x18\x01 \x01(\x08\"\x1e\n\rFloatResponse\x12\r\n\x05value\x18\x01 \x01(\t\" \n\x0eStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\"\x19\n\nGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\x0bGetResponse\x12\x12\n\x05value\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x08\n\x06_value\"o\n\nSetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65xpire_seconds\x18\x03 \x01(\x04\x12\x15\n\rexpire_millis\x18\x04 \x01(\x04\x12\n\n\x02nx\x18\x05 \x01(\x08\x12\n\n\x02xx\x18\x06 \x01(\x08\"\x19\n\x0bSetResponse\x12\n\n\x02ok\x18\x01 \x01(\x08\"\x1a\n\nDelRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"\x1e\n\x0b\x44\x65lResponse\x12\x0f\n\x07\x64\x65leted\x18\x01 \x01(\x03\"\x1b\n\x0bMGetRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"7\n\x0cMGetResponse\x12\'\n\x06values\x18\x01 \x03(\x0b\x32\x17.ember.v1.OptionalValue\"-\n\rOptionalValue\x12\x12\n\x05value\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x08\n\x06_value\"0\n\x0bMSetRequest\x12!\n\x05pairs\x18\x01 \x03(\x0b\x32\x12.ember.v1.KeyValue\"&\n\x08KeyValue\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x0e\n\x0cMSetResponse\"\x1a\n\x0bIncrRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\rIncrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x03\"+\n\rDecrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x03\"0\n\x12IncrByFloatRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x02 \x01(\x01\"+\n\rAppendRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1c\n\rStrlenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1d\n\rExistsRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"-\n\rExpireRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07seconds\x18\x02 \x01(\x04\"3\n\x0ePExpireRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x14\n\x0cmilliseconds\x18\x02 \x01(\x04\"\x1d\n\x0ePersistRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x19\n\nTtlRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bPTtlRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1c\n\x0bTtlResponse\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1a\n\x0bTypeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"!\n\x0cTypeResponse\x12\x11\n\ttype_name\x18\x01 \x01(\t\"\x1e\n\x0bKeysRequest\x12\x0f\n\x07pattern\x18\x01 \x01(\t\"\x1c\n\x0cKeysResponse\x12\x0c\n\x04keys\x18\x01 \x03(\t\"-\n\rRenameRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07new_key\x18\x02 \x01(\t\"N\n\x0bScanRequest\x12\x0e\n\x06\x63ursor\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x14\n\x07pattern\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\",\n\x0cScanResponse\x12\x0e\n\x06\x63ursor\x18\x01 \x01(\x04\x12\x0c\n\x04keys\x18\x02 \x03(\t\"+\n\x0cLPushRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06values\x18\x02 \x03(\x0c\"+\n\x0cRPushRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06values\x18\x02 \x03(\x0c\"\x1a\n\x0bLPopRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bRPopRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"9\n\rLRangeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05start\x18\x02 \x01(\x03\x12\x0c\n\x04stop\x18\x03 \x01(\x03\"\x1f\n\rArrayResponse\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1a\n\x0bLLenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"@\n\x0bHSetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x14.ember.v1.FieldValue\"*\n\nFieldValue\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\")\n\x0bHGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\x1d\n\x0eHGetAllRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"4\n\x0cHashResponse\x12$\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x14.ember.v1.FieldValue\"*\n\x0bHDelRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06\x66ields\x18\x02 \x03(\t\",\n\x0eHExistsRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\x1a\n\x0bHLenRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\";\n\x0eHIncrByRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\x12\r\n\x05\x64\x65lta\x18\x03 \x01(\x03\"\x1b\n\x0cHKeysRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1b\n\x0cHValsRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"+\n\x0cHMGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06\x66ields\x18\x02 \x03(\t\"@\n\x15OptionalArrayResponse\x12\'\n\x06values\x18\x01 \x03(\x0b\x32\x17.ember.v1.OptionalValue\"+\n\x0bSAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\"+\n\x0bSRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\"\x1e\n\x0fSMembersRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"/\n\x10SIsMemberRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"\x1b\n\x0cSCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"~\n\x0bZAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x07members\x18\x02 \x03(\x0b\x32\x15.ember.v1.ScoreMember\x12\n\n\x02nx\x18\x03 \x01(\x08\x12\n\n\x02xx\x18\x04 \x01(\x08\x12\n\n\x02gt\x18\x05 \x01(\x08\x12\n\n\x02lt\x18\x06 \x01(\x08\x12\n\n\x02\x63h\x18\x07 \x01(\x08\",\n\x0bScoreMember\x12\r\n\x05score\x18\x01 \x01(\x01\x12\x0e\n\x06member\x18\x02 \x01(\t\"+\n\x0bZRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07members\x18\x02 \x03(\t\",\n\rZScoreRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"5\n\x15OptionalFloatResponse\x12\x12\n\x05value\x18\x01 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value\"+\n\x0cZRankRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06member\x18\x02 \x01(\t\"3\n\x13OptionalIntResponse\x12\x12\n\x05value\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x08\n\x06_value\"\x1b\n\x0cZCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"N\n\rZRangeRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05start\x18\x02 \x01(\x03\x12\x0c\n\x04stop\x18\x03 \x01(\x03\x12\x13\n\x0bwith_scores\x18\x04 \x01(\x08\"8\n\x0eZRangeResponse\x12&\n\x07members\x18\x01 \x03(\x0b\x32\x15.ember.v1.ScoreMember\"\xf9\x01\n\x0bVAddRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\x12\x12\n\x06vector\x18\x03 \x03(\x02\x42\x02\x10\x01\x12&\n\x06metric\x18\x04 \x01(\x0e\x32\x16.ember.v1.VectorMetric\x12\x32\n\x0cquantization\x18\x05 \x01(\x0e\x32\x1c.ember.v1.VectorQuantization\x12\x19\n\x0c\x63onnectivity\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0f\x65\x66_construction\x18\x07 \x01(\rH\x01\x88\x01\x01\x42\x0f\n\r_connectivityB\x12\n\x10_ef_construction\"5\n\x0eVAddBatchEntry\x12\x0f\n\x07\x65lement\x18\x01 \x01(\t\x12\x12\n\x06vector\x18\x02 \x03(\x02\x42\x02\x10\x01\"\x84\x02\n\x10VAddBatchRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x07\x65ntries\x18\x02 \x03(\x0b\x32\x18.ember.v1.VAddBatchEntry\x12&\n\x06metric\x18\x03 \x01(\x0e\x32\x16.ember.v1.VectorMetric\x12\x32\n\x0cquantization\x18\x04 \x01(\x0e\x32\x1c.ember.v1.VectorQuantization\x12\x19\n\x0c\x63onnectivity\x18\x05 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0f\x65\x66_construction\x18\x06 \x01(\rH\x01\x88\x01\x01\x42\x0f\n\r_connectivityB\x12\n\x10_ef_construction\"b\n\x0bVSimRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x11\n\x05query\x18\x02 \x03(\x02\x42\x02\x10\x01\x12\r\n\x05\x63ount\x18\x03 \x01(\r\x12\x16\n\tef_search\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x0c\n\n_ef_search\"5\n\x0cVSimResponse\x12%\n\x07results\x18\x01 \x03(\x0b\x32\x14.ember.v1.VSimResult\"/\n\nVSimResult\x12\x0f\n\x07\x65lement\x18\x01 \x01(\t\x12\x10\n\x08\x64istance\x18\x02 \x01(\x02\"+\n\x0bVRemRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\"+\n\x0bVGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0f\n\x07\x65lement\x18\x02 \x01(\t\"B\n\x0cVGetResponse\x12\x13\n\x06\x65xists\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x12\n\x06vector\x18\x02 \x03(\x02\x42\x02\x10\x01\x42\t\n\x07_exists\"\x1b\n\x0cVCardRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1a\n\x0bVDimRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1b\n\x0cVInfoRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"C\n\rVInfoResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\x12\"\n\x04info\x18\x02 \x03(\x0b\x32\x14.ember.v1.FieldValue\"/\n\x0bPingRequest\x12\x14\n\x07message\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_message\"\x1f\n\x0cPingResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1f\n\x0e\x46lushDbRequest\x12\r\n\x05\x61sync\x18\x01 \x01(\x08\"\x0f\n\rDbSizeRequest\"/\n\x0bInfoRequest\x12\x14\n\x07section\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_section\"\x1c\n\x0cInfoResponse\x12\x0c\n\x04info\x18\x01 \x01(\t\"\x1e\n\x0b\x45\x63hoRequest\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1f\n\x0c\x45\x63hoResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1a\n\x0b\x44\x65\x63rRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x1d\n\rUnlinkRequest\x12\x0c\n\x04keys\x18\x01 \x03(\t\"\x0f\n\rBgSaveRequest\"\x15\n\x13\x42gRewriteAofRequest\"1\n\x11SlowLogGetRequest\x12\x12\n\x05\x63ount\x18\x01 \x01(\rH\x00\x88\x01\x01\x42\x08\n\x06_count\"=\n\x12SlowLogGetResponse\x12\'\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x16.ember.v1.SlowLogEntry\"\\\n\x0cSlowLogEntry\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x16\n\x0etimestamp_unix\x18\x02 \x01(\x04\x12\x17\n\x0f\x64uration_micros\x18\x03 \x01(\x04\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\"\x13\n\x11SlowLogLenRequest\"\x15\n\x13SlowLogResetRequest\"2\n\x0ePublishRequest\x12\x0f\n\x07\x63hannel\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\x0c\"6\n\x10SubscribeRequest\x12\x10\n\x08\x63hannels\x18\x01 \x03(\t\x12\x10\n\x08patterns\x18\x02 \x03(\t\"_\n\x0eSubscribeEvent\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x14\n\x07pattern\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\"9\n\x15PubSubChannelsRequest\x12\x14\n\x07pattern\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_pattern\"\'\n\x13PubSubNumSubRequest\x12\x10\n\x08\x63hannels\x18\x01 \x03(\t\">\n\x14PubSubNumSubResponse\x12&\n\x06\x63ounts\x18\x01 \x03(\x0b\x32\x16.ember.v1.ChannelCount\"\x15\n\x13PubSubNumPatRequest\".\n\x0c\x43hannelCount\x12\x0f\n\x07\x63hannel\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\"\x85\x18\n\x0fPipelineRequest\x12\n\n\x02id\x18\x01 \x01(\x04\x12#\n\x03get\x18\x02 \x01(\x0b\x32\x14.ember.v1.GetRequestH\x00\x12#\n\x03set\x18\x03 \x01(\x0b\x32\x14.ember.v1.SetRequestH\x00\x12#\n\x03\x64\x65l\x18\x04 \x01(\x0b\x32\x14.ember.v1.DelRequestH\x00\x12)\n\x06\x65xists\x18\x05 \x01(\x0b\x32\x17.ember.v1.ExistsRequestH\x00\x12%\n\x04incr\x18\x06 \x01(\x0b\x32\x15.ember.v1.IncrRequestH\x00\x12*\n\x07incr_by\x18\x07 \x01(\x0b\x32\x17.ember.v1.IncrByRequestH\x00\x12*\n\x07\x64\x65\x63r_by\x18\x08 \x01(\x0b\x32\x17.ember.v1.DecrByRequestH\x00\x12\x35\n\rincr_by_float\x18\t \x01(\x0b\x32\x1c.ember.v1.IncrByFloatRequestH\x00\x12)\n\x06\x61ppend\x18\n \x01(\x0b\x32\x17.ember.v1.AppendRequestH\x00\x12)\n\x06strlen\x18\x0b \x01(\x0b\x32\x17.ember.v1.StrlenRequestH\x00\x12)\n\x06\x65xpire\x18\x0c \x01(\x0b\x32\x17.ember.v1.ExpireRequestH\x00\x12+\n\x07pexpire\x18\r \x01(\x0b\x32\x18.ember.v1.PExpireRequestH\x00\x12+\n\x07persist\x18\x0e \x01(\x0b\x32\x18.ember.v1.PersistRequestH\x00\x12#\n\x03ttl\x18\x0f \x01(\x0b\x32\x14.ember.v1.TtlRequestH\x00\x12%\n\x04pttl\x18\x10 \x01(\x0b\x32\x15.ember.v1.PTtlRequestH\x00\x12%\n\x04type\x18\x11 \x01(\x0b\x32\x15.ember.v1.TypeRequestH\x00\x12\'\n\x05lpush\x18\x12 \x01(\x0b\x32\x16.ember.v1.LPushRequestH\x00\x12\'\n\x05rpush\x18\x13 \x01(\x0b\x32\x16.ember.v1.RPushRequestH\x00\x12%\n\x04lpop\x18\x14 \x01(\x0b\x32\x15.ember.v1.LPopRequestH\x00\x12%\n\x04rpop\x18\x15 \x01(\x0b\x32\x15.ember.v1.RPopRequestH\x00\x12)\n\x06lrange\x18\x16 \x01(\x0b\x32\x17.ember.v1.LRangeRequestH\x00\x12%\n\x04llen\x18\x17 \x01(\x0b\x32\x15.ember.v1.LLenRequestH\x00\x12%\n\x04hset\x18\x18 \x01(\x0b\x32\x15.ember.v1.HSetRequestH\x00\x12%\n\x04hget\x18\x19 \x01(\x0b\x32\x15.ember.v1.HGetRequestH\x00\x12+\n\x07hgetall\x18\x1a \x01(\x0b\x32\x18.ember.v1.HGetAllRequestH\x00\x12%\n\x04hdel\x18\x1b \x01(\x0b\x32\x15.ember.v1.HDelRequestH\x00\x12+\n\x07hexists\x18\x1c \x01(\x0b\x32\x18.ember.v1.HExistsRequestH\x00\x12%\n\x04hlen\x18\x1d \x01(\x0b\x32\x15.ember.v1.HLenRequestH\x00\x12,\n\x08hincr_by\x18\x1e \x01(\x0b\x32\x18.ember.v1.HIncrByRequestH\x00\x12\'\n\x05hkeys\x18\x1f \x01(\x0b\x32\x16.ember.v1.HKeysRequestH\x00\x12\'\n\x05hvals\x18 \x01(\x0b\x32\x16.ember.v1.HValsRequestH\x00\x12\'\n\x05hmget\x18! \x01(\x0b\x32\x16.ember.v1.HMGetRequestH\x00\x12%\n\x04sadd\x18\" \x01(\x0b\x32\x15.ember.v1.SAddRequestH\x00\x12%\n\x04srem\x18# \x01(\x0b\x32\x15.ember.v1.SRemRequestH\x00\x12-\n\x08smembers\x18$ \x01(\x0b\x32\x19.ember.v1.SMembersRequestH\x00\x12/\n\tsismember\x18% \x01(\x0b\x32\x1a.ember.v1.SIsMemberRequestH\x00\x12\'\n\x05scard\x18& \x01(\x0b\x32\x16.ember.v1.SCardRequestH\x00\x12%\n\x04zadd\x18\' \x01(\x0b\x32\x15.ember.v1.ZAddRequestH\x00\x12%\n\x04zrem\x18( \x01(\x0b\x32\x15.ember.v1.ZRemRequestH\x00\x12)\n\x06zscore\x18) \x01(\x0b\x32\x17.ember.v1.ZScoreRequestH\x00\x12\'\n\x05zrank\x18* \x01(\x0b\x32\x16.ember.v1.ZRankRequestH\x00\x12\'\n\x05zcard\x18+ \x01(\x0b\x32\x16.ember.v1.ZCardRequestH\x00\x12)\n\x06zrange\x18, \x01(\x0b\x32\x17.ember.v1.ZRangeRequestH\x00\x12%\n\x04vadd\x18- \x01(\x0b\x32\x15.ember.v1.VAddRequestH\x00\x12%\n\x04vsim\x18. \x01(\x0b\x32\x15.ember.v1.VSimRequestH\x00\x12%\n\x04vrem\x18/ \x01(\x0b\x32\x15.ember.v1.VRemRequestH\x00\x12%\n\x04vget\x18\x30 \x01(\x0b\x32\x15.ember.v1.VGetRequestH\x00\x12\'\n\x05vcard\x18\x31 \x01(\x0b\x32\x16.ember.v1.VCardRequestH\x00\x12%\n\x04vdim\x18\x32 \x01(\x0b\x32\x15.ember.v1.VDimRequestH\x00\x12\'\n\x05vinfo\x18\x33 \x01(\x0b\x32\x16.ember.v1.VInfoRequestH\x00\x12%\n\x04ping\x18\x34 \x01(\x0b\x32\x15.ember.v1.PingRequestH\x00\x12+\n\x07\x66lushdb\x18\x35 \x01(\x0b\x32\x18.ember.v1.FlushDbRequestH\x00\x12)\n\x06\x64\x62size\x18\x36 \x01(\x0b\x32\x17.ember.v1.DbSizeRequestH\x00\x12%\n\x04mget\x18\x37 \x01(\x0b\x32\x15.ember.v1.MGetRequestH\x00\x12%\n\x04mset\x18\x38 \x01(\x0b\x32\x15.ember.v1.MSetRequestH\x00\x12%\n\x04keys\x18\x39 \x01(\x0b\x32\x15.ember.v1.KeysRequestH\x00\x12)\n\x06rename\x18: \x01(\x0b\x32\x17.ember.v1.RenameRequestH\x00\x12%\n\x04scan\x18; \x01(\x0b\x32\x15.ember.v1.ScanRequestH\x00\x12%\n\x04\x65\x63ho\x18< \x01(\x0b\x32\x15.ember.v1.EchoRequestH\x00\x12%\n\x04\x64\x65\x63r\x18= \x01(\x0b\x32\x15.ember.v1.DecrRequestH\x00\x12)\n\x06unlink\x18> \x01(\x0b\x32\x17.ember.v1.UnlinkRequestH\x00\x12)\n\x06\x62gsave\x18? \x01(\x0b\x32\x17.ember.v1.BgSaveRequestH\x00\x12\x35\n\x0c\x62grewriteaof\x18@ \x01(\x0b\x32\x1d.ember.v1.BgRewriteAofRequestH\x00\x12\x32\n\x0bslowlog_get\x18\x41 \x01(\x0b\x32\x1b.ember.v1.SlowLogGetRequestH\x00\x12\x32\n\x0bslowlog_len\x18\x42 \x01(\x0b\x32\x1b.ember.v1.SlowLogLenRequestH\x00\x12\x36\n\rslowlog_reset\x18\x43 \x01(\x0b\x32\x1d.ember.v1.SlowLogResetRequestH\x00\x12+\n\x07publish\x18\x44 \x01(\x0b\x32\x18.ember.v1.PublishRequestH\x00\x12:\n\x0fpubsub_channels\x18\x45 \x01(\x0b\x32\x1f.ember.v1.PubSubChannelsRequestH\x00\x12\x36\n\rpubsub_numsub\x18\x46 \x01(\x0b\x32\x1d.ember.v1.PubSubNumSubRequestH\x00\x12\x36\n\rpubsub_numpat\x18G \x01(\x0b\x32\x1d.ember.v1.PubSubNumPatRequestH\x00\x12\x30\n\nvadd_batch\x18H \x01(\x0b\x32\x1a.ember.v1.VAddBatchRequestH\x00\x42\t\n\x07\x63ommand\"\xed\t\n\x10PipelineResponse\x12\n\n\x02id\x18\x01 \x01(\x04\x12$\n\x03get\x18\x02 \x01(\x0b\x32\x15.ember.v1.GetResponseH\x00\x12$\n\x03set\x18\x03 \x01(\x0b\x32\x15.ember.v1.SetResponseH\x00\x12$\n\x03\x64\x65l\x18\x04 \x01(\x0b\x32\x15.ember.v1.DelResponseH\x00\x12(\n\x07int_val\x18\x05 \x01(\x0b\x32\x15.ember.v1.IntResponseH\x00\x12*\n\x08\x62ool_val\x18\x06 \x01(\x0b\x32\x16.ember.v1.BoolResponseH\x00\x12,\n\tfloat_val\x18\x07 \x01(\x0b\x32\x17.ember.v1.FloatResponseH\x00\x12*\n\x06status\x18\x08 \x01(\x0b\x32\x18.ember.v1.StatusResponseH\x00\x12$\n\x03ttl\x18\t \x01(\x0b\x32\x15.ember.v1.TtlResponseH\x00\x12&\n\x04type\x18\n \x01(\x0b\x32\x16.ember.v1.TypeResponseH\x00\x12(\n\x05\x61rray\x18\x0b \x01(\x0b\x32\x17.ember.v1.ArrayResponseH\x00\x12&\n\x04hash\x18\x0c \x01(\x0b\x32\x16.ember.v1.HashResponseH\x00\x12\x39\n\x0eoptional_array\x18\r \x01(\x0b\x32\x1f.ember.v1.OptionalArrayResponseH\x00\x12&\n\x04keys\x18\x0e \x01(\x0b\x32\x16.ember.v1.KeysResponseH\x00\x12&\n\x04scan\x18\x0f \x01(\x0b\x32\x16.ember.v1.ScanResponseH\x00\x12\x39\n\x0eoptional_float\x18\x10 \x01(\x0b\x32\x1f.ember.v1.OptionalFloatResponseH\x00\x12\x35\n\x0coptional_int\x18\x11 \x01(\x0b\x32\x1d.ember.v1.OptionalIntResponseH\x00\x12*\n\x06zrange\x18\x12 \x01(\x0b\x32\x18.ember.v1.ZRangeResponseH\x00\x12&\n\x04vsim\x18\x13 \x01(\x0b\x32\x16.ember.v1.VSimResponseH\x00\x12&\n\x04vget\x18\x14 \x01(\x0b\x32\x16.ember.v1.VGetResponseH\x00\x12(\n\x05vinfo\x18\x15 \x01(\x0b\x32\x17.ember.v1.VInfoResponseH\x00\x12&\n\x04mget\x18\x16 \x01(\x0b\x32\x16.ember.v1.MGetResponseH\x00\x12&\n\x04mset\x18\x17 \x01(\x0b\x32\x16.ember.v1.MSetResponseH\x00\x12&\n\x04ping\x18\x18 \x01(\x0b\x32\x16.ember.v1.PingResponseH\x00\x12(\n\x05\x65rror\x18\x19 \x01(\x0b\x32\x17.ember.v1.ErrorResponseH\x00\x12&\n\x04info\x18\x1a \x01(\x0b\x32\x16.ember.v1.InfoResponseH\x00\x12&\n\x04\x65\x63ho\x18\x1b \x01(\x0b\x32\x16.ember.v1.EchoResponseH\x00\x12\x33\n\x0bslowlog_get\x18\x1c \x01(\x0b\x32\x1c.ember.v1.SlowLogGetResponseH\x00\x12\x37\n\rpubsub_numsub\x18\x1d \x01(\x0b\x32\x1e.ember.v1.PubSubNumSubResponseH\x00\x42\x08\n\x06result\"C\n\rErrorResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\x12!\n\x04kind\x18\x02 \x01(\x0e\x32\x13.ember.v1.ErrorKind*f\n\x0cVectorMetric\x12\x18\n\x14VECTOR_METRIC_COSINE\x10\x00\x12\x1b\n\x17VECTOR_METRIC_EUCLIDEAN\x10\x01\x12\x1f\n\x1bVECTOR_METRIC_INNER_PRODUCT\x10\x02*k\n\x12VectorQuantization\x12\x1c\n\x18VECTOR_QUANTIZATION_NONE\x10\x00\x12\x1b\n\x17VECTOR_QUANTIZATION_F16\x10\x01\x12\x1a\n\x16VECTOR_QUANTIZATION_I8\x10\x02*\x9a\x01\n\tErrorKind\x12\x1a\n\x16\x45RROR_KIND_UNSPECIFIED\x10\x00\x12\x19\n\x15\x45RROR_KIND_WRONG_TYPE\x10\x01\x12\x1c\n\x18\x45RROR_KIND_OUT_OF_MEMORY\x10\x02\x12\x17\n\x13\x45RROR_KIND_INTERNAL\x10\x03\x12\x1f\n\x1b\x45RROR_KIND_INVALID_ARGUMENT\x10\x04\x32\xa3\"\n\nEmberCache\x12\x32\n\x03Get\x12\x14.ember.v1.GetRequest\x1a\x15.ember.v1.GetResponse\x12\x32\n\x03Set\x12\x14.ember.v1.SetRequest\x1a\x15.ember.v1.SetResponse\x12\x32\n\x03\x44\x65l\x12\x14.ember.v1.DelRequest\x1a\x15.ember.v1.DelResponse\x12\x35\n\x04MGet\x12\x15.ember.v1.MGetRequest\x1a\x16.ember.v1.MGetResponse\x12\x35\n\x04MSet\x12\x15.ember.v1.MSetRequest\x1a\x16.ember.v1.MSetResponse\x12\x34\n\x04Incr\x12\x15.ember.v1.IncrRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06IncrBy\x12\x17.ember.v1.IncrByRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06\x44\x65\x63rBy\x12\x17.ember.v1.DecrByRequest\x1a\x15.ember.v1.IntResponse\x12\x44\n\x0bIncrByFloat\x12\x1c.ember.v1.IncrByFloatRequest\x1a\x17.ember.v1.FloatResponse\x12\x38\n\x06\x41ppend\x12\x17.ember.v1.AppendRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06Strlen\x12\x17.ember.v1.StrlenRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06\x45xists\x12\x17.ember.v1.ExistsRequest\x1a\x15.ember.v1.IntResponse\x12\x39\n\x06\x45xpire\x12\x17.ember.v1.ExpireRequest\x1a\x16.ember.v1.BoolResponse\x12;\n\x07PExpire\x12\x18.ember.v1.PExpireRequest\x1a\x16.ember.v1.BoolResponse\x12;\n\x07Persist\x12\x18.ember.v1.PersistRequest\x1a\x16.ember.v1.BoolResponse\x12\x32\n\x03Ttl\x12\x14.ember.v1.TtlRequest\x1a\x15.ember.v1.TtlResponse\x12\x34\n\x04PTtl\x12\x15.ember.v1.PTtlRequest\x1a\x15.ember.v1.TtlResponse\x12\x35\n\x04Type\x12\x15.ember.v1.TypeRequest\x1a\x16.ember.v1.TypeResponse\x12\x35\n\x04Keys\x12\x15.ember.v1.KeysRequest\x1a\x16.ember.v1.KeysResponse\x12;\n\x06Rename\x12\x17.ember.v1.RenameRequest\x1a\x18.ember.v1.StatusResponse\x12\x35\n\x04Scan\x12\x15.ember.v1.ScanRequest\x1a\x16.ember.v1.ScanResponse\x12\x36\n\x05LPush\x12\x16.ember.v1.LPushRequest\x1a\x15.ember.v1.IntResponse\x12\x36\n\x05RPush\x12\x16.ember.v1.RPushRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04LPop\x12\x15.ember.v1.LPopRequest\x1a\x15.ember.v1.GetResponse\x12\x34\n\x04RPop\x12\x15.ember.v1.RPopRequest\x1a\x15.ember.v1.GetResponse\x12:\n\x06LRange\x12\x17.ember.v1.LRangeRequest\x1a\x17.ember.v1.ArrayResponse\x12\x34\n\x04LLen\x12\x15.ember.v1.LLenRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04HSet\x12\x15.ember.v1.HSetRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04HGet\x12\x15.ember.v1.HGetRequest\x1a\x15.ember.v1.GetResponse\x12;\n\x07HGetAll\x12\x18.ember.v1.HGetAllRequest\x1a\x16.ember.v1.HashResponse\x12\x34\n\x04HDel\x12\x15.ember.v1.HDelRequest\x1a\x15.ember.v1.IntResponse\x12;\n\x07HExists\x12\x18.ember.v1.HExistsRequest\x1a\x16.ember.v1.BoolResponse\x12\x34\n\x04HLen\x12\x15.ember.v1.HLenRequest\x1a\x15.ember.v1.IntResponse\x12:\n\x07HIncrBy\x12\x18.ember.v1.HIncrByRequest\x1a\x15.ember.v1.IntResponse\x12\x37\n\x05HKeys\x12\x16.ember.v1.HKeysRequest\x1a\x16.ember.v1.KeysResponse\x12\x38\n\x05HVals\x12\x16.ember.v1.HValsRequest\x1a\x17.ember.v1.ArrayResponse\x12@\n\x05HMGet\x12\x16.ember.v1.HMGetRequest\x1a\x1f.ember.v1.OptionalArrayResponse\x12\x34\n\x04SAdd\x12\x15.ember.v1.SAddRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04SRem\x12\x15.ember.v1.SRemRequest\x1a\x15.ember.v1.IntResponse\x12=\n\x08SMembers\x12\x19.ember.v1.SMembersRequest\x1a\x16.ember.v1.KeysResponse\x12?\n\tSIsMember\x12\x1a.ember.v1.SIsMemberRequest\x1a\x16.ember.v1.BoolResponse\x12\x36\n\x05SCard\x12\x16.ember.v1.SCardRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04ZAdd\x12\x15.ember.v1.ZAddRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04ZRem\x12\x15.ember.v1.ZRemRequest\x1a\x15.ember.v1.IntResponse\x12\x42\n\x06ZScore\x12\x17.ember.v1.ZScoreRequest\x1a\x1f.ember.v1.OptionalFloatResponse\x12>\n\x05ZRank\x12\x16.ember.v1.ZRankRequest\x1a\x1d.ember.v1.OptionalIntResponse\x12\x36\n\x05ZCard\x12\x16.ember.v1.ZCardRequest\x1a\x15.ember.v1.IntResponse\x12;\n\x06ZRange\x12\x17.ember.v1.ZRangeRequest\x1a\x18.ember.v1.ZRangeResponse\x12\x35\n\x04VAdd\x12\x15.ember.v1.VAddRequest\x1a\x16.ember.v1.BoolResponse\x12>\n\tVAddBatch\x12\x1a.ember.v1.VAddBatchRequest\x1a\x15.ember.v1.IntResponse\x12\x35\n\x04VSim\x12\x15.ember.v1.VSimRequest\x1a\x16.ember.v1.VSimResponse\x12\x35\n\x04VRem\x12\x15.ember.v1.VRemRequest\x1a\x16.ember.v1.BoolResponse\x12\x35\n\x04VGet\x12\x15.ember.v1.VGetRequest\x1a\x16.ember.v1.VGetResponse\x12\x36\n\x05VCard\x12\x16.ember.v1.VCardRequest\x1a\x15.ember.v1.IntResponse\x12\x34\n\x04VDim\x12\x15.ember.v1.VDimRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x05VInfo\x12\x16.ember.v1.VInfoRequest\x1a\x17.ember.v1.VInfoResponse\x12\x35\n\x04Ping\x12\x15.ember.v1.PingRequest\x1a\x16.ember.v1.PingResponse\x12\x35\n\x04\x45\x63ho\x12\x15.ember.v1.EchoRequest\x1a\x16.ember.v1.EchoResponse\x12\x34\n\x04\x44\x65\x63r\x12\x15.ember.v1.DecrRequest\x1a\x15.ember.v1.IntResponse\x12\x38\n\x06Unlink\x12\x17.ember.v1.UnlinkRequest\x1a\x15.ember.v1.DelResponse\x12=\n\x07\x46lushDb\x12\x18.ember.v1.FlushDbRequest\x1a\x18.ember.v1.StatusResponse\x12\x38\n\x06\x44\x62Size\x12\x17.ember.v1.DbSizeRequest\x1a\x15.ember.v1.IntResponse\x12\x35\n\x04Info\x12\x15.ember.v1.InfoRequest\x1a\x16.ember.v1.InfoResponse\x12;\n\x06\x42gSave\x12\x17.ember.v1.BgSaveRequest\x1a\x18.ember.v1.StatusResponse\x12G\n\x0c\x42gRewriteAof\x12\x1d.ember.v1.BgRewriteAofRequest\x1a\x18.ember.v1.StatusResponse\x12G\n\nSlowLogGet\x12\x1b.ember.v1.SlowLogGetRequest\x1a\x1c.ember.v1.SlowLogGetResponse\x12@\n\nSlowLogLen\x12\x1b.ember.v1.SlowLogLenRequest\x1a\x15.ember.v1.IntResponse\x12G\n\x0cSlowLogReset\x12\x1d.ember.v1.SlowLogResetRequest\x1a\x18.ember.v1.StatusResponse\x12:\n\x07Publish\x12\x18.ember.v1.PublishRequest\x1a\x15.ember.v1.IntResponse\x12\x43\n\tSubscribe\x12\x1a.ember.v1.SubscribeRequest\x1a\x18.ember.v1.SubscribeEvent0\x01\x12I\n\x0ePubSubChannels\x12\x1f.ember.v1.PubSubChannelsRequest\x1a\x16.ember.v1.KeysResponse\x12M\n\x0cPubSubNumSub\x12\x1d.ember.v1.PubSubNumSubRequest\x1a\x1e.ember.v1.PubSubNumSubResponse\x12\x44\n\x0cPubSubNumPat\x12\x1d.ember.v1.PubSubNumPatRequest\x1a\x15.ember.v1.IntResponse\x12\x45\n\x08Pipeline\x12\x19.ember.v1.PipelineRequest\x1a\x1a.ember.v1.PipelineResponse(\x01\x30\x01\x42\x31Z/github.com/kacy/ember-go/proto/ember/v1;emberv1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -34,16 +34,18 @@ _globals['DESCRIPTOR']._serialized_options = b'Z/github.com/kacy/ember-go/proto/ember/v1;emberv1' _globals['_VADDREQUEST'].fields_by_name['vector']._loaded_options = None _globals['_VADDREQUEST'].fields_by_name['vector']._serialized_options = b'\020\001' + _globals['_VADDBATCHENTRY'].fields_by_name['vector']._loaded_options = None + _globals['_VADDBATCHENTRY'].fields_by_name['vector']._serialized_options = b'\020\001' _globals['_VSIMREQUEST'].fields_by_name['query']._loaded_options = None _globals['_VSIMREQUEST'].fields_by_name['query']._serialized_options = b'\020\001' _globals['_VGETRESPONSE'].fields_by_name['vector']._loaded_options = None _globals['_VGETRESPONSE'].fields_by_name['vector']._serialized_options = b'\020\001' - _globals['_VECTORMETRIC']._serialized_start=9296 - _globals['_VECTORMETRIC']._serialized_end=9398 - _globals['_VECTORQUANTIZATION']._serialized_start=9400 - _globals['_VECTORQUANTIZATION']._serialized_end=9507 - _globals['_ERRORKIND']._serialized_start=9510 - _globals['_ERRORKIND']._serialized_end=9664 + _globals['_VECTORMETRIC']._serialized_start=9664 + _globals['_VECTORMETRIC']._serialized_end=9766 + _globals['_VECTORQUANTIZATION']._serialized_start=9768 + _globals['_VECTORQUANTIZATION']._serialized_end=9875 + _globals['_ERRORKIND']._serialized_start=9878 + _globals['_ERRORKIND']._serialized_end=10032 _globals['_INTRESPONSE']._serialized_start=34 _globals['_INTRESPONSE']._serialized_end=62 _globals['_BOOLRESPONSE']._serialized_start=64 @@ -188,82 +190,86 @@ _globals['_ZRANGERESPONSE']._serialized_end=3095 _globals['_VADDREQUEST']._serialized_start=3098 _globals['_VADDREQUEST']._serialized_end=3347 - _globals['_VSIMREQUEST']._serialized_start=3349 - _globals['_VSIMREQUEST']._serialized_end=3447 - _globals['_VSIMRESPONSE']._serialized_start=3449 - _globals['_VSIMRESPONSE']._serialized_end=3502 - _globals['_VSIMRESULT']._serialized_start=3504 - _globals['_VSIMRESULT']._serialized_end=3551 - _globals['_VREMREQUEST']._serialized_start=3553 - _globals['_VREMREQUEST']._serialized_end=3596 - _globals['_VGETREQUEST']._serialized_start=3598 - _globals['_VGETREQUEST']._serialized_end=3641 - _globals['_VGETRESPONSE']._serialized_start=3643 - _globals['_VGETRESPONSE']._serialized_end=3709 - _globals['_VCARDREQUEST']._serialized_start=3711 - _globals['_VCARDREQUEST']._serialized_end=3738 - _globals['_VDIMREQUEST']._serialized_start=3740 - _globals['_VDIMREQUEST']._serialized_end=3766 - _globals['_VINFOREQUEST']._serialized_start=3768 - _globals['_VINFOREQUEST']._serialized_end=3795 - _globals['_VINFORESPONSE']._serialized_start=3797 - _globals['_VINFORESPONSE']._serialized_end=3864 - _globals['_PINGREQUEST']._serialized_start=3866 - _globals['_PINGREQUEST']._serialized_end=3913 - _globals['_PINGRESPONSE']._serialized_start=3915 - _globals['_PINGRESPONSE']._serialized_end=3946 - _globals['_FLUSHDBREQUEST']._serialized_start=3948 - _globals['_FLUSHDBREQUEST']._serialized_end=3979 - _globals['_DBSIZEREQUEST']._serialized_start=3981 - _globals['_DBSIZEREQUEST']._serialized_end=3996 - _globals['_INFOREQUEST']._serialized_start=3998 - _globals['_INFOREQUEST']._serialized_end=4045 - _globals['_INFORESPONSE']._serialized_start=4047 - _globals['_INFORESPONSE']._serialized_end=4075 - _globals['_ECHOREQUEST']._serialized_start=4077 - _globals['_ECHOREQUEST']._serialized_end=4107 - _globals['_ECHORESPONSE']._serialized_start=4109 - _globals['_ECHORESPONSE']._serialized_end=4140 - _globals['_DECRREQUEST']._serialized_start=4142 - _globals['_DECRREQUEST']._serialized_end=4168 - _globals['_UNLINKREQUEST']._serialized_start=4170 - _globals['_UNLINKREQUEST']._serialized_end=4199 - _globals['_BGSAVEREQUEST']._serialized_start=4201 - _globals['_BGSAVEREQUEST']._serialized_end=4216 - _globals['_BGREWRITEAOFREQUEST']._serialized_start=4218 - _globals['_BGREWRITEAOFREQUEST']._serialized_end=4239 - _globals['_SLOWLOGGETREQUEST']._serialized_start=4241 - _globals['_SLOWLOGGETREQUEST']._serialized_end=4290 - _globals['_SLOWLOGGETRESPONSE']._serialized_start=4292 - _globals['_SLOWLOGGETRESPONSE']._serialized_end=4353 - _globals['_SLOWLOGENTRY']._serialized_start=4355 - _globals['_SLOWLOGENTRY']._serialized_end=4447 - _globals['_SLOWLOGLENREQUEST']._serialized_start=4449 - _globals['_SLOWLOGLENREQUEST']._serialized_end=4468 - _globals['_SLOWLOGRESETREQUEST']._serialized_start=4470 - _globals['_SLOWLOGRESETREQUEST']._serialized_end=4491 - _globals['_PUBLISHREQUEST']._serialized_start=4493 - _globals['_PUBLISHREQUEST']._serialized_end=4543 - _globals['_SUBSCRIBEREQUEST']._serialized_start=4545 - _globals['_SUBSCRIBEREQUEST']._serialized_end=4599 - _globals['_SUBSCRIBEEVENT']._serialized_start=4601 - _globals['_SUBSCRIBEEVENT']._serialized_end=4696 - _globals['_PUBSUBCHANNELSREQUEST']._serialized_start=4698 - _globals['_PUBSUBCHANNELSREQUEST']._serialized_end=4755 - _globals['_PUBSUBNUMSUBREQUEST']._serialized_start=4757 - _globals['_PUBSUBNUMSUBREQUEST']._serialized_end=4796 - _globals['_PUBSUBNUMSUBRESPONSE']._serialized_start=4798 - _globals['_PUBSUBNUMSUBRESPONSE']._serialized_end=4860 - _globals['_PUBSUBNUMPATREQUEST']._serialized_start=4862 - _globals['_PUBSUBNUMPATREQUEST']._serialized_end=4883 - _globals['_CHANNELCOUNT']._serialized_start=4885 - _globals['_CHANNELCOUNT']._serialized_end=4931 - _globals['_PIPELINEREQUEST']._serialized_start=4934 - _globals['_PIPELINEREQUEST']._serialized_end=7961 - _globals['_PIPELINERESPONSE']._serialized_start=7964 - _globals['_PIPELINERESPONSE']._serialized_end=9225 - _globals['_ERRORRESPONSE']._serialized_start=9227 - _globals['_ERRORRESPONSE']._serialized_end=9294 - _globals['_EMBERCACHE']._serialized_start=9667 - _globals['_EMBERCACHE']._serialized_end=13990 + _globals['_VADDBATCHENTRY']._serialized_start=3349 + _globals['_VADDBATCHENTRY']._serialized_end=3402 + _globals['_VADDBATCHREQUEST']._serialized_start=3405 + _globals['_VADDBATCHREQUEST']._serialized_end=3665 + _globals['_VSIMREQUEST']._serialized_start=3667 + _globals['_VSIMREQUEST']._serialized_end=3765 + _globals['_VSIMRESPONSE']._serialized_start=3767 + _globals['_VSIMRESPONSE']._serialized_end=3820 + _globals['_VSIMRESULT']._serialized_start=3822 + _globals['_VSIMRESULT']._serialized_end=3869 + _globals['_VREMREQUEST']._serialized_start=3871 + _globals['_VREMREQUEST']._serialized_end=3914 + _globals['_VGETREQUEST']._serialized_start=3916 + _globals['_VGETREQUEST']._serialized_end=3959 + _globals['_VGETRESPONSE']._serialized_start=3961 + _globals['_VGETRESPONSE']._serialized_end=4027 + _globals['_VCARDREQUEST']._serialized_start=4029 + _globals['_VCARDREQUEST']._serialized_end=4056 + _globals['_VDIMREQUEST']._serialized_start=4058 + _globals['_VDIMREQUEST']._serialized_end=4084 + _globals['_VINFOREQUEST']._serialized_start=4086 + _globals['_VINFOREQUEST']._serialized_end=4113 + _globals['_VINFORESPONSE']._serialized_start=4115 + _globals['_VINFORESPONSE']._serialized_end=4182 + _globals['_PINGREQUEST']._serialized_start=4184 + _globals['_PINGREQUEST']._serialized_end=4231 + _globals['_PINGRESPONSE']._serialized_start=4233 + _globals['_PINGRESPONSE']._serialized_end=4264 + _globals['_FLUSHDBREQUEST']._serialized_start=4266 + _globals['_FLUSHDBREQUEST']._serialized_end=4297 + _globals['_DBSIZEREQUEST']._serialized_start=4299 + _globals['_DBSIZEREQUEST']._serialized_end=4314 + _globals['_INFOREQUEST']._serialized_start=4316 + _globals['_INFOREQUEST']._serialized_end=4363 + _globals['_INFORESPONSE']._serialized_start=4365 + _globals['_INFORESPONSE']._serialized_end=4393 + _globals['_ECHOREQUEST']._serialized_start=4395 + _globals['_ECHOREQUEST']._serialized_end=4425 + _globals['_ECHORESPONSE']._serialized_start=4427 + _globals['_ECHORESPONSE']._serialized_end=4458 + _globals['_DECRREQUEST']._serialized_start=4460 + _globals['_DECRREQUEST']._serialized_end=4486 + _globals['_UNLINKREQUEST']._serialized_start=4488 + _globals['_UNLINKREQUEST']._serialized_end=4517 + _globals['_BGSAVEREQUEST']._serialized_start=4519 + _globals['_BGSAVEREQUEST']._serialized_end=4534 + _globals['_BGREWRITEAOFREQUEST']._serialized_start=4536 + _globals['_BGREWRITEAOFREQUEST']._serialized_end=4557 + _globals['_SLOWLOGGETREQUEST']._serialized_start=4559 + _globals['_SLOWLOGGETREQUEST']._serialized_end=4608 + _globals['_SLOWLOGGETRESPONSE']._serialized_start=4610 + _globals['_SLOWLOGGETRESPONSE']._serialized_end=4671 + _globals['_SLOWLOGENTRY']._serialized_start=4673 + _globals['_SLOWLOGENTRY']._serialized_end=4765 + _globals['_SLOWLOGLENREQUEST']._serialized_start=4767 + _globals['_SLOWLOGLENREQUEST']._serialized_end=4786 + _globals['_SLOWLOGRESETREQUEST']._serialized_start=4788 + _globals['_SLOWLOGRESETREQUEST']._serialized_end=4809 + _globals['_PUBLISHREQUEST']._serialized_start=4811 + _globals['_PUBLISHREQUEST']._serialized_end=4861 + _globals['_SUBSCRIBEREQUEST']._serialized_start=4863 + _globals['_SUBSCRIBEREQUEST']._serialized_end=4917 + _globals['_SUBSCRIBEEVENT']._serialized_start=4919 + _globals['_SUBSCRIBEEVENT']._serialized_end=5014 + _globals['_PUBSUBCHANNELSREQUEST']._serialized_start=5016 + _globals['_PUBSUBCHANNELSREQUEST']._serialized_end=5073 + _globals['_PUBSUBNUMSUBREQUEST']._serialized_start=5075 + _globals['_PUBSUBNUMSUBREQUEST']._serialized_end=5114 + _globals['_PUBSUBNUMSUBRESPONSE']._serialized_start=5116 + _globals['_PUBSUBNUMSUBRESPONSE']._serialized_end=5178 + _globals['_PUBSUBNUMPATREQUEST']._serialized_start=5180 + _globals['_PUBSUBNUMPATREQUEST']._serialized_end=5201 + _globals['_CHANNELCOUNT']._serialized_start=5203 + _globals['_CHANNELCOUNT']._serialized_end=5249 + _globals['_PIPELINEREQUEST']._serialized_start=5252 + _globals['_PIPELINEREQUEST']._serialized_end=8329 + _globals['_PIPELINERESPONSE']._serialized_start=8332 + _globals['_PIPELINERESPONSE']._serialized_end=9593 + _globals['_ERRORRESPONSE']._serialized_start=9595 + _globals['_ERRORRESPONSE']._serialized_end=9662 + _globals['_EMBERCACHE']._serialized_start=10035 + _globals['_EMBERCACHE']._serialized_end=14422 # @@protoc_insertion_point(module_scope) diff --git a/clients/ember-py/ember/proto/ember/v1/ember_pb2_grpc.py b/clients/ember-py/ember/proto/ember/v1/ember_pb2_grpc.py index 4117d383..08911599 100644 --- a/clients/ember-py/ember/proto/ember/v1/ember_pb2_grpc.py +++ b/clients/ember-py/ember/proto/ember/v1/ember_pb2_grpc.py @@ -283,6 +283,11 @@ def __init__(self, channel): request_serializer=ember_dot_v1_dot_ember__pb2.VAddRequest.SerializeToString, response_deserializer=ember_dot_v1_dot_ember__pb2.BoolResponse.FromString, _registered_method=True) + self.VAddBatch = channel.unary_unary( + '/ember.v1.EmberCache/VAddBatch', + request_serializer=ember_dot_v1_dot_ember__pb2.VAddBatchRequest.SerializeToString, + response_deserializer=ember_dot_v1_dot_ember__pb2.IntResponse.FromString, + _registered_method=True) self.VSim = channel.unary_unary( '/ember.v1.EmberCache/VSim', request_serializer=ember_dot_v1_dot_ember__pb2.VSimRequest.SerializeToString, @@ -719,6 +724,12 @@ def VAdd(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def VAddBatch(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def VSim(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -1120,6 +1131,11 @@ def add_EmberCacheServicer_to_server(servicer, server): request_deserializer=ember_dot_v1_dot_ember__pb2.VAddRequest.FromString, response_serializer=ember_dot_v1_dot_ember__pb2.BoolResponse.SerializeToString, ), + 'VAddBatch': grpc.unary_unary_rpc_method_handler( + servicer.VAddBatch, + request_deserializer=ember_dot_v1_dot_ember__pb2.VAddBatchRequest.FromString, + response_serializer=ember_dot_v1_dot_ember__pb2.IntResponse.SerializeToString, + ), 'VSim': grpc.unary_unary_rpc_method_handler( servicer.VSim, request_deserializer=ember_dot_v1_dot_ember__pb2.VSimRequest.FromString, @@ -2578,6 +2594,33 @@ def VAdd(request, metadata, _registered_method=True) + @staticmethod + def VAddBatch(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ember.v1.EmberCache/VAddBatch', + ember_dot_v1_dot_ember__pb2.VAddBatchRequest.SerializeToString, + ember_dot_v1_dot_ember__pb2.IntResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + @staticmethod def VSim(request, target, diff --git a/crates/ember-core/src/keyspace.rs b/crates/ember-core/src/keyspace.rs index c574552d..cbb6e910 100644 --- a/crates/ember-core/src/keyspace.rs +++ b/crates/ember-core/src/keyspace.rs @@ -144,6 +144,17 @@ pub struct VAddResult { pub added: bool, } +/// Result of a VADD_BATCH operation. +#[cfg(feature = "vector")] +#[derive(Debug, Clone)] +pub struct VAddBatchResult { + /// Number of newly added elements (not updates). + pub added_count: usize, + /// Elements that were actually inserted or updated, with their vectors. + /// Only these should be persisted to the AOF. + pub applied: Vec<(String, Vec)>, +} + /// Errors from vector write operations. #[cfg(feature = "vector")] #[derive(Debug, Clone, PartialEq, Eq)] @@ -1936,6 +1947,134 @@ impl Keyspace { }) } + /// Adds multiple vectors to a vector set in a single operation. + /// + /// All vectors are validated upfront (NaN/inf check) before any are inserted. + /// Memory is estimated for the entire batch with one `enforce_memory_limit` call. + /// On usearch error mid-batch, returns the error but already-applied vectors + /// are included in the result for AOF persistence. + #[cfg(feature = "vector")] + #[allow(clippy::too_many_arguments)] + pub fn vadd_batch( + &mut self, + key: &str, + entries: &[(String, Vec)], + metric: crate::types::vector::DistanceMetric, + quantization: crate::types::vector::QuantizationType, + connectivity: usize, + expansion_add: usize, + ) -> Result { + use crate::types::vector::VectorSet; + + if entries.is_empty() { + return Ok(VAddBatchResult { + added_count: 0, + applied: Vec::new(), + }); + } + + self.remove_if_expired(key); + + // type check + let is_new = match self.entries.get(key) { + None => true, + Some(e) if matches!(e.value, Value::Vector(_)) => false, + Some(_) => return Err(VectorWriteError::WrongType), + }; + + // validate all vectors upfront — reject entire batch on NaN/inf + let dim = entries[0].1.len(); + for (elem, vec) in entries { + if vec.len() != dim { + return Err(VectorWriteError::IndexError(format!( + "dimension mismatch: expected {dim}, element '{elem}' has {}", + vec.len() + ))); + } + for &v in vec { + if v.is_nan() || v.is_infinite() { + return Err(VectorWriteError::IndexError(format!( + "element '{elem}' contains NaN or infinity" + ))); + } + } + } + + // estimate total memory for all vectors + let per_vector = dim + .saturating_mul(quantization.bytes_per_element()) + .saturating_add(connectivity.saturating_mul(16)) + .saturating_add(80); + let total_elem_names: usize = entries.iter().map(|(e, _)| e.len()).sum(); + let vectors_cost = entries + .len() + .saturating_mul(per_vector) + .saturating_add(total_elem_names); + let estimated_increase = if is_new { + memory::ENTRY_OVERHEAD + key.len() + VectorSet::BASE_OVERHEAD + vectors_cost + } else { + vectors_cost + }; + if !self.enforce_memory_limit(estimated_increase) { + return Err(VectorWriteError::OutOfMemory); + } + + // create vector set if new + if is_new { + let vs = VectorSet::new(dim, metric, quantization, connectivity, expansion_add) + .map_err(|e| VectorWriteError::IndexError(e.to_string()))?; + let value = Value::Vector(vs); + self.memory.add(key, &value); + self.entries.insert(key.to_owned(), Entry::new(value, None)); + } + + let entry = match self.entries.get_mut(key) { + Some(e) => e, + None => return Err(VectorWriteError::IndexError("entry missing".into())), + }; + let old_entry_size = memory::entry_size(key, &entry.value); + + let mut added_count = 0; + let mut applied = Vec::with_capacity(entries.len()); + + match entry.value { + Value::Vector(ref mut vs) => { + for (element, vector) in entries { + match vs.add(element.clone(), vector) { + Ok(added) => { + if added { + added_count += 1; + } + applied.push((element.clone(), vector.clone())); + } + Err(e) => { + // partial insert: return what we applied so far + error + // caller should persist the applied vectors + entry.touch(); + let new_entry_size = memory::entry_size(key, &entry.value); + self.memory.adjust(old_entry_size, new_entry_size); + return Err(VectorWriteError::IndexError(format!( + "error at element '{}': {e} ({} vectors applied before failure)", + element, + applied.len() + ))); + } + } + } + } + _ => return Err(VectorWriteError::WrongType), + } + + entry.touch(); + let new_entry_size = memory::entry_size(key, &entry.value); + self.memory.adjust(old_entry_size, new_entry_size); + + Ok(VAddBatchResult { + added_count, + applied, + }) + } + /// Searches for the k nearest neighbors in a vector set. #[cfg(feature = "vector")] pub fn vsim( diff --git a/crates/ember-core/src/shard.rs b/crates/ember-core/src/shard.rs index 40919bbf..142cd655 100644 --- a/crates/ember-core/src/shard.rs +++ b/crates/ember-core/src/shard.rs @@ -271,6 +271,17 @@ pub enum ShardRequest { connectivity: u32, expansion_add: u32, }, + /// Adds multiple vectors to a vector set in a single command. + #[cfg(feature = "vector")] + VAddBatch { + key: String, + entries: Vec<(String, Vec)>, + dim: usize, + metric: u8, + quantization: u8, + connectivity: u32, + expansion_add: u32, + }, /// Searches for nearest neighbors in a vector set. #[cfg(feature = "vector")] VSim { @@ -412,6 +423,12 @@ pub enum ShardResponse { vector: Vec, added: bool, }, + /// VADD_BATCH result: count of newly added elements + applied entries for AOF. + #[cfg(feature = "vector")] + VAddBatchResult { + added_count: usize, + applied: Vec<(String, Vec)>, + }, /// VSIM result: nearest neighbors with distances. #[cfg(feature = "vector")] VSimResult(Vec<(String, f32)>), @@ -728,16 +745,17 @@ fn process_message( schema_registry, ); - // write AOF record for successful mutations + // write AOF records for successful mutations if let Some(ref mut writer) = aof_writer { - if let Some(record) = to_aof_record(&msg.request, &response) { - if let Err(e) = writer.write_record(&record) { + let records = to_aof_records(&msg.request, &response); + for record in &records { + if let Err(e) = writer.write_record(record) { warn!(shard_id, "aof write failed: {e}"); } - if fsync_policy == FsyncPolicy::Always { - if let Err(e) = writer.sync() { - warn!(shard_id, "aof sync failed: {e}"); - } + } + if !records.is_empty() && fsync_policy == FsyncPolicy::Always { + if let Err(e) = writer.sync() { + warn!(shard_id, "aof sync failed: {e}"); } } } @@ -1061,6 +1079,36 @@ fn dispatch( } } #[cfg(feature = "vector")] + ShardRequest::VAddBatch { + key, + entries, + metric, + quantization, + connectivity, + expansion_add, + .. + } => { + use crate::types::vector::{DistanceMetric, QuantizationType}; + match ks.vadd_batch( + key, + entries, + DistanceMetric::from_u8(*metric), + QuantizationType::from_u8(*quantization), + *connectivity as usize, + *expansion_add as usize, + ) { + Ok(result) => ShardResponse::VAddBatchResult { + added_count: result.added_count, + applied: result.applied, + }, + Err(crate::keyspace::VectorWriteError::WrongType) => ShardResponse::WrongType, + Err(crate::keyspace::VectorWriteError::OutOfMemory) => ShardResponse::OutOfMemory, + Err(crate::keyspace::VectorWriteError::IndexError(e)) => { + ShardResponse::Err(format!("ERR vector index: {e}")) + } + } + } + #[cfg(feature = "vector")] ShardRequest::VSim { key, query, @@ -1246,7 +1294,7 @@ fn duration_to_expire_ms(d: Duration) -> i64 { /// Converts a successful mutation request+response pair into an AOF record. /// Returns None for non-mutation requests or failed mutations. -fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option { +fn to_aof_records(req: &ShardRequest, resp: &ShardResponse) -> Vec { match (req, resp) { ( ShardRequest::Set { @@ -1255,129 +1303,129 @@ fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option ShardResponse::Ok, ) => { let expire_ms = expire.map(duration_to_expire_ms).unwrap_or(-1); - Some(AofRecord::Set { + vec![AofRecord::Set { key: key.clone(), value: value.clone(), expire_ms, - }) + }] } (ShardRequest::Del { key }, ShardResponse::Bool(true)) | (ShardRequest::Unlink { key }, ShardResponse::Bool(true)) => { - Some(AofRecord::Del { key: key.clone() }) + vec![AofRecord::Del { key: key.clone() }] } (ShardRequest::Expire { key, seconds }, ShardResponse::Bool(true)) => { - Some(AofRecord::Expire { + vec![AofRecord::Expire { key: key.clone(), seconds: *seconds, - }) + }] } - (ShardRequest::LPush { key, values }, ShardResponse::Len(_)) => Some(AofRecord::LPush { + (ShardRequest::LPush { key, values }, ShardResponse::Len(_)) => vec![AofRecord::LPush { key: key.clone(), values: values.clone(), - }), - (ShardRequest::RPush { key, values }, ShardResponse::Len(_)) => Some(AofRecord::RPush { + }], + (ShardRequest::RPush { key, values }, ShardResponse::Len(_)) => vec![AofRecord::RPush { key: key.clone(), values: values.clone(), - }), + }], (ShardRequest::LPop { key }, ShardResponse::Value(Some(_))) => { - Some(AofRecord::LPop { key: key.clone() }) + vec![AofRecord::LPop { key: key.clone() }] } (ShardRequest::RPop { key }, ShardResponse::Value(Some(_))) => { - Some(AofRecord::RPop { key: key.clone() }) + vec![AofRecord::RPop { key: key.clone() }] } (ShardRequest::ZAdd { key, .. }, ShardResponse::ZAddLen { applied, .. }) if !applied.is_empty() => { - Some(AofRecord::ZAdd { + vec![AofRecord::ZAdd { key: key.clone(), members: applied.clone(), - }) + }] } (ShardRequest::ZRem { key, .. }, ShardResponse::ZRemLen { removed, .. }) if !removed.is_empty() => { - Some(AofRecord::ZRem { + vec![AofRecord::ZRem { key: key.clone(), members: removed.clone(), - }) + }] } (ShardRequest::Incr { key }, ShardResponse::Integer(_)) => { - Some(AofRecord::Incr { key: key.clone() }) + vec![AofRecord::Incr { key: key.clone() }] } (ShardRequest::Decr { key }, ShardResponse::Integer(_)) => { - Some(AofRecord::Decr { key: key.clone() }) + vec![AofRecord::Decr { key: key.clone() }] } (ShardRequest::IncrBy { key, delta }, ShardResponse::Integer(_)) => { - Some(AofRecord::IncrBy { + vec![AofRecord::IncrBy { key: key.clone(), delta: *delta, - }) + }] } (ShardRequest::DecrBy { key, delta }, ShardResponse::Integer(_)) => { - Some(AofRecord::DecrBy { + vec![AofRecord::DecrBy { key: key.clone(), delta: *delta, - }) + }] } // INCRBYFLOAT: record as a SET with the resulting value to avoid // float rounding drift during replay. (ShardRequest::IncrByFloat { key, .. }, ShardResponse::BulkString(val)) => { - Some(AofRecord::Set { + vec![AofRecord::Set { key: key.clone(), value: Bytes::from(val.clone()), expire_ms: -1, - }) + }] } // APPEND: record the appended value for replay - (ShardRequest::Append { key, value }, ShardResponse::Len(_)) => Some(AofRecord::Append { + (ShardRequest::Append { key, value }, ShardResponse::Len(_)) => vec![AofRecord::Append { key: key.clone(), value: value.clone(), - }), - (ShardRequest::Rename { key, newkey }, ShardResponse::Ok) => Some(AofRecord::Rename { + }], + (ShardRequest::Rename { key, newkey }, ShardResponse::Ok) => vec![AofRecord::Rename { key: key.clone(), newkey: newkey.clone(), - }), + }], (ShardRequest::Persist { key }, ShardResponse::Bool(true)) => { - Some(AofRecord::Persist { key: key.clone() }) + vec![AofRecord::Persist { key: key.clone() }] } (ShardRequest::Pexpire { key, milliseconds }, ShardResponse::Bool(true)) => { - Some(AofRecord::Pexpire { + vec![AofRecord::Pexpire { key: key.clone(), milliseconds: *milliseconds, - }) + }] } // Hash commands - (ShardRequest::HSet { key, fields }, ShardResponse::Len(_)) => Some(AofRecord::HSet { + (ShardRequest::HSet { key, fields }, ShardResponse::Len(_)) => vec![AofRecord::HSet { key: key.clone(), fields: fields.clone(), - }), + }], (ShardRequest::HDel { key, .. }, ShardResponse::HDelLen { removed, .. }) if !removed.is_empty() => { - Some(AofRecord::HDel { + vec![AofRecord::HDel { key: key.clone(), fields: removed.clone(), - }) + }] } (ShardRequest::HIncrBy { key, field, delta }, ShardResponse::Integer(_)) => { - Some(AofRecord::HIncrBy { + vec![AofRecord::HIncrBy { key: key.clone(), field: field.clone(), delta: *delta, - }) + }] } // Set commands (ShardRequest::SAdd { key, members }, ShardResponse::Len(count)) if *count > 0 => { - Some(AofRecord::SAdd { + vec![AofRecord::SAdd { key: key.clone(), members: members.clone(), - }) + }] } (ShardRequest::SRem { key, members }, ShardResponse::Len(count)) if *count > 0 => { - Some(AofRecord::SRem { + vec![AofRecord::SRem { key: key.clone(), members: members.clone(), - }) + }] } // Proto commands #[cfg(feature = "protobuf")] @@ -1392,19 +1440,19 @@ fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option ShardResponse::Ok, ) => { let expire_ms = expire.map(duration_to_expire_ms).unwrap_or(-1); - Some(AofRecord::ProtoSet { + vec![AofRecord::ProtoSet { key: key.clone(), type_name: type_name.clone(), data: data.clone(), expire_ms, - }) + }] } #[cfg(feature = "protobuf")] (ShardRequest::ProtoRegisterAof { name, descriptor }, ShardResponse::Ok) => { - Some(AofRecord::ProtoRegister { + vec![AofRecord::ProtoRegister { name: name.clone(), descriptor: descriptor.clone(), - }) + }] } // atomic field ops persist as a full ProtoSet (the whole re-encoded value) #[cfg(feature = "protobuf")] @@ -1417,12 +1465,12 @@ fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option }, ) => { let expire_ms = expire.map(duration_to_expire_ms).unwrap_or(-1); - Some(AofRecord::ProtoSet { + vec![AofRecord::ProtoSet { key: key.clone(), type_name: type_name.clone(), data: data.clone(), expire_ms, - }) + }] } // Vector commands #[cfg(feature = "vector")] @@ -1438,7 +1486,7 @@ fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option ShardResponse::VAddResult { element, vector, .. }, - ) => Some(AofRecord::VAdd { + ) => vec![AofRecord::VAdd { key: key.clone(), element: element.clone(), vector: vector.clone(), @@ -1446,13 +1494,37 @@ fn to_aof_record(req: &ShardRequest, resp: &ShardResponse) -> Option quantization: *quantization, connectivity: *connectivity, expansion_add: *expansion_add, - }), + }], + // VADD_BATCH: expand each applied entry into its own AofRecord::VAdd + #[cfg(feature = "vector")] + ( + ShardRequest::VAddBatch { + key, + metric, + quantization, + connectivity, + expansion_add, + .. + }, + ShardResponse::VAddBatchResult { applied, .. }, + ) => applied + .iter() + .map(|(element, vector)| AofRecord::VAdd { + key: key.clone(), + element: element.clone(), + vector: vector.clone(), + metric: *metric, + quantization: *quantization, + connectivity: *connectivity, + expansion_add: *expansion_add, + }) + .collect(), #[cfg(feature = "vector")] - (ShardRequest::VRem { key, element }, ShardResponse::Bool(true)) => Some(AofRecord::VRem { + (ShardRequest::VRem { key, element }, ShardResponse::Bool(true)) => vec![AofRecord::VRem { key: key.clone(), element: element.clone(), - }), - _ => None, + }], + _ => vec![], } } @@ -1948,7 +2020,7 @@ mod tests { } #[test] - fn to_aof_record_for_set() { + fn to_aof_records_for_set() { let req = ShardRequest::Set { key: "k".into(), value: Bytes::from("v"), @@ -1957,7 +2029,7 @@ mod tests { xx: false, }; let resp = ShardResponse::Ok; - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::Set { key, expire_ms, .. } => { assert_eq!(key, "k"); @@ -1968,7 +2040,7 @@ mod tests { } #[test] - fn to_aof_record_skips_failed_set() { + fn to_aof_records_skips_failed_set() { let req = ShardRequest::Set { key: "k".into(), value: Bytes::from("v"), @@ -1977,22 +2049,22 @@ mod tests { xx: false, }; let resp = ShardResponse::OutOfMemory; - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] - fn to_aof_record_for_del() { + fn to_aof_records_for_del() { let req = ShardRequest::Del { key: "k".into() }; let resp = ShardResponse::Bool(true); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); assert!(matches!(record, AofRecord::Del { .. })); } #[test] - fn to_aof_record_skips_failed_del() { + fn to_aof_records_skips_failed_del() { let req = ShardRequest::Del { key: "k".into() }; let resp = ShardResponse::Bool(false); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] @@ -2109,13 +2181,13 @@ mod tests { } #[test] - fn to_aof_record_for_append() { + fn to_aof_records_for_append() { let req = ShardRequest::Append { key: "k".into(), value: Bytes::from("data"), }; let resp = ShardResponse::Len(10); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::Append { key, value } => { assert_eq!(key, "k"); @@ -2145,29 +2217,29 @@ mod tests { } #[test] - fn to_aof_record_for_incr() { + fn to_aof_records_for_incr() { let req = ShardRequest::Incr { key: "c".into() }; let resp = ShardResponse::Integer(1); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); assert!(matches!(record, AofRecord::Incr { .. })); } #[test] - fn to_aof_record_for_decr() { + fn to_aof_records_for_decr() { let req = ShardRequest::Decr { key: "c".into() }; let resp = ShardResponse::Integer(-1); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); assert!(matches!(record, AofRecord::Decr { .. })); } #[test] - fn to_aof_record_for_incrby() { + fn to_aof_records_for_incrby() { let req = ShardRequest::IncrBy { key: "c".into(), delta: 5, }; let resp = ShardResponse::Integer(15); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::IncrBy { key, delta } => { assert_eq!(key, "c"); @@ -2178,13 +2250,13 @@ mod tests { } #[test] - fn to_aof_record_for_decrby() { + fn to_aof_records_for_decrby() { let req = ShardRequest::DecrBy { key: "c".into(), delta: 3, }; let resp = ShardResponse::Integer(7); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::DecrBy { key, delta } => { assert_eq!(key, "c"); @@ -2266,28 +2338,28 @@ mod tests { } #[test] - fn to_aof_record_for_persist() { + fn to_aof_records_for_persist() { let req = ShardRequest::Persist { key: "k".into() }; let resp = ShardResponse::Bool(true); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); assert!(matches!(record, AofRecord::Persist { .. })); } #[test] - fn to_aof_record_skips_failed_persist() { + fn to_aof_records_skips_failed_persist() { let req = ShardRequest::Persist { key: "k".into() }; let resp = ShardResponse::Bool(false); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] - fn to_aof_record_for_pexpire() { + fn to_aof_records_for_pexpire() { let req = ShardRequest::Pexpire { key: "k".into(), milliseconds: 5000, }; let resp = ShardResponse::Bool(true); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::Pexpire { key, milliseconds } => { assert_eq!(key, "k"); @@ -2298,13 +2370,13 @@ mod tests { } #[test] - fn to_aof_record_skips_failed_pexpire() { + fn to_aof_records_skips_failed_pexpire() { let req = ShardRequest::Pexpire { key: "k".into(), milliseconds: 5000, }; let resp = ShardResponse::Bool(false); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] @@ -2389,7 +2461,7 @@ mod tests { } #[test] - fn to_aof_record_skips_nx_blocked_set() { + fn to_aof_records_skips_nx_blocked_set() { let req = ShardRequest::Set { key: "k".into(), value: Bytes::from("v"), @@ -2399,7 +2471,7 @@ mod tests { }; // when NX blocks, the shard returns Value(None), not Ok let resp = ShardResponse::Value(None); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] @@ -2469,13 +2541,13 @@ mod tests { } #[test] - fn to_aof_record_for_hset() { + fn to_aof_records_for_hset() { let req = ShardRequest::HSet { key: "h".into(), fields: vec![("f1".into(), Bytes::from("v1"))], }; let resp = ShardResponse::Len(1); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::HSet { key, fields } => { assert_eq!(key, "h"); @@ -2486,7 +2558,7 @@ mod tests { } #[test] - fn to_aof_record_for_hdel() { + fn to_aof_records_for_hdel() { let req = ShardRequest::HDel { key: "h".into(), fields: vec!["f1".into(), "f2".into()], @@ -2495,7 +2567,7 @@ mod tests { count: 2, removed: vec!["f1".into(), "f2".into()], }; - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::HDel { key, fields } => { assert_eq!(key, "h"); @@ -2506,7 +2578,7 @@ mod tests { } #[test] - fn to_aof_record_skips_hdel_when_none_removed() { + fn to_aof_records_skips_hdel_when_none_removed() { let req = ShardRequest::HDel { key: "h".into(), fields: vec!["f1".into()], @@ -2515,18 +2587,18 @@ mod tests { count: 0, removed: vec![], }; - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] - fn to_aof_record_for_hincrby() { + fn to_aof_records_for_hincrby() { let req = ShardRequest::HIncrBy { key: "h".into(), field: "counter".into(), delta: 5, }; let resp = ShardResponse::Integer(10); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::HIncrBy { key, field, delta } => { assert_eq!(key, "h"); @@ -2538,13 +2610,13 @@ mod tests { } #[test] - fn to_aof_record_for_sadd() { + fn to_aof_records_for_sadd() { let req = ShardRequest::SAdd { key: "s".into(), members: vec!["m1".into(), "m2".into()], }; let resp = ShardResponse::Len(2); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::SAdd { key, members } => { assert_eq!(key, "s"); @@ -2555,23 +2627,23 @@ mod tests { } #[test] - fn to_aof_record_skips_sadd_when_none_added() { + fn to_aof_records_skips_sadd_when_none_added() { let req = ShardRequest::SAdd { key: "s".into(), members: vec!["m1".into()], }; let resp = ShardResponse::Len(0); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] - fn to_aof_record_for_srem() { + fn to_aof_records_for_srem() { let req = ShardRequest::SRem { key: "s".into(), members: vec!["m1".into()], }; let resp = ShardResponse::Len(1); - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::SRem { key, members } => { assert_eq!(key, "s"); @@ -2582,13 +2654,13 @@ mod tests { } #[test] - fn to_aof_record_skips_srem_when_none_removed() { + fn to_aof_records_skips_srem_when_none_removed() { let req = ShardRequest::SRem { key: "s".into(), members: vec!["m1".into()], }; let resp = ShardResponse::Len(0); - assert!(to_aof_record(&req, &resp).is_none()); + assert!(to_aof_records(&req, &resp).is_empty()); } #[test] @@ -2642,13 +2714,13 @@ mod tests { } #[test] - fn to_aof_record_for_rename() { + fn to_aof_records_for_rename() { let req = ShardRequest::Rename { key: "old".into(), newkey: "new".into(), }; let resp = ShardResponse::Ok; - let record = to_aof_record(&req, &resp).unwrap(); + let record = to_aof_records(&req, &resp).into_iter().next().unwrap(); match record { AofRecord::Rename { key, newkey } => { assert_eq!(key, "old"); @@ -2657,4 +2729,58 @@ mod tests { other => panic!("expected Rename, got {other:?}"), } } + + #[test] + #[cfg(feature = "vector")] + fn to_aof_records_for_vadd_batch() { + let req = ShardRequest::VAddBatch { + key: "vecs".into(), + entries: vec![ + ("a".into(), vec![1.0, 2.0]), + ("b".into(), vec![3.0, 4.0]), + ("c".into(), vec![5.0, 6.0]), + ], + dim: 2, + metric: 0, + quantization: 0, + connectivity: 16, + expansion_add: 64, + }; + let resp = ShardResponse::VAddBatchResult { + added_count: 3, + applied: vec![ + ("a".into(), vec![1.0, 2.0]), + ("b".into(), vec![3.0, 4.0]), + ("c".into(), vec![5.0, 6.0]), + ], + }; + let records = to_aof_records(&req, &resp); + assert_eq!(records.len(), 3); + for (i, record) in records.iter().enumerate() { + match record { + AofRecord::VAdd { + key, + element, + metric, + quantization, + connectivity, + expansion_add, + .. + } => { + assert_eq!(key, "vecs"); + assert_eq!(*metric, 0); + assert_eq!(*quantization, 0); + assert_eq!(*connectivity, 16); + assert_eq!(*expansion_add, 64); + match i { + 0 => assert_eq!(element, "a"), + 1 => assert_eq!(element, "b"), + 2 => assert_eq!(element, "c"), + _ => unreachable!(), + } + } + other => panic!("expected VAdd, got {other:?}"), + } + } + } } diff --git a/crates/ember-protocol/src/command.rs b/crates/ember-protocol/src/command.rs index bf6646bd..bb10b0d4 100644 --- a/crates/ember-protocol/src/command.rs +++ b/crates/ember-protocol/src/command.rs @@ -26,6 +26,11 @@ const MAX_VSIM_COUNT: u64 = 10_000; /// larger values cause worst-case O(n) graph traversal with no accuracy gain. const MAX_VSIM_EF: u64 = MAX_HNSW_PARAM; +/// Maximum number of vectors in a single VADD_BATCH command. 10,000 keeps +/// per-command latency bounded while still being large enough to amortize +/// round-trip overhead for bulk inserts. +const MAX_VADD_BATCH_SIZE: usize = 10_000; + /// Expiration option for the SET command. #[derive(Debug, Clone, PartialEq, Eq)] pub enum SetExpire { @@ -355,6 +360,22 @@ pub enum Command { expansion_add: u32, }, + /// VADD_BATCH key DIM n element1 f32... element2 f32... [METRIC COSINE|L2|IP] + /// [QUANT F32|F16|I8] [M n] [EF n]. Adds multiple vectors in a single command. + VAddBatch { + key: String, + entries: Vec<(String, Vec)>, + dim: usize, + /// 0 = cosine (default), 1 = l2, 2 = inner product + metric: u8, + /// 0 = f32 (default), 1 = f16, 2 = i8 + quantization: u8, + /// HNSW connectivity parameter (default 16) + connectivity: u32, + /// HNSW construction beam width (default 64) + expansion_add: u32, + }, + /// VSIM key f32 [f32 ...] COUNT k [EF n] [WITHSCORES]. /// Searches for k nearest neighbors. VSim { @@ -552,6 +573,7 @@ impl Command { Command::PubSubNumSub { .. } => "pubsub", Command::PubSubNumPat => "pubsub", Command::VAdd { .. } => "vadd", + Command::VAddBatch { .. } => "vadd_batch", Command::VSim { .. } => "vsim", Command::VRem { .. } => "vrem", Command::VGet { .. } => "vget", @@ -665,6 +687,7 @@ impl Command { "PUBLISH" => parse_publish(&frames[1..]), "PUBSUB" => parse_pubsub(&frames[1..]), "VADD" => parse_vadd(&frames[1..]), + "VADD_BATCH" => parse_vadd_batch(&frames[1..]), "VSIM" => parse_vsim(&frames[1..]), "VREM" => parse_vrem(&frames[1..]), "VGET" => parse_vget(&frames[1..]), @@ -1959,6 +1982,180 @@ fn parse_vadd(args: &[Frame]) -> Result { }) } +/// VADD_BATCH key DIM n element1 f32... element2 f32... [METRIC COSINE|L2|IP] +/// [QUANT F32|F16|I8] [M n] [EF n] +fn parse_vadd_batch(args: &[Frame]) -> Result { + // minimum: key + DIM + n (even an empty batch needs the DIM declaration) + if args.len() < 3 { + return Err(ProtocolError::WrongArity("VADD_BATCH".into())); + } + + let key = extract_string(&args[0])?; + + // require DIM keyword + let dim_kw = extract_string(&args[1])?.to_ascii_uppercase(); + if dim_kw != "DIM" { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: expected DIM keyword".into(), + )); + } + + let dim = parse_u64(&args[2], "VADD_BATCH")? as usize; + if dim == 0 { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: DIM must be at least 1".into(), + )); + } + if dim > MAX_VECTOR_DIMS { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: DIM {dim} exceeds max {MAX_VECTOR_DIMS}" + ))); + } + + // parse entries: each is element_name followed by exactly `dim` floats. + // stop when we see a known flag or run out of args. + let mut idx = 3; + let mut entries: Vec<(String, Vec)> = Vec::new(); + let flags = ["METRIC", "QUANT", "M", "EF"]; + + while idx < args.len() { + let token = extract_string(&args[idx])?; + if flags.contains(&token.to_ascii_uppercase().as_str()) { + break; + } + + // this token is an element name + let element = token; + idx += 1; + + // read exactly `dim` floats + if idx + dim > args.len() { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: not enough floats for element '{element}' (expected {dim})" + ))); + } + + let mut vector = Vec::with_capacity(dim); + for _ in 0..dim { + let s = extract_string(&args[idx])?; + let v = s.parse::().map_err(|_| { + ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: expected float, got '{s}'" + )) + })?; + vector.push(v); + idx += 1; + } + + entries.push((element, vector)); + + if entries.len() > MAX_VADD_BATCH_SIZE { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: batch size exceeds max {MAX_VADD_BATCH_SIZE}" + ))); + } + } + + // parse optional flags (same logic as parse_vadd) + let mut metric: u8 = 0; + let mut quantization: u8 = 0; + let mut connectivity: u32 = 16; + let mut expansion_add: u32 = 64; + + while idx < args.len() { + let flag = extract_string(&args[idx])?.to_ascii_uppercase(); + match flag.as_str() { + "METRIC" => { + idx += 1; + if idx >= args.len() { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: METRIC requires a value".into(), + )); + } + let val = extract_string(&args[idx])?.to_ascii_uppercase(); + metric = match val.as_str() { + "COSINE" => 0, + "L2" => 1, + "IP" => 2, + _ => { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: unknown metric '{val}'" + ))) + } + }; + idx += 1; + } + "QUANT" => { + idx += 1; + if idx >= args.len() { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: QUANT requires a value".into(), + )); + } + let val = extract_string(&args[idx])?.to_ascii_uppercase(); + quantization = match val.as_str() { + "F32" => 0, + "F16" => 1, + "I8" | "Q8" => 2, + _ => { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: unknown quantization '{val}'" + ))) + } + }; + idx += 1; + } + "M" => { + idx += 1; + if idx >= args.len() { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: M requires a value".into(), + )); + } + let m = parse_u64(&args[idx], "VADD_BATCH")?; + if m > MAX_HNSW_PARAM { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: M value {m} exceeds max {MAX_HNSW_PARAM}" + ))); + } + connectivity = m as u32; + idx += 1; + } + "EF" => { + idx += 1; + if idx >= args.len() { + return Err(ProtocolError::InvalidCommandFrame( + "VADD_BATCH: EF requires a value".into(), + )); + } + let ef = parse_u64(&args[idx], "VADD_BATCH")?; + if ef > MAX_HNSW_PARAM { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: EF value {ef} exceeds max {MAX_HNSW_PARAM}" + ))); + } + expansion_add = ef as u32; + idx += 1; + } + _ => { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD_BATCH: unexpected argument '{flag}'" + ))); + } + } + } + + Ok(Command::VAddBatch { + key, + entries, + dim, + metric, + quantization, + connectivity, + expansion_add, + }) +} + /// VSIM key f32 [f32 ...] COUNT k [EF n] [WITHSCORES] fn parse_vsim(args: &[Frame]) -> Result { // minimum: key + at least one float + COUNT + k @@ -4815,6 +5012,145 @@ mod tests { assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); } + // --- vadd_batch --- + + #[test] + fn vadd_batch_basic() { + assert_eq!( + Command::from_frame(cmd(&[ + "VADD_BATCH", "vecs", "DIM", "3", "a", "0.1", "0.2", "0.3", "b", "0.4", "0.5", + "0.6" + ])) + .unwrap(), + Command::VAddBatch { + key: "vecs".into(), + entries: vec![ + ("a".into(), vec![0.1, 0.2, 0.3]), + ("b".into(), vec![0.4, 0.5, 0.6]), + ], + dim: 3, + metric: 0, + quantization: 0, + connectivity: 16, + expansion_add: 64, + }, + ); + } + + #[test] + fn vadd_batch_with_options() { + assert_eq!( + Command::from_frame(cmd(&[ + "VADD_BATCH", "vecs", "DIM", "2", "a", "1.0", "2.0", "METRIC", "L2", "QUANT", + "F16", "M", "32", "EF", "128" + ])) + .unwrap(), + Command::VAddBatch { + key: "vecs".into(), + entries: vec![("a".into(), vec![1.0, 2.0])], + dim: 2, + metric: 1, + quantization: 1, + connectivity: 32, + expansion_add: 128, + }, + ); + } + + #[test] + fn vadd_batch_single_entry() { + assert_eq!( + Command::from_frame(cmd(&["VADD_BATCH", "vecs", "DIM", "1", "x", "3.14"])).unwrap(), + Command::VAddBatch { + key: "vecs".into(), + entries: vec![("x".into(), vec![3.14])], + dim: 1, + metric: 0, + quantization: 0, + connectivity: 16, + expansion_add: 64, + }, + ); + } + + #[test] + fn vadd_batch_empty_entries() { + // key + DIM + n but no entries — valid, returns empty batch + assert_eq!( + Command::from_frame(cmd(&["VADD_BATCH", "vecs", "DIM", "3"])).unwrap(), + Command::VAddBatch { + key: "vecs".into(), + entries: vec![], + dim: 3, + metric: 0, + quantization: 0, + connectivity: 16, + expansion_add: 64, + }, + ); + } + + #[test] + fn vadd_batch_wrong_arity() { + let err = Command::from_frame(cmd(&["VADD_BATCH"])).unwrap_err(); + assert!(matches!(err, ProtocolError::WrongArity(_))); + + let err = Command::from_frame(cmd(&["VADD_BATCH", "key"])).unwrap_err(); + assert!(matches!(err, ProtocolError::WrongArity(_))); + + let err = Command::from_frame(cmd(&["VADD_BATCH", "key", "DIM"])).unwrap_err(); + assert!(matches!(err, ProtocolError::WrongArity(_))); + } + + #[test] + fn vadd_batch_missing_dim_keyword() { + let err = + Command::from_frame(cmd(&["VADD_BATCH", "key", "3", "a", "1.0"])).unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + + #[test] + fn vadd_batch_dim_zero() { + let err = + Command::from_frame(cmd(&["VADD_BATCH", "key", "DIM", "0"])).unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + + #[test] + fn vadd_batch_dim_exceeds_max() { + let err = + Command::from_frame(cmd(&["VADD_BATCH", "key", "DIM", "99999"])).unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + + #[test] + fn vadd_batch_insufficient_floats() { + // DIM=3 but only 2 floats for element "a" + let err = Command::from_frame(cmd(&[ + "VADD_BATCH", "key", "DIM", "3", "a", "1.0", "2.0", + ])) + .unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + + #[test] + fn vadd_batch_m_exceeds_max() { + let err = Command::from_frame(cmd(&[ + "VADD_BATCH", "key", "DIM", "2", "a", "1.0", "2.0", "M", "9999", + ])) + .unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + + #[test] + fn vadd_batch_ef_exceeds_max() { + let err = Command::from_frame(cmd(&[ + "VADD_BATCH", "key", "DIM", "2", "a", "1.0", "2.0", "EF", "9999", + ])) + .unwrap_err(); + assert!(matches!(err, ProtocolError::InvalidCommandFrame(_))); + } + #[test] fn vsim_basic() { assert_eq!( diff --git a/crates/ember-server/src/connection.rs b/crates/ember-server/src/connection.rs index bc54689b..617cc397 100644 --- a/crates/ember-server/src/connection.rs +++ b/crates/ember-server/src/connection.rs @@ -110,6 +110,9 @@ enum ResponseTag { /// Vector VADD result #[cfg(feature = "vector")] VAddResult, + /// Vector VADD_BATCH result + #[cfg(feature = "vector")] + VAddBatchResult, /// Vector VSIM result #[cfg(feature = "vector")] VSimResult { with_scores: bool }, @@ -1039,6 +1042,30 @@ async fn dispatch_command( ) } #[cfg(feature = "vector")] + Command::VAddBatch { + key, + entries, + dim, + metric, + quantization, + connectivity, + expansion_add, + } => { + dispatch!( + key, + ShardRequest::VAddBatch { + key, + entries, + dim, + metric, + quantization, + connectivity, + expansion_add + }, + ResponseTag::VAddBatchResult + ) + } + #[cfg(feature = "vector")] Command::VSim { key, query, @@ -1448,6 +1475,16 @@ fn resolve_shard_response(resp: ShardResponse, tag: ResponseTag) -> Frame { other => Frame::Error(format!("ERR unexpected shard response: {other:?}")), }, #[cfg(feature = "vector")] + ResponseTag::VAddBatchResult => match resp { + ShardResponse::VAddBatchResult { added_count, .. } => { + Frame::Integer(added_count as i64) + } + ShardResponse::WrongType => wrongtype_error(), + ShardResponse::OutOfMemory => oom_error(), + ShardResponse::Err(msg) => Frame::Error(format!("ERR {msg}")), + other => Frame::Error(format!("ERR unexpected shard response: {other:?}")), + }, + #[cfg(feature = "vector")] ResponseTag::VSimResult { with_scores } => match resp { ShardResponse::VSimResult(results) => { let mut frames = Vec::new(); @@ -1605,6 +1642,7 @@ async fn cluster_slot_check(ctx: &ServerContext, cmd: &Command) -> Option | Command::ProtoSetField { ref key, .. } | Command::ProtoDelField { ref key, .. } | Command::VAdd { ref key, .. } + | Command::VAddBatch { ref key, .. } | Command::VSim { ref key, .. } | Command::VRem { ref key, .. } | Command::VGet { ref key, .. } @@ -2689,6 +2727,38 @@ async fn execute( } } + #[cfg(feature = "vector")] + Command::VAddBatch { + key, + entries, + dim, + metric, + quantization, + connectivity, + expansion_add, + } => { + let idx = engine.shard_for_key(&key); + let req = ShardRequest::VAddBatch { + key, + entries, + dim, + metric, + quantization, + connectivity, + expansion_add, + }; + match engine.send_to_shard(idx, req).await { + Ok(ShardResponse::VAddBatchResult { added_count, .. }) => { + Frame::Integer(added_count as i64) + } + Ok(ShardResponse::WrongType) => wrongtype_error(), + Ok(ShardResponse::OutOfMemory) => oom_error(), + Ok(ShardResponse::Err(msg)) => Frame::Error(format!("ERR {msg}")), + Ok(other) => Frame::Error(format!("ERR unexpected shard response: {other:?}")), + Err(e) => Frame::Error(format!("ERR {e}")), + } + } + #[cfg(feature = "vector")] Command::VSim { key, @@ -2797,6 +2867,7 @@ async fn execute( #[cfg(not(feature = "vector"))] Command::VAdd { .. } + | Command::VAddBatch { .. } | Command::VSim { .. } | Command::VRem { .. } | Command::VGet { .. } diff --git a/crates/ember-server/src/grpc.rs b/crates/ember-server/src/grpc.rs index 45772319..cb24cd1a 100644 --- a/crates/ember-server/src/grpc.rs +++ b/crates/ember-server/src/grpc.rs @@ -1387,6 +1387,110 @@ impl EmberCache for EmberService { } } + async fn v_add_batch( + &self, + request: Request, + ) -> Result, Status> { + #[cfg(not(feature = "vector"))] + { + let _ = request; + return Err(Status::unimplemented( + "vector commands require the 'vector' feature", + )); + } + + #[cfg(feature = "vector")] + { + let start = Instant::now(); + let req = request.into_inner(); + validate_key(&req.key)?; + + if req.entries.is_empty() { + return Ok(Response::new(IntResponse { value: 0 })); + } + if req.entries.len() > 10_000 { + return Err(Status::invalid_argument(format!( + "batch size {} exceeds max 10000", + req.entries.len() + ))); + } + + // validate all vectors have same dimensionality + let dim = req.entries[0].vector.len(); + if dim == 0 || dim > MAX_VECTOR_DIMS { + return Err(Status::invalid_argument(format!( + "vector dimensions {dim} out of range (1..{MAX_VECTOR_DIMS})" + ))); + } + for entry in &req.entries { + if entry.vector.len() != dim { + return Err(Status::invalid_argument(format!( + "dimension mismatch: expected {dim}, element '{}' has {}", + entry.element, + entry.vector.len() + ))); + } + } + + if let Some(m) = req.connectivity { + if m > MAX_HNSW_M { + return Err(Status::invalid_argument(format!( + "connectivity {m} exceeds max {MAX_HNSW_M}" + ))); + } + } + if let Some(ef) = req.ef_construction { + if ef > MAX_HNSW_EF { + return Err(Status::invalid_argument(format!( + "ef_construction {ef} exceeds max {MAX_HNSW_EF}" + ))); + } + } + + let metric = match req.metric() { + VectorMetric::Cosine => 0, + VectorMetric::Euclidean => 1, + VectorMetric::InnerProduct => 2, + }; + let quantization = match req.quantization() { + VectorQuantization::None => 0, + VectorQuantization::F16 => 1, + VectorQuantization::I8 => 2, + }; + + let entries: Vec<(String, Vec)> = req + .entries + .into_iter() + .map(|e| (e.element, e.vector)) + .collect(); + + let resp = self + .route( + &req.key, + ShardRequest::VAddBatch { + key: req.key.clone(), + entries, + dim, + metric, + quantization, + connectivity: req.connectivity.unwrap_or(16), + expansion_add: req.ef_construction.unwrap_or(64), + }, + ) + .await?; + self.record_command(start, "VADD_BATCH"); + + match resp { + ShardResponse::VAddBatchResult { added_count, .. } => { + Ok(Response::new(IntResponse { + value: added_count as i64, + })) + } + other => Err(unexpected_response(&other)), + } + } + } + async fn v_sim(&self, request: Request) -> Result, Status> { #[cfg(not(feature = "vector"))] { @@ -2063,6 +2167,7 @@ async fn handle_pipeline_command( // vector commands Vadd => v_add => BoolVal, + VaddBatch => v_add_batch => IntVal, Vsim => v_sim => Vsim, Vrem => v_rem => BoolVal, Vget => v_get => Vget, diff --git a/proto/ember/v1/ember.proto b/proto/ember/v1/ember.proto index e63e7c84..35981d98 100644 --- a/proto/ember/v1/ember.proto +++ b/proto/ember/v1/ember.proto @@ -77,6 +77,7 @@ service EmberCache { // only available when the server is built with the vector feature. rpc VAdd(VAddRequest) returns (BoolResponse); + rpc VAddBatch(VAddBatchRequest) returns (IntResponse); rpc VSim(VSimRequest) returns (VSimResponse); rpc VRem(VRemRequest) returns (BoolResponse); rpc VGet(VGetRequest) returns (VGetResponse); @@ -505,6 +506,20 @@ message VAddRequest { optional uint32 ef_construction = 7; } +message VAddBatchEntry { + string element = 1; + repeated float vector = 2 [packed = true]; +} + +message VAddBatchRequest { + string key = 1; + repeated VAddBatchEntry entries = 2; + VectorMetric metric = 3; + VectorQuantization quantization = 4; + optional uint32 connectivity = 5; + optional uint32 ef_construction = 6; +} + message VSimRequest { string key = 1; repeated float query = 2 [packed = true]; @@ -741,6 +756,7 @@ message PipelineRequest { PubSubChannelsRequest pubsub_channels = 69; PubSubNumSubRequest pubsub_numsub = 70; PubSubNumPatRequest pubsub_numpat = 71; + VAddBatchRequest vadd_batch = 72; } }