You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2022/01/26 01:25:51 UTC

[skywalking-banyandb] branch main updated: Check schema equality while updating (#71)

This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git


The following commit(s) were added to refs/heads/main by this push:
     new dfa4121  Check schema equality while updating (#71)
dfa4121 is described below

commit dfa4121234e75c74214eb6b4d29a7f8d5fdd98a9
Author: Jiajing LU <lu...@gmail.com>
AuthorDate: Wed Jan 26 09:21:52 2022 +0800

    Check schema equality while updating (#71)
    
    * support entity check
---
 api/proto/banyandb/common/v1/common.pb.go    |   2 +-
 api/proto/banyandb/common/v1/common.proto    |   2 +-
 api/proto/banyandb/database/v1/schema.pb.go  | 396 +++++++++++++--------------
 api/proto/banyandb/database/v1/schema.proto  |  20 +-
 banyand/metadata/metadata.go                 |  13 +
 banyand/metadata/schema/checker.go           |  65 +++++
 banyand/metadata/schema/checker_test.go      | 209 ++++++++++++++
 banyand/metadata/schema/etcd.go              |  46 +++-
 banyand/metadata/schema/etcd_test.go         |  40 ++-
 banyand/metadata/schema/schema.go            |  51 +++-
 banyand/metadata/schema/schema_suite_test.go |  30 ++
 banyand/metadata/schema/testdata/stream.json |   2 +-
 banyand/query/processor.go                   |   6 +-
 go.mod                                       |   3 +-
 go.sum                                       |   4 +-
 pkg/test/measure/testdata/measure.json       |   2 +-
 pkg/test/stream/testdata/stream.json         |   2 +-
 17 files changed, 662 insertions(+), 231 deletions(-)

diff --git a/api/proto/banyandb/common/v1/common.pb.go b/api/proto/banyandb/common/v1/common.pb.go
index bed7c73..0f8ac5d 100644
--- a/api/proto/banyandb/common/v1/common.pb.go
+++ b/api/proto/banyandb/common/v1/common.pb.go
@@ -180,7 +180,7 @@ type Group struct {
 
 	// name of the group
 	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	// updated_at_nanoseconds indicates when resources of the group are updated
+	// updated_at indicates when resources of the group are updated
 	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
diff --git a/api/proto/banyandb/common/v1/common.proto b/api/proto/banyandb/common/v1/common.proto
index d09e264..5a8ced0 100644
--- a/api/proto/banyandb/common/v1/common.proto
+++ b/api/proto/banyandb/common/v1/common.proto
@@ -47,6 +47,6 @@ message Metadata {
 message Group {
     // name of the group
     string name = 1;
-    // updated_at_nanoseconds indicates when resources of the group are updated
+    // updated_at indicates when resources of the group are updated
     google.protobuf.Timestamp updated_at = 2;
 }
diff --git a/api/proto/banyandb/database/v1/schema.pb.go b/api/proto/banyandb/database/v1/schema.pb.go
index 5f69192..588796e 100644
--- a/api/proto/banyandb/database/v1/schema.pb.go
+++ b/api/proto/banyandb/database/v1/schema.pb.go
@@ -578,8 +578,8 @@ type Stream struct {
 	// entity indicates how to generate a series and shard a stream
 	Entity *Entity       `protobuf:"bytes,3,opt,name=entity,proto3" json:"entity,omitempty"`
 	Opts   *ResourceOpts `protobuf:"bytes,4,opt,name=opts,proto3" json:"opts,omitempty"`
-	// updated_at_nanoseconds indicates when the stream is updated
-	UpdatedAtNanoseconds *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=updated_at_nanoseconds,json=updatedAtNanoseconds,proto3" json:"updated_at_nanoseconds,omitempty"`
+	// updated_at indicates when the stream is updated
+	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
 func (x *Stream) Reset() {
@@ -642,9 +642,9 @@ func (x *Stream) GetOpts() *ResourceOpts {
 	return nil
 }
 
-func (x *Stream) GetUpdatedAtNanoseconds() *timestamppb.Timestamp {
+func (x *Stream) GetUpdatedAt() *timestamppb.Timestamp {
 	if x != nil {
-		return x.UpdatedAtNanoseconds
+		return x.UpdatedAt
 	}
 	return nil
 }
@@ -948,8 +948,8 @@ type Measure struct {
 	IntervalRules []*IntervalRule `protobuf:"bytes,5,rep,name=interval_rules,json=intervalRules,proto3" json:"interval_rules,omitempty"`
 	// opts is basic resource management options
 	Opts *ResourceOpts `protobuf:"bytes,6,opt,name=opts,proto3" json:"opts,omitempty"`
-	// updated_at_nanoseconds indicates when the measure is updated
-	UpdatedAtNanoseconds *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at_nanoseconds,json=updatedAtNanoseconds,proto3" json:"updated_at_nanoseconds,omitempty"`
+	// updated_at indicates when the measure is updated
+	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
 func (x *Measure) Reset() {
@@ -1026,9 +1026,9 @@ func (x *Measure) GetOpts() *ResourceOpts {
 	return nil
 }
 
-func (x *Measure) GetUpdatedAtNanoseconds() *timestamppb.Timestamp {
+func (x *Measure) GetUpdatedAt() *timestamppb.Timestamp {
 	if x != nil {
-		return x.UpdatedAtNanoseconds
+		return x.UpdatedAt
 	}
 	return nil
 }
@@ -1058,8 +1058,8 @@ type TopNAggregation struct {
 	CountersNumber int32 `protobuf:"varint,7,opt,name=counters_number,json=countersNumber,proto3" json:"counters_number,omitempty"`
 	// opts is basic resource management options
 	Opts *ResourceOpts `protobuf:"bytes,8,opt,name=opts,proto3" json:"opts,omitempty"`
-	// updated_at_nanoseconds indicates when the measure is updated
-	UpdatedAtNanoseconds *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=updated_at_nanoseconds,json=updatedAtNanoseconds,proto3" json:"updated_at_nanoseconds,omitempty"`
+	// updated_at indicates when the measure is updated
+	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
 func (x *TopNAggregation) Reset() {
@@ -1150,9 +1150,9 @@ func (x *TopNAggregation) GetOpts() *ResourceOpts {
 	return nil
 }
 
-func (x *TopNAggregation) GetUpdatedAtNanoseconds() *timestamppb.Timestamp {
+func (x *TopNAggregation) GetUpdatedAt() *timestamppb.Timestamp {
 	if x != nil {
-		return x.UpdatedAtNanoseconds
+		return x.UpdatedAt
 	}
 	return nil
 }
@@ -1174,7 +1174,7 @@ type IndexRule struct {
 	Type IndexRule_Type `protobuf:"varint,3,opt,name=type,proto3,enum=banyandb.database.v1.IndexRule_Type" json:"type,omitempty"`
 	// location indicates where to store index.
 	Location IndexRule_Location `protobuf:"varint,4,opt,name=location,proto3,enum=banyandb.database.v1.IndexRule_Location" json:"location,omitempty"`
-	// updated_at_nanoseconds indicates when the IndexRule is updated
+	// updated_at indicates when the IndexRule is updated
 	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
@@ -1322,7 +1322,7 @@ type IndexRuleBinding struct {
 	// expire_at_nanoseconds it the timestamp, after which the binding will be inactive
 	// expire_at_nanoseconds must be larger than begin_at_nanoseconds
 	ExpireAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=expire_at,json=expireAt,proto3" json:"expire_at,omitempty"`
-	// updated_at_nanoseconds indicates when the IndexRuleBinding is updated
+	// updated_at indicates when the IndexRuleBinding is updated
 	UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
 }
 
@@ -1438,7 +1438,7 @@ var file_banyandb_database_v1_schema_proto_rawDesc = []byte{
 	0x65, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
 	0x1d, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
 	0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
-	0x74, 0x79, 0x70, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12,
+	0x74, 0x79, 0x70, 0x65, 0x22, 0xb3, 0x02, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12,
 	0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
 	0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
@@ -1454,193 +1454,189 @@ var file_banyandb_database_v1_schema_proto_rawDesc = []byte{
 	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
 	0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73,
 	0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12,
-	0x50, 0x0a, 0x16, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6e, 0x61,
-	0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-	0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x75, 0x70, 0x64,
-	0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
-	0x73, 0x22, 0x25, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74,
-	0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08,
-	0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x68, 0x61, 0x72,
-	0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x68, 0x61,
-	0x72, 0x64, 0x4e, 0x75, 0x6d, 0x12, 0x30, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61,
-	0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x22, 0x86, 0x02, 0x0a, 0x09, 0x46, 0x69, 0x65, 0x6c,
-	0x64, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x66, 0x69, 0x65,
-	0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e,
+	0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
+	0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x25, 0x0a, 0x06, 0x45, 0x6e,
+	0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65,
+	0x73, 0x22, 0x5d, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x74,
+	0x73, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x4e, 0x75, 0x6d, 0x12, 0x30,
+	0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x61,
+	0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e,
+	0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c,
+	0x22, 0x86, 0x02, 0x0a, 0x09, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
+	0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69,
+	0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79,
+	0x70, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6d,
+	0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61,
+	0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e,
+	0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+	0x64, 0x52, 0x0e, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+	0x64, 0x12, 0x56, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+	0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e,
 	0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73,
-	0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09,
-	0x66, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x65, 0x6e, 0x63,
-	0x6f, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61,
-	0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69,
-	0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0e, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69,
-	0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x56, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70,
-	0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
-	0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
-	0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x11, 0x63,
-	0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64,
-	0x22, 0x7a, 0x0a, 0x0c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65,
-	0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x73,
-	0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12,
-	0x12, 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x03,
-	0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42,
-	0x0b, 0x0a, 0x09, 0x74, 0x61, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcf, 0x03, 0x0a,
-	0x07, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e,
-	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e,
-	0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
-	0x74, 0x61, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x61, 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69,
-	0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61,
-	0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e,
-	0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0b, 0x74,
-	0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x66, 0x69,
-	0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x61, 0x6e,
+	0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+	0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
+	0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x7a, 0x0a, 0x0c, 0x49, 0x6e, 0x74,
+	0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, 0x67,
+	0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x67,
+	0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x48, 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x12, 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x03, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x61, 0x67, 0x5f,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb8, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72,
+	0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+	0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x0c, 0x74,
+	0x61, 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74,
+	0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69,
+	0x6c, 0x79, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0b, 0x74, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c,
+	0x69, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64,
+	0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64,
+	0x53, 0x70, 0x65, 0x63, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x06,
+	0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62,
+	0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65,
+	0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69,
+	0x74, 0x79, 0x12, 0x49, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x72,
+	0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e,
 	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76,
-	0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x70, 0x65, 0x63, 0x52, 0x06, 0x66, 0x69, 0x65,
-	0x6c, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64,
-	0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74,
-	0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x0e, 0x69, 0x6e, 0x74,
-	0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74,
-	0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
-	0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52,
-	0x75, 0x6c, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01,
+	0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x36, 0x0a,
+	0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61,
+	0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e,
+	0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x73, 0x52,
+	0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
+	0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
+	0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
+	0x22, 0xf4, 0x03, 0x0a, 0x0f, 0x54, 0x6f, 0x70, 0x4e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
+	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61,
+	0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43,
+	0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
+	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61,
+	0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x61, 0x73,
+	0x75, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61,
+	0x6d, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62,
+	0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x31,
+	0x2e, 0x53, 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75,
+	0x65, 0x53, 0x6f, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x62,
+	0x79, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
+	0x09, 0x52, 0x0f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x79, 0x54, 0x61, 0x67, 0x4e, 0x61, 0x6d,
+	0x65, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x18, 0x06,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
+	0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69,
+	0x61, 0x52, 0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x27, 0x0a, 0x0f, 0x63,
+	0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x4e, 0x75,
+	0x6d, 0x62, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01,
 	0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61,
 	0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
-	0x63, 0x65, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x16,
-	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73,
-	0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
-	0x64, 0x41, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x8b,
-	0x04, 0x0a, 0x0f, 0x54, 0x6f, 0x70, 0x4e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
-	0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0e,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
-	0x74, 0x61, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72,
-	0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65,
-	0x12, 0x41, 0x0a, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f,
-	0x73, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62, 0x61, 0x6e,
-	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53,
-	0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53,
-	0x6f, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x62, 0x79, 0x5f,
-	0x74, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x0f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x79, 0x54, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x73,
-	0x12, 0x37, 0x0a, 0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x18, 0x06, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f,
-	0x64, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x52,
-	0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x75,
-	0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01,
-	0x28, 0x05, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x4e, 0x75, 0x6d, 0x62,
-	0x65, 0x72, 0x12, 0x36, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61,
-	0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x16, 0x75, 0x70,
-	0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63,
-	0x6f, 0x6e, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
-	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41,
-	0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0xa4, 0x03, 0x0a,
-	0x09, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65,
-	0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62,
-	0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76,
-	0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03,
-	0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
-	0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e,
-	0x64, 0x65, 0x78, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79,
-	0x70, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
-	0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65,
-	0x78, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61,
-	0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
+	0x63, 0x65, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0a,
+	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70,
+	0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xa4, 0x03, 0x0a, 0x09, 0x49, 0x6e, 0x64, 0x65,
+	0x78, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+	0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
+	0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74,
+	0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
+	0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74,
+	0x61, 0x67, 0x73, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74,
+	0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75,
+	0x6c, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x44, 0x0a,
+	0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x28, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
+	0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75, 0x6c, 0x65,
+	0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
+	0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x3e,
+	0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55,
+	0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09,
+	0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x54,
+	0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x4e,
+	0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f,
+	0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+	0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e,
+	0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x43,
+	0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x02, 0x22, 0x54,
+	0x0a, 0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x07, 0x63, 0x61, 0x74,
+	0x61, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e,
+	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e,
+	0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67,
+	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x22, 0xc6, 0x02, 0x0a, 0x10, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75,
+	0x6c, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74,
+	0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61,
+	0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
+	0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
+	0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
+	0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x62,
+	0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x6e,
+	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76,
+	0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65,
+	0x63, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x52, 0x07, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x78, 0x70,
+	0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
 	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
-	0x64, 0x41, 0x74, 0x22, 0x3e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54,
-	0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-	0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x01,
-	0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x45, 0x52, 0x54, 0x45,
-	0x44, 0x10, 0x02, 0x22, 0x4e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
-	0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50,
-	0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x43,
-	0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x10, 0x01, 0x12, 0x13,
-	0x0a, 0x0f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41,
-	0x4c, 0x10, 0x02, 0x22, 0x54, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x35,
-	0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
-	0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61,
-	0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xc6, 0x02, 0x0a, 0x10, 0x49, 0x6e,
-	0x64, 0x65, 0x78, 0x52, 0x75, 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x38,
-	0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08,
-	0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65,
-	0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x37,
-	0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x1d, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
-	0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07,
-	0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x62, 0x65, 0x67, 0x69, 0x6e,
-	0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x12, 0x37,
-	0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65,
-	0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74,
-	0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
-	0x41, 0x74, 0x2a, 0x97, 0x01, 0x0a, 0x07, 0x54, 0x61, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18,
-	0x0a, 0x14, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x41, 0x47, 0x5f,
-	0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a,
-	0x0c, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12,
-	0x19, 0x0a, 0x15, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49,
-	0x4e, 0x47, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41,
-	0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59,
-	0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44,
-	0x41, 0x54, 0x41, 0x5f, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x05, 0x2a, 0x6e, 0x0a, 0x09,
-	0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x45,
-	0x4c, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54,
-	0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e,
-	0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x02,
-	0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44,
-	0x41, 0x54, 0x41, 0x5f, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x03, 0x2a, 0x4e, 0x0a, 0x0e,
-	0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f,
-	0x0a, 0x1b, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f,
-	0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
-	0x1b, 0x0a, 0x17, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x45, 0x54, 0x48,
-	0x4f, 0x44, 0x5f, 0x47, 0x4f, 0x52, 0x49, 0x4c, 0x4c, 0x41, 0x10, 0x01, 0x2a, 0x54, 0x0a, 0x11,
-	0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f,
-	0x64, 0x12, 0x22, 0x0a, 0x1e, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e,
-	0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53,
-	0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x5a, 0x53, 0x54, 0x44,
-	0x10, 0x01, 0x42, 0x72, 0x0a, 0x2a, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65,
-	0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x62, 0x61, 0x6e, 0x79,
-	0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31,
-	0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61,
-	0x63, 0x68, 0x65, 0x2f, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2d, 0x62,
-	0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2f, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62,
-	0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
+	0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+	0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x2a, 0x97, 0x01,
+	0x0a, 0x07, 0x54, 0x61, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 0x47,
+	0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+	0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
+	0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x5f,
+	0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x41,
+	0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x41, 0x52,
+	0x52, 0x41, 0x59, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50,
+	0x45, 0x5f, 0x49, 0x4e, 0x54, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x04, 0x12, 0x18, 0x0a,
+	0x14, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42,
+	0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x05, 0x2a, 0x6e, 0x0a, 0x09, 0x46, 0x69, 0x65, 0x6c, 0x64,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x59,
+	0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+	0x12, 0x15, 0x0a, 0x11, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
+	0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x46, 0x49, 0x45, 0x4c, 0x44,
+	0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x46,
+	0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x42,
+	0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x03, 0x2a, 0x4e, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x6f, 0x64,
+	0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x4e, 0x43,
+	0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53,
+	0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x4e,
+	0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x47, 0x4f,
+	0x52, 0x49, 0x4c, 0x4c, 0x41, 0x10, 0x01, 0x2a, 0x54, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x72,
+	0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x22, 0x0a, 0x1e,
+	0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48,
+	0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+	0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f,
+	0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x5a, 0x53, 0x54, 0x44, 0x10, 0x01, 0x42, 0x72, 0x0a,
+	0x2a, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x6b, 0x79, 0x77,
+	0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
+	0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x5a, 0x44, 0x67, 0x69, 0x74,
+	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x73,
+	0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
+	0x64, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x61, 0x6e,
+	0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76,
+	0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1692,7 +1688,7 @@ var file_banyandb_database_v1_schema_proto_depIdxs = []int32{
 	8,  // 4: banyandb.database.v1.Stream.tag_families:type_name -> banyandb.database.v1.TagFamilySpec
 	11, // 5: banyandb.database.v1.Stream.entity:type_name -> banyandb.database.v1.Entity
 	12, // 6: banyandb.database.v1.Stream.opts:type_name -> banyandb.database.v1.ResourceOpts
-	21, // 7: banyandb.database.v1.Stream.updated_at_nanoseconds:type_name -> google.protobuf.Timestamp
+	21, // 7: banyandb.database.v1.Stream.updated_at:type_name -> google.protobuf.Timestamp
 	7,  // 8: banyandb.database.v1.ResourceOpts.ttl:type_name -> banyandb.database.v1.Duration
 	1,  // 9: banyandb.database.v1.FieldSpec.field_type:type_name -> banyandb.database.v1.FieldType
 	2,  // 10: banyandb.database.v1.FieldSpec.encoding_method:type_name -> banyandb.database.v1.EncodingMethod
@@ -1703,13 +1699,13 @@ var file_banyandb_database_v1_schema_proto_depIdxs = []int32{
 	11, // 15: banyandb.database.v1.Measure.entity:type_name -> banyandb.database.v1.Entity
 	14, // 16: banyandb.database.v1.Measure.interval_rules:type_name -> banyandb.database.v1.IntervalRule
 	12, // 17: banyandb.database.v1.Measure.opts:type_name -> banyandb.database.v1.ResourceOpts
-	21, // 18: banyandb.database.v1.Measure.updated_at_nanoseconds:type_name -> google.protobuf.Timestamp
+	21, // 18: banyandb.database.v1.Measure.updated_at:type_name -> google.protobuf.Timestamp
 	20, // 19: banyandb.database.v1.TopNAggregation.metadata:type_name -> banyandb.common.v1.Metadata
 	20, // 20: banyandb.database.v1.TopNAggregation.source_measure:type_name -> banyandb.common.v1.Metadata
 	22, // 21: banyandb.database.v1.TopNAggregation.field_value_sort:type_name -> banyandb.model.v1.Sort
 	23, // 22: banyandb.database.v1.TopNAggregation.criteria:type_name -> banyandb.model.v1.Criteria
 	12, // 23: banyandb.database.v1.TopNAggregation.opts:type_name -> banyandb.database.v1.ResourceOpts
-	21, // 24: banyandb.database.v1.TopNAggregation.updated_at_nanoseconds:type_name -> google.protobuf.Timestamp
+	21, // 24: banyandb.database.v1.TopNAggregation.updated_at:type_name -> google.protobuf.Timestamp
 	20, // 25: banyandb.database.v1.IndexRule.metadata:type_name -> banyandb.common.v1.Metadata
 	5,  // 26: banyandb.database.v1.IndexRule.type:type_name -> banyandb.database.v1.IndexRule.Type
 	6,  // 27: banyandb.database.v1.IndexRule.location:type_name -> banyandb.database.v1.IndexRule.Location
diff --git a/api/proto/banyandb/database/v1/schema.proto b/api/proto/banyandb/database/v1/schema.proto
index 624766c..e759ed3 100644
--- a/api/proto/banyandb/database/v1/schema.proto
+++ b/api/proto/banyandb/database/v1/schema.proto
@@ -51,7 +51,7 @@ enum TagType {
 message TagFamilySpec {
     string name = 1;
     // tags defines accepted tags
-    repeated TagSpec tags = 2; 
+    repeated TagSpec tags = 2;
 }
 
 message TagSpec {
@@ -63,13 +63,13 @@ message TagSpec {
 message Stream {
     // metadata is the identity of a trace series
     common.v1.Metadata metadata = 1;
-    // tag_families 
+    // tag_families
     repeated TagFamilySpec tag_families = 2;
     // entity indicates how to generate a series and shard a stream
     Entity entity = 3;
     ResourceOpts opts = 4;
-    // updated_at_nanoseconds indicates when the stream is updated
-    google.protobuf.Timestamp updated_at_nanoseconds = 5;
+    // updated_at indicates when the stream is updated
+    google.protobuf.Timestamp updated_at = 5;
 }
 
 message Entity {
@@ -139,8 +139,8 @@ message Measure {
     repeated IntervalRule interval_rules = 5;
     // opts is basic resource management options
     ResourceOpts opts = 6;
-    // updated_at_nanoseconds indicates when the measure is updated
-    google.protobuf.Timestamp updated_at_nanoseconds = 7;
+    // updated_at indicates when the measure is updated
+    google.protobuf.Timestamp updated_at = 7;
 }
 
 // TopNAggregation generates offline TopN statistics for a measure's TopN approximation
@@ -164,8 +164,8 @@ message TopNAggregation {
     int32 counters_number = 7;
     // opts is basic resource management options
     ResourceOpts opts = 8;
-    // updated_at_nanoseconds indicates when the measure is updated
-    google.protobuf.Timestamp updated_at_nanoseconds = 9;
+    // updated_at indicates when the measure is updated
+    google.protobuf.Timestamp updated_at = 9;
 }
 
 // IndexRule defines how to generate indices based on tags and the index type
@@ -192,7 +192,7 @@ message IndexRule {
     }
     // location indicates where to store index.
     Location location = 4;
-    // updated_at_nanoseconds indicates when the IndexRule is updated
+    // updated_at indicates when the IndexRule is updated
     google.protobuf.Timestamp updated_at = 5;
 }
 
@@ -219,6 +219,6 @@ message IndexRuleBinding {
     // expire_at_nanoseconds it the timestamp, after which the binding will be inactive
     // expire_at_nanoseconds must be larger than begin_at_nanoseconds
     google.protobuf.Timestamp expire_at = 5;
-    // updated_at_nanoseconds indicates when the IndexRuleBinding is updated
+    // updated_at indicates when the IndexRuleBinding is updated
     google.protobuf.Timestamp updated_at = 6;
 }
diff --git a/banyand/metadata/metadata.go b/banyand/metadata/metadata.go
index a85faf5..40ae923 100644
--- a/banyand/metadata/metadata.go
+++ b/banyand/metadata/metadata.go
@@ -185,6 +185,10 @@ func (s *service) Subjects(ctx context.Context, indexRule *databasev1.IndexRule,
 			continue
 		}
 
+		if !contains(binding.GetRules(), indexRule.GetMetadata().GetName()) {
+			continue
+		}
+
 		switch catalog {
 		case commonv1.Catalog_CATALOG_STREAM:
 			stream, getErr := s.schemaRegistry.GetStream(context.TODO(), &commonv1.Metadata{
@@ -209,3 +213,12 @@ func (s *service) Subjects(ctx context.Context, indexRule *databasev1.IndexRule,
 
 	return foundSubjects, subjectErr
 }
+
+func contains(s []string, e string) bool {
+	for _, a := range s {
+		if a == e {
+			return true
+		}
+	}
+	return false
+}
diff --git a/banyand/metadata/schema/checker.go b/banyand/metadata/schema/checker.go
new file mode 100644
index 0000000..2298e6f
--- /dev/null
+++ b/banyand/metadata/schema/checker.go
@@ -0,0 +1,65 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package schema
+
+import (
+	"github.com/google/go-cmp/cmp"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/testing/protocmp"
+
+	commonv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1"
+	databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
+)
+
+type equalityChecker func(a, b proto.Message) bool
+
+var (
+	checkerMap = map[Kind]equalityChecker{
+		KindIndexRuleBinding: func(a, b proto.Message) bool {
+			return cmp.Equal(a, b,
+				protocmp.IgnoreUnknown(),
+				protocmp.IgnoreFields(&databasev1.IndexRuleBinding{}, "updated_at"),
+				protocmp.IgnoreFields(&commonv1.Metadata{}, "id", "create_revision", "mod_revision"),
+				protocmp.Transform(),
+			)
+		},
+		KindIndexRule: func(a, b proto.Message) bool {
+			return cmp.Equal(a, b,
+				protocmp.IgnoreUnknown(),
+				protocmp.IgnoreFields(&databasev1.IndexRule{}, "updated_at"),
+				protocmp.IgnoreFields(&commonv1.Metadata{}, "id", "create_revision", "mod_revision"),
+				protocmp.Transform(),
+			)
+		},
+		KindMeasure: func(a, b proto.Message) bool {
+			return cmp.Equal(a, b,
+				protocmp.IgnoreUnknown(),
+				protocmp.IgnoreFields(&databasev1.Measure{}, "updated_at"),
+				protocmp.IgnoreFields(&commonv1.Metadata{}, "id", "create_revision", "mod_revision"),
+				protocmp.Transform(),
+			)
+		},
+		KindStream: func(a, b proto.Message) bool {
+			return cmp.Equal(a, b,
+				protocmp.IgnoreUnknown(),
+				protocmp.IgnoreFields(&databasev1.Stream{}, "updated_at"),
+				protocmp.IgnoreFields(&commonv1.Metadata{}, "id", "create_revision", "mod_revision"),
+				protocmp.Transform())
+		},
+	}
+)
diff --git a/banyand/metadata/schema/checker_test.go b/banyand/metadata/schema/checker_test.go
new file mode 100644
index 0000000..cebb64f
--- /dev/null
+++ b/banyand/metadata/schema/checker_test.go
@@ -0,0 +1,209 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package schema
+
+import (
+	"time"
+
+	"github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"google.golang.org/protobuf/encoding/protojson"
+	"google.golang.org/protobuf/types/known/timestamppb"
+
+	databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
+)
+
+func loadStream() *databasev1.Stream {
+	s := &databasev1.Stream{}
+	// preload stream
+	Expect(protojson.Unmarshal([]byte(streamJSON), s)).To(Succeed())
+	return s
+}
+
+func loadIndexRuleBinding() *databasev1.IndexRuleBinding {
+	irb := &databasev1.IndexRuleBinding{}
+	// preload index rule binding
+	Expect(protojson.Unmarshal([]byte(indexRuleBindingJSON), irb)).To(Succeed())
+	return irb
+}
+
+func loadIndexRule() *databasev1.IndexRule {
+	ir := &databasev1.IndexRule{}
+	data, err := indexRuleStore.ReadFile(indexRuleDir + "/db.instance.json")
+	Expect(err).NotTo(HaveOccurred())
+	Expect(protojson.Unmarshal(data, ir)).To(Succeed())
+	return ir
+}
+
+var _ = ginkgo.Describe("Utils", func() {
+	ginkgo.Context("Check equality for Stream", func() {
+		var s *databasev1.Stream
+		var checker equalityChecker
+
+		ginkgo.BeforeEach(func() {
+			s = loadStream()
+			checker = checkerMap[KindStream]
+		})
+
+		ginkgo.It("should be equal if nothing changed", func() {
+			Expect(checker(s, s)).Should(BeTrue())
+		})
+
+		ginkgo.It("should not be equal if metadata.name changed", func() {
+			newS := loadStream()
+			newS.Metadata.Name = "new-name"
+			Expect(checker(s, newS)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if metadata.group changed", func() {
+			newS := loadStream()
+			newS.GetMetadata().Group = "new-group"
+			Expect(checker(s, newS)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if entity changed", func() {
+			newS := loadStream()
+			newS.GetEntity().TagNames = []string{"new-entity-tag"}
+			Expect(checker(s, newS)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if tag name changed", func() {
+			newS := loadStream()
+			newS.GetTagFamilies()[0].Tags[0].Name = "binary-tag"
+			Expect(checker(s, newS)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if tag type changed", func() {
+			newS := loadStream()
+			newS.GetTagFamilies()[0].Tags[0].Type = databasev1.TagType_TAG_TYPE_STRING
+			Expect(checker(s, newS)).Should(BeFalse())
+		})
+
+		ginkgo.It("should be equal if UpdatedAt changed", func() {
+			newS := loadStream()
+			newS.UpdatedAt = timestamppb.Now()
+			Expect(checker(s, newS)).Should(BeTrue())
+		})
+
+		ginkgo.It("should be equal if metadata.mod_revision changed", func() {
+			newS := loadStream()
+			newS.Metadata.ModRevision = 10000
+			Expect(checker(s, newS)).Should(BeTrue())
+		})
+
+		ginkgo.It("should be equal if metadata.create_revision changed", func() {
+			newS := loadStream()
+			newS.Metadata.CreateRevision = 10000
+			Expect(checker(s, newS)).Should(BeTrue())
+		})
+	})
+
+	ginkgo.Context("Check equality for IndexRuleBinding", func() {
+		var irb *databasev1.IndexRuleBinding
+		var checker equalityChecker
+
+		ginkgo.BeforeEach(func() {
+			irb = loadIndexRuleBinding()
+			checker = checkerMap[KindIndexRuleBinding]
+		})
+
+		ginkgo.It("should be equal if nothing changed", func() {
+			Expect(checker(irb, irb)).Should(BeTrue())
+		})
+
+		ginkgo.It("should not be equal if metadata.name changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.Metadata.Name = "new-name"
+			Expect(checker(irb, newIrb)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if metadata.group changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.GetMetadata().Group = "new-group"
+			Expect(checker(irb, newIrb)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if rules changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.Rules = []string{}
+			Expect(checker(irb, newIrb)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if beginAt changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.BeginAt = timestamppb.New(time.Now())
+			Expect(checker(irb, newIrb)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if expireAt changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.ExpireAt = timestamppb.New(time.Now())
+			Expect(checker(irb, newIrb)).Should(BeFalse())
+		})
+
+		ginkgo.It("should be equal if UpdatedAtNanoseconds changed", func() {
+			newIrb := loadIndexRuleBinding()
+			newIrb.UpdatedAt = timestamppb.Now()
+			Expect(checker(irb, newIrb)).Should(BeTrue())
+		})
+	})
+
+	ginkgo.Context("Check equality for IndexRule", func() {
+		var ir *databasev1.IndexRule
+		var checker equalityChecker
+
+		ginkgo.BeforeEach(func() {
+			ir = loadIndexRule()
+			checker = checkerMap[KindIndexRule]
+		})
+
+		ginkgo.It("should be equal if nothing changed", func() {
+			Expect(checker(ir, ir)).Should(BeTrue())
+		})
+
+		ginkgo.It("should not be equal if metadata.name changed", func() {
+			newIr := loadIndexRule()
+			newIr.Metadata.Name = "new-name"
+			Expect(checker(ir, newIr)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if metadata.id changed", func() {
+			newIr := loadIndexRule()
+			newIr.Metadata.Id = 1000
+			Expect(checker(ir, newIr)).Should(BeTrue())
+		})
+
+		ginkgo.It("should not be equal if metadata.group changed", func() {
+			newIr := loadIndexRule()
+			newIr.GetMetadata().Group = "new-group"
+			Expect(checker(ir, newIr)).Should(BeFalse())
+		})
+
+		ginkgo.It("should not be equal if rules changed", func() {
+			newIr := loadIndexRule()
+			newIr.Tags = []string{"new-tag"}
+			Expect(checker(ir, newIr)).Should(BeFalse())
+		})
+
+		ginkgo.It("should be equal if UpdatedAtNanoseconds changed", func() {
+			newIr := loadIndexRule()
+			newIr.UpdatedAt = timestamppb.Now()
+			Expect(checker(ir, newIr)).Should(BeTrue())
+		})
+	})
+})
diff --git a/banyand/metadata/schema/etcd.go b/banyand/metadata/schema/etcd.go
index 8e3685c..7836ca2 100644
--- a/banyand/metadata/schema/etcd.go
+++ b/banyand/metadata/schema/etcd.go
@@ -45,6 +45,7 @@ var (
 
 	ErrEntityNotFound             = errors.New("entity is not found")
 	ErrUnexpectedNumberOfEntities = errors.New("unexpected number of entities")
+	ErrConcurrentModification     = errors.New("concurrent modification of entities")
 
 	unixDomainSockScheme = "unix"
 
@@ -498,14 +499,49 @@ func (e *etcdSchemaRegistry) get(ctx context.Context, key string, message proto.
 }
 
 func (e *etcdSchemaRegistry) update(ctx context.Context, group *commonv1.Group, metadata Metadata) error {
-	val, err := proto.Marshal(metadata.Spec.(proto.Message))
+	key, err := metadata.Key()
 	if err != nil {
 		return err
 	}
-	_, err = e.kv.Put(ctx, metadata.Key(), string(val))
+	getResp, err := e.kv.Get(ctx, key)
+	if err != nil {
+		return err
+	}
+	if getResp.Count > 1 {
+		return ErrUnexpectedNumberOfEntities
+	}
+	val, err := proto.Marshal(metadata.Spec.(proto.Message))
 	if err != nil {
 		return err
 	}
+	replace := getResp.Count > 0
+	if replace {
+		existingVal, innerErr := metadata.Unmarshal(getResp.Kvs[0].Value)
+		if innerErr != nil {
+			return innerErr
+		}
+		// directly return if we have the same entity
+		if metadata.Equal(existingVal) {
+			return nil
+		}
+
+		modRevision := getResp.Kvs[0].ModRevision
+		txnResp, txnErr := e.kv.Txn(context.Background()).
+			If(clientv3.Compare(clientv3.ModRevision(key), "=", modRevision)).
+			Then(clientv3.OpPut(key, string(val))).
+			Commit()
+		if txnErr != nil {
+			return txnErr
+		}
+		if !txnResp.Succeeded {
+			return ErrConcurrentModification
+		}
+	} else {
+		_, err = e.kv.Put(ctx, key, string(val))
+		if err != nil {
+			return err
+		}
+	}
 	e.notifyUpdate(metadata)
 	return e.touchGroup(ctx, group)
 }
@@ -550,7 +586,11 @@ func (e *etcdSchemaRegistry) listPrefixesForEntity(ctx context.Context, opt List
 }
 
 func (e *etcdSchemaRegistry) delete(ctx context.Context, g *commonv1.Group, metadata Metadata) (bool, error) {
-	resp, err := e.kv.Delete(ctx, metadata.Key(), clientv3.WithPrevKV())
+	key, err := metadata.Key()
+	if err != nil {
+		return false, err
+	}
+	resp, err := e.kv.Delete(ctx, key, clientv3.WithPrevKV())
 	if err != nil {
 		return false, err
 	}
diff --git a/banyand/metadata/schema/etcd_test.go b/banyand/metadata/schema/etcd_test.go
index 16a2867..e7f58d1 100644
--- a/banyand/metadata/schema/etcd_test.go
+++ b/banyand/metadata/schema/etcd_test.go
@@ -418,6 +418,24 @@ func Test_Notify(t *testing.T) {
 				return r.UpdateIndexRule(ctx, ir)
 			},
 			validationFunc: func(mocked *mockedEventHandler) bool {
+				return mocked.AssertNumberOfCalls(t, "OnAddOrUpdate", 1) &&
+					mocked.AssertNumberOfCalls(t, "OnDelete", 0)
+			},
+		},
+		{
+			name: "modify indexRule without modification",
+			testFunc: func(ctx context.Context, r Registry) error {
+				ir, err := r.GetIndexRule(ctx, &commonv1.Metadata{
+					Name:  "db.instance",
+					Group: "default",
+				})
+				if err != nil {
+					return err
+				}
+
+				return r.UpdateIndexRule(ctx, ir)
+			},
+			validationFunc: func(mocked *mockedEventHandler) bool {
 				return mocked.AssertNumberOfCalls(t, "OnAddOrUpdate", 0) &&
 					mocked.AssertNumberOfCalls(t, "OnDelete", 0)
 			},
@@ -438,7 +456,7 @@ func Test_Notify(t *testing.T) {
 			},
 			validationFunc: func(mocked *mockedEventHandler) bool {
 				return mocked.AssertNumberOfCalls(t, "OnAddOrUpdate", 0) &&
-					mocked.AssertNumberOfCalls(t, "OnDelete", 0)
+					mocked.AssertNumberOfCalls(t, "OnDelete", 1)
 			},
 		},
 		{
@@ -461,6 +479,24 @@ func Test_Notify(t *testing.T) {
 			},
 		},
 		{
+			name: "update indexRuleBinding without modification",
+			testFunc: func(ctx context.Context, r Registry) error {
+				irb, err := r.GetIndexRuleBinding(ctx, &commonv1.Metadata{
+					Name:  "sw-index-rule-binding",
+					Group: "default",
+				})
+				if err != nil {
+					return err
+				}
+
+				return r.UpdateIndexRuleBinding(ctx, irb)
+			},
+			validationFunc: func(mocked *mockedEventHandler) bool {
+				return mocked.AssertNumberOfCalls(t, "OnAddOrUpdate", 0) &&
+					mocked.AssertNumberOfCalls(t, "OnDelete", 0)
+			},
+		},
+		{
 			name: "delete indexRuleBinding",
 			testFunc: func(ctx context.Context, r Registry) error {
 				_, err := r.DeleteIndexRuleBinding(ctx, &commonv1.Metadata{
@@ -487,7 +523,7 @@ func Test_Notify(t *testing.T) {
 			mockedObj := new(mockedEventHandler)
 			mockedObj.On("OnAddOrUpdate", mock.Anything).Return()
 			mockedObj.On("OnDelete", mock.Anything).Return()
-			registry.RegisterHandler(KindStream|KindIndexRuleBinding, mockedObj)
+			registry.RegisterHandler(KindStream|KindIndexRuleBinding|KindIndexRule, mockedObj)
 
 			err := tt.testFunc(context.TODO(), registry)
 			req.NoError(err)
diff --git a/banyand/metadata/schema/schema.go b/banyand/metadata/schema/schema.go
index ab0f260..093bc65 100644
--- a/banyand/metadata/schema/schema.go
+++ b/banyand/metadata/schema/schema.go
@@ -21,10 +21,17 @@ import (
 	"context"
 	"io"
 
+	"github.com/pkg/errors"
+	"google.golang.org/protobuf/proto"
+
 	commonv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1"
 	databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
 )
 
+var (
+	ErrUnsupportedEntityType = errors.New("unsupported entity type")
+)
+
 type Kind int
 
 type EventHandler interface {
@@ -74,31 +81,63 @@ type Metadata struct {
 type Spec interface {
 }
 
-func (m Metadata) Key() string {
+func (tm TypeMeta) Unmarshal(data []byte) (m proto.Message, err error) {
+	switch tm.Kind {
+	case KindStream:
+		m = &databasev1.Stream{}
+		err = proto.Unmarshal(data, m)
+	case KindMeasure:
+		m = &databasev1.Measure{}
+		err = proto.Unmarshal(data, m)
+	case KindIndexRuleBinding:
+		m = &databasev1.IndexRuleBinding{}
+		err = proto.Unmarshal(data, m)
+	case KindIndexRule:
+		m = &databasev1.IndexRule{}
+		err = proto.Unmarshal(data, m)
+	default:
+		return nil, ErrUnsupportedEntityType
+	}
+	return
+}
+
+func (m Metadata) Key() (string, error) {
 	switch m.Kind {
 	case KindMeasure:
 		return formatMeasureKey(&commonv1.Metadata{
 			Group: m.Group,
 			Name:  m.Name,
-		})
+		}), nil
 	case KindStream:
 		return formatStreamKey(&commonv1.Metadata{
 			Group: m.Group,
 			Name:  m.Name,
-		})
+		}), nil
 	case KindIndexRule:
 		return formatIndexRuleKey(&commonv1.Metadata{
 			Group: m.Group,
 			Name:  m.Name,
-		})
+		}), nil
 	case KindIndexRuleBinding:
 		return formatIndexRuleBindingKey(&commonv1.Metadata{
 			Group: m.Group,
 			Name:  m.Name,
-		})
+		}), nil
 	default:
-		panic("unsupported Kind")
+		return "", ErrUnsupportedEntityType
+	}
+}
+
+func (m Metadata) Equal(other proto.Message) bool {
+	if other == nil {
+		return false
+	}
+
+	if checker, ok := checkerMap[m.Kind]; ok {
+		return checker(m.Spec.(proto.Message), other)
 	}
+
+	return false
 }
 
 type Stream interface {
diff --git a/banyand/metadata/schema/schema_suite_test.go b/banyand/metadata/schema/schema_suite_test.go
new file mode 100644
index 0000000..34372bc
--- /dev/null
+++ b/banyand/metadata/schema/schema_suite_test.go
@@ -0,0 +1,30 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package schema
+
+import (
+	"testing"
+
+	"github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestSchema(t *testing.T) {
+	RegisterFailHandler(ginkgo.Fail)
+	ginkgo.RunSpecs(t, "Schema Suite")
+}
diff --git a/banyand/metadata/schema/testdata/stream.json b/banyand/metadata/schema/testdata/stream.json
index d4f9df9..767cc15 100644
--- a/banyand/metadata/schema/testdata/stream.json
+++ b/banyand/metadata/schema/testdata/stream.json
@@ -89,5 +89,5 @@
       "unit": "DURATION_UNIT_DAY"
     }
   },
-  "updated_at_nanoseconds": "2021-04-15T01:30:15.01Z"
+  "updated_at": "2021-04-15T01:30:15.01Z"
 }
\ No newline at end of file
diff --git a/banyand/query/processor.go b/banyand/query/processor.go
index 507fb5f..ba1d544 100644
--- a/banyand/query/processor.go
+++ b/banyand/query/processor.go
@@ -61,7 +61,9 @@ func (q *queryProcessor) Rev(message bus.Message) (resp bus.Message) {
 	meta := queryCriteria.GetMetadata()
 	ec, err := q.streamService.Stream(meta)
 	if err != nil {
-		q.log.Error().Err(err).Msg("fail to get measure execution context")
+		q.log.Error().Err(err).
+			Str("stream", meta.GetName()).
+			Msg("fail to get execution context for stream")
 		return
 	}
 
@@ -73,7 +75,7 @@ func (q *queryProcessor) Rev(message bus.Message) (resp bus.Message) {
 
 	s, err := analyzer.BuildStreamSchema(context.TODO(), meta)
 	if err != nil {
-		q.log.Error().Err(err).Msg("fail to build trace schema")
+		q.log.Error().Err(err).Msg("fail to build stream schema")
 		return
 	}
 
diff --git a/go.mod b/go.mod
index b307f42..22513ff 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/dgraph-io/ristretto v0.1.0
 	github.com/golang/mock v1.5.0
 	github.com/golang/protobuf v1.5.2
-	github.com/google/go-cmp v0.5.6
+	github.com/google/go-cmp v0.5.7
 	github.com/google/uuid v1.3.0
 	github.com/klauspost/compress v1.13.1
 	github.com/oklog/run v1.1.0
@@ -98,6 +98,7 @@ require (
 	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
 	golang.org/x/text v0.3.6 // indirect
 	golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 	gopkg.in/ini.v1 v1.62.0 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index b409e5e..d0e069f 100644
--- a/go.sum
+++ b/go.sum
@@ -207,8 +207,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
diff --git a/pkg/test/measure/testdata/measure.json b/pkg/test/measure/testdata/measure.json
index 125a44b..a0ab240 100644
--- a/pkg/test/measure/testdata/measure.json
+++ b/pkg/test/measure/testdata/measure.json
@@ -67,5 +67,5 @@
       "unit": "DURATION_UNIT_DAY"
     }
   },
-  "updated_at_nanoseconds": "2021-04-15T01:30:15.01Z"
+  "updated_at": "2021-04-15T01:30:15.01Z"
 }
\ No newline at end of file
diff --git a/pkg/test/stream/testdata/stream.json b/pkg/test/stream/testdata/stream.json
index d4f9df9..767cc15 100644
--- a/pkg/test/stream/testdata/stream.json
+++ b/pkg/test/stream/testdata/stream.json
@@ -89,5 +89,5 @@
       "unit": "DURATION_UNIT_DAY"
     }
   },
-  "updated_at_nanoseconds": "2021-04-15T01:30:15.01Z"
+  "updated_at": "2021-04-15T01:30:15.01Z"
 }
\ No newline at end of file