diff --git a/admin/client.go b/admin/client.go index 192bd7715..3a6fb6d65 100644 --- a/admin/client.go +++ b/admin/client.go @@ -332,6 +332,7 @@ func (c *Client) ListChangeSummaries( seq, snapshotMeta.Msg.Lamport, snapshotMeta.Msg.Snapshot, + snapshotMeta.Msg.LatestVectorClock, ) if err != nil { diff --git a/api/converter/from_pb.go b/api/converter/from_pb.go index b4e6aba11..7f4cd57b6 100644 --- a/api/converter/from_pb.go +++ b/api/converter/from_pb.go @@ -102,13 +102,25 @@ func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) { return nil, err } + lvv, err := time.NewVectorClockFromJSON(pbPack.LatestVersionVector) + if err != nil { + return nil, err + } + + svv, err := time.NewVectorClockFromJSON(pbPack.SyncedVersionVector) + if err != nil { + return nil, err + } + return &change.Pack{ - DocumentKey: key.Key(pbPack.DocumentKey), - Checkpoint: fromCheckpoint(pbPack.Checkpoint), - Changes: changes, - Snapshot: pbPack.Snapshot, - MinSyncedTicket: minSyncedTicket, - IsRemoved: pbPack.IsRemoved, + DocumentKey: key.Key(pbPack.DocumentKey), + Checkpoint: fromCheckpoint(pbPack.Checkpoint), + Changes: changes, + Snapshot: pbPack.Snapshot, + MinSyncedTicket: minSyncedTicket, + IsRemoved: pbPack.IsRemoved, + LatestVersionVector: lvv, + SyncedVersionVector: svv, }, nil } @@ -116,6 +128,7 @@ func fromCheckpoint(pbCheckpoint *api.Checkpoint) change.Checkpoint { return change.NewCheckpoint( pbCheckpoint.ServerSeq, pbCheckpoint.ClientSeq, + pbCheckpoint.LatestServerSeq, ) } @@ -136,6 +149,8 @@ func FromChanges(pbChanges []*api.Change) ([]*change.Change, error) { pbChange.Message, ops, FromPresenceChange(pbChange.PresenceChange), + pbChange.VectorClock, + pbChange.DetachFlag, )) } @@ -372,12 +387,6 @@ func fromEdit(pbEdit *api.Operation_Edit) (*operations.Edit, error) { if err != nil { return nil, err } - createdAtMapByActor, err := fromCreatedAtMapByActor( - pbEdit.CreatedAtMapByActor, - ) - if err != nil { - return nil, err - } executedAt, err := fromTimeTicket(pbEdit.ExecutedAt) if err != nil { return nil, err @@ -386,7 +395,7 @@ func fromEdit(pbEdit *api.Operation_Edit) (*operations.Edit, error) { parentCreatedAt, from, to, - createdAtMapByActor, + pbEdit.VectorClock, pbEdit.Content, pbEdit.Attributes, executedAt, diff --git a/api/converter/to_pb.go b/api/converter/to_pb.go index 49f0e7a8e..253824ce9 100644 --- a/api/converter/to_pb.go +++ b/api/converter/to_pb.go @@ -149,8 +149,9 @@ func ToChangePack(pack *change.Pack) (*api.ChangePack, error) { // ToCheckpoint converts the given model format to Protobuf format. func ToCheckpoint(cp change.Checkpoint) *api.Checkpoint { return &api.Checkpoint{ - ServerSeq: cp.ServerSeq, - ClientSeq: cp.ClientSeq, + ServerSeq: cp.ServerSeq, + ClientSeq: cp.ClientSeq, + LatestServerSeq: cp.LatestChangeSeq, } } @@ -246,6 +247,8 @@ func ToChanges(changes []*change.Change) ([]*api.Change, error) { Message: c.Message(), Operations: pbOperations, PresenceChange: ToPresenceChange(c.PresenceChange()), + VectorClock: c.VectorClock(), + DetachFlag: c.DetachFlag(), }) } @@ -308,13 +311,13 @@ func toRemove(remove *operations.Remove) (*api.Operation_Remove_, error) { func toEdit(e *operations.Edit) (*api.Operation_Edit_, error) { return &api.Operation_Edit_{ Edit: &api.Operation_Edit{ - ParentCreatedAt: ToTimeTicket(e.ParentCreatedAt()), - From: toTextNodePos(e.From()), - To: toTextNodePos(e.To()), - CreatedAtMapByActor: toCreatedAtMapByActor(e.CreatedAtMapByActor()), - Content: e.Content(), - Attributes: e.Attributes(), - ExecutedAt: ToTimeTicket(e.ExecutedAt()), + ParentCreatedAt: ToTimeTicket(e.ParentCreatedAt()), + From: toTextNodePos(e.From()), + To: toTextNodePos(e.To()), + VectorClock: e.VectorClock(), + Content: e.Content(), + Attributes: e.Attributes(), + ExecutedAt: ToTimeTicket(e.ExecutedAt()), }, }, nil } diff --git a/api/yorkie/v1/admin.pb.go b/api/yorkie/v1/admin.pb.go index 7ff402031..c092fa1d5 100644 --- a/api/yorkie/v1/admin.pb.go +++ b/api/yorkie/v1/admin.pb.go @@ -1011,8 +1011,9 @@ type GetSnapshotMetaResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Snapshot []byte `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` - Lamport int64 `protobuf:"varint,2,opt,name=lamport,proto3" json:"lamport,omitempty"` + Snapshot []byte `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + Lamport int64 `protobuf:"varint,2,opt,name=lamport,proto3" json:"lamport,omitempty"` + LatestVectorClock string `protobuf:"bytes,3,opt,name=latest_vector_clock,json=latestVectorClock,proto3" json:"latest_vector_clock,omitempty"` } func (x *GetSnapshotMetaResponse) Reset() { @@ -1061,6 +1062,13 @@ func (x *GetSnapshotMetaResponse) GetLamport() int64 { return 0 } +func (x *GetSnapshotMetaResponse) GetLatestVectorClock() string { + if x != nil { + return x.LatestVectorClock + } + return "" +} + type SearchDocumentsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1403,111 +1411,114 @@ var file_yorkie_v1_admin_proto_rawDesc = []byte{ 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x09, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x71, 0x22, 0x53, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, - 0x1c, 0x0a, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x42, 0x02, 0x30, 0x01, 0x52, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x6e, 0x0a, - 0x16, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x74, 0x0a, - 0x17, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x64, 0x6f, 0x63, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x09, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, - 0x0c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, - 0x12, 0x25, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x73, 0x65, 0x71, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x53, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x22, 0x42, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x79, 0x6f, - 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x07, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x32, 0xf5, 0x07, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, - 0x55, 0x70, 0x12, 0x18, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x05, 0x4c, 0x6f, 0x67, - 0x49, 0x6e, 0x12, 0x17, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x6f, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x79, 0x6f, - 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1f, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x71, 0x22, 0x83, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x12, 0x1c, 0x0a, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2e, + 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, + 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x61, 0x74, + 0x65, 0x73, 0x74, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x6e, + 0x0a, 0x16, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x74, + 0x0a, 0x17, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x64, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x09, 0x64, 0x6f, 0x63, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, + 0x79, 0x12, 0x25, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x73, 0x65, + 0x71, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x0b, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x6f, 0x75, 0x73, 0x53, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x22, 0x42, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x79, + 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x32, 0xf5, 0x07, 0x0a, 0x0c, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x53, 0x69, 0x67, + 0x6e, 0x55, 0x70, 0x12, 0x18, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x05, 0x4c, 0x6f, + 0x67, 0x49, 0x6e, 0x12, 0x17, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x79, + 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1f, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1e, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x4b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1c, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, - 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1f, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, + 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1e, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x1c, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, + 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x1f, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, - 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x15, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x12, 0x27, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x79, 0x6f, - 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x2e, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, - 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x79, 0x6f, 0x72, 0x6b, - 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1d, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x15, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x12, 0x27, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x79, + 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, + 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x4e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x1d, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x45, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2d, 0x74, 0x65, 0x61, 0x6d, 0x2f, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2d, 0x74, 0x65, 0x61, 0x6d, 0x2f, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/yorkie/v1/admin.proto b/api/yorkie/v1/admin.proto index 753e3181c..52faa5206 100644 --- a/api/yorkie/v1/admin.proto +++ b/api/yorkie/v1/admin.proto @@ -130,6 +130,7 @@ message GetSnapshotMetaRequest { message GetSnapshotMetaResponse { bytes snapshot = 1; int64 lamport = 2 [jstype = JS_STRING]; + string latest_vector_clock = 3; } message SearchDocumentsRequest { diff --git a/api/yorkie/v1/resources.pb.go b/api/yorkie/v1/resources.pb.go index c9af821f0..466537534 100644 --- a/api/yorkie/v1/resources.pb.go +++ b/api/yorkie/v1/resources.pb.go @@ -288,12 +288,14 @@ type ChangePack struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - DocumentKey string `protobuf:"bytes,1,opt,name=document_key,json=documentKey,proto3" json:"document_key,omitempty"` - Checkpoint *Checkpoint `protobuf:"bytes,2,opt,name=checkpoint,proto3" json:"checkpoint,omitempty"` - Snapshot []byte `protobuf:"bytes,3,opt,name=snapshot,proto3" json:"snapshot,omitempty"` - Changes []*Change `protobuf:"bytes,4,rep,name=changes,proto3" json:"changes,omitempty"` - MinSyncedTicket *TimeTicket `protobuf:"bytes,5,opt,name=min_synced_ticket,json=minSyncedTicket,proto3" json:"min_synced_ticket,omitempty"` - IsRemoved bool `protobuf:"varint,6,opt,name=is_removed,json=isRemoved,proto3" json:"is_removed,omitempty"` + DocumentKey string `protobuf:"bytes,1,opt,name=document_key,json=documentKey,proto3" json:"document_key,omitempty"` + Checkpoint *Checkpoint `protobuf:"bytes,2,opt,name=checkpoint,proto3" json:"checkpoint,omitempty"` + Snapshot []byte `protobuf:"bytes,3,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + Changes []*Change `protobuf:"bytes,4,rep,name=changes,proto3" json:"changes,omitempty"` + MinSyncedTicket *TimeTicket `protobuf:"bytes,5,opt,name=min_synced_ticket,json=minSyncedTicket,proto3" json:"min_synced_ticket,omitempty"` + IsRemoved bool `protobuf:"varint,6,opt,name=is_removed,json=isRemoved,proto3" json:"is_removed,omitempty"` + LatestVersionVector string `protobuf:"bytes,7,opt,name=latest_version_vector,json=latestVersionVector,proto3" json:"latest_version_vector,omitempty"` + SyncedVersionVector string `protobuf:"bytes,8,opt,name=synced_version_vector,json=syncedVersionVector,proto3" json:"synced_version_vector,omitempty"` } func (x *ChangePack) Reset() { @@ -370,15 +372,31 @@ func (x *ChangePack) GetIsRemoved() bool { return false } +func (x *ChangePack) GetLatestVersionVector() string { + if x != nil { + return x.LatestVersionVector + } + return "" +} + +func (x *ChangePack) GetSyncedVersionVector() string { + if x != nil { + return x.SyncedVersionVector + } + return "" +} + type Change struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id *ChangeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` - Operations []*Operation `protobuf:"bytes,3,rep,name=operations,proto3" json:"operations,omitempty"` - PresenceChange *PresenceChange `protobuf:"bytes,4,opt,name=presence_change,json=presenceChange,proto3" json:"presence_change,omitempty"` + Id *ChangeID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Operations []*Operation `protobuf:"bytes,3,rep,name=operations,proto3" json:"operations,omitempty"` + PresenceChange *PresenceChange `protobuf:"bytes,4,opt,name=presence_change,json=presenceChange,proto3" json:"presence_change,omitempty"` + VectorClock map[string]int64 `protobuf:"bytes,5,rep,name=vector_clock,json=vectorClock,proto3" json:"vector_clock,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + DetachFlag bool `protobuf:"varint,6,opt,name=detach_flag,json=detachFlag,proto3" json:"detach_flag,omitempty"` } func (x *Change) Reset() { @@ -441,6 +459,20 @@ func (x *Change) GetPresenceChange() *PresenceChange { return nil } +func (x *Change) GetVectorClock() map[string]int64 { + if x != nil { + return x.VectorClock + } + return nil +} + +func (x *Change) GetDetachFlag() bool { + if x != nil { + return x.DetachFlag + } + return false +} + type ChangeID struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1919,8 +1951,9 @@ type Checkpoint struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ServerSeq int64 `protobuf:"varint,1,opt,name=server_seq,json=serverSeq,proto3" json:"server_seq,omitempty"` - ClientSeq uint32 `protobuf:"varint,2,opt,name=client_seq,json=clientSeq,proto3" json:"client_seq,omitempty"` + ServerSeq int64 `protobuf:"varint,1,opt,name=server_seq,json=serverSeq,proto3" json:"server_seq,omitempty"` + ClientSeq uint32 `protobuf:"varint,2,opt,name=client_seq,json=clientSeq,proto3" json:"client_seq,omitempty"` + LatestServerSeq int64 `protobuf:"varint,3,opt,name=latest_server_seq,json=latestServerSeq,proto3" json:"latest_server_seq,omitempty"` } func (x *Checkpoint) Reset() { @@ -1969,6 +2002,13 @@ func (x *Checkpoint) GetClientSeq() uint32 { return 0 } +func (x *Checkpoint) GetLatestServerSeq() int64 { + if x != nil { + return x.LatestServerSeq + } + return 0 +} + type TextNodePos struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2227,7 +2267,7 @@ type Operation_Set struct { func (x *Operation_Set) Reset() { *x = Operation_Set{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[28] + mi := &file_yorkie_v1_resources_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2240,7 +2280,7 @@ func (x *Operation_Set) String() string { func (*Operation_Set) ProtoMessage() {} func (x *Operation_Set) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[28] + mi := &file_yorkie_v1_resources_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2298,7 +2338,7 @@ type Operation_Add struct { func (x *Operation_Add) Reset() { *x = Operation_Add{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[29] + mi := &file_yorkie_v1_resources_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2311,7 +2351,7 @@ func (x *Operation_Add) String() string { func (*Operation_Add) ProtoMessage() {} func (x *Operation_Add) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[29] + mi := &file_yorkie_v1_resources_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2369,7 +2409,7 @@ type Operation_Move struct { func (x *Operation_Move) Reset() { *x = Operation_Move{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[30] + mi := &file_yorkie_v1_resources_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2382,7 +2422,7 @@ func (x *Operation_Move) String() string { func (*Operation_Move) ProtoMessage() {} func (x *Operation_Move) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[30] + mi := &file_yorkie_v1_resources_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2439,7 +2479,7 @@ type Operation_Remove struct { func (x *Operation_Remove) Reset() { *x = Operation_Remove{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[31] + mi := &file_yorkie_v1_resources_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2452,7 +2492,7 @@ func (x *Operation_Remove) String() string { func (*Operation_Remove) ProtoMessage() {} func (x *Operation_Remove) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[31] + mi := &file_yorkie_v1_resources_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2494,19 +2534,19 @@ type Operation_Edit struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ParentCreatedAt *TimeTicket `protobuf:"bytes,1,opt,name=parent_created_at,json=parentCreatedAt,proto3" json:"parent_created_at,omitempty"` - From *TextNodePos `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"` - To *TextNodePos `protobuf:"bytes,3,opt,name=to,proto3" json:"to,omitempty"` - CreatedAtMapByActor map[string]*TimeTicket `protobuf:"bytes,4,rep,name=created_at_map_by_actor,json=createdAtMapByActor,proto3" json:"created_at_map_by_actor,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` - ExecutedAt *TimeTicket `protobuf:"bytes,6,opt,name=executed_at,json=executedAt,proto3" json:"executed_at,omitempty"` - Attributes map[string]string `protobuf:"bytes,7,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ParentCreatedAt *TimeTicket `protobuf:"bytes,1,opt,name=parent_created_at,json=parentCreatedAt,proto3" json:"parent_created_at,omitempty"` + From *TextNodePos `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"` + To *TextNodePos `protobuf:"bytes,3,opt,name=to,proto3" json:"to,omitempty"` + VectorClock map[string]int64 `protobuf:"bytes,4,rep,name=vector_clock,json=vectorClock,proto3" json:"vector_clock,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` + ExecutedAt *TimeTicket `protobuf:"bytes,6,opt,name=executed_at,json=executedAt,proto3" json:"executed_at,omitempty"` + Attributes map[string]string `protobuf:"bytes,7,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Operation_Edit) Reset() { *x = Operation_Edit{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[32] + mi := &file_yorkie_v1_resources_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2519,7 +2559,7 @@ func (x *Operation_Edit) String() string { func (*Operation_Edit) ProtoMessage() {} func (x *Operation_Edit) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[32] + mi := &file_yorkie_v1_resources_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2556,9 +2596,9 @@ func (x *Operation_Edit) GetTo() *TextNodePos { return nil } -func (x *Operation_Edit) GetCreatedAtMapByActor() map[string]*TimeTicket { +func (x *Operation_Edit) GetVectorClock() map[string]int64 { if x != nil { - return x.CreatedAtMapByActor + return x.VectorClock } return nil } @@ -2602,7 +2642,7 @@ type Operation_Select struct { func (x *Operation_Select) Reset() { *x = Operation_Select{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[33] + mi := &file_yorkie_v1_resources_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2615,7 +2655,7 @@ func (x *Operation_Select) String() string { func (*Operation_Select) ProtoMessage() {} func (x *Operation_Select) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[33] + mi := &file_yorkie_v1_resources_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2675,7 +2715,7 @@ type Operation_Style struct { func (x *Operation_Style) Reset() { *x = Operation_Style{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[34] + mi := &file_yorkie_v1_resources_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2688,7 +2728,7 @@ func (x *Operation_Style) String() string { func (*Operation_Style) ProtoMessage() {} func (x *Operation_Style) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[34] + mi := &file_yorkie_v1_resources_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2759,7 +2799,7 @@ type Operation_Increase struct { func (x *Operation_Increase) Reset() { *x = Operation_Increase{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[35] + mi := &file_yorkie_v1_resources_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2772,7 +2812,7 @@ func (x *Operation_Increase) String() string { func (*Operation_Increase) ProtoMessage() {} func (x *Operation_Increase) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[35] + mi := &file_yorkie_v1_resources_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2826,7 +2866,7 @@ type Operation_TreeEdit struct { func (x *Operation_TreeEdit) Reset() { *x = Operation_TreeEdit{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[36] + mi := &file_yorkie_v1_resources_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2839,7 +2879,7 @@ func (x *Operation_TreeEdit) String() string { func (*Operation_TreeEdit) ProtoMessage() {} func (x *Operation_TreeEdit) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[36] + mi := &file_yorkie_v1_resources_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2920,7 +2960,7 @@ type Operation_TreeStyle struct { func (x *Operation_TreeStyle) Reset() { *x = Operation_TreeStyle{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[37] + mi := &file_yorkie_v1_resources_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2933,7 +2973,7 @@ func (x *Operation_TreeStyle) String() string { func (*Operation_TreeStyle) ProtoMessage() {} func (x *Operation_TreeStyle) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[37] + mi := &file_yorkie_v1_resources_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3005,7 +3045,7 @@ type JSONElement_JSONObject struct { func (x *JSONElement_JSONObject) Reset() { *x = JSONElement_JSONObject{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[44] + mi := &file_yorkie_v1_resources_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3018,7 +3058,7 @@ func (x *JSONElement_JSONObject) String() string { func (*JSONElement_JSONObject) ProtoMessage() {} func (x *JSONElement_JSONObject) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[44] + mi := &file_yorkie_v1_resources_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3076,7 +3116,7 @@ type JSONElement_JSONArray struct { func (x *JSONElement_JSONArray) Reset() { *x = JSONElement_JSONArray{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[45] + mi := &file_yorkie_v1_resources_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3089,7 +3129,7 @@ func (x *JSONElement_JSONArray) String() string { func (*JSONElement_JSONArray) ProtoMessage() {} func (x *JSONElement_JSONArray) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[45] + mi := &file_yorkie_v1_resources_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3148,7 +3188,7 @@ type JSONElement_Primitive struct { func (x *JSONElement_Primitive) Reset() { *x = JSONElement_Primitive{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[46] + mi := &file_yorkie_v1_resources_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3161,7 +3201,7 @@ func (x *JSONElement_Primitive) String() string { func (*JSONElement_Primitive) ProtoMessage() {} func (x *JSONElement_Primitive) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[46] + mi := &file_yorkie_v1_resources_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3226,7 +3266,7 @@ type JSONElement_Text struct { func (x *JSONElement_Text) Reset() { *x = JSONElement_Text{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[47] + mi := &file_yorkie_v1_resources_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3239,7 +3279,7 @@ func (x *JSONElement_Text) String() string { func (*JSONElement_Text) ProtoMessage() {} func (x *JSONElement_Text) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[47] + mi := &file_yorkie_v1_resources_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3298,7 +3338,7 @@ type JSONElement_Counter struct { func (x *JSONElement_Counter) Reset() { *x = JSONElement_Counter{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[48] + mi := &file_yorkie_v1_resources_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3311,7 +3351,7 @@ func (x *JSONElement_Counter) String() string { func (*JSONElement_Counter) ProtoMessage() {} func (x *JSONElement_Counter) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[48] + mi := &file_yorkie_v1_resources_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3376,7 +3416,7 @@ type JSONElement_Tree struct { func (x *JSONElement_Tree) Reset() { *x = JSONElement_Tree{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[49] + mi := &file_yorkie_v1_resources_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3389,7 +3429,7 @@ func (x *JSONElement_Tree) String() string { func (*JSONElement_Tree) ProtoMessage() {} func (x *JSONElement_Tree) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[49] + mi := &file_yorkie_v1_resources_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3444,7 +3484,7 @@ type UpdatableProjectFields_AuthWebhookMethods struct { func (x *UpdatableProjectFields_AuthWebhookMethods) Reset() { *x = UpdatableProjectFields_AuthWebhookMethods{} if protoimpl.UnsafeEnabled { - mi := &file_yorkie_v1_resources_proto_msgTypes[52] + mi := &file_yorkie_v1_resources_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3457,7 +3497,7 @@ func (x *UpdatableProjectFields_AuthWebhookMethods) String() string { func (*UpdatableProjectFields_AuthWebhookMethods) ProtoMessage() {} func (x *UpdatableProjectFields_AuthWebhookMethods) ProtoReflect() protoreflect.Message { - mi := &file_yorkie_v1_resources_proto_msgTypes[52] + mi := &file_yorkie_v1_resources_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3502,7 +3542,7 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x91, 0x02, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf9, 0x02, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, @@ -3519,19 +3559,36 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x69, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xc1, 0x01, 0x0a, 0x06, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x70, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x70, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x85, 0x01, + 0x69, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x32, 0x0a, + 0x15, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x79, + 0x6e, 0x63, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x22, 0xe9, 0x02, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, + 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x56, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x0b, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, + 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0a, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x46, 0x6c, 0x61, 0x67, 0x1a, 0x3e, 0x0a, + 0x10, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x85, 0x01, 0x0a, 0x08, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x44, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x71, 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x65, 0x72, @@ -3540,7 +3597,7 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x49, 0x64, 0x22, 0xb6, 0x1e, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x74, 0x6f, 0x72, 0x49, 0x64, 0x22, 0xfc, 0x1d, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x48, 0x00, 0x52, 0x03, 0x73, 0x65, @@ -3630,7 +3687,7 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x1a, 0xc2, 0x04, 0x0a, 0x04, 0x45, 0x64, 0x69, 0x74, 0x12, 0x41, 0x0a, 0x11, + 0x64, 0x41, 0x74, 0x1a, 0x88, 0x04, 0x0a, 0x04, 0x45, 0x64, 0x69, 0x74, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, @@ -3640,206 +3697,258 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x26, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, - 0x02, 0x74, 0x6f, 0x12, 0x68, 0x0a, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, - 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x18, 0x0a, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x49, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x2e, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x5d, 0x0a, 0x18, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, - 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xd7, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, + 0x02, 0x74, 0x6f, 0x12, 0x4d, 0x0a, 0x0c, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x45, 0x64, 0x69, 0x74, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x0b, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x49, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, + 0x64, 0x69, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, + 0x3e, 0x0a, 0x10, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, + 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xd7, + 0x01, 0x0a, 0x06, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x04, + 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, + 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x26, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, + 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xab, 0x04, 0x0a, 0x05, 0x53, 0x74, 0x79, + 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, + 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, + 0x6d, 0x12, 0x26, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, + 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x4a, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x69, 0x0a, + 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x5f, + 0x62, 0x79, 0x5f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, + 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xb9, 0x01, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x72, 0x65, + 0x61, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, - 0x6f, 0x6d, 0x12, 0x26, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, - 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x1a, 0xab, 0x04, 0x0a, 0x05, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x11, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x2a, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, - 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x26, 0x0a, 0x02, 0x74, - 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x52, - 0x02, 0x74, 0x6f, 0x12, 0x4a, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, - 0x79, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, + 0x41, 0x74, 0x1a, 0xf1, 0x03, 0x0a, 0x08, 0x54, 0x72, 0x65, 0x65, 0x45, 0x64, 0x69, 0x74, 0x12, + 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, + 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x22, 0x0a, 0x02, 0x74, 0x6f, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x6c, + 0x0a, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x70, + 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x36, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x45, 0x64, 0x69, 0x74, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, + 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x08, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, + 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x69, 0x0a, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x74, - 0x6f, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, - 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, - 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, - 0x6f, 0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x5d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, - 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x1a, 0xb9, 0x01, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x12, 0x41, 0x0a, - 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, - 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, - 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, - 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, - 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xf1, 0x03, 0x0a, - 0x08, 0x54, 0x72, 0x65, 0x65, 0x45, 0x64, 0x69, 0x74, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, + 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x5d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x26, 0x0a, 0x04, - 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, - 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x22, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, - 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x6c, 0x0a, 0x17, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x79, 0x6f, 0x72, 0x6b, - 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x54, 0x72, 0x65, 0x65, 0x45, 0x64, 0x69, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, 0x70, 0x42, - 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x08, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x70, 0x6c, 0x69, - 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, - 0x70, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x1a, 0x5d, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x61, - 0x70, 0x42, 0x79, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x93, 0x03, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x53, + 0x74, 0x79, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, + 0x22, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x52, + 0x02, 0x74, 0x6f, 0x12, 0x4e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x72, + 0x65, 0x65, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x3d, 0x0a, + 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x1a, 0x93, 0x03, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x12, 0x41, - 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, - 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, - 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, - 0x50, 0x6f, 0x73, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x22, 0x0a, 0x02, 0x74, 0x6f, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x4e, 0x0a, - 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x79, 0x6c, - 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, - 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x0d, 0x0a, 0x0b, 0x4a, 0x53, 0x4f, + 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, + 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x48, 0x00, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x41, + 0x0a, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, + 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x41, + 0x72, 0x72, 0x61, 0x79, 0x48, 0x00, 0x52, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x61, + 0x79, 0x12, 0x40, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x09, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, + 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x48, 0x00, + 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, + 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, + 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x48, 0x00, 0x52, + 0x04, 0x74, 0x72, 0x65, 0x65, 0x1a, 0xd4, 0x01, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, 0x4e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x48, 0x54, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x54, - 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf1, - 0x01, 0x0a, 0x11, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, - 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, + 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xd3, 0x01, 0x0a, + 0x09, 0x4a, 0x53, 0x4f, 0x4e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, - 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, + 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0xa9, 0x0d, 0x0a, 0x0b, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, - 0x4a, 0x53, 0x4f, 0x4e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x6a, 0x73, - 0x6f, 0x6e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x41, 0x0a, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, - 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x48, 0x00, - 0x52, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x40, 0x0a, 0x09, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x48, 0x00, 0x52, 0x09, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x31, 0x0a, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x79, 0x6f, - 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x3a, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, - 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x04, - 0x74, 0x72, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x48, 0x00, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x1a, - 0xd4, 0x01, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, 0x4e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, - 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x48, 0x54, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, + 0x41, 0x74, 0x1a, 0xe9, 0x01, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, - 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xcf, + 0x01, 0x0a, 0x04, 0x54, 0x65, 0x78, 0x74, 0x12, 0x29, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, + 0x1a, 0xe7, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, + 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, + 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xd3, 0x01, 0x0a, 0x09, 0x4a, 0x53, 0x4f, 0x4e, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xcf, 0x01, 0x0a, 0x04, 0x54, + 0x72, 0x65, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, @@ -3849,315 +3958,262 @@ var file_yorkie_v1_resources_proto_rawDesc = []byte{ 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xe9, 0x01, 0x0a, - 0x09, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x42, 0x06, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x22, 0x4d, 0x0a, 0x07, 0x52, 0x48, 0x54, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, + 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x22, 0x63, 0x0a, 0x07, 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x26, + 0x0a, 0x04, 0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, + 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x04, 0x6e, 0x65, 0x78, 0x74, 0x12, 0x30, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x22, 0xcd, 0x02, 0x0a, 0x08, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, 0x6e, + 0x73, 0x50, 0x72, 0x65, 0x76, 0x49, 0x64, 0x12, 0x43, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x52, 0x0a, 0x0f, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x5a, 0x0a, 0x0a, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x12, 0x34, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xcf, 0x01, 0x0a, 0x04, 0x54, 0x65, 0x78, - 0x74, 0x12, 0x29, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, - 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, - 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, - 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x1a, 0xe7, 0x01, 0x0a, 0x07, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, + 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0xae, 0x03, 0x0a, + 0x08, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x34, - 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x64, 0x41, 0x74, 0x1a, 0xcf, 0x01, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x29, 0x0a, - 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, 0x6e, + 0x73, 0x50, 0x72, 0x65, 0x76, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x5f, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, - 0x0a, 0x08, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x4d, - 0x0a, 0x07, 0x52, 0x48, 0x54, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x07, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x45, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x63, 0x0a, - 0x07, 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6e, 0x65, 0x78, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x47, 0x41, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x65, 0x78, 0x74, - 0x12, 0x30, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x53, - 0x4f, 0x4e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x72, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, - 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xcd, 0x02, 0x0a, 0x08, 0x54, - 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x12, 0x43, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x52, 0x0a, 0x0f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3a, 0x0a, + 0x09, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x0a, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x7c, 0x0a, 0x07, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, + 0x12, 0x32, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, - 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, - 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x50, 0x72, 0x65, 0x76, 0x49, - 0x64, 0x12, 0x43, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x52, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x72, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x0a, 0x54, 0x65, - 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, - 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, - 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0xae, 0x03, 0x0a, 0x08, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, - 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x41, 0x74, 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, - 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x50, 0x72, 0x65, 0x76, 0x49, - 0x64, 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x09, 0x69, - 0x6e, 0x73, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, - 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x43, - 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x1a, 0x52, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x72, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3a, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x0a, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, - 0x44, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x7c, 0x0a, 0x07, 0x54, 0x72, 0x65, 0x65, 0x50, 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x09, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x0f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x73, 0x69, 0x62, + 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x64, 0x65, 0x49, 0x44, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3d, - 0x0a, 0x0f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x52, 0x0d, - 0x6c, 0x65, 0x66, 0x74, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x22, 0x6d, 0x0a, - 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x03, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xfd, 0x02, 0x0a, - 0x07, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, - 0x6b, 0x55, 0x72, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, - 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x5f, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 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, 0x88, 0x03, 0x0a, - 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x61, 0x75, 0x74, - 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, - 0x6c, 0x12, 0x66, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, - 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x34, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, - 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x5c, 0x0a, 0x1b, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x19, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x54, 0x68, - 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x1a, 0x2e, 0x0a, 0x12, 0x41, 0x75, 0x74, 0x68, 0x57, - 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0x82, 0x02, 0x0a, 0x0f, 0x44, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, - 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 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, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 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, 0x22, 0xea, 0x01, 0x0a, - 0x0e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, - 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, - 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, - 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x6d, 0x0a, 0x0a, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x48, 0x41, 0x4e, - 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x48, - 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, - 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x10, 0x03, 0x22, 0x76, 0x0a, 0x08, 0x50, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x4e, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x21, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, - 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x71, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x71, 0x22, 0x84, 0x01, 0x0a, 0x0b, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, - 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x63, 0x0a, 0x0a, 0x54, 0x69, 0x6d, 0x65, - 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x07, 0x6c, 0x61, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x22, 0x3e, 0x0a, - 0x0c, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, - 0x70, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x82, 0x01, - 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x2a, 0xd4, 0x02, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, - 0x55, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x01, 0x12, 0x16, 0x0a, - 0x12, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, - 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, - 0x04, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x41, 0x4c, 0x55, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x06, 0x12, 0x13, - 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, - 0x45, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x08, 0x12, - 0x19, 0x0a, 0x15, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x53, - 0x4f, 0x4e, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x09, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, - 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x10, 0x0a, 0x12, - 0x1a, 0x0a, 0x16, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x5f, 0x43, 0x4e, 0x54, 0x10, 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x56, - 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x5f, 0x43, - 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x0d, 0x2a, 0xa6, 0x01, 0x0a, 0x0c, 0x44, 0x6f, - 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x4f, + 0x64, 0x65, 0x49, 0x44, 0x52, 0x0d, 0x6c, 0x65, 0x66, 0x74, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, + 0x67, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x22, 0xfd, 0x02, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x12, 0x28, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, + 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x61, 0x75, + 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, + 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x3e, 0x0a, 0x1b, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x19, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x39, 0x0a, 0x0a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, 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, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 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, 0x88, 0x03, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x30, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x46, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, + 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, 0x6c, 0x12, 0x66, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x68, 0x5f, + 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, + 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x12, 0x61, 0x75, 0x74, + 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, + 0x5c, 0x0a, 0x1b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x19, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x1a, 0x2e, 0x0a, + 0x12, 0x41, 0x75, 0x74, 0x68, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0x82, 0x02, + 0x0a, 0x0f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, + 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 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, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 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, 0x0a, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x65, 0x64, 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, 0x22, 0xea, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, + 0x22, 0x6d, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, + 0x0a, 0x17, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x54, 0x10, 0x01, + 0x12, 0x16, 0x0a, 0x12, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x4e, + 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x10, 0x03, 0x22, + 0x76, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, + 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7e, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x73, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x09, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x71, 0x12, 0x2e, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x42, 0x02, 0x30, 0x01, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x71, 0x22, 0x84, 0x01, 0x0a, 0x0b, 0x54, 0x65, 0x78, 0x74, + 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x79, 0x6f, + 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x63, + 0x0a, 0x0a, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x07, + 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x02, 0x30, + 0x01, 0x52, 0x07, 0x6c, 0x61, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, + 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x49, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, + 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x2a, 0xd4, 0x02, 0x0a, 0x09, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x56, + 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, + 0x4e, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x56, + 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0x03, + 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, + 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, 0x4c, 0x55, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x14, + 0x0a, 0x10, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, + 0x45, 0x53, 0x10, 0x06, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x45, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x41, 0x4c, + 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, + 0x45, 0x43, 0x54, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x09, + 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, + 0x45, 0x58, 0x54, 0x10, 0x0a, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x5f, 0x43, 0x4e, 0x54, 0x10, + 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x4c, 0x4f, 0x4e, 0x47, 0x5f, 0x43, 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x41, + 0x4c, 0x55, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x0d, 0x2a, + 0xa6, 0x01, 0x0a, 0x0c, 0x44, 0x6f, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, + 0x47, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, + 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, + 0x5f, 0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, - 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x23, 0x0a, 0x1f, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x57, 0x41, 0x54, 0x43, 0x48, - 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, - 0x55, 0x4e, 0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x44, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x44, - 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, - 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, - 0x10, 0x03, 0x42, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x2e, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2d, 0x74, 0x65, 0x61, - 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x79, 0x6f, 0x72, - 0x6b, 0x69, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x44, 0x10, + 0x02, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x4f, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x52, 0x4f, + 0x41, 0x44, 0x43, 0x41, 0x53, 0x54, 0x10, 0x03, 0x42, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x2e, + 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, + 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, + 0x69, 0x65, 0x2d, 0x74, 0x65, 0x61, 0x6d, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x79, 0x6f, 0x72, 0x6b, 0x69, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4173,7 +4229,7 @@ func file_yorkie_v1_resources_proto_rawDescGZIP() []byte { } var file_yorkie_v1_resources_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_yorkie_v1_resources_proto_msgTypes = make([]protoimpl.MessageInfo, 54) +var file_yorkie_v1_resources_proto_msgTypes = make([]protoimpl.MessageInfo, 55) var file_yorkie_v1_resources_proto_goTypes = []interface{}{ (ValueType)(0), // 0: yorkie.v1.ValueType (DocEventType)(0), // 1: yorkie.v1.DocEventType @@ -4206,34 +4262,35 @@ var file_yorkie_v1_resources_proto_goTypes = []interface{}{ (*DocEventBody)(nil), // 28: yorkie.v1.DocEventBody (*DocEvent)(nil), // 29: yorkie.v1.DocEvent nil, // 30: yorkie.v1.Snapshot.PresencesEntry - (*Operation_Set)(nil), // 31: yorkie.v1.Operation.Set - (*Operation_Add)(nil), // 32: yorkie.v1.Operation.Add - (*Operation_Move)(nil), // 33: yorkie.v1.Operation.Move - (*Operation_Remove)(nil), // 34: yorkie.v1.Operation.Remove - (*Operation_Edit)(nil), // 35: yorkie.v1.Operation.Edit - (*Operation_Select)(nil), // 36: yorkie.v1.Operation.Select - (*Operation_Style)(nil), // 37: yorkie.v1.Operation.Style - (*Operation_Increase)(nil), // 38: yorkie.v1.Operation.Increase - (*Operation_TreeEdit)(nil), // 39: yorkie.v1.Operation.TreeEdit - (*Operation_TreeStyle)(nil), // 40: yorkie.v1.Operation.TreeStyle - nil, // 41: yorkie.v1.Operation.Edit.CreatedAtMapByActorEntry - nil, // 42: yorkie.v1.Operation.Edit.AttributesEntry - nil, // 43: yorkie.v1.Operation.Style.AttributesEntry - nil, // 44: yorkie.v1.Operation.Style.CreatedAtMapByActorEntry - nil, // 45: yorkie.v1.Operation.TreeEdit.CreatedAtMapByActorEntry - nil, // 46: yorkie.v1.Operation.TreeStyle.AttributesEntry - (*JSONElement_JSONObject)(nil), // 47: yorkie.v1.JSONElement.JSONObject - (*JSONElement_JSONArray)(nil), // 48: yorkie.v1.JSONElement.JSONArray - (*JSONElement_Primitive)(nil), // 49: yorkie.v1.JSONElement.Primitive - (*JSONElement_Text)(nil), // 50: yorkie.v1.JSONElement.Text - (*JSONElement_Counter)(nil), // 51: yorkie.v1.JSONElement.Counter - (*JSONElement_Tree)(nil), // 52: yorkie.v1.JSONElement.Tree - nil, // 53: yorkie.v1.TextNode.AttributesEntry - nil, // 54: yorkie.v1.TreeNode.AttributesEntry - (*UpdatableProjectFields_AuthWebhookMethods)(nil), // 55: yorkie.v1.UpdatableProjectFields.AuthWebhookMethods - nil, // 56: yorkie.v1.Presence.DataEntry - (*timestamppb.Timestamp)(nil), // 57: google.protobuf.Timestamp - (*wrapperspb.StringValue)(nil), // 58: google.protobuf.StringValue + nil, // 31: yorkie.v1.Change.VectorClockEntry + (*Operation_Set)(nil), // 32: yorkie.v1.Operation.Set + (*Operation_Add)(nil), // 33: yorkie.v1.Operation.Add + (*Operation_Move)(nil), // 34: yorkie.v1.Operation.Move + (*Operation_Remove)(nil), // 35: yorkie.v1.Operation.Remove + (*Operation_Edit)(nil), // 36: yorkie.v1.Operation.Edit + (*Operation_Select)(nil), // 37: yorkie.v1.Operation.Select + (*Operation_Style)(nil), // 38: yorkie.v1.Operation.Style + (*Operation_Increase)(nil), // 39: yorkie.v1.Operation.Increase + (*Operation_TreeEdit)(nil), // 40: yorkie.v1.Operation.TreeEdit + (*Operation_TreeStyle)(nil), // 41: yorkie.v1.Operation.TreeStyle + nil, // 42: yorkie.v1.Operation.Edit.VectorClockEntry + nil, // 43: yorkie.v1.Operation.Edit.AttributesEntry + nil, // 44: yorkie.v1.Operation.Style.AttributesEntry + nil, // 45: yorkie.v1.Operation.Style.CreatedAtMapByActorEntry + nil, // 46: yorkie.v1.Operation.TreeEdit.CreatedAtMapByActorEntry + nil, // 47: yorkie.v1.Operation.TreeStyle.AttributesEntry + (*JSONElement_JSONObject)(nil), // 48: yorkie.v1.JSONElement.JSONObject + (*JSONElement_JSONArray)(nil), // 49: yorkie.v1.JSONElement.JSONArray + (*JSONElement_Primitive)(nil), // 50: yorkie.v1.JSONElement.Primitive + (*JSONElement_Text)(nil), // 51: yorkie.v1.JSONElement.Text + (*JSONElement_Counter)(nil), // 52: yorkie.v1.JSONElement.Counter + (*JSONElement_Tree)(nil), // 53: yorkie.v1.JSONElement.Tree + nil, // 54: yorkie.v1.TextNode.AttributesEntry + nil, // 55: yorkie.v1.TreeNode.AttributesEntry + (*UpdatableProjectFields_AuthWebhookMethods)(nil), // 56: yorkie.v1.UpdatableProjectFields.AuthWebhookMethods + nil, // 57: yorkie.v1.Presence.DataEntry + (*timestamppb.Timestamp)(nil), // 58: google.protobuf.Timestamp + (*wrapperspb.StringValue)(nil), // 59: google.protobuf.StringValue } var file_yorkie_v1_resources_proto_depIdxs = []int32{ 9, // 0: yorkie.v1.Snapshot.root:type_name -> yorkie.v1.JSONElement @@ -4244,106 +4301,106 @@ var file_yorkie_v1_resources_proto_depIdxs = []int32{ 6, // 5: yorkie.v1.Change.id:type_name -> yorkie.v1.ChangeID 7, // 6: yorkie.v1.Change.operations:type_name -> yorkie.v1.Operation 23, // 7: yorkie.v1.Change.presence_change:type_name -> yorkie.v1.PresenceChange - 31, // 8: yorkie.v1.Operation.set:type_name -> yorkie.v1.Operation.Set - 32, // 9: yorkie.v1.Operation.add:type_name -> yorkie.v1.Operation.Add - 33, // 10: yorkie.v1.Operation.move:type_name -> yorkie.v1.Operation.Move - 34, // 11: yorkie.v1.Operation.remove:type_name -> yorkie.v1.Operation.Remove - 35, // 12: yorkie.v1.Operation.edit:type_name -> yorkie.v1.Operation.Edit - 36, // 13: yorkie.v1.Operation.select:type_name -> yorkie.v1.Operation.Select - 37, // 14: yorkie.v1.Operation.style:type_name -> yorkie.v1.Operation.Style - 38, // 15: yorkie.v1.Operation.increase:type_name -> yorkie.v1.Operation.Increase - 39, // 16: yorkie.v1.Operation.tree_edit:type_name -> yorkie.v1.Operation.TreeEdit - 40, // 17: yorkie.v1.Operation.tree_style:type_name -> yorkie.v1.Operation.TreeStyle - 27, // 18: yorkie.v1.JSONElementSimple.created_at:type_name -> yorkie.v1.TimeTicket - 27, // 19: yorkie.v1.JSONElementSimple.moved_at:type_name -> yorkie.v1.TimeTicket - 27, // 20: yorkie.v1.JSONElementSimple.removed_at:type_name -> yorkie.v1.TimeTicket - 0, // 21: yorkie.v1.JSONElementSimple.type:type_name -> yorkie.v1.ValueType - 47, // 22: yorkie.v1.JSONElement.json_object:type_name -> yorkie.v1.JSONElement.JSONObject - 48, // 23: yorkie.v1.JSONElement.json_array:type_name -> yorkie.v1.JSONElement.JSONArray - 49, // 24: yorkie.v1.JSONElement.primitive:type_name -> yorkie.v1.JSONElement.Primitive - 50, // 25: yorkie.v1.JSONElement.text:type_name -> yorkie.v1.JSONElement.Text - 51, // 26: yorkie.v1.JSONElement.counter:type_name -> yorkie.v1.JSONElement.Counter - 52, // 27: yorkie.v1.JSONElement.tree:type_name -> yorkie.v1.JSONElement.Tree - 9, // 28: yorkie.v1.RHTNode.element:type_name -> yorkie.v1.JSONElement - 11, // 29: yorkie.v1.RGANode.next:type_name -> yorkie.v1.RGANode - 9, // 30: yorkie.v1.RGANode.element:type_name -> yorkie.v1.JSONElement - 27, // 31: yorkie.v1.NodeAttr.updated_at:type_name -> yorkie.v1.TimeTicket - 14, // 32: yorkie.v1.TextNode.id:type_name -> yorkie.v1.TextNodeID - 27, // 33: yorkie.v1.TextNode.removed_at:type_name -> yorkie.v1.TimeTicket - 14, // 34: yorkie.v1.TextNode.ins_prev_id:type_name -> yorkie.v1.TextNodeID - 53, // 35: yorkie.v1.TextNode.attributes:type_name -> yorkie.v1.TextNode.AttributesEntry - 27, // 36: yorkie.v1.TextNodeID.created_at:type_name -> yorkie.v1.TimeTicket - 17, // 37: yorkie.v1.TreeNode.id:type_name -> yorkie.v1.TreeNodeID - 27, // 38: yorkie.v1.TreeNode.removed_at:type_name -> yorkie.v1.TimeTicket - 17, // 39: yorkie.v1.TreeNode.ins_prev_id:type_name -> yorkie.v1.TreeNodeID - 17, // 40: yorkie.v1.TreeNode.ins_next_id:type_name -> yorkie.v1.TreeNodeID - 54, // 41: yorkie.v1.TreeNode.attributes:type_name -> yorkie.v1.TreeNode.AttributesEntry - 15, // 42: yorkie.v1.TreeNodes.content:type_name -> yorkie.v1.TreeNode - 27, // 43: yorkie.v1.TreeNodeID.created_at:type_name -> yorkie.v1.TimeTicket - 17, // 44: yorkie.v1.TreePos.parent_id:type_name -> yorkie.v1.TreeNodeID - 17, // 45: yorkie.v1.TreePos.left_sibling_id:type_name -> yorkie.v1.TreeNodeID - 57, // 46: yorkie.v1.User.created_at:type_name -> google.protobuf.Timestamp - 57, // 47: yorkie.v1.Project.created_at:type_name -> google.protobuf.Timestamp - 57, // 48: yorkie.v1.Project.updated_at:type_name -> google.protobuf.Timestamp - 58, // 49: yorkie.v1.UpdatableProjectFields.name:type_name -> google.protobuf.StringValue - 58, // 50: yorkie.v1.UpdatableProjectFields.auth_webhook_url:type_name -> google.protobuf.StringValue - 55, // 51: yorkie.v1.UpdatableProjectFields.auth_webhook_methods:type_name -> yorkie.v1.UpdatableProjectFields.AuthWebhookMethods - 58, // 52: yorkie.v1.UpdatableProjectFields.client_deactivate_threshold:type_name -> google.protobuf.StringValue - 57, // 53: yorkie.v1.DocumentSummary.created_at:type_name -> google.protobuf.Timestamp - 57, // 54: yorkie.v1.DocumentSummary.accessed_at:type_name -> google.protobuf.Timestamp - 57, // 55: yorkie.v1.DocumentSummary.updated_at:type_name -> google.protobuf.Timestamp - 2, // 56: yorkie.v1.PresenceChange.type:type_name -> yorkie.v1.PresenceChange.ChangeType - 24, // 57: yorkie.v1.PresenceChange.presence:type_name -> yorkie.v1.Presence - 56, // 58: yorkie.v1.Presence.data:type_name -> yorkie.v1.Presence.DataEntry - 27, // 59: yorkie.v1.TextNodePos.created_at:type_name -> yorkie.v1.TimeTicket - 1, // 60: yorkie.v1.DocEvent.type:type_name -> yorkie.v1.DocEventType - 28, // 61: yorkie.v1.DocEvent.body:type_name -> yorkie.v1.DocEventBody - 24, // 62: yorkie.v1.Snapshot.PresencesEntry.value:type_name -> yorkie.v1.Presence - 27, // 63: yorkie.v1.Operation.Set.parent_created_at:type_name -> yorkie.v1.TimeTicket - 8, // 64: yorkie.v1.Operation.Set.value:type_name -> yorkie.v1.JSONElementSimple - 27, // 65: yorkie.v1.Operation.Set.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 66: yorkie.v1.Operation.Add.parent_created_at:type_name -> yorkie.v1.TimeTicket - 27, // 67: yorkie.v1.Operation.Add.prev_created_at:type_name -> yorkie.v1.TimeTicket - 8, // 68: yorkie.v1.Operation.Add.value:type_name -> yorkie.v1.JSONElementSimple - 27, // 69: yorkie.v1.Operation.Add.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 70: yorkie.v1.Operation.Move.parent_created_at:type_name -> yorkie.v1.TimeTicket - 27, // 71: yorkie.v1.Operation.Move.prev_created_at:type_name -> yorkie.v1.TimeTicket - 27, // 72: yorkie.v1.Operation.Move.created_at:type_name -> yorkie.v1.TimeTicket - 27, // 73: yorkie.v1.Operation.Move.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 74: yorkie.v1.Operation.Remove.parent_created_at:type_name -> yorkie.v1.TimeTicket - 27, // 75: yorkie.v1.Operation.Remove.created_at:type_name -> yorkie.v1.TimeTicket - 27, // 76: yorkie.v1.Operation.Remove.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 77: yorkie.v1.Operation.Edit.parent_created_at:type_name -> yorkie.v1.TimeTicket - 26, // 78: yorkie.v1.Operation.Edit.from:type_name -> yorkie.v1.TextNodePos - 26, // 79: yorkie.v1.Operation.Edit.to:type_name -> yorkie.v1.TextNodePos - 41, // 80: yorkie.v1.Operation.Edit.created_at_map_by_actor:type_name -> yorkie.v1.Operation.Edit.CreatedAtMapByActorEntry - 27, // 81: yorkie.v1.Operation.Edit.executed_at:type_name -> yorkie.v1.TimeTicket - 42, // 82: yorkie.v1.Operation.Edit.attributes:type_name -> yorkie.v1.Operation.Edit.AttributesEntry - 27, // 83: yorkie.v1.Operation.Select.parent_created_at:type_name -> yorkie.v1.TimeTicket - 26, // 84: yorkie.v1.Operation.Select.from:type_name -> yorkie.v1.TextNodePos - 26, // 85: yorkie.v1.Operation.Select.to:type_name -> yorkie.v1.TextNodePos - 27, // 86: yorkie.v1.Operation.Select.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 87: yorkie.v1.Operation.Style.parent_created_at:type_name -> yorkie.v1.TimeTicket - 26, // 88: yorkie.v1.Operation.Style.from:type_name -> yorkie.v1.TextNodePos - 26, // 89: yorkie.v1.Operation.Style.to:type_name -> yorkie.v1.TextNodePos - 43, // 90: yorkie.v1.Operation.Style.attributes:type_name -> yorkie.v1.Operation.Style.AttributesEntry - 27, // 91: yorkie.v1.Operation.Style.executed_at:type_name -> yorkie.v1.TimeTicket - 44, // 92: yorkie.v1.Operation.Style.created_at_map_by_actor:type_name -> yorkie.v1.Operation.Style.CreatedAtMapByActorEntry - 27, // 93: yorkie.v1.Operation.Increase.parent_created_at:type_name -> yorkie.v1.TimeTicket - 8, // 94: yorkie.v1.Operation.Increase.value:type_name -> yorkie.v1.JSONElementSimple - 27, // 95: yorkie.v1.Operation.Increase.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 96: yorkie.v1.Operation.TreeEdit.parent_created_at:type_name -> yorkie.v1.TimeTicket - 18, // 97: yorkie.v1.Operation.TreeEdit.from:type_name -> yorkie.v1.TreePos - 18, // 98: yorkie.v1.Operation.TreeEdit.to:type_name -> yorkie.v1.TreePos - 45, // 99: yorkie.v1.Operation.TreeEdit.created_at_map_by_actor:type_name -> yorkie.v1.Operation.TreeEdit.CreatedAtMapByActorEntry - 16, // 100: yorkie.v1.Operation.TreeEdit.contents:type_name -> yorkie.v1.TreeNodes - 27, // 101: yorkie.v1.Operation.TreeEdit.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 102: yorkie.v1.Operation.TreeStyle.parent_created_at:type_name -> yorkie.v1.TimeTicket - 18, // 103: yorkie.v1.Operation.TreeStyle.from:type_name -> yorkie.v1.TreePos - 18, // 104: yorkie.v1.Operation.TreeStyle.to:type_name -> yorkie.v1.TreePos - 46, // 105: yorkie.v1.Operation.TreeStyle.attributes:type_name -> yorkie.v1.Operation.TreeStyle.AttributesEntry - 27, // 106: yorkie.v1.Operation.TreeStyle.executed_at:type_name -> yorkie.v1.TimeTicket - 27, // 107: yorkie.v1.Operation.Edit.CreatedAtMapByActorEntry.value:type_name -> yorkie.v1.TimeTicket + 31, // 8: yorkie.v1.Change.vector_clock:type_name -> yorkie.v1.Change.VectorClockEntry + 32, // 9: yorkie.v1.Operation.set:type_name -> yorkie.v1.Operation.Set + 33, // 10: yorkie.v1.Operation.add:type_name -> yorkie.v1.Operation.Add + 34, // 11: yorkie.v1.Operation.move:type_name -> yorkie.v1.Operation.Move + 35, // 12: yorkie.v1.Operation.remove:type_name -> yorkie.v1.Operation.Remove + 36, // 13: yorkie.v1.Operation.edit:type_name -> yorkie.v1.Operation.Edit + 37, // 14: yorkie.v1.Operation.select:type_name -> yorkie.v1.Operation.Select + 38, // 15: yorkie.v1.Operation.style:type_name -> yorkie.v1.Operation.Style + 39, // 16: yorkie.v1.Operation.increase:type_name -> yorkie.v1.Operation.Increase + 40, // 17: yorkie.v1.Operation.tree_edit:type_name -> yorkie.v1.Operation.TreeEdit + 41, // 18: yorkie.v1.Operation.tree_style:type_name -> yorkie.v1.Operation.TreeStyle + 27, // 19: yorkie.v1.JSONElementSimple.created_at:type_name -> yorkie.v1.TimeTicket + 27, // 20: yorkie.v1.JSONElementSimple.moved_at:type_name -> yorkie.v1.TimeTicket + 27, // 21: yorkie.v1.JSONElementSimple.removed_at:type_name -> yorkie.v1.TimeTicket + 0, // 22: yorkie.v1.JSONElementSimple.type:type_name -> yorkie.v1.ValueType + 48, // 23: yorkie.v1.JSONElement.json_object:type_name -> yorkie.v1.JSONElement.JSONObject + 49, // 24: yorkie.v1.JSONElement.json_array:type_name -> yorkie.v1.JSONElement.JSONArray + 50, // 25: yorkie.v1.JSONElement.primitive:type_name -> yorkie.v1.JSONElement.Primitive + 51, // 26: yorkie.v1.JSONElement.text:type_name -> yorkie.v1.JSONElement.Text + 52, // 27: yorkie.v1.JSONElement.counter:type_name -> yorkie.v1.JSONElement.Counter + 53, // 28: yorkie.v1.JSONElement.tree:type_name -> yorkie.v1.JSONElement.Tree + 9, // 29: yorkie.v1.RHTNode.element:type_name -> yorkie.v1.JSONElement + 11, // 30: yorkie.v1.RGANode.next:type_name -> yorkie.v1.RGANode + 9, // 31: yorkie.v1.RGANode.element:type_name -> yorkie.v1.JSONElement + 27, // 32: yorkie.v1.NodeAttr.updated_at:type_name -> yorkie.v1.TimeTicket + 14, // 33: yorkie.v1.TextNode.id:type_name -> yorkie.v1.TextNodeID + 27, // 34: yorkie.v1.TextNode.removed_at:type_name -> yorkie.v1.TimeTicket + 14, // 35: yorkie.v1.TextNode.ins_prev_id:type_name -> yorkie.v1.TextNodeID + 54, // 36: yorkie.v1.TextNode.attributes:type_name -> yorkie.v1.TextNode.AttributesEntry + 27, // 37: yorkie.v1.TextNodeID.created_at:type_name -> yorkie.v1.TimeTicket + 17, // 38: yorkie.v1.TreeNode.id:type_name -> yorkie.v1.TreeNodeID + 27, // 39: yorkie.v1.TreeNode.removed_at:type_name -> yorkie.v1.TimeTicket + 17, // 40: yorkie.v1.TreeNode.ins_prev_id:type_name -> yorkie.v1.TreeNodeID + 17, // 41: yorkie.v1.TreeNode.ins_next_id:type_name -> yorkie.v1.TreeNodeID + 55, // 42: yorkie.v1.TreeNode.attributes:type_name -> yorkie.v1.TreeNode.AttributesEntry + 15, // 43: yorkie.v1.TreeNodes.content:type_name -> yorkie.v1.TreeNode + 27, // 44: yorkie.v1.TreeNodeID.created_at:type_name -> yorkie.v1.TimeTicket + 17, // 45: yorkie.v1.TreePos.parent_id:type_name -> yorkie.v1.TreeNodeID + 17, // 46: yorkie.v1.TreePos.left_sibling_id:type_name -> yorkie.v1.TreeNodeID + 58, // 47: yorkie.v1.User.created_at:type_name -> google.protobuf.Timestamp + 58, // 48: yorkie.v1.Project.created_at:type_name -> google.protobuf.Timestamp + 58, // 49: yorkie.v1.Project.updated_at:type_name -> google.protobuf.Timestamp + 59, // 50: yorkie.v1.UpdatableProjectFields.name:type_name -> google.protobuf.StringValue + 59, // 51: yorkie.v1.UpdatableProjectFields.auth_webhook_url:type_name -> google.protobuf.StringValue + 56, // 52: yorkie.v1.UpdatableProjectFields.auth_webhook_methods:type_name -> yorkie.v1.UpdatableProjectFields.AuthWebhookMethods + 59, // 53: yorkie.v1.UpdatableProjectFields.client_deactivate_threshold:type_name -> google.protobuf.StringValue + 58, // 54: yorkie.v1.DocumentSummary.created_at:type_name -> google.protobuf.Timestamp + 58, // 55: yorkie.v1.DocumentSummary.accessed_at:type_name -> google.protobuf.Timestamp + 58, // 56: yorkie.v1.DocumentSummary.updated_at:type_name -> google.protobuf.Timestamp + 2, // 57: yorkie.v1.PresenceChange.type:type_name -> yorkie.v1.PresenceChange.ChangeType + 24, // 58: yorkie.v1.PresenceChange.presence:type_name -> yorkie.v1.Presence + 57, // 59: yorkie.v1.Presence.data:type_name -> yorkie.v1.Presence.DataEntry + 27, // 60: yorkie.v1.TextNodePos.created_at:type_name -> yorkie.v1.TimeTicket + 1, // 61: yorkie.v1.DocEvent.type:type_name -> yorkie.v1.DocEventType + 28, // 62: yorkie.v1.DocEvent.body:type_name -> yorkie.v1.DocEventBody + 24, // 63: yorkie.v1.Snapshot.PresencesEntry.value:type_name -> yorkie.v1.Presence + 27, // 64: yorkie.v1.Operation.Set.parent_created_at:type_name -> yorkie.v1.TimeTicket + 8, // 65: yorkie.v1.Operation.Set.value:type_name -> yorkie.v1.JSONElementSimple + 27, // 66: yorkie.v1.Operation.Set.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 67: yorkie.v1.Operation.Add.parent_created_at:type_name -> yorkie.v1.TimeTicket + 27, // 68: yorkie.v1.Operation.Add.prev_created_at:type_name -> yorkie.v1.TimeTicket + 8, // 69: yorkie.v1.Operation.Add.value:type_name -> yorkie.v1.JSONElementSimple + 27, // 70: yorkie.v1.Operation.Add.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 71: yorkie.v1.Operation.Move.parent_created_at:type_name -> yorkie.v1.TimeTicket + 27, // 72: yorkie.v1.Operation.Move.prev_created_at:type_name -> yorkie.v1.TimeTicket + 27, // 73: yorkie.v1.Operation.Move.created_at:type_name -> yorkie.v1.TimeTicket + 27, // 74: yorkie.v1.Operation.Move.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 75: yorkie.v1.Operation.Remove.parent_created_at:type_name -> yorkie.v1.TimeTicket + 27, // 76: yorkie.v1.Operation.Remove.created_at:type_name -> yorkie.v1.TimeTicket + 27, // 77: yorkie.v1.Operation.Remove.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 78: yorkie.v1.Operation.Edit.parent_created_at:type_name -> yorkie.v1.TimeTicket + 26, // 79: yorkie.v1.Operation.Edit.from:type_name -> yorkie.v1.TextNodePos + 26, // 80: yorkie.v1.Operation.Edit.to:type_name -> yorkie.v1.TextNodePos + 42, // 81: yorkie.v1.Operation.Edit.vector_clock:type_name -> yorkie.v1.Operation.Edit.VectorClockEntry + 27, // 82: yorkie.v1.Operation.Edit.executed_at:type_name -> yorkie.v1.TimeTicket + 43, // 83: yorkie.v1.Operation.Edit.attributes:type_name -> yorkie.v1.Operation.Edit.AttributesEntry + 27, // 84: yorkie.v1.Operation.Select.parent_created_at:type_name -> yorkie.v1.TimeTicket + 26, // 85: yorkie.v1.Operation.Select.from:type_name -> yorkie.v1.TextNodePos + 26, // 86: yorkie.v1.Operation.Select.to:type_name -> yorkie.v1.TextNodePos + 27, // 87: yorkie.v1.Operation.Select.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 88: yorkie.v1.Operation.Style.parent_created_at:type_name -> yorkie.v1.TimeTicket + 26, // 89: yorkie.v1.Operation.Style.from:type_name -> yorkie.v1.TextNodePos + 26, // 90: yorkie.v1.Operation.Style.to:type_name -> yorkie.v1.TextNodePos + 44, // 91: yorkie.v1.Operation.Style.attributes:type_name -> yorkie.v1.Operation.Style.AttributesEntry + 27, // 92: yorkie.v1.Operation.Style.executed_at:type_name -> yorkie.v1.TimeTicket + 45, // 93: yorkie.v1.Operation.Style.created_at_map_by_actor:type_name -> yorkie.v1.Operation.Style.CreatedAtMapByActorEntry + 27, // 94: yorkie.v1.Operation.Increase.parent_created_at:type_name -> yorkie.v1.TimeTicket + 8, // 95: yorkie.v1.Operation.Increase.value:type_name -> yorkie.v1.JSONElementSimple + 27, // 96: yorkie.v1.Operation.Increase.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 97: yorkie.v1.Operation.TreeEdit.parent_created_at:type_name -> yorkie.v1.TimeTicket + 18, // 98: yorkie.v1.Operation.TreeEdit.from:type_name -> yorkie.v1.TreePos + 18, // 99: yorkie.v1.Operation.TreeEdit.to:type_name -> yorkie.v1.TreePos + 46, // 100: yorkie.v1.Operation.TreeEdit.created_at_map_by_actor:type_name -> yorkie.v1.Operation.TreeEdit.CreatedAtMapByActorEntry + 16, // 101: yorkie.v1.Operation.TreeEdit.contents:type_name -> yorkie.v1.TreeNodes + 27, // 102: yorkie.v1.Operation.TreeEdit.executed_at:type_name -> yorkie.v1.TimeTicket + 27, // 103: yorkie.v1.Operation.TreeStyle.parent_created_at:type_name -> yorkie.v1.TimeTicket + 18, // 104: yorkie.v1.Operation.TreeStyle.from:type_name -> yorkie.v1.TreePos + 18, // 105: yorkie.v1.Operation.TreeStyle.to:type_name -> yorkie.v1.TreePos + 47, // 106: yorkie.v1.Operation.TreeStyle.attributes:type_name -> yorkie.v1.Operation.TreeStyle.AttributesEntry + 27, // 107: yorkie.v1.Operation.TreeStyle.executed_at:type_name -> yorkie.v1.TimeTicket 27, // 108: yorkie.v1.Operation.Style.CreatedAtMapByActorEntry.value:type_name -> yorkie.v1.TimeTicket 27, // 109: yorkie.v1.Operation.TreeEdit.CreatedAtMapByActorEntry.value:type_name -> yorkie.v1.TimeTicket 10, // 110: yorkie.v1.JSONElement.JSONObject.nodes:type_name -> yorkie.v1.RHTNode @@ -4709,7 +4766,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Set); i { case 0: return &v.state @@ -4721,7 +4778,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Add); i { case 0: return &v.state @@ -4733,7 +4790,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Move); i { case 0: return &v.state @@ -4745,7 +4802,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Remove); i { case 0: return &v.state @@ -4757,7 +4814,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Edit); i { case 0: return &v.state @@ -4769,7 +4826,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Select); i { case 0: return &v.state @@ -4781,7 +4838,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Style); i { case 0: return &v.state @@ -4793,7 +4850,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_Increase); i { case 0: return &v.state @@ -4805,7 +4862,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_TreeEdit); i { case 0: return &v.state @@ -4817,7 +4874,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Operation_TreeStyle); i { case 0: return &v.state @@ -4829,7 +4886,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_JSONObject); i { case 0: return &v.state @@ -4841,7 +4898,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_JSONArray); i { case 0: return &v.state @@ -4853,7 +4910,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_Primitive); i { case 0: return &v.state @@ -4865,7 +4922,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_Text); i { case 0: return &v.state @@ -4877,7 +4934,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_Counter); i { case 0: return &v.state @@ -4889,7 +4946,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONElement_Tree); i { case 0: return &v.state @@ -4901,7 +4958,7 @@ func file_yorkie_v1_resources_proto_init() { return nil } } - file_yorkie_v1_resources_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_yorkie_v1_resources_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdatableProjectFields_AuthWebhookMethods); i { case 0: return &v.state @@ -4940,7 +4997,7 @@ func file_yorkie_v1_resources_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_yorkie_v1_resources_proto_rawDesc, NumEnums: 3, - NumMessages: 54, + NumMessages: 55, NumExtensions: 0, NumServices: 0, }, diff --git a/api/yorkie/v1/resources.proto b/api/yorkie/v1/resources.proto index 1b186a94a..d485d407f 100644 --- a/api/yorkie/v1/resources.proto +++ b/api/yorkie/v1/resources.proto @@ -46,6 +46,8 @@ message ChangePack { repeated Change changes = 4; TimeTicket min_synced_ticket = 5; bool is_removed = 6; + string latest_version_vector = 7; + string synced_version_vector = 8; } message Change { @@ -53,6 +55,8 @@ message Change { string message = 2; repeated Operation operations = 3; PresenceChange presence_change = 4; + map vector_clock = 5; + bool detach_flag = 6; } message ChangeID { @@ -90,7 +94,7 @@ message Operation { TimeTicket parent_created_at = 1; TextNodePos from = 2; TextNodePos to = 3; - map created_at_map_by_actor = 4; + map vector_clock = 4; string content = 5; TimeTicket executed_at = 6; map attributes = 7; @@ -325,6 +329,7 @@ message Presence { message Checkpoint { int64 server_seq = 1 [jstype = JS_STRING]; uint32 client_seq = 2; + int64 latest_server_seq = 3 [jstype = JS_STRING]; } message TextNodePos { diff --git a/client/client.go b/client/client.go index f1673a9ac..5d042cd62 100644 --- a/client/client.go +++ b/client/client.go @@ -272,6 +272,7 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document, options ... } doc.SetActor(c.id) + doc.InternalDocument().VersionVector().ChangeActorID(c.id) if err := doc.Update(func(root *json.Object, p *presence.Presence) error { p.Initialize(opts.Presence) @@ -353,6 +354,10 @@ func (c *Client) Detach(ctx context.Context, doc *document.Document, options ... return err } + if err := doc.SetDetachFlag(); err != nil { + return err + } + pbChangePack, err := converter.ToChangePack(doc.CreateChangePack()) if err != nil { return err @@ -629,7 +634,6 @@ func (c *Client) pushPullChanges(ctx context.Context, opt SyncOptions) error { if err != nil { return err } - if err := attachment.doc.ApplyChangePack(pack); err != nil { return err } diff --git a/pkg/document/change/change.go b/pkg/document/change/change.go index 88a638ba1..ffe3fb513 100644 --- a/pkg/document/change/change.go +++ b/pkg/document/change/change.go @@ -39,15 +39,24 @@ type Change struct { // presenceChange represents the presenceChange of the user who made the change. // TODO(hackerwins): Consider using changes instead of entire presenceChange. presenceChange *innerpresence.PresenceChange + + // vectorClock is a Actor's vectorClock with this change applied. + vectorClock time.VectorClock + + // detachFlag indicates that the Actor has been removed since this change. + detachFlag bool } // New creates a new instance of Change. -func New(id ID, message string, operations []operations.Operation, p *innerpresence.PresenceChange) *Change { +func New(id ID, message string, operations []operations.Operation, + p *innerpresence.PresenceChange, vc time.VectorClock, dflag bool) *Change { return &Change{ id: id, message: message, operations: operations, presenceChange: p, + vectorClock: vc, + detachFlag: dflag, } } @@ -112,3 +121,23 @@ func (c *Change) SetActor(actor *time.ActorID) { func (c *Change) PresenceChange() *innerpresence.PresenceChange { return c.presenceChange } + +// VectorClock returns the vectorClock of this change. +func (c *Change) VectorClock() time.VectorClock { + return c.vectorClock +} + +// SetVectorClock copy and sets the given vectorClock. +func (c *Change) SetVectorClock(vectorClock time.VectorClock) { + c.vectorClock = vectorClock.Copy() +} + +// DetachFlag returns the detach flag of this change. +func (c *Change) DetachFlag() bool { + return c.detachFlag +} + +// SetDetachFlag sets the given detach flag. +func (c *Change) SetDetachFlag(flag bool) { + c.detachFlag = flag +} diff --git a/pkg/document/change/checkpoint.go b/pkg/document/change/checkpoint.go index 8967b9c43..7eddb8e1d 100644 --- a/pkg/document/change/checkpoint.go +++ b/pkg/document/change/checkpoint.go @@ -28,18 +28,24 @@ const ( // InitialServerSeq is the initial sequence number of the server. InitialServerSeq = 0 + // LatestChangeSeq is the latest change's server sequence of the client. + LatestChangeSeq = 0 + // MaxClientSeq is the maximum sequence number of the client. MaxClientSeq = math.MaxUint32 // MaxServerSeq is the maximum sequence number of the server. MaxServerSeq = int64(math.MaxInt64) + + // MaxLatestChangeSeq is the maximum sequence number of the latest change. + MaxLatestChangeSeq = int64(math.MaxInt64) ) // InitialCheckpoint is the initial value of Checkpoint. -var InitialCheckpoint = NewCheckpoint(InitialServerSeq, InitialClientSeq) +var InitialCheckpoint = NewCheckpoint(InitialServerSeq, InitialClientSeq, LatestChangeSeq) // MaxCheckpoint is the maximum value of Checkpoint. -var MaxCheckpoint = NewCheckpoint(MaxServerSeq, MaxClientSeq) +var MaxCheckpoint = NewCheckpoint(MaxServerSeq, MaxClientSeq, MaxLatestChangeSeq) // Checkpoint is used to determine the client received changes. // It is not meant to be used to determine the logical order of changes. @@ -52,13 +58,17 @@ type Checkpoint struct { // clientSeq is the sequence of the change within the client that made the // change. ClientSeq uint32 + + // LatestChangeSeq is the latest change's server sequence of the client. + LatestChangeSeq int64 } // NewCheckpoint creates a new instance of Checkpoint. -func NewCheckpoint(serverSeq int64, clientSeq uint32) Checkpoint { +func NewCheckpoint(serverSeq int64, clientSeq uint32, latestChangeSeq int64) Checkpoint { return Checkpoint{ - ServerSeq: serverSeq, - ClientSeq: clientSeq, + ServerSeq: serverSeq, + ClientSeq: clientSeq, + LatestChangeSeq: latestChangeSeq, } } @@ -68,7 +78,7 @@ func (cp Checkpoint) NextServerSeq(serverSeq int64) Checkpoint { return cp } - return NewCheckpoint(serverSeq, cp.ClientSeq) + return NewCheckpoint(serverSeq, cp.ClientSeq, cp.LatestChangeSeq) } // NextClientSeq creates a new instance with next client sequence. @@ -81,14 +91,14 @@ func (cp Checkpoint) IncreaseClientSeq(inc uint32) Checkpoint { if inc == 0 { return cp } - return NewCheckpoint(cp.ServerSeq, cp.ClientSeq+inc) + return NewCheckpoint(cp.ServerSeq, cp.ClientSeq+inc, cp.LatestChangeSeq) } // SyncClientSeq updates the given clientSeq if it is greater than the internal // value. func (cp Checkpoint) SyncClientSeq(clientSeq uint32) Checkpoint { if cp.ClientSeq < clientSeq { - return NewCheckpoint(cp.ServerSeq, clientSeq) + return NewCheckpoint(cp.ServerSeq, clientSeq, cp.LatestChangeSeq) } return cp @@ -111,7 +121,7 @@ func (cp Checkpoint) Forward(other Checkpoint) Checkpoint { maxClientSeq = other.ClientSeq } - return NewCheckpoint(maxServerSeq, maxClientSeq) + return NewCheckpoint(maxServerSeq, maxClientSeq, cp.LatestChangeSeq) } // Equals returns whether the given checkpoint is equal to this checkpoint or not. @@ -124,3 +134,8 @@ func (cp Checkpoint) Equals(other Checkpoint) bool { func (cp Checkpoint) String() string { return fmt.Sprintf("serverSeq=%d, clientSeq=%d", cp.ServerSeq, cp.ClientSeq) } + +// SetLatestChangeSeq sets the latest change's server sequence of the client. +func (cp *Checkpoint) SetLatestChangeSeq(seq int64) { + cp.LatestChangeSeq = seq +} diff --git a/pkg/document/change/checkpoint_test.go b/pkg/document/change/checkpoint_test.go index 940c146f7..6fe5b238a 100644 --- a/pkg/document/change/checkpoint_test.go +++ b/pkg/document/change/checkpoint_test.go @@ -26,30 +26,30 @@ import ( func TestCheckPoint(t *testing.T) { t.Run("check point test", func(t *testing.T) { - cp := change.NewCheckpoint(change.InitialServerSeq, change.InitialClientSeq) - assert.True(t, cp.Equals(change.NewCheckpoint(0, 0))) - assert.False(t, cp.Equals(change.NewCheckpoint(1, 1))) - assert.False(t, cp.Equals(change.NewCheckpoint(1, 0))) - assert.False(t, cp.Equals(change.NewCheckpoint(0, 1))) - assert.False(t, cp.Equals(change.NewCheckpoint(1, 1))) + cp := change.NewCheckpoint(change.InitialServerSeq, change.InitialClientSeq, change.LatestChangeSeq) + assert.True(t, cp.Equals(change.NewCheckpoint(0, 0, 0))) + assert.False(t, cp.Equals(change.NewCheckpoint(1, 1, 0))) + assert.False(t, cp.Equals(change.NewCheckpoint(1, 0, 0))) + assert.False(t, cp.Equals(change.NewCheckpoint(0, 1, 0))) + assert.False(t, cp.Equals(change.NewCheckpoint(1, 1, 0))) assert.Equal(t, "serverSeq=0, clientSeq=0", cp.String()) assert.Equal(t, cp, cp.NextServerSeq(0)) - assert.Equal(t, change.NewCheckpoint(5, 0), cp.NextServerSeq(5)) - assert.Equal(t, change.NewCheckpoint(0, 1), cp.NextClientSeq()) - assert.Equal(t, change.NewCheckpoint(0, 0), cp.IncreaseClientSeq(0)) - assert.Equal(t, change.NewCheckpoint(0, 5), cp.IncreaseClientSeq(5)) - - cp = change.NewCheckpoint(10, 20) - assert.Equal(t, change.NewCheckpoint(10, 20), cp.SyncClientSeq(5)) - assert.Equal(t, change.NewCheckpoint(10, 30), cp.SyncClientSeq(30)) - - assert.Equal(t, cp, cp.Forward(change.NewCheckpoint(1, 2))) - assert.Equal(t, change.NewCheckpoint(20, 30), - cp.Forward(change.NewCheckpoint(20, 30))) - assert.Equal(t, change.NewCheckpoint(10, 30), - cp.Forward(change.NewCheckpoint(5, 30))) - assert.Equal(t, change.NewCheckpoint(20, 20), - cp.Forward(change.NewCheckpoint(20, 5))) + assert.Equal(t, change.NewCheckpoint(5, 0, 0), cp.NextServerSeq(5)) + assert.Equal(t, change.NewCheckpoint(0, 1, 0), cp.NextClientSeq()) + assert.Equal(t, change.NewCheckpoint(0, 0, 0), cp.IncreaseClientSeq(0)) + assert.Equal(t, change.NewCheckpoint(0, 5, 0), cp.IncreaseClientSeq(5)) + + cp = change.NewCheckpoint(10, 20, 0) + assert.Equal(t, change.NewCheckpoint(10, 20, 0), cp.SyncClientSeq(5)) + assert.Equal(t, change.NewCheckpoint(10, 30, 0), cp.SyncClientSeq(30)) + + assert.Equal(t, cp, cp.Forward(change.NewCheckpoint(1, 2, 0))) + assert.Equal(t, change.NewCheckpoint(20, 30, 0), + cp.Forward(change.NewCheckpoint(20, 30, 0))) + assert.Equal(t, change.NewCheckpoint(10, 30, 0), + cp.Forward(change.NewCheckpoint(5, 30, 0))) + assert.Equal(t, change.NewCheckpoint(20, 20, 0), + cp.Forward(change.NewCheckpoint(20, 5, 0))) }) } diff --git a/pkg/document/change/context.go b/pkg/document/change/context.go index c494644fb..377f64dc0 100644 --- a/pkg/document/change/context.go +++ b/pkg/document/change/context.go @@ -33,14 +33,16 @@ type Context struct { delimiter uint32 root *crdt.Root presenceChange *innerpresence.PresenceChange + vectorClock time.VectorClock } // NewContext creates a new instance of Context. -func NewContext(id ID, message string, root *crdt.Root) *Context { +func NewContext(id ID, message string, root *crdt.Root, vectorClock time.VectorClock) *Context { return &Context{ - id: id, - message: message, - root: root, + id: id, + message: message, + root: root, + vectorClock: vectorClock, } } @@ -51,7 +53,7 @@ func (c *Context) ID() ID { // ToChange creates a new change of this context. func (c *Context) ToChange() *Change { - return New(c.id, c.message, c.operations, c.presenceChange) + return New(c.id, c.message, c.operations, c.presenceChange, nil, false) } // HasChange returns whether this context has changes. @@ -94,3 +96,8 @@ func (c *Context) LastTimeTicket() *time.Ticket { func (c *Context) SetPresenceChange(presenceChange innerpresence.PresenceChange) { c.presenceChange = &presenceChange } + +// VectorClock returns the vector clock of this context. +func (c *Context) VectorClock() time.VectorClock { + return c.vectorClock +} diff --git a/pkg/document/change/pack.go b/pkg/document/change/pack.go index 55f6409ab..06f288f19 100644 --- a/pkg/document/change/pack.go +++ b/pkg/document/change/pack.go @@ -41,6 +41,14 @@ type Pack struct { // IsRemoved is a flag that indicates whether the document is removed. IsRemoved bool + + // LatestVersionVector is the latest VersionVector of the document. + // It used to build document from the snapshot. + LatestVersionVector time.VectorClock + + // SyncedVersionVector is the Synced VersionVector of the document. + // It used to collect garbage on the replica on the client. + SyncedVersionVector time.VectorClock } // NewPack creates a new instance of Pack. diff --git a/pkg/document/crdt/element.go b/pkg/document/crdt/element.go index 5330ced41..91f344cd3 100644 --- a/pkg/document/crdt/element.go +++ b/pkg/document/crdt/element.go @@ -43,7 +43,8 @@ type Container interface { type GCElement interface { Element removedNodesLen() int - purgeRemovedNodesBefore(ticket *time.Ticket) (int, error) + //TODO(highcloud100): Check the case where minSeqVector[actor.String()] is nil + purgeRemovedNodesBefore(minSeqVector time.VectorClock) (int, error) } // Element represents JSON element. diff --git a/pkg/document/crdt/rga_tree_split.go b/pkg/document/crdt/rga_tree_split.go index b1f497d2f..82c8f18c1 100644 --- a/pkg/document/crdt/rga_tree_split.go +++ b/pkg/document/crdt/rga_tree_split.go @@ -445,23 +445,23 @@ func (s *RGATreeSplit[V]) findFloorNode(id *RGATreeSplitNodeID) *RGATreeSplitNod func (s *RGATreeSplit[V]) edit( from *RGATreeSplitNodePos, to *RGATreeSplitNodePos, - latestCreatedAtMapByActor map[string]*time.Ticket, + vectorClock *time.VectorClock, content V, editedAt *time.Ticket, -) (*RGATreeSplitNodePos, map[string]*time.Ticket, error) { +) (*RGATreeSplitNodePos, error) { // 01. Split nodes with from and to toLeft, toRight, err := s.findNodeWithSplit(to, editedAt) if err != nil { - return nil, nil, err + return nil, err } fromLeft, fromRight, err := s.findNodeWithSplit(from, editedAt) if err != nil { - return nil, nil, err + return nil, err } // 02. delete between from and to nodesToDelete := s.findBetween(fromRight, toRight) - latestCreatedAtMap, removedNodeMapByNodeKey := s.deleteNodes(nodesToDelete, latestCreatedAtMapByActor, editedAt) + removedNodeMapByNodeKey := s.deleteNodes(nodesToDelete, vectorClock, editedAt) var caretID *RGATreeSplitNodeID if toRight == nil { @@ -482,7 +482,7 @@ func (s *RGATreeSplit[V]) edit( s.removedNodeMap[key] = removedNode } - return caretPos, latestCreatedAtMap, nil + return caretPos, nil } func (s *RGATreeSplit[V]) findBetween(from, to *RGATreeSplitNode[V]) []*RGATreeSplitNode[V] { @@ -497,14 +497,13 @@ func (s *RGATreeSplit[V]) findBetween(from, to *RGATreeSplitNode[V]) []*RGATreeS func (s *RGATreeSplit[V]) deleteNodes( candidates []*RGATreeSplitNode[V], - latestCreatedAtMapByActor map[string]*time.Ticket, + vectorClock *time.VectorClock, editedAt *time.Ticket, -) (map[string]*time.Ticket, map[string]*RGATreeSplitNode[V]) { - createdAtMapByActor := make(map[string]*time.Ticket) +) map[string]*RGATreeSplitNode[V] { removedNodeMap := make(map[string]*RGATreeSplitNode[V]) if len(candidates) == 0 { - return createdAtMapByActor, removedNodeMap + return removedNodeMap } // There are 2 types of nodes in `candidates`: should delete, should not delete. @@ -515,27 +514,25 @@ func (s *RGATreeSplit[V]) deleteNodes( nodesToKeep = append(nodesToKeep, leftEdge) for _, node := range candidates { - actorIDHex := node.createdAt().ActorIDHex() - - var latestCreatedAt *time.Ticket - if latestCreatedAtMapByActor == nil { - latestCreatedAt = time.MaxTicket + actorID := node.createdAt().ActorID() + + // TODO(highcloud100): rename the latestSyncedAt. + // vectorClock can replace the editedAt, + // but then the way to get editedAt.ActorID() disappears. + // replace and add argument of actorID to the vectorClock. + var latestSyncedAt *time.Ticket + if vectorClock == nil { + latestSyncedAt = time.MaxTicket } else { - createdAt, ok := latestCreatedAtMapByActor[actorIDHex] + createdAt, ok := (*vectorClock)[actorID.String()] if ok { - latestCreatedAt = createdAt + latestSyncedAt = time.NewTicket(createdAt, time.MaxDelimiter, editedAt.ActorID()) } else { - latestCreatedAt = time.InitialTicket + latestSyncedAt = time.InitialTicket } } - if node.Remove(editedAt, latestCreatedAt) { - latestCreatedAt := createdAtMapByActor[actorIDHex] - createdAt := node.id.createdAt - if latestCreatedAt == nil || createdAt.After(latestCreatedAt) { - createdAtMapByActor[actorIDHex] = createdAt - } - + if node.Remove(editedAt, latestSyncedAt) { removedNodeMap[node.id.key()] = node } else { nodesToKeep = append(nodesToKeep, node) @@ -544,7 +541,7 @@ func (s *RGATreeSplit[V]) deleteNodes( nodesToKeep = append(nodesToKeep, rightEdge) s.deleteIndexNodes(nodesToKeep) - return createdAtMapByActor, removedNodeMap + return removedNodeMap } // findEdgesOfCandidates finds the edges outside `candidates`, @@ -623,9 +620,12 @@ func (s *RGATreeSplit[V]) removedNodesLen() int { } // purgeRemovedNodesBefore physically purges nodes that have been removed. -func (s *RGATreeSplit[V]) purgeRemovedNodesBefore(ticket *time.Ticket) (int, error) { +func (s *RGATreeSplit[V]) purgeRemovedNodesBefore(minSeqVector time.VectorClock) (int, error) { count := 0 for _, node := range s.removedNodeMap { + lamport := minSeqVector[node.removedAt.ActorID().String()] + // For now new ticket's actorID is always the same as the node's actorID. + ticket := time.NewTicket(lamport, time.MaxDelimiter, node.removedAt.ActorID()) if node.removedAt != nil && ticket.Compare(node.removedAt) >= 0 { s.treeByIndex.Delete(node.indexNode) s.purge(node) diff --git a/pkg/document/crdt/root.go b/pkg/document/crdt/root.go index 73db7de88..581e0904a 100644 --- a/pkg/document/crdt/root.go +++ b/pkg/document/crdt/root.go @@ -138,11 +138,20 @@ func (r *Root) DeepCopy() (*Root, error) { } // GarbageCollect purge elements that were removed before the given time. -func (r *Root) GarbageCollect(ticket *time.Ticket) (int, error) { +func (r *Root) GarbageCollect(SyncedVersionVector time.VectorClock) (int, error) { count := 0 + if len(r.removedElementPairMapByCreatedAt) == 0 && len(r.elementHasRemovedNodesSetByCreatedAt) == 0 { + return count, nil + } + for _, pair := range r.removedElementPairMapByCreatedAt { - if pair.elem.RemovedAt() != nil && ticket.Compare(pair.elem.RemovedAt()) >= 0 { + actor := pair.elem.RemovedAt().ActorID() + + //TODO(highcloud100): Check the case where SyncedVersionVector[actor.String()] is nil + minTicket := time.NewTicket(SyncedVersionVector[actor.String()], time.MaxDelimiter, actor) + + if pair.elem.RemovedAt() != nil && minTicket.Compare(pair.elem.RemovedAt()) >= 0 { if err := pair.parent.Purge(pair.elem); err != nil { return 0, err } @@ -152,7 +161,8 @@ func (r *Root) GarbageCollect(ticket *time.Ticket) (int, error) { } for _, node := range r.elementHasRemovedNodesSetByCreatedAt { - purgedNodes, err := node.purgeRemovedNodesBefore(ticket) + + purgedNodes, err := node.purgeRemovedNodesBefore(SyncedVersionVector) if err != nil { return 0, err } diff --git a/pkg/document/crdt/root_test.go b/pkg/document/crdt/root_test.go index e6c6a8b2e..798cdd7cf 100644 --- a/pkg/document/crdt/root_test.go +++ b/pkg/document/crdt/root_test.go @@ -22,7 +22,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/yorkie-team/yorkie/pkg/document/crdt" - "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/test/helper" ) @@ -54,7 +53,7 @@ func TestRoot(t *testing.T) { assert.Equal(t, "[0,2]", array.Marshal()) assert.Equal(t, 1, root.GarbageLen()) - n, err := root.GarbageCollect(time.MaxTicket) + n, err := root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 1, n) assert.Equal(t, 0, root.GarbageLen()) @@ -66,28 +65,28 @@ func TestRoot(t *testing.T) { text := crdt.NewText(crdt.NewRGATreeSplit(crdt.InitialTextNode()), ctx.IssueTimeTicket()) fromPos, toPos, _ := text.CreateRange(0, 0) - _, _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) + _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, "Hello World", text.String()) assert.Equal(t, 0, root.GarbageLen()) fromPos, toPos, _ = text.CreateRange(5, 10) - _, _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, "HelloYorkied", text.String()) assert.Equal(t, 1, root.GarbageLen()) fromPos, toPos, _ = text.CreateRange(0, 5) - _, _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, "Yorkied", text.String()) assert.Equal(t, 2, root.GarbageLen()) fromPos, toPos, _ = text.CreateRange(6, 7) - _, _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, "Yorkie", text.String()) @@ -98,7 +97,7 @@ func TestRoot(t *testing.T) { nodeLen := len(text.Nodes()) assert.Equal(t, 4, nodeLen) - n, err := root.GarbageCollect(time.MaxTicket) + n, err := root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 3, n) assert.Equal(t, 0, root.GarbageLen()) @@ -128,14 +127,14 @@ func TestRoot(t *testing.T) { for _, tc := range tests { fromPos, toPos, _ := text.CreateRange(tc.from, tc.to) - _, _, err := text.Edit(fromPos, toPos, nil, tc.content, nil, ctx.IssueTimeTicket()) + _, err := text.Edit(fromPos, toPos, nil, tc.content, nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, tc.want, text.String()) assert.Equal(t, tc.garbage, root.GarbageLen()) } - n, err := root.GarbageCollect(time.MaxTicket) + n, err := root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 3, n) assert.Equal(t, 0, root.GarbageLen()) @@ -147,21 +146,21 @@ func TestRoot(t *testing.T) { text := crdt.NewText(crdt.NewRGATreeSplit(crdt.InitialTextNode()), ctx.IssueTimeTicket()) fromPos, toPos, _ := text.CreateRange(0, 0) - _, _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) + _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, `[{"val":"Hello World"}]`, text.Marshal()) assert.Equal(t, 0, root.GarbageLen()) fromPos, toPos, _ = text.CreateRange(6, 11) - _, _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, `[{"val":"Hello "},{"val":"Yorkie"}]`, text.Marshal()) assert.Equal(t, 1, root.GarbageLen()) fromPos, toPos, _ = text.CreateRange(0, 6) - _, _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) registerElementHasRemovedNodes(fromPos, toPos, root, text) assert.Equal(t, `[{"val":"Yorkie"}]`, text.Marshal()) @@ -172,7 +171,7 @@ func TestRoot(t *testing.T) { nodeLen := len(text.Nodes()) assert.Equal(t, 3, nodeLen) - garbageLen, err := root.GarbageCollect(time.MaxTicket) + garbageLen, err := root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 2, garbageLen) assert.Equal(t, 0, root.GarbageLen()) @@ -210,7 +209,7 @@ func TestRoot(t *testing.T) { assert.Equal(t, `{"1":1,"3":3}`, obj.Marshal()) assert.Equal(t, 4, root.GarbageLen()) - n, err := root.GarbageCollect(time.MaxTicket) + n, err := root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 4, n) assert.Equal(t, 0, root.GarbageLen()) @@ -220,7 +219,7 @@ func TestRoot(t *testing.T) { assert.Equal(t, `{"1":1}`, obj.Marshal()) assert.Equal(t, 1, root.GarbageLen()) - n, err = root.GarbageCollect(time.MaxTicket) + n, err = root.GarbageCollect(helper.MaxVectorClock()) assert.NoError(t, err) assert.Equal(t, 1, n) assert.Equal(t, 0, root.GarbageLen()) diff --git a/pkg/document/crdt/text.go b/pkg/document/crdt/text.go index a5e81ad1d..47fbe99b5 100644 --- a/pkg/document/crdt/text.go +++ b/pkg/document/crdt/text.go @@ -223,11 +223,11 @@ func (t *Text) CreateRange(from, to int) (*RGATreeSplitNodePos, *RGATreeSplitNod func (t *Text) Edit( from, to *RGATreeSplitNodePos, - latestCreatedAtMapByActor map[string]*time.Ticket, + vectorClock *time.VectorClock, content string, attributes map[string]string, executedAt *time.Ticket, -) (*RGATreeSplitNodePos, map[string]*time.Ticket, error) { +) (*RGATreeSplitNodePos, error) { val := NewTextValue(content, NewRHT()) for key, value := range attributes { val.attrs.Set(key, value, executedAt) @@ -236,7 +236,7 @@ func (t *Text) Edit( return t.rgaTreeSplit.edit( from, to, - latestCreatedAtMapByActor, + vectorClock, val, executedAt, ) @@ -323,6 +323,6 @@ func (t *Text) removedNodesLen() int { } // purgeRemovedNodesBefore physically purges nodes that have been removed. -func (t *Text) purgeRemovedNodesBefore(ticket *time.Ticket) (int, error) { - return t.rgaTreeSplit.purgeRemovedNodesBefore(ticket) +func (t *Text) purgeRemovedNodesBefore(minSeqVector time.VectorClock) (int, error) { + return t.rgaTreeSplit.purgeRemovedNodesBefore(minSeqVector) } diff --git a/pkg/document/crdt/text_test.go b/pkg/document/crdt/text_test.go index 0b2ee5ed1..e97acab2a 100644 --- a/pkg/document/crdt/text_test.go +++ b/pkg/document/crdt/text_test.go @@ -32,12 +32,12 @@ func TestText(t *testing.T) { text := crdt.NewText(crdt.NewRGATreeSplit(crdt.InitialTextNode()), ctx.IssueTimeTicket()) fromPos, toPos, _ := text.CreateRange(0, 0) - _, _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) + _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) assert.Equal(t, `[{"val":"Hello World"}]`, text.Marshal()) fromPos, toPos, _ = text.CreateRange(6, 11) - _, _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) assert.Equal(t, `[{"val":"Hello "},{"val":"Yorkie"}]`, text.Marshal()) }) @@ -70,12 +70,12 @@ func TestText(t *testing.T) { text := crdt.NewText(crdt.NewRGATreeSplit(crdt.InitialTextNode()), ctx.IssueTimeTicket()) fromPos, toPos, _ := text.CreateRange(0, 0) - _, _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) + _, err := text.Edit(fromPos, toPos, nil, "Hello World", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) assert.Equal(t, `[{"val":"Hello World"}]`, text.Marshal()) fromPos, toPos, _ = text.CreateRange(6, 11) - _, _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) + _, err = text.Edit(fromPos, toPos, nil, "Yorkie", nil, ctx.IssueTimeTicket()) assert.NoError(t, err) assert.Equal(t, `[{"val":"Hello "},{"val":"Yorkie"}]`, text.Marshal()) diff --git a/pkg/document/crdt/tree.go b/pkg/document/crdt/tree.go index ad160a420..017333483 100644 --- a/pkg/document/crdt/tree.go +++ b/pkg/document/crdt/tree.go @@ -427,11 +427,13 @@ func (t *Tree) removedNodesLen() int { } // purgeRemovedNodesBefore physically purges nodes that have been removed. -func (t *Tree) purgeRemovedNodesBefore(ticket *time.Ticket) (int, error) { +func (t *Tree) purgeRemovedNodesBefore(minSeqVector time.VectorClock) (int, error) { count := 0 nodesToBeRemoved := make(map[*TreeNode]bool) for _, node := range t.removedNodeMap { + lamport := minSeqVector[node.RemovedAt.ActorID().String()] + ticket := time.NewTicket(lamport, time.MaxDelimiter, node.RemovedAt.ActorID()) if node.RemovedAt != nil && ticket.Compare(node.RemovedAt) >= 0 { count++ nodesToBeRemoved[node] = true diff --git a/pkg/document/document.go b/pkg/document/document.go index 347b25507..df7a5e2e4 100644 --- a/pkg/document/document.go +++ b/pkg/document/document.go @@ -99,6 +99,40 @@ type Document struct { payload []byte) error } +// // PrintSyncedVectorMap prints the synced vector map. +// func (d *Document) PrintSyncedVectorMap(me string) { +// you := "" +// if me == "A" { +// you = "B" +// } else { +// you = "A" +// } + +// cur := d.doc.ActorID().String() +// testMap := make(map[string](map[string]int64)) +// who := "" +// for k, v := range d.doc.syncedVectorMap { +// temp := make(map[string]int64) +// for k2, v2 := range v { +// if k2 == cur { +// who = me +// } else { +// who = you +// } +// temp[who] = v2 +// } +// if k == cur { +// who = me +// } else { +// who = you +// } +// testMap[who] = temp +// } + +// v, _ := gojson.Marshal(testMap) +// fmt.Println(string(v)) +// } + // New creates a new instance of Document. func New(key key.Key) *Document { return &Document{ @@ -124,11 +158,13 @@ func (d *Document) Update( if err := d.ensureClone(); err != nil { return err } + actorID := d.doc.ActorID().String() - ctx := change.NewContext( + ctx := change.NewContext( // vectorClock update and copy d.doc.changeID.Next(), messageFromMsgAndArgs(msgAndArgs...), d.cloneRoot, + d.doc.versionVector.CopyAndSet(actorID, d.doc.Lamport()+1), ) if err := updater( @@ -147,6 +183,11 @@ func (d *Document) Update( return err } + // Update the vector clock of the actor. + d.doc.versionVector[actorID] = ctx.ID().Lamport() + // Set the vector clock to change. + c.SetVectorClock(d.doc.versionVector) + d.doc.localChanges = append(d.doc.localChanges, c) d.doc.changeID = ctx.ID() } @@ -160,7 +201,8 @@ func (d *Document) ApplyChangePack(pack *change.Pack) error { if len(pack.Snapshot) > 0 { d.cloneRoot = nil d.clonePresences = nil - if err := d.doc.applySnapshot(pack.Snapshot, pack.Checkpoint.ServerSeq); err != nil { + if err := d.doc.applySnapshot(pack.Snapshot, pack.Checkpoint.ServerSeq, + pack.LatestVersionVector); err != nil { return err } } else { @@ -197,7 +239,7 @@ func (d *Document) ApplyChangePack(pack *change.Pack) error { d.doc.checkpoint = d.doc.checkpoint.Forward(pack.Checkpoint) // 04. Do Garbage collection. - d.GarbageCollect(pack.MinSyncedTicket) + d.GarbageCollect(pack.SyncedVersionVector) // 05. Update the status. if pack.IsRemoved { @@ -274,19 +316,19 @@ func (d *Document) Root() *json.Object { panic(err) } - ctx := change.NewContext(d.doc.changeID.Next(), "", d.cloneRoot) + ctx := change.NewContext(d.doc.changeID.Next(), "", d.cloneRoot, d.doc.versionVector.Copy()) return json.NewObject(ctx, d.cloneRoot.Object()) } // GarbageCollect purge elements that were removed before the given time. -func (d *Document) GarbageCollect(ticket *time.Ticket) int { +func (d *Document) GarbageCollect(SyncedVersionVector time.VectorClock) int { if d.cloneRoot != nil { - if _, err := d.cloneRoot.GarbageCollect(ticket); err != nil { + if _, err := d.cloneRoot.GarbageCollect(SyncedVersionVector); err != nil { panic(err) } } - n, err := d.doc.GarbageCollect(ticket) + n, err := d.doc.GarbageCollect(SyncedVersionVector) if err != nil { panic(err) } @@ -430,3 +472,9 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { } return "" } + +// SetDetachFlag set the last change's detach flag as true. +// It is used to remove the vector clock of detached Actor from SyncedVectorClock. +func (d *Document) SetDetachFlag() error { + return d.doc.SetDetachFlag() +} diff --git a/pkg/document/document_test.go b/pkg/document/document_test.go index 1046efd53..9b81730e2 100644 --- a/pkg/document/document_test.go +++ b/pkg/document/document_test.go @@ -28,7 +28,7 @@ import ( "github.com/yorkie-team/yorkie/pkg/document/crdt" "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/presence" - "github.com/yorkie-team/yorkie/pkg/document/time" + "github.com/yorkie-team/yorkie/test/helper" ) var ( @@ -487,7 +487,7 @@ func TestDocument(t *testing.T) { ) assert.Equal(t, 1, doc.GarbageLen()) - doc.GarbageCollect(time.MaxTicket) + doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID())) assert.Equal(t, 0, doc.GarbageLen()) assert.Equal( t, @@ -520,7 +520,7 @@ func TestDocument(t *testing.T) { assert.Equal(t, "{}", doc.Marshal()) assert.Equal(t, 2, doc.GarbageLen()) - doc.GarbageCollect(time.MaxTicket) + doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID())) assert.Equal(t, "{}", doc.Marshal()) assert.Equal(t, 0, doc.GarbageLen()) }) diff --git a/pkg/document/internal_document.go b/pkg/document/internal_document.go index 4f1cdd1ad..637b622d6 100644 --- a/pkg/document/internal_document.go +++ b/pkg/document/internal_document.go @@ -85,6 +85,9 @@ type InternalDocument struct { // localChanges is the list of the changes that are not yet sent to the // server. localChanges []*change.Change + + // versionVector is the version vector of the document. + versionVector time.VectorClock } // NewInternalDocument creates a new instance of InternalDocument. @@ -100,6 +103,7 @@ func NewInternalDocument(k key.Key) *InternalDocument { changeID: change.InitialID, presences: innerpresence.NewMap(), onlineClients: &gosync.Map{}, + versionVector: time.InitialVectorClock(), } } @@ -109,12 +113,24 @@ func NewInternalDocumentFromSnapshot( serverSeq int64, lamport int64, snapshot []byte, + versionVector string, ) (*InternalDocument, error) { obj, presences, err := converter.BytesToSnapshot(snapshot) if err != nil { return nil, err } + id := change.InitialID.SyncLamport(lamport) + + versionVec, err := time.NewVectorClockFromJSON(versionVector) + if err != nil { + return nil, err + } + + if versionVec == nil { + versionVec = time.VectorClock{time.InitialActorID.String(): id.Lamport()} + } + return &InternalDocument{ key: k, status: StatusDetached, @@ -122,7 +138,8 @@ func NewInternalDocumentFromSnapshot( presences: presences, onlineClients: &gosync.Map{}, checkpoint: change.InitialCheckpoint.NextServerSeq(serverSeq), - changeID: change.InitialID.SyncLamport(lamport), + changeID: id, + versionVector: versionVec, }, nil } @@ -145,7 +162,7 @@ func (d *InternalDocument) HasLocalChanges() bool { func (d *InternalDocument) ApplyChangePack(pack *change.Pack) error { // 01. Apply remote changes to both the cloneRoot and the document. if len(pack.Snapshot) > 0 { - if err := d.applySnapshot(pack.Snapshot, pack.Checkpoint.ServerSeq); err != nil { + if err := d.applySnapshot(pack.Snapshot, pack.Checkpoint.ServerSeq, pack.LatestVersionVector); err != nil { return err } } else { @@ -166,18 +183,16 @@ func (d *InternalDocument) ApplyChangePack(pack *change.Pack) error { // 03. Update the checkpoint. d.checkpoint = d.checkpoint.Forward(pack.Checkpoint) - if pack.MinSyncedTicket != nil { - if _, err := d.GarbageCollect(pack.MinSyncedTicket); err != nil { - return err - } + if _, err := d.GarbageCollect(pack.SyncedVersionVector); err != nil { + return err } return nil } // GarbageCollect purge elements that were removed before the given time. -func (d *InternalDocument) GarbageCollect(ticket *time.Ticket) (int, error) { - return d.root.GarbageCollect(ticket) +func (d *InternalDocument) GarbageCollect(SyncedVersionVector time.VectorClock) (int, error) { + return d.root.GarbageCollect(SyncedVersionVector) } // GarbageLen returns the count of removed elements. @@ -237,15 +252,24 @@ func (d *InternalDocument) RootObject() *crdt.Object { return d.root.Object() } -func (d *InternalDocument) applySnapshot(snapshot []byte, serverSeq int64) error { +func (d *InternalDocument) applySnapshot( + snapshot []byte, + serverSeq int64, + LatestVersionVector time.VectorClock, +) error { rootObj, presences, err := converter.BytesToSnapshot(snapshot) if err != nil { return err } + // Delete initial actor from VersionVector. + // Initial actor used for the server or the not attached client. + delete(LatestVersionVector, time.InitialActorID.String()) + d.root = crdt.NewRoot(rootObj) d.presences = presences d.changeID = d.changeID.SyncLamport(serverSeq) + d.versionVector = LatestVersionVector return nil } @@ -296,6 +320,10 @@ func (d *InternalDocument) ApplyChanges(changes ...*change.Change) ([]DocEvent, } d.changeID = d.changeID.SyncLamport(c.ID().Lamport()) + changeActorID := c.ID().ActorID().String() + + // update self's synced vector + d.VersionVector()[changeActorID] = c.ID().Lamport() } return events, nil @@ -372,3 +400,27 @@ func (d *InternalDocument) AddOnlineClient(clientID string) { func (d *InternalDocument) RemoveOnlineClient(clientID string) { d.onlineClients.Delete(clientID) } + +// SyncedVectorMap returns the synced vector map of the document. +// NOTE(highcloud100): For now, return the reference to the original map. +// It should be changed to return a deep copy of the map. +// func (d *InternalDocument) SyncedVectorMap() time.SyncedVectorMap { +// return d.syncedVectorMap +// } + +// VersionVector returns the VersionVector of the document. +func (d *InternalDocument) VersionVector() time.VectorClock { + return d.versionVector +} + +// SetDetachFlag set the detach flag as true. +func (d *InternalDocument) SetDetachFlag() error { + length := len(d.localChanges) + + if length == 0 { + return errors.New("doc doesn't have changes") + } + + d.localChanges[length-1].SetDetachFlag(true) + return nil +} diff --git a/pkg/document/json/text.go b/pkg/document/json/text.go index 29cf0e9fa..c77a066bb 100644 --- a/pkg/document/json/text.go +++ b/pkg/document/json/text.go @@ -68,7 +68,7 @@ func (p *Text) Edit(from, to int, content string, attributes ...map[string]strin } ticket := p.context.IssueTimeTicket() - _, maxCreationMapByActor, err := p.Text.Edit( + _, err = p.Text.Edit( fromPos, toPos, nil, @@ -84,7 +84,7 @@ func (p *Text) Edit(from, to int, content string, attributes ...map[string]strin p.CreatedAt(), fromPos, toPos, - maxCreationMapByActor, + p.context.VectorClock(), content, attrs, ticket, diff --git a/pkg/document/operations/edit.go b/pkg/document/operations/edit.go index adafeec43..d24fa8066 100644 --- a/pkg/document/operations/edit.go +++ b/pkg/document/operations/edit.go @@ -34,9 +34,9 @@ type Edit struct { // to represents the end point of the editing range. to *crdt.RGATreeSplitNodePos - // latestCreatedAtMapByActor is a map that stores the latest creation time - // by actor for the nodes included in the editing range. - latestCreatedAtMapByActor map[string]*time.Ticket + // vectorClock present the actor's vector clock when this edit executed + // for the nodes included in the editing range. + vectorClock time.VectorClock // content is the content of text added when editing. content string @@ -53,19 +53,19 @@ func NewEdit( parentCreatedAt *time.Ticket, from *crdt.RGATreeSplitNodePos, to *crdt.RGATreeSplitNodePos, - latestCreatedAtMapByActor map[string]*time.Ticket, + vectorClock time.VectorClock, content string, attributes map[string]string, executedAt *time.Ticket, ) *Edit { return &Edit{ - parentCreatedAt: parentCreatedAt, - from: from, - to: to, - latestCreatedAtMapByActor: latestCreatedAtMapByActor, - content: content, - attributes: attributes, - executedAt: executedAt, + parentCreatedAt: parentCreatedAt, + from: from, + to: to, + vectorClock: vectorClock, + content: content, + attributes: attributes, + executedAt: executedAt, } } @@ -75,7 +75,7 @@ func (e *Edit) Execute(root *crdt.Root) error { switch obj := parent.(type) { case *crdt.Text: - _, _, err := obj.Edit(e.from, e.to, e.latestCreatedAtMapByActor, e.content, e.attributes, e.executedAt) + _, err := obj.Edit(e.from, e.to, &e.vectorClock, e.content, e.attributes, e.executedAt) if err != nil { return err } @@ -124,8 +124,7 @@ func (e *Edit) Attributes() map[string]string { return e.attributes } -// CreatedAtMapByActor returns the map that stores the latest creation time -// by actor for the nodes included in the editing range. -func (e *Edit) CreatedAtMapByActor() map[string]*time.Ticket { - return e.latestCreatedAtMapByActor +// VectorClock returns the vector clock of this operation. +func (e *Edit) VectorClock() time.VectorClock { + return e.vectorClock } diff --git a/pkg/document/time/vector_clock.go b/pkg/document/time/vector_clock.go new file mode 100644 index 000000000..07ea3c68f --- /dev/null +++ b/pkg/document/time/vector_clock.go @@ -0,0 +1,77 @@ +package time + +import ( + "encoding/json" + "fmt" +) + +// VectorClock is a map of actor id to its sequence number. +type VectorClock map[string]int64 + +// NewVectorClockFromJSON creates a new instance of VectorClock. +func NewVectorClockFromJSON(encodedChange string) (VectorClock, error) { + if encodedChange == "" { + return VectorClock{}, nil + } + + vc := VectorClock{} + if err := json.Unmarshal([]byte(encodedChange), &vc); err != nil { + return nil, fmt.Errorf("unmarshal vector clock: %w", err) + } + + return vc, nil +} + +// InitialVectorClock returns an initial vector clock. +func InitialVectorClock() VectorClock { + return VectorClock{InitialActorID.String(): 0} +} + +// ChangeActorID changes the initial ID to given ID of the vector clock. +func (vc VectorClock) ChangeActorID(id *ActorID) { + newID := id.String() + // Already has actor id given from the server. + if vc[newID] != 0 { + return + } + + initID := InitialActorID.String() + + // If current actor id is initial actor id + vc[newID] = vc[initID] + + // delete initialID + delete(vc, initID) +} + +// EncodeToString encodes the given vector clock to string. +func (vc VectorClock) EncodeToString() (string, error) { + bytes, err := json.Marshal(vc) + if err != nil { + return "", fmt.Errorf("marshal vector clock to bytes: %w", err) + } + + return string(bytes), nil +} + +// Copy returns a new deep copied VectorClock. +func (vc VectorClock) Copy() VectorClock { + if vc == nil { + return nil + } + rep := make(VectorClock, len(vc)) + for k, v := range vc { + rep[k] = v + } + return rep +} + +// CopyAndSet copy vectorClock and update `replica[id] = value` and return the replica. +func (vc VectorClock) CopyAndSet(id string, value int64) VectorClock { + if vc == nil { + vc = make(VectorClock) + } + repl := vc.Copy() + repl[id] = value + return repl +} diff --git a/pkg/document/time/vector_clock_test.go b/pkg/document/time/vector_clock_test.go new file mode 100644 index 000000000..30d6dd468 --- /dev/null +++ b/pkg/document/time/vector_clock_test.go @@ -0,0 +1,52 @@ +package time_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/yorkie-team/yorkie/pkg/document/time" + "github.com/yorkie-team/yorkie/test/helper" +) + +func TestVectorClock(t *testing.T) { + t.Run("ChangeActorID test", func(t *testing.T) { + newID, err := time.ActorIDFromHex("111111111111111111111111") + assert.NoError(t, err) + newID2, err := time.ActorIDFromHex("222222222222222222222222") + assert.NoError(t, err) + + vec := time.InitialVectorClock() + vec[newID2.String()] = 2 + + vec.ChangeActorID(newID) + + assert.Equal(t, time.VectorClock{ + newID.String(): 0, + newID2.String(): 2, + }, vec) + }) + + t.Run("MaxVectorClock initial ID test", func(t *testing.T) { + vec := helper.MaxVectorClock() + + assert.Equal(t, time.VectorClock{ + time.InitialActorID.String(): time.MaxLamport, + }, vec) + }) + + t.Run("MaxVectorClock arbitrary IDs test", func(t *testing.T) { + newID1, err := time.ActorIDFromHex("111111111111111111111111") + assert.NoError(t, err) + + newID2, err := time.ActorIDFromHex("222222222222222222222222") + assert.NoError(t, err) + + vec := helper.MaxVectorClock(newID1, newID2) + + assert.Equal(t, time.VectorClock{ + newID1.String(): time.MaxLamport, + newID2.String(): time.MaxLamport, + }, vec) + }) +} diff --git a/server/backend/database/change_info.go b/server/backend/database/change_info.go index f35635d6c..a29a02177 100644 --- a/server/backend/database/change_info.go +++ b/server/backend/database/change_info.go @@ -50,6 +50,9 @@ type ChangeInfo struct { Message string `bson:"message"` Operations [][]byte `bson:"operations"` PresenceChange string `bson:"presence_change"` + VectorClock string `bson:"vector_clock"` + VersionVector string `bson:"version_vector"` + DetachFlag bool `bson:"detach_flag"` } // EncodeOperations encodes the given operations into bytes array. @@ -114,7 +117,12 @@ func (i *ChangeInfo) ToChange() (*change.Change, error) { return nil, err } - c := change.New(changeID, i.Message, ops, p) + vc, err := time.NewVectorClockFromJSON(i.VectorClock) + if err != nil { + return nil, err + } + + c := change.New(changeID, i.Message, ops, p, vc, i.DetachFlag) c.SetServerSeq(i.ServerSeq) return c, nil diff --git a/server/backend/database/client_info.go b/server/backend/database/client_info.go index 0c9e4f3e8..e75ef367b 100644 --- a/server/backend/database/client_info.go +++ b/server/backend/database/client_info.go @@ -49,9 +49,10 @@ const ( // ClientDocInfo is a structure representing information of the document // attached to the client. type ClientDocInfo struct { - Status string `bson:"status"` - ServerSeq int64 `bson:"server_seq"` - ClientSeq uint32 `bson:"client_seq"` + Status string `bson:"status"` + ServerSeq int64 `bson:"server_seq"` + ClientSeq uint32 `bson:"client_seq"` + LatestChangeSeq int64 `bson:"latest_change_seq"` } // ClientDocInfoMap is a map that associates DocRefKey with ClientDocInfo instances. @@ -174,7 +175,7 @@ func (i *ClientInfo) Checkpoint(docID types.ID) change.Checkpoint { return change.InitialCheckpoint } - return change.NewCheckpoint(clientDocInfo.ServerSeq, clientDocInfo.ClientSeq) + return change.NewCheckpoint(clientDocInfo.ServerSeq, clientDocInfo.ClientSeq, clientDocInfo.LatestChangeSeq) } // UpdateCheckpoint updates the checkpoint of the given document. @@ -188,6 +189,7 @@ func (i *ClientInfo) UpdateCheckpoint( i.Documents[docID].ServerSeq = cp.ServerSeq i.Documents[docID].ClientSeq = cp.ClientSeq + i.Documents[docID].LatestChangeSeq = cp.LatestChangeSeq i.UpdatedAt = time.Now() return nil diff --git a/server/backend/database/database.go b/server/backend/database/database.go index a5016dce8..c586787f9 100644 --- a/server/backend/database/database.go +++ b/server/backend/database/database.go @@ -194,6 +194,7 @@ type Database interface { initialServerSeq int64, changes []*change.Change, isRemoved bool, + latestVersionVector time.VectorClock, ) error // PurgeStaleChanges delete changes before the smallest in `syncedseqs` to @@ -246,14 +247,14 @@ type Database interface { docRefKey types.DocRefKey, ) (*SyncedSeqInfo, error) - // UpdateAndFindMinSyncedTicket updates the given serverSeq of the given client - // and returns the min synced ticket. - UpdateAndFindMinSyncedTicket( + // UpdateAndFindSyncdVersionVector updates the given serverSeq of the given client + // and returns the SyncedVersionVector of the document. + UpdateAndFindSyncdVersionVector( ctx context.Context, clientInfo *ClientInfo, docRefKey types.DocRefKey, serverSeq int64, - ) (*time.Ticket, error) + ) (string, error) // UpdateSyncedSeq updates the syncedSeq of the given client. UpdateSyncedSeq( diff --git a/server/backend/database/doc_info.go b/server/backend/database/doc_info.go index 088efcaff..3c06f1846 100644 --- a/server/backend/database/doc_info.go +++ b/server/backend/database/doc_info.go @@ -51,6 +51,10 @@ type DocInfo struct { // RemovedAt is the time when the document is removed. RemovedAt time.Time `bson:"removed_at"` + + // LatestVersionVector is the latest vector clock of the document. + // It is calculated by the cumulative of the vector clocks of the changes. + LatestVersionVector string `bson:"latest_version_vector"` } // IncreaseServerSeq increases server sequence of the document. diff --git a/server/backend/database/memory/database.go b/server/backend/database/memory/database.go index 8e1f1185d..c2421519f 100644 --- a/server/backend/database/memory/database.go +++ b/server/backend/database/memory/database.go @@ -826,7 +826,11 @@ func (d *DB) CreateChangeInfos( initialServerSeq int64, changes []*change.Change, isRemoved bool, + latestVersionVector time.VectorClock, ) error { + // NOTE(highcloud100) : Need to update memory database like mongoDB + _ = latestVersionVector + txn := d.db.Txn(true) defer txn.Abort() @@ -1120,54 +1124,61 @@ func (d *DB) FindMinSyncedSeqInfo( return syncedSeqInfo, nil } -// UpdateAndFindMinSyncedTicket updates the given serverSeq of the given client -// and returns the min synced ticket. -func (d *DB) UpdateAndFindMinSyncedTicket( +// UpdateAndFindSyncdVersionVector updates the given serverSeq of the given client +// and returns the SyncdVersionVector of the document. +func (d *DB) UpdateAndFindSyncdVersionVector( ctx context.Context, clientInfo *database.ClientInfo, docRefKey types.DocRefKey, serverSeq int64, -) (*time.Ticket, error) { - if err := d.UpdateSyncedSeq(ctx, clientInfo, docRefKey, serverSeq); err != nil { - return nil, err - } - - txn := d.db.Txn(false) - defer txn.Abort() - - iterator, err := txn.LowerBound( - tblSyncedSeqs, - "doc_id_lamport_actor_id", - docRefKey.DocID.String(), - int64(0), - time.InitialActorID.String(), - ) - if err != nil { - return nil, fmt.Errorf("fetch smallest syncedseq of %s: %w", docRefKey.DocID, err) - } - - var syncedSeqInfo *database.SyncedSeqInfo - if raw := iterator.Next(); raw != nil { - info := raw.(*database.SyncedSeqInfo) - if info.DocID == docRefKey.DocID { - syncedSeqInfo = info - } - } - - if syncedSeqInfo == nil || syncedSeqInfo.ServerSeq == change.InitialServerSeq { - return time.InitialTicket, nil - } - - actorID, err := time.ActorIDFromHex(syncedSeqInfo.ActorID.String()) - if err != nil { - return nil, err - } - - return time.NewTicket( - syncedSeqInfo.Lamport, - time.MaxDelimiter, - actorID, - ), nil +) (string, error) { + // NOTE(highcloud100) : Need to update memory database like mongoDB + _ = serverSeq + _ = ctx + _ = clientInfo + _ = docRefKey + return "", nil + + // if err := d.UpdateSyncedSeq(ctx, clientInfo, docRefKey, serverSeq); err != nil { + // return nil, err + // } + + // txn := d.db.Txn(false) + // defer txn.Abort() + + // iterator, err := txn.LowerBound( + // tblSyncedSeqs, + // "doc_id_lamport_actor_id", + // docRefKey.DocID.String(), + // int64(0), + // time.InitialActorID.String(), + // ) + // if err != nil { + // return nil, fmt.Errorf("fetch smallest syncedseq of %s: %w", docRefKey.DocID, err) + // } + + // var syncedSeqInfo *database.SyncedSeqInfo + // if raw := iterator.Next(); raw != nil { + // info := raw.(*database.SyncedSeqInfo) + // if info.DocID == docRefKey.DocID { + // syncedSeqInfo = info + // } + // } + + // if syncedSeqInfo == nil || syncedSeqInfo.ServerSeq == change.InitialServerSeq { + // return time.InitialTicket, nil + // } + + // actorID, err := time.ActorIDFromHex(syncedSeqInfo.ActorID.String()) + // if err != nil { + // return nil, err + // } + + // return time.NewTicket( + // syncedSeqInfo.Lamport, + // time.MaxDelimiter, + // actorID, + // ), nil } // UpdateSyncedSeq updates the syncedSeq of the given client. diff --git a/server/backend/database/mongo/client.go b/server/backend/database/mongo/client.go index 6a9f40e38..8c9718cd6 100644 --- a/server/backend/database/mongo/client.go +++ b/server/backend/database/mongo/client.go @@ -43,6 +43,8 @@ import ( const ( // StatusKey is the key of the status field. StatusKey = "status" + // ServerSeqKey is the key of the server_seq field. + ServerSeqKey = "server_seq" ) // Client is a client that connects to Mongo DB and reads or saves Yorkie data. @@ -579,8 +581,9 @@ func (c *Client) UpdateClientInfoAfterPushPull( updater := bson.M{ "$max": bson.M{ - clientDocInfoKey + "server_seq": clientDocInfo.ServerSeq, - clientDocInfoKey + "client_seq": clientDocInfo.ClientSeq, + clientDocInfoKey + ServerSeqKey: clientDocInfo.ServerSeq, + clientDocInfoKey + "client_seq": clientDocInfo.ClientSeq, + clientDocInfoKey + "latest_change_seq": clientDocInfo.LatestChangeSeq, }, "$set": bson.M{ clientDocInfoKey + StatusKey: clientDocInfo.Status, @@ -596,7 +599,7 @@ func (c *Client) UpdateClientInfoAfterPushPull( if !attached { updater = bson.M{ "$set": bson.M{ - clientDocInfoKey + "server_seq": 0, + clientDocInfoKey + ServerSeqKey: 0, clientDocInfoKey + "client_seq": 0, clientDocInfoKey + StatusKey: clientDocInfo.Status, "updated_at": clientInfo.UpdatedAt, @@ -684,7 +687,7 @@ func (c *Client) FindDocInfoByKeyAndOwner( }, bson.M{ "$set": bson.M{ "owner": clientRefKey.ClientID, - "server_seq": 0, + ServerSeqKey: 0, "created_at": now, }, }) @@ -795,6 +798,7 @@ func (c *Client) CreateChangeInfos( initialServerSeq int64, changes []*change.Change, isRemoved bool, + latestVersionVector time.VectorClock, ) error { docRefKey := docInfo.RefKey() @@ -808,11 +812,24 @@ func (c *Client) CreateChangeInfos( if err != nil { return err } + encodedVectorClock, err := cn.VectorClock().EncodeToString() + if err != nil { + return err + } + + // update the latest version vector + latestVersionVector[cn.ID().ActorID().String()] = max( + cn.ID().Lamport(), latestVersionVector[cn.ID().ActorID().String()]) + + lvv, err := latestVersionVector.EncodeToString() + if err != nil { + return err + } models = append(models, mongo.NewUpdateOneModel().SetFilter(bson.M{ "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, - "server_seq": cn.ServerSeq(), + ServerSeqKey: cn.ServerSeq(), }).SetUpdate(bson.M{"$set": bson.M{ "actor_id": cn.ID().ActorID(), "client_seq": cn.ID().ClientSeq(), @@ -820,6 +837,9 @@ func (c *Client) CreateChangeInfos( "message": cn.Message(), "operations": encodedOperations, "presence_change": encodedPresence, + "vector_clock": encodedVectorClock, + "version_vector": lvv, + "detach_flag": cn.DetachFlag(), }}).SetUpsert(true)) } @@ -835,10 +855,17 @@ func (c *Client) CreateChangeInfos( } } + // encode string and save the latest vector clock + lvv, err := latestVersionVector.EncodeToString() + if err != nil { + return err + } + now := gotime.Now() updateFields := bson.M{ - "server_seq": docInfo.ServerSeq, - "updated_at": now, + ServerSeqKey: docInfo.ServerSeq, + "updated_at": now, + "latest_version_vector": lvv, } if isRemoved { updateFields["removed_at"] = now @@ -847,7 +874,7 @@ func (c *Client) CreateChangeInfos( res, err := c.collection(ColDocuments).UpdateOne(ctx, bson.M{ "project_id": docRefKey.ProjectID, "_id": docRefKey.DocID, - "server_seq": initialServerSeq, + ServerSeqKey: initialServerSeq, }, bson.M{ "$set": updateFields, }) @@ -878,7 +905,7 @@ func (c *Client) PurgeStaleChanges( "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, }, - options.FindOne().SetSort(bson.M{"server_seq": 1}), + options.FindOne().SetSort(bson.M{ServerSeqKey: 1}), ) if result.Err() == mongo.ErrNoDocuments { return nil @@ -897,7 +924,7 @@ func (c *Client) PurgeStaleChanges( bson.M{ "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, - "server_seq": bson.M{"$lt": minSyncedSeqInfo.ServerSeq}, + ServerSeqKey: bson.M{"$lt": minSyncedSeqInfo.ServerSeq}, }, options.Delete(), ); err != nil { @@ -941,7 +968,7 @@ func (c *Client) FindChangeInfosBetweenServerSeqs( cursor, err := c.collection(ColChanges).Find(ctx, bson.M{ "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, - "server_seq": bson.M{ + ServerSeqKey: bson.M{ "$gte": from, "$lte": to, }, @@ -969,13 +996,19 @@ func (c *Client) CreateSnapshotInfo( return err } + latestVectorClock, err := doc.VersionVector().EncodeToString() + if err != nil { + return err + } + if _, err := c.collection(ColSnapshots).InsertOne(ctx, bson.M{ - "project_id": docRefKey.ProjectID, - "doc_id": docRefKey.DocID, - "server_seq": doc.Checkpoint().ServerSeq, - "lamport": doc.Lamport(), - "snapshot": snapshot, - "created_at": gotime.Now(), + "project_id": docRefKey.ProjectID, + "doc_id": docRefKey.DocID, + ServerSeqKey: doc.Checkpoint().ServerSeq, + "lamport": doc.Lamport(), + "snapshot": snapshot, + "created_at": gotime.Now(), + "latest_vector_clock": latestVectorClock, }); err != nil { return fmt.Errorf("insert snapshot: %w", err) } @@ -991,7 +1024,7 @@ func (c *Client) FindSnapshotInfoByRefKey( result := c.collection(ColSnapshots).FindOne(ctx, bson.M{ "project_id": refKey.ProjectID, "doc_id": refKey.DocID, - "server_seq": refKey.ServerSeq, + ServerSeqKey: refKey.ServerSeq, }) snapshotInfo := &database.SnapshotInfo{} @@ -1017,7 +1050,7 @@ func (c *Client) FindClosestSnapshotInfo( includeSnapshot bool, ) (*database.SnapshotInfo, error) { option := options.FindOne().SetSort(bson.M{ - "server_seq": -1, + ServerSeqKey: -1, }) if !includeSnapshot { @@ -1027,7 +1060,7 @@ func (c *Client) FindClosestSnapshotInfo( result := c.collection(ColSnapshots).FindOne(ctx, bson.M{ "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, - "server_seq": bson.M{ + ServerSeqKey: bson.M{ "$lte": serverSeq, }, }, option) @@ -1056,7 +1089,7 @@ func (c *Client) FindMinSyncedSeqInfo( "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, }, options.FindOne().SetSort(bson.D{ - {Key: "server_seq", Value: 1}, + {Key: ServerSeqKey, Value: 1}, })) if syncedSeqResult.Err() == mongo.ErrNoDocuments { syncedSeqInfo := database.SyncedSeqInfo{} @@ -1074,51 +1107,82 @@ func (c *Client) FindMinSyncedSeqInfo( return &syncedSeqInfo, nil } -// UpdateAndFindMinSyncedTicket updates the given serverSeq of the given client -// and returns the min synced ticket. -func (c *Client) UpdateAndFindMinSyncedTicket( +// UpdateAndFindSyncdVersionVector updates the given serverSeq of the given client +// and returns the SyncdVersionVetor of the document. +func (c *Client) UpdateAndFindSyncdVersionVector( ctx context.Context, clientInfo *database.ClientInfo, docRefKey types.DocRefKey, serverSeq int64, -) (*time.Ticket, error) { +) (string, error) { if err := c.UpdateSyncedSeq(ctx, clientInfo, docRefKey, serverSeq); err != nil { - return nil, err + return "", err } - // 02. find min synced seq of the given document. - result := c.collection(ColSyncedSeqs).FindOne(ctx, bson.M{ - "project_id": docRefKey.ProjectID, - "doc_id": docRefKey.DocID, + // NOTE(highcloud100) : we need to decide the standard of the synced sequence. + // Now Assume that the change client took is synchronized sequence. + // However, as with the previous version, the changes taken by the client cannot be assumed to be applied + + clientDocInfoKey := getClientDocInfoKey(docRefKey.DocID) + result := c.collection(ColClients).FindOne(ctx, bson.M{ + "project_id": docRefKey.ProjectID, + "status": database.ClientActivated, + clientDocInfoKey + "status": database.DocumentAttached, }, options.FindOne().SetSort(bson.D{ - {Key: "lamport", Value: 1}, - {Key: "actor_id", Value: 1}, + {Key: clientDocInfoKey + ServerSeqKey, Value: 1}, })) if result.Err() == mongo.ErrNoDocuments { - return time.InitialTicket, nil + return "", nil } if result.Err() != nil { - return nil, fmt.Errorf("find smallest syncedseq: %w", result.Err()) + return "", fmt.Errorf("find smallest syncedseq: %w", result.Err()) } - syncedSeqInfo := database.SyncedSeqInfo{} + + syncedSeqInfo := database.ClientInfo{} if err := result.Decode(&syncedSeqInfo); err != nil { - return nil, fmt.Errorf("decode syncedseq: %w", err) + return "", fmt.Errorf("decode syncedseq: %w", err) + } + + // // 02. find min synced seq of the given document. + // result := c.collection(ColSyncedSeqs).FindOne(ctx, bson.M{ + // "project_id": docRefKey.ProjectID, + // "doc_id": docRefKey.DocID, + // }, options.FindOne().SetSort(bson.D{ + // {Key: ServerSeqKey, Value: 1}, + // })) + // if result.Err() == mongo.ErrNoDocuments { + // return "", nil + // } + // if result.Err() != nil { + // return "", fmt.Errorf("find smallest syncedseq: %w", result.Err()) + // } + + // syncedSeqInfo := database.SyncedSeqInfo{} + // if err := result.Decode(&syncedSeqInfo); err != nil { + // return "", fmt.Errorf("decode syncedseq: %w", err) + // } + + // 03. find the latest vector clock of the smallest synced seq. + result = c.collection(ColChanges).FindOne(ctx, bson.M{ + "project_id": docRefKey.ProjectID, + "doc_id": docRefKey.DocID, + ServerSeqKey: syncedSeqInfo.Documents[docRefKey.DocID].ServerSeq, + }, options.FindOne().SetSort(bson.D{ + {Key: "lamport", Value: 1}, + })) + if result.Err() == mongo.ErrNoDocuments { + return "", nil } - - if syncedSeqInfo.ServerSeq == change.InitialServerSeq { - return time.InitialTicket, nil + if result.Err() != nil { + return "", fmt.Errorf("find server seq's change: %w", result.Err()) } - actorID, err := time.ActorIDFromHex(syncedSeqInfo.ActorID.String()) - if err != nil { - return nil, err + changeInfo := database.ChangeInfo{} + if err := result.Decode(&changeInfo); err != nil { + return "", fmt.Errorf("decode change: %w", err) } - return time.NewTicket( - syncedSeqInfo.Lamport, - time.MaxDelimiter, - actorID, - ), nil + return changeInfo.VersionVector, nil } // FindDocInfosByPaging returns the docInfos of the given paging. @@ -1234,7 +1298,7 @@ func (c *Client) UpdateSyncedSeq( "$set": bson.M{ "lamport": ticket.Lamport(), "actor_id": ticket.ActorID(), - "server_seq": serverSeq, + ServerSeqKey: serverSeq, }, }, options.Update().SetUpsert(true)); err != nil { return fmt.Errorf("upsert synced seq: %w", err) @@ -1279,7 +1343,7 @@ func (c *Client) findTicketByServerSeq( result := c.collection(ColChanges).FindOne(ctx, bson.M{ "project_id": docRefKey.ProjectID, "doc_id": docRefKey.DocID, - "server_seq": serverSeq, + ServerSeqKey: serverSeq, }) if result.Err() == mongo.ErrNoDocuments { return nil, fmt.Errorf( diff --git a/server/backend/database/snapshot_info.go b/server/backend/database/snapshot_info.go index ca0255f96..314f0ee7f 100644 --- a/server/backend/database/snapshot_info.go +++ b/server/backend/database/snapshot_info.go @@ -44,6 +44,9 @@ type SnapshotInfo struct { // CreatedAt is the time when the snapshot is created. CreatedAt time.Time `bson:"created_at"` + + // VersionVector is the latest vector clock of the snapshot. + VersionVector string `bson:"version_vector"` } // DeepCopy returns a deep copy of the SnapshotInfo. @@ -53,13 +56,14 @@ func (i *SnapshotInfo) DeepCopy() *SnapshotInfo { } return &SnapshotInfo{ - ID: i.ID, - ProjectID: i.ProjectID, - DocID: i.DocID, - ServerSeq: i.ServerSeq, - Lamport: i.Lamport, - Snapshot: i.Snapshot, - CreatedAt: i.CreatedAt, + ID: i.ID, + ProjectID: i.ProjectID, + DocID: i.DocID, + ServerSeq: i.ServerSeq, + Lamport: i.Lamport, + Snapshot: i.Snapshot, + CreatedAt: i.CreatedAt, + VersionVector: i.VersionVector, } } diff --git a/server/backend/database/testcases/testcases.go b/server/backend/database/testcases/testcases.go index bddbfb9d7..99bf2a904 100644 --- a/server/backend/database/testcases/testcases.go +++ b/server/backend/database/testcases/testcases.go @@ -206,6 +206,8 @@ func RunFindChangesBetweenServerSeqsTest( actorID, _ := time.ActorIDFromBytes(bytesID) doc := document.New(key.Key(t.Name())) doc.SetActor(actorID) + doc.InternalDocument().VersionVector().ChangeActorID(actorID) + assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error { root.SetNewArray("array") return nil @@ -222,7 +224,7 @@ func RunFindChangesBetweenServerSeqsTest( } // Store changes - err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, pack.Changes, false) + err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, pack.Changes, false, time.VectorClock{}) assert.NoError(t, err) // Find changes @@ -250,6 +252,7 @@ func RunFindClosestSnapshotInfoTest(t *testing.T, db database.Database, projectI doc := document.New(key.Key(t.Name())) doc.SetActor(actorID) + doc.InternalDocument().VersionVector().ChangeActorID(actorID) assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error { root.SetNewArray("array") @@ -694,9 +697,9 @@ func RunFindDocInfosByPagingTest(t *testing.T, db database.Database, projectID t AssertKeys(t, docKeysInReverse, result) // 03. Remove some documents. - err = db.CreateChangeInfos(ctx, projectInfo.ID, docInfos[1], 0, []*change.Change{}, true) + err = db.CreateChangeInfos(ctx, projectInfo.ID, docInfos[1], 0, []*change.Change{}, true, time.VectorClock{}) assert.NoError(t, err) - err = db.CreateChangeInfos(ctx, projectInfo.ID, docInfos[3], 0, []*change.Change{}, true) + err = db.CreateChangeInfos(ctx, projectInfo.ID, docInfos[3], 0, []*change.Change{}, true, time.VectorClock{}) assert.NoError(t, err) // 04. List the documents again and check the filtered result. @@ -724,7 +727,7 @@ func RunCreateChangeInfosTest(t *testing.T, db database.Database, projectID type assert.NoError(t, db.UpdateClientInfoAfterPushPull(ctx, clientInfo, docInfo)) // 02. Remove the document and check the document is removed. - err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, []*change.Change{}, true) + err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, []*change.Change{}, true, time.VectorClock{}) assert.NoError(t, err) docInfo, err = db.FindDocInfoByRefKey(ctx, docRefKey) assert.NoError(t, err) @@ -744,7 +747,7 @@ func RunCreateChangeInfosTest(t *testing.T, db database.Database, projectID type // 02. Remove the document. assert.NoError(t, clientInfo1.RemoveDocument(docRefKey1.DocID)) - err := db.CreateChangeInfos(ctx, projectID, docInfo1, 0, []*change.Change{}, true) + err := db.CreateChangeInfos(ctx, projectID, docInfo1, 0, []*change.Change{}, true, time.VectorClock{}) assert.NoError(t, err) // 03. Create a document with same key and check they have same key but different id. @@ -771,7 +774,7 @@ func RunCreateChangeInfosTest(t *testing.T, db database.Database, projectID type // Set removed_at in docInfo and store changes assert.NoError(t, clientInfo.RemoveDocument(docInfo.ID)) - err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, pack.Changes, true) + err := db.CreateChangeInfos(ctx, projectID, docInfo, 0, pack.Changes, true, time.VectorClock{}) assert.NoError(t, err) // Check whether removed_at is set in docInfo diff --git a/server/packs/packs.go b/server/packs/packs.go index 6015dbf68..a3f392d09 100644 --- a/server/packs/packs.go +++ b/server/packs/packs.go @@ -30,6 +30,7 @@ import ( "github.com/yorkie-team/yorkie/pkg/document" "github.com/yorkie-team/yorkie/pkg/document/change" "github.com/yorkie-team/yorkie/pkg/document/key" + "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/pkg/units" "github.com/yorkie-team/yorkie/server/backend" "github.com/yorkie-team/yorkie/server/backend/database" @@ -70,6 +71,12 @@ func PushPull( // We should check the change.pack with checkpoint to make sure the changes are in the correct order. initialServerSeq := docInfo.ServerSeq + // This used to save the LatestVersionVector in each serverSeq's change info. + latestVersionVector, err := time.NewVectorClockFromJSON(docInfo.LatestVersionVector) + if err != nil { + return nil, err + } + // 01. push changes: filter out the changes that are already saved in the database. cpAfterPush, pushedChanges := pushChanges(ctx, clientInfo, docInfo, reqPack, initialServerSeq) be.Metrics.AddPushPullReceivedChanges(reqPack.ChangesLen()) @@ -98,6 +105,7 @@ func PushPull( initialServerSeq, pushedChanges, reqPack.IsRemoved, + latestVersionVector, ); err != nil { return nil, err } @@ -110,7 +118,7 @@ func PushPull( // 04. update and find min synced ticket for garbage collection. // NOTE(hackerwins): Since the client could not receive the response, the // requested seq(reqPack) is stored instead of the response seq(resPack). - minSyncedTicket, err := be.DB.UpdateAndFindMinSyncedTicket( + syncedVersionVector, err := be.DB.UpdateAndFindSyncdVersionVector( ctx, clientInfo, docRefKey, @@ -119,8 +127,9 @@ func PushPull( if err != nil { return nil, err } - respPack.MinSyncedTicket = minSyncedTicket + respPack.ApplyDocInfo(docInfo) + respPack.SyncedVersionVector = syncedVersionVector pullLog := strconv.Itoa(respPack.ChangesLen()) if respPack.SnapshotLen() > 0 { @@ -132,7 +141,7 @@ func PushPull( clientInfo.Key, len(pushedChanges), pullLog, - minSyncedTicket.ToTestString(), + //minSyncedTicket.ToTestString(), ) // 05. publish document change event then store snapshot asynchronously. @@ -177,7 +186,6 @@ func PushPull( ctx, be, docInfo, - minSyncedTicket, ); err != nil { logging.From(ctx).Error(err) } @@ -213,6 +221,7 @@ func BuildDocumentForServerSeq( snapshotInfo.ServerSeq, snapshotInfo.Lamport, snapshotInfo.Snapshot, + snapshotInfo.VersionVector, ) if err != nil { return nil, err diff --git a/server/packs/pushpull.go b/server/packs/pushpull.go index ca87c87ae..4e52e9187 100644 --- a/server/packs/pushpull.go +++ b/server/packs/pushpull.go @@ -63,6 +63,11 @@ func pushChanges( cp = cp.SyncClientSeq(cn.ClientSeq()) } + // If the client has pushed changes, update the latest change seq. + if len(reqPack.Changes) > 0 { + cp.SetLatestChangeSeq(cp.ServerSeq) + } + if len(reqPack.Changes) > 0 { logging.From(ctx).Debugf( "PUSH: '%s' pushes %d changes into '%s', rejected %d changes, serverSeq: %d -> %d, cp: %s", @@ -95,7 +100,7 @@ func pullPack( return NewServerPack(docInfo.Key, change.Checkpoint{ ServerSeq: reqPack.Checkpoint.ServerSeq, ClientSeq: cpAfterPush.ClientSeq, - }, nil, nil), nil + }, nil, nil, "", ""), nil } if initialServerSeq < reqPack.Checkpoint.ServerSeq { @@ -122,7 +127,7 @@ func pullPack( return nil, err } - return NewServerPack(docInfo.Key, cpAfterPull, pulledChanges, nil), nil + return NewServerPack(docInfo.Key, cpAfterPull, pulledChanges, nil, "", ""), nil } return pullSnapshot(ctx, be, clientInfo, docInfo, reqPack, cpAfterPush, initialServerSeq) @@ -155,6 +160,7 @@ func pullSnapshot( return nil, err } } + cpAfterPull := cpAfterPush.NextServerSeq(docInfo.ServerSeq) snapshot, err := converter.SnapshotToBytes(doc.RootObject(), doc.AllPresences()) @@ -171,7 +177,12 @@ func pullSnapshot( cpAfterPull, ) - return NewServerPack(docInfo.Key, cpAfterPull, nil, snapshot), err + latestVersionVector, err := doc.VersionVector().EncodeToString() + if err != nil { + return nil, err + } + + return NewServerPack(docInfo.Key, cpAfterPull, nil, snapshot, latestVersionVector, ""), err } func pullChangeInfos( diff --git a/server/packs/serverpacks.go b/server/packs/serverpacks.go index e77152bb6..d38572090 100644 --- a/server/packs/serverpacks.go +++ b/server/packs/serverpacks.go @@ -49,6 +49,12 @@ type ServerPack struct { // IsRemoved is a flag that indicates whether the document is removed. IsRemoved bool + + // LatestVersionVector is the latest vector clock of the document. + LatestVersionVector string + + // SyncedVersionVector is the minimum vector clock of the document. + SyncedVersionVector string } // NewServerPack creates a new instance of ServerPack. @@ -57,12 +63,16 @@ func NewServerPack( cp change.Checkpoint, changeInfos []*database.ChangeInfo, snapshot []byte, + latestVersionVector string, + syncedVersionVector string, ) *ServerPack { return &ServerPack{ - DocumentKey: key, - Checkpoint: cp, - ChangeInfos: changeInfos, - Snapshot: snapshot, + DocumentKey: key, + Checkpoint: cp, + ChangeInfos: changeInfos, + Snapshot: snapshot, + LatestVersionVector: latestVersionVector, + SyncedVersionVector: syncedVersionVector, } } @@ -109,21 +119,30 @@ func (p *ServerPack) ToPBChangePack() (*api.ChangePack, error) { return nil, err } + vc, err := time.NewVectorClockFromJSON(info.VectorClock) + if err != nil { + return nil, err + } + pbChanges = append(pbChanges, &api.Change{ Id: converter.ToChangeID(changeID), Message: info.Message, Operations: pbOps, PresenceChange: converter.ToPresenceChange(p), + VectorClock: vc, + DetachFlag: info.DetachFlag, }) } return &api.ChangePack{ - DocumentKey: p.DocumentKey.String(), - Checkpoint: converter.ToCheckpoint(p.Checkpoint), - Changes: pbChanges, - Snapshot: p.Snapshot, - MinSyncedTicket: converter.ToTimeTicket(p.MinSyncedTicket), - IsRemoved: p.IsRemoved, + DocumentKey: p.DocumentKey.String(), + Checkpoint: converter.ToCheckpoint(p.Checkpoint), + Changes: pbChanges, + Snapshot: p.Snapshot, + MinSyncedTicket: converter.ToTimeTicket(p.MinSyncedTicket), + IsRemoved: p.IsRemoved, + LatestVersionVector: p.LatestVersionVector, + SyncedVersionVector: p.SyncedVersionVector, }, nil } diff --git a/server/packs/snapshots.go b/server/packs/snapshots.go index 39b0c915d..5b534fdd7 100644 --- a/server/packs/snapshots.go +++ b/server/packs/snapshots.go @@ -21,7 +21,6 @@ import ( "github.com/yorkie-team/yorkie/pkg/document" "github.com/yorkie-team/yorkie/pkg/document/change" - "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/server/backend" "github.com/yorkie-team/yorkie/server/backend/database" "github.com/yorkie-team/yorkie/server/logging" @@ -31,7 +30,6 @@ func storeSnapshot( ctx context.Context, be *backend.Backend, docInfo *database.DocInfo, - minSyncedTicket *time.Ticket, ) error { // 01. get the closest snapshot's metadata of this docInfo docRefKey := docInfo.RefKey() @@ -78,6 +76,7 @@ func storeSnapshot( snapshotInfo.ServerSeq, snapshotInfo.Lamport, snapshotInfo.Snapshot, + snapshotInfo.VersionVector, ) if err != nil { return err @@ -89,7 +88,6 @@ func storeSnapshot( changes, nil, ) - pack.MinSyncedTicket = minSyncedTicket if err := doc.ApplyChangePack(pack); err != nil { return err diff --git a/server/rpc/admin_server.go b/server/rpc/admin_server.go index dc57c66c9..69ee10a7a 100644 --- a/server/rpc/admin_server.go +++ b/server/rpc/admin_server.go @@ -231,9 +231,15 @@ func (s *adminServer) GetSnapshotMeta( return nil, err } + latestVectorClock, err := doc.VersionVector().EncodeToString() + if err != nil { + return nil, err + } + return connect.NewResponse(&api.GetSnapshotMetaResponse{ - Lamport: doc.Lamport(), - Snapshot: snapshot, + Lamport: doc.Lamport(), + Snapshot: snapshot, + LatestVectorClock: latestVectorClock, }), nil } diff --git a/test/bench/document_bench_test.go b/test/bench/document_bench_test.go index 2c3de7dff..9cf150c64 100644 --- a/test/bench/document_bench_test.go +++ b/test/bench/document_bench_test.go @@ -30,7 +30,7 @@ import ( "github.com/yorkie-team/yorkie/pkg/document/crdt" "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/presence" - "github.com/yorkie-team/yorkie/pkg/document/time" + "github.com/yorkie-team/yorkie/test/helper" ) func BenchmarkDocument(b *testing.B) { @@ -582,7 +582,7 @@ func benchmarkTreeEditGC(cnt int, b *testing.B) { }) assert.NoError(b, err) assert.Equal(b, cnt, doc.GarbageLen()) - assert.Equal(b, cnt, doc.GarbageCollect(time.MaxTicket)) + assert.Equal(b, cnt, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) } } @@ -617,7 +617,7 @@ func benchmarkTreeSplitGC(cnt int, b *testing.B) { }) assert.NoError(b, err) assert.Equal(b, cnt, doc.GarbageLen()) - assert.Equal(b, cnt, doc.GarbageCollect(time.MaxTicket)) + assert.Equal(b, cnt, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) } } @@ -686,7 +686,7 @@ func benchmarkTextEditGC(cnt int, b *testing.B) { }, "replace contents with b") assert.NoError(b, err) assert.Equal(b, cnt, doc.GarbageLen()) - assert.Equal(b, cnt, doc.GarbageCollect(time.MaxTicket)) + assert.Equal(b, cnt, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) } } @@ -718,7 +718,7 @@ func benchmarkTextSplitGC(cnt int, b *testing.B) { assert.NoError(b, err) assert.Equal(b, cnt, doc.GarbageLen()) - assert.Equal(b, cnt, doc.GarbageCollect(time.MaxTicket)) + assert.Equal(b, cnt, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) } } @@ -756,7 +756,7 @@ func benchmarkArrayGC(cnt int, b *testing.B) { }, "deletes the array") assert.NoError(b, err) - assert.Equal(b, cnt+1, doc.GarbageCollect(time.MaxTicket)) + assert.Equal(b, cnt+1, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) assert.NoError(b, err) } } diff --git a/test/bench/push_pull_bench_test.go b/test/bench/push_pull_bench_test.go index b6d981037..b1964f2c0 100644 --- a/test/bench/push_pull_bench_test.go +++ b/test/bench/push_pull_bench_test.go @@ -97,6 +97,7 @@ func setUpClientsAndDocs( actorID, _ := time.ActorIDFromBytes(bytesID) doc := document.New(docKey) doc.SetActor(actorID) + doc.InternalDocument().VersionVector().ChangeActorID(actorID) assert.NoError(b, doc.Update(func(root *json.Object, _ *presence.Presence) error { root.SetNewArray("array") return nil diff --git a/test/helper/helper.go b/test/helper/helper.go index 1dc282b74..fc3fd9efc 100644 --- a/test/helper/helper.go +++ b/test/helper/helper.go @@ -116,6 +116,7 @@ func TextChangeContext(root *crdt.Root) *change.Context { change.InitialID, "", root, + time.VectorClock{change.InitialID.ActorID().String(): 0}, ) } @@ -486,3 +487,19 @@ func WaitForServerToStart(addr string) error { return fmt.Errorf("timeout for server to start: %s", addr) } + +// MaxVectorClock return the SyncedVectorMap that contains the given actors as key and Max Lamport. +func MaxVectorClock(actors ...*time.ActorID) time.VectorClock { + + if len(actors) == 0 { + actors = append(actors, time.InitialActorID) + } + + vectorClock := time.VectorClock{} + + for i := 0; i < len(actors); i++ { + vectorClock[actors[i].String()] = time.MaxLamport + } + + return vectorClock +} diff --git a/test/integration/array_test.go b/test/integration/array_test.go index f4935ef8a..deded6e62 100644 --- a/test/integration/array_test.go +++ b/test/integration/array_test.go @@ -29,7 +29,6 @@ import ( "github.com/yorkie-team/yorkie/pkg/document/crdt" "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/presence" - "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/test/helper" ) @@ -265,7 +264,7 @@ func TestArray(t *testing.T) { })) assert.Equal(t, 8, d1.GarbageLen()) - assert.Equal(t, 8, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, 8, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) }) t.Run("array.set with value sync test", func(t *testing.T) { @@ -467,7 +466,7 @@ func TestArraySet(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, tt.tombstones, d1.GarbageLen()) - assert.Equal(t, tt.tombstones, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, tt.tombstones, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) }) } } diff --git a/test/integration/gc_test.go b/test/integration/gc_test.go index 0c972d5bf..5a710c815 100644 --- a/test/integration/gc_test.go +++ b/test/integration/gc_test.go @@ -27,7 +27,6 @@ import ( "github.com/yorkie-team/yorkie/pkg/document" "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/presence" - "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/test/helper" ) @@ -56,11 +55,11 @@ func TestGarbageCollection(t *testing.T) { assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 0, d2.GarbageLen()) - // (0, 0) -> (1, 0): syncedseqs:(0, 0) + // push A[A:2] pull [B:1] -> A:[A:2,B:1] err = c1.Sync(ctx) assert.NoError(t, err) - // (1, 0) -> (1, 1): syncedseqs:(0, 0) + // pull A[A:2] -> B:[A:2,B:1] err = c2.Sync(ctx) assert.NoError(t, err) @@ -72,35 +71,18 @@ func TestGarbageCollection(t *testing.T) { assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 4, d2.GarbageLen()) - // (1, 1) -> (1, 2): syncedseqs:(0, 1) + // push B[A:2,B:4] -> B[A:2,B:4] err = c2.Sync(ctx) assert.NoError(t, err) assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 4, d2.GarbageLen()) - // (1, 2) -> (2, 2): syncedseqs:(1, 1) - err = c1.Sync(ctx) - assert.NoError(t, err) - assert.Equal(t, 4, d1.GarbageLen()) - assert.Equal(t, 4, d2.GarbageLen()) - - // (2, 2) -> (2, 2): syncedseqs:(1, 2) - err = c2.Sync(ctx) - assert.NoError(t, err) - assert.Equal(t, 4, d1.GarbageLen()) - assert.Equal(t, 4, d2.GarbageLen()) - - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition + // pull B[A:2, B:4] -> A[A:2,B:4] -> meet GC err = c1.Sync(ctx) assert.NoError(t, err) - assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 0, d1.GarbageLen()) // gc collected garbage assert.Equal(t, 4, d2.GarbageLen()) - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition - err = c2.Sync(ctx) - assert.NoError(t, err) - assert.Equal(t, 0, d1.GarbageLen()) - assert.Equal(t, 0, d2.GarbageLen()) }) t.Run("garbage collection for text type test", func(t *testing.T) { @@ -124,11 +106,11 @@ func TestGarbageCollection(t *testing.T) { assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 0, d2.GarbageLen()) - // (0, 0) -> (1, 0): syncedseqs:(0, 0) + // push A[A:2] err = c1.Sync(ctx) assert.NoError(t, err) - // (1, 0) -> (1, 1): syncedseqs:(0, 0) + // pull A[A:2] -> B[A:2,B:1] err = c2.Sync(ctx) assert.NoError(t, err) @@ -140,39 +122,23 @@ func TestGarbageCollection(t *testing.T) { Edit(0, 1, "a", map[string]string{"b": "1"}) return nil }, "edit text type elements") - assert.NoError(t, err) - assert.Equal(t, 0, d1.GarbageLen()) - assert.Equal(t, 3, d2.GarbageLen()) - // (1, 1) -> (1, 2): syncedseqs:(0, 1) - err = c2.Sync(ctx) assert.NoError(t, err) assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 3, d2.GarbageLen()) - // (1, 2) -> (2, 2): syncedseqs:(1, 1) - err = c1.Sync(ctx) - assert.NoError(t, err) - assert.Equal(t, 3, d1.GarbageLen()) - assert.Equal(t, 3, d2.GarbageLen()) - - // (2, 2) -> (2, 2): syncedseqs:(1, 2) + // push B[A:2,B:4] -> B[A:2,B:4] err = c2.Sync(ctx) assert.NoError(t, err) - assert.Equal(t, 3, d1.GarbageLen()) + assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 3, d2.GarbageLen()) - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition + // pull B[A:2,B:4] -> A[A:2,B:4] : meet GC condition err = c1.Sync(ctx) assert.NoError(t, err) assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 3, d2.GarbageLen()) - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition - err = c2.Sync(ctx) - assert.NoError(t, err) - assert.Equal(t, 0, d1.GarbageLen()) - assert.Equal(t, 0, d2.GarbageLen()) }) t.Run("garbage collection for tree type test", func(t *testing.T) { @@ -208,10 +174,11 @@ func TestGarbageCollection(t *testing.T) { }) // [text(a), text(b)] + // A: {[A:3]} assert.NoError(t, err) - assert.Equal(t, doc.GarbageLen(), 2) - assert.Equal(t, doc.GarbageCollect(time.MaxTicket), 2) - assert.Equal(t, doc.GarbageLen(), 0) + assert.Equal(t, 2, doc.GarbageLen()) + assert.Equal(t, 2, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) + assert.Equal(t, 0, doc.GarbageLen()) err = doc.Update(func(root *json.Object, p *presence.Presence) error { root.GetTree("t").EditByPath([]int{0, 0, 0}, []int{0, 0, 2}, &json.TreeNode{Type: "text", Value: "cv"}, 0) @@ -220,10 +187,11 @@ func TestGarbageCollection(t *testing.T) { }) // [text(gh)] + // A: {[A:4]} assert.NoError(t, err) - assert.Equal(t, doc.GarbageLen(), 1) - assert.Equal(t, doc.GarbageCollect(time.MaxTicket), 1) - assert.Equal(t, doc.GarbageLen(), 0) + assert.Equal(t, 1, doc.GarbageLen()) + assert.Equal(t, 1, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) + assert.Equal(t, 0, doc.GarbageLen()) err = doc.Update(func(root *json.Object, p *presence.Presence) error { root.GetTree("t").EditByPath([]int{0}, []int{1}, &json.TreeNode{ @@ -237,10 +205,11 @@ func TestGarbageCollection(t *testing.T) { }) // [p, tn, tn, text(cv), text(cd)] + // A: {[A:5]} assert.NoError(t, err) - assert.Equal(t, doc.GarbageLen(), 5) - assert.Equal(t, doc.GarbageCollect(time.MaxTicket), 5) - assert.Equal(t, doc.GarbageLen(), 0) + assert.Equal(t, 5, doc.GarbageLen()) + assert.Equal(t, 5, doc.GarbageCollect(helper.MaxVectorClock(doc.ActorID()))) + assert.Equal(t, 0, doc.GarbageLen()) }) t.Run("garbage collection for tree type test (multi clients)", func(t *testing.T) { @@ -274,11 +243,11 @@ func TestGarbageCollection(t *testing.T) { assert.Equal(t, 0, d1.GarbageLen()) assert.Equal(t, 0, d2.GarbageLen()) - // (0, 0) -> (1, 0): syncedseqs:(0, 0) + // push A[A:2] pull [B:1] => A:[A:2,B:1] err = c1.Sync(ctx) assert.NoError(t, err) - // (1, 0) -> (1, 1): syncedseqs:(0, 0) + // pull A[A:2] -> B:[A:2,B:1] err = c2.Sync(ctx) assert.NoError(t, err) @@ -290,31 +259,31 @@ func TestGarbageCollection(t *testing.T) { assert.Equal(t, d1.GarbageLen(), 0) assert.Equal(t, d2.GarbageLen(), 2) - // (1, 1) -> (1, 2): syncedseqs:(0, 1) + // push B[A:2,B:4] -> B[A:2,B:4] err = c2.Sync(ctx) assert.NoError(t, err) assert.Equal(t, d1.GarbageLen(), 0) assert.Equal(t, d2.GarbageLen(), 2) - // (1, 2) -> (2, 2): syncedseqs:(1, 1) + // pull B[A:2,B:4] -> A[A:2,B:4] meet GC condition err = c1.Sync(ctx) assert.NoError(t, err) - assert.Equal(t, d1.GarbageLen(), 2) + assert.Equal(t, d1.GarbageLen(), 0) assert.Equal(t, d2.GarbageLen(), 2) - // (2, 2) -> (2, 2): syncedseqs:(1, 2) + // B[A:2,B:4] err = c2.Sync(ctx) assert.NoError(t, err) - assert.Equal(t, d1.GarbageLen(), 2) - assert.Equal(t, d2.GarbageLen(), 2) + assert.Equal(t, d1.GarbageLen(), 0) + assert.Equal(t, d2.GarbageLen(), 0) - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition + // A[A:2,B:4], B[A:2,B:4] err = c1.Sync(ctx) assert.NoError(t, err) assert.Equal(t, d1.GarbageLen(), 0) - assert.Equal(t, d2.GarbageLen(), 2) + assert.Equal(t, d2.GarbageLen(), 0) - // (2, 2) -> (2, 2): syncedseqs:(2, 2): meet GC condition + // A[A:2,B:4], B[A:2,B:4] err = c2.Sync(ctx) assert.NoError(t, err) assert.Equal(t, d1.GarbageLen(), 0) @@ -322,6 +291,7 @@ func TestGarbageCollection(t *testing.T) { }) t.Run("garbage collection with detached document test", func(t *testing.T) { + t.Skip("skipping test now, because it is not implemented yet") ctx := context.Background() d1 := document.New(helper.TestDocKey(t)) err := c1.Attach(ctx, d1) @@ -398,11 +368,15 @@ func TestGarbageCollection(t *testing.T) { SetInteger("point.y", 0) return nil }) + + // push A[A:2] -> A: { A:[A:2] } err = c1.Sync(ctx) assert.NoError(t, err) + // push B[B:1], pull A[A:2] -> B: { A:[A:2], B:[A:2,B:1] } err = c2.Attach(ctx, d2) assert.NoError(t, err) + // A@3 : delete point err = d1.Update(func(root *json.Object, p *presence.Presence) error { root.Delete("point") return nil @@ -410,6 +384,7 @@ func TestGarbageCollection(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 3, d1.GarbageLen()) + // B@4 : delete point.x err = d2.Update(func(root *json.Object, p *presence.Presence) error { root.GetObject("point").Delete("point.x") return nil @@ -417,18 +392,38 @@ func TestGarbageCollection(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 1, d2.GarbageLen()) + // push A[A:3], pull B[B:1] -> A:[A:3,B:1] err = c1.Sync(ctx) assert.NoError(t, err) + + // push B[A:2,B:4], pull A[A:3] -> B:[A:3,B:4] -> B GC 3@A err = c2.Sync(ctx) assert.NoError(t, err) + assert.Equal(t, 0, d2.GarbageLen()) + + // pull B[A:2,B:4] -> A:[A:3,B:4] -> A GC 3@A err = c1.Sync(ctx) assert.NoError(t, err) - assert.Equal(t, 3, d1.GarbageLen()) - assert.Equal(t, 3, d2.GarbageLen()) + assert.Equal(t, 0, d1.GarbageLen()) // 3@A remains + assert.Equal(t, 0, d2.GarbageLen()) + + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewObject("point2") + return nil + }) + assert.NoError(t, err) + + // push B[A:3,B:6] -> B:[A:3,B:6] + err = c2.Sync(ctx) + assert.NoError(t, err) + + // pull B[A:3,B:6] -> A:[A:3,B:6] + err = c1.Sync(ctx) + assert.NoError(t, err) - assert.Equal(t, d1.GarbageCollect(time.MaxTicket), 3) - assert.Equal(t, d2.GarbageCollect(time.MaxTicket), 3) + assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) }) t.Run("deregister nested object gc test", func(t *testing.T) { @@ -449,7 +444,191 @@ func TestGarbageCollection(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 5, d1.GarbageLen()) - assert.Equal(t, 5, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, 5, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) }) + // gc_test.go + t.Run("should not garbage collection", func(t *testing.T) { + ctx := context.Background() + d1 := document.New(helper.TestDocKey(t)) + err := c1.Attach(ctx, d1) + assert.NoError(t, err) + + d2 := document.New(helper.TestDocKey(t)) + err = c2.Attach(ctx, d2) + assert.NoError(t, err) + + err = d1.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewText("text").Edit(0, 0, "a").Edit(1, 1, "b").Edit(2, 2, "c") + return nil + }, "sets text") + assert.NoError(t, err) + err = c1.Sync(ctx) + assert.NoError(t, err) + err = c2.Sync(ctx) + assert.NoError(t, err) + + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(2, 2, "c") + return nil + }, "insert c") + assert.NoError(t, err) + + err = d1.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(1, 3, "") + return nil + }, "delete bd") + assert.NoError(t, err) + assert.Equal(t, 2, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) + + err = c2.Sync(ctx) + assert.NoError(t, err) + err = c2.Sync(ctx) + assert.NoError(t, err) + err = c1.Sync(ctx) + assert.NoError(t, err) + err = c1.Sync(ctx) + assert.NoError(t, err) + assert.Equal(t, 2, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) + + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(2, 2, "1") + return nil + }, "insert 1") + assert.NoError(t, err) + + err = c2.Sync(ctx) // GC purge 4@A node + assert.NoError(t, err) + err = c2.Sync(ctx) + assert.NoError(t, err) + assert.Equal(t, 2, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) + + err = c1.Sync(ctx) + assert.NoError(t, err) + assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) + }) + + t.Run("should not garbage collection int Text delete", func(t *testing.T) { + ctx := context.Background() + d1 := document.New(helper.TestDocKey(t)) + err := c1.Attach(ctx, d1) + assert.NoError(t, err) + + d2 := document.New(helper.TestDocKey(t)) + err = c2.Attach(ctx, d2) + assert.NoError(t, err) + + err = d1.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewText("text").Edit(0, 0, "a").Edit(1, 1, "b") + return nil + }) + + // push A[A:2] -> A:[A:2] + c1.Sync(ctx) + c1.Sync(ctx) + + // push B[A:1,B:1], pull A[A:2] -> B:[A:2,B:1] + c2.Sync(ctx) + c2.Sync(ctx) + + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(2, 2, "d") + return nil + }) + + // push B[A:2,B:4] -> B:[A:2,B:4] + c2.Sync(ctx) + c2.Sync(ctx) + + // pull B[A:2,B:4] -> A:[A:2,B:4] -> Synced VersionVector : [2, 4] + c1.Sync(ctx) + c1.Sync(ctx) + + // 5@A : insert 'c' + err = d1.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(2, 2, "c") + return nil + }) + + // 5@B : delete "bcd" + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("text").Edit(2, 2, "1").Edit(1, 4, "") + return nil + }) + + assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 3, d2.GarbageLen()) + + // push B[A:2,B:5] -> B:[A:2,B:5] + c2.Sync(ctx) + c2.Sync(ctx) + + // push A[A:5,B:4], pull B[A:2,B:5] -> A:[A:5,B:5] -> Synced VersionVector : [2, 5] + c1.Sync(ctx) + c1.Sync(ctx) + + assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 3, d2.GarbageLen()) + + // pull A[A:5,B:4] -> B:[A:5,B:5] -> Synced VersionVector : [5, 5] + c2.Sync(ctx) + c2.Sync(ctx) + + assert.Equal(t, 0, d1.GarbageLen()) + assert.Equal(t, 0, d2.GarbageLen()) + }) +} + +func TestVectorClock(t *testing.T) { + t.Run("Delete actor's vector clock who has detaced", func(t *testing.T) { + clients := activeClients(t, 2) + c1, c2 := clients[0], clients[1] + + ctx := context.Background() + d1 := document.New(helper.TestDocKey(t)) + err := c1.Attach(ctx, d1) + assert.NoError(t, err) + + d2 := document.New(helper.TestDocKey(t)) + err = c2.Attach(ctx, d2) + assert.NoError(t, err) + + // update and delete + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewObject("obj").SetInteger("1", 1) + root.Delete("obj") + return nil + }) + + // push B[A:1,B:3] -> B[A:1,B:3] + c2.Sync(ctx) + + // currently d2 has garbage, Synced VersionVector is [A:1] due to client A. + assert.Equal(t, 2, d2.GarbageLen()) + + // If client A detaches, Synced VersionVector promote to [A:1, B:3]. + // push A[A:2] -> A:[A:2,B:3] + err = c1.Detach(ctx, d1) + assert.NoError(t, err) + + // pull A[A:2] -> B:[A:2,B:3] -> GC + c2.Sync(ctx) + assert.Equal(t, 0, d2.GarbageLen()) + + err = d2.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewObject("obj2").SetInteger("1", 1) + root.Delete("obj2") + return nil + }) + assert.Equal(t, 2, d2.GarbageLen()) + + // A is detached, so B's Synced VersionVector is [A:2, B:5]. + // push B[A:2,B:5] -> B:[A:2,B:5] + c2.Sync(ctx) + assert.Equal(t, 0, d2.GarbageLen()) + }) } diff --git a/test/integration/object_test.go b/test/integration/object_test.go index 374953c76..67489cc5d 100644 --- a/test/integration/object_test.go +++ b/test/integration/object_test.go @@ -29,7 +29,6 @@ import ( "github.com/yorkie-team/yorkie/pkg/document/crdt" "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/presence" - "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/test/helper" ) @@ -223,9 +222,9 @@ func TestObject(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, 10, d1.GarbageLen()) - assert.Equal(t, 10, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, 10, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) assert.Equal(t, 10, d2.GarbageLen()) - assert.Equal(t, 10, d2.GarbageCollect(time.MaxTicket)) + assert.Equal(t, 10, d2.GarbageCollect(helper.MaxVectorClock(d2.ActorID()))) }) t.Run("object.set with json literal sync test", func(t *testing.T) { @@ -285,7 +284,7 @@ func TestObject(t *testing.T) { // 03. garbage collect (3 elements: array, 1, 2) assert.Equal(t, 3, d1.GarbageLen()) - assert.Equal(t, 3, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, 3, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) }) t.Run("object.set with json literal counter type test", func(t *testing.T) { @@ -667,7 +666,7 @@ func TestObjectSet(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, tt.tombstones, d1.GarbageLen()) - assert.Equal(t, tt.tombstones, d1.GarbageCollect(time.MaxTicket)) + assert.Equal(t, tt.tombstones, d1.GarbageCollect(helper.MaxVectorClock(d1.ActorID()))) }) } diff --git a/test/integration/snapshot_test.go b/test/integration/snapshot_test.go index 7e3cc3a73..ee4bf7312 100644 --- a/test/integration/snapshot_test.go +++ b/test/integration/snapshot_test.go @@ -30,6 +30,7 @@ import ( "github.com/yorkie-team/yorkie/pkg/document" "github.com/yorkie-team/yorkie/pkg/document/json" + "github.com/yorkie-team/yorkie/pkg/document/key" "github.com/yorkie-team/yorkie/pkg/document/presence" "github.com/yorkie-team/yorkie/server/backend/background" "github.com/yorkie-team/yorkie/test/helper" @@ -169,4 +170,114 @@ func TestSnapshot(t *testing.T) { syncClientsThenAssertEqual(t, []clientAndDocPair{{c1, d1}, {c2, d2}}) }) + + // t.Run("Initialize vector clock from snapshot test", func(t *testing.T) { + // t.Skip("This test is not working as expected. It is not clear what the expected behavior is.") + // ctx := context.Background() + // d1 := document.New(helper.TestDocKey(t)) + // err := c1.Attach(ctx, d1) + // assert.NoError(t, err) + + // for i := 0; i < int(helper.SnapshotThreshold); i++ { + // err = d1.Update(func(root *json.Object, p *presence.Presence) error { + // root.SetInteger(fmt.Sprintf("Padding %d", i), i) + // return nil + // }) + // assert.NoError(t, err) + // } + + // c1.Sync(ctx) + // c1.Sync(ctx) + + // d2 := document.New(helper.TestDocKey(t)) + // err = c2.Attach(ctx, d2) + // assert.NoError(t, err) + + // c1ID := c1.ID().String() + // c2ID := c2.ID().String() + + // assert.Equal(t, time.SyncedVectorMap{ + // c1ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold}, + // }, d1.InternalDocument().SyncedVectorMap()) + // assert.Equal(t, time.SyncedVectorMap{ + // c1ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold}, + // c2ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold, c2ID: 1}, + // }, d2.InternalDocument().SyncedVectorMap()) + + // assert.Equal(t, d1.Marshal(), d2.Marshal()) + + // err = d2.Update(func(root *json.Object, p *presence.Presence) error { + // root.SetInteger("Padding", 1) + // return nil + // }) + + // c2.Sync(ctx) + // c2.Sync(ctx) + + // c1.Sync(ctx) + // c1.Sync(ctx) + + // assert.Equal(t, time.SyncedVectorMap{ + // c1ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold, c2ID: 3 + helper.SnapshotThreshold}, + // c2ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold, c2ID: 3 + helper.SnapshotThreshold}, + // }, d1.InternalDocument().SyncedVectorMap()) + // assert.Equal(t, time.SyncedVectorMap{ + // c1ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold}, + // c2ID: time.VectorClock{c1ID: 1 + helper.SnapshotThreshold, c2ID: 3 + helper.SnapshotThreshold}, + // }, d2.InternalDocument().SyncedVectorMap()) + // }) +} + +func TestSnapshotlimit(t *testing.T) { + + initialState := json.TreeNode{ + Type: "root", + Children: []json.TreeNode{ + {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "a"}}}, + {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "b"}}}, + {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "c"}}}, + }, + } + initialXML := `

a

b

c

` + + for i := 0; i < 301; i++ { + t.Run(fmt.Sprintf("iteration"), func(t *testing.T) { + if i == 117 { + fmt.Println("break") + } + fmt.Println("-------------------------iteration ", i) + ctx := context.Background() + clients := activeClients(t, 2) + c1, c2 := clients[0], clients[1] + //defer deactivateAndCloseClients(t, clients) + + d1 := document.New(key.Key("testsnapshotlimit-iteration")) + err := c1.Attach(ctx, d1) + if err != nil { + println(err.Error()) + } + assert.NoError(t, err) + d2 := document.New(key.Key("testsnapshotlimit-iteration")) + err = c2.Attach(ctx, d2) + if err != nil { + println(err.Error()) + } + assert.NoError(t, err) + + assert.NoError(t, d1.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewTree("t", &initialState) + return nil + }, "set initial state")) + assert.NoError(t, c1.Sync(ctx)) + assert.NoError(t, c2.Sync(ctx)) + assert.Equal(t, initialXML, d1.Root().GetTree("t").ToXML()) + assert.Equal(t, initialXML, d2.Root().GetTree("t").ToXML()) + + // op1.run(t, d1, 0, ranges) + // op2.run(t, d2, 1, ranges) + + _ = syncClientsThenCheckEqual(t, []clientAndDocPair{{c1, d1}, {c2, d2}}) + + }) + } }