Nick Cabatoff
2024-04-15 16:08:57 -04:00
committed by GitHub
parent 0701cc368c
commit 2560beea8e
13 changed files with 222 additions and 183 deletions

View File

@@ -19,13 +19,14 @@ const (
) )
type ClusterInfo struct { type ClusterInfo struct {
APIAddr string `json:"api_address,omitempty" mapstructure:"api_address"` APIAddr string `json:"api_address,omitempty" mapstructure:"api_address"`
ClusterAddress string `json:"cluster_address,omitempty" mapstructure:"cluster_address"` ClusterAddress string `json:"cluster_address,omitempty" mapstructure:"cluster_address"`
ConnectionStatus string `json:"connection_status,omitempty" mapstructure:"connection_status"` ConnectionStatus string `json:"connection_status,omitempty" mapstructure:"connection_status"`
LastHeartBeat string `json:"last_heartbeat,omitempty" mapstructure:"last_heartbeat"` LastHeartBeat string `json:"last_heartbeat,omitempty" mapstructure:"last_heartbeat"`
LastHeartBeatDurationMillis string `json:"last_heartbeat_duration_ms,omitempty" mapstructure:"last_heartbeat_duration_ms"` LastHeartBeatDurationMillis string `json:"last_heartbeat_duration_ms,omitempty" mapstructure:"last_heartbeat_duration_ms"`
ClockSkewMillis string `json:"clock_skew_ms,omitempty" mapstructure:"clock_skew_ms"` ClockSkewMillis string `json:"clock_skew_ms,omitempty" mapstructure:"clock_skew_ms"`
NodeID string `json:"node_id,omitempty" mapstructure:"node_id"` NodeID string `json:"node_id,omitempty" mapstructure:"node_id"`
ReplicationPrimaryCanaryAgeMillis string `json:"replication_primary_canary_age_ms,omitempty" mapstructure:"replication_primary_canary_age_ms"`
} }
type ReplicationStatusGenericResponse struct { type ReplicationStatusGenericResponse struct {

View File

@@ -35,14 +35,15 @@ type HAStatusResponse struct {
} }
type HANode struct { type HANode struct {
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
APIAddress string `json:"api_address"` APIAddress string `json:"api_address"`
ClusterAddress string `json:"cluster_address"` ClusterAddress string `json:"cluster_address"`
ActiveNode bool `json:"active_node"` ActiveNode bool `json:"active_node"`
LastEcho *time.Time `json:"last_echo"` LastEcho *time.Time `json:"last_echo"`
EchoDurationMillis int64 `json:"echo_duration_ms"` EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"` ClockSkewMillis int64 `json:"clock_skew_ms"`
Version string `json:"version"` Version string `json:"version"`
UpgradeVersion string `json:"upgrade_version,omitempty"` UpgradeVersion string `json:"upgrade_version,omitempty"`
RedundancyZone string `json:"redundancy_zone,omitempty"` RedundancyZone string `json:"redundancy_zone,omitempty"`
ReplicationPrimaryCanaryAgeMillis int64 `json:"replication_primary_canary_age_ms"`
} }

View File

@@ -38,18 +38,19 @@ func (c *Sys) HealthWithContext(ctx context.Context) (*HealthResponse, error) {
} }
type HealthResponse struct { type HealthResponse struct {
Initialized bool `json:"initialized"` Initialized bool `json:"initialized"`
Sealed bool `json:"sealed"` Sealed bool `json:"sealed"`
Standby bool `json:"standby"` Standby bool `json:"standby"`
PerformanceStandby bool `json:"performance_standby"` PerformanceStandby bool `json:"performance_standby"`
ReplicationPerformanceMode string `json:"replication_performance_mode"` ReplicationPerformanceMode string `json:"replication_performance_mode"`
ReplicationDRMode string `json:"replication_dr_mode"` ReplicationDRMode string `json:"replication_dr_mode"`
ServerTimeUTC int64 `json:"server_time_utc"` ServerTimeUTC int64 `json:"server_time_utc"`
Version string `json:"version"` Version string `json:"version"`
ClusterName string `json:"cluster_name,omitempty"` ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"` ClusterID string `json:"cluster_id,omitempty"`
LastWAL uint64 `json:"last_wal,omitempty"` LastWAL uint64 `json:"last_wal,omitempty"`
Enterprise bool `json:"enterprise"` Enterprise bool `json:"enterprise"`
EchoDurationMillis int64 `json:"echo_duration_ms"` EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"` ClockSkewMillis int64 `json:"clock_skew_ms"`
ReplicationPrimaryCanaryAgeMillis int64 `json:"replication_primary_canary_age_ms"`
} }

3
changelog/26406.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
replication (enterprise): Periodically write current time on the primary to storage, use that downstream to measure replication lag in time, expose that in health and replication status endpoints.
```

View File

@@ -1682,11 +1682,17 @@ func (c *ServerCommand) Run(args []string) int {
level, err := loghelper.ParseLogLevel(config.LogLevel) level, err := loghelper.ParseLogLevel(config.LogLevel)
if err != nil { if err != nil {
c.logger.Error("unknown log level found on reload", "level", config.LogLevel) c.logger.Error("unknown log level found on reload", "level", config.LogLevel)
goto RUNRELOADFUNCS } else {
core.SetLogLevel(level)
} }
core.SetLogLevel(level)
} }
if err := core.ReloadCensus(); err != nil {
c.UI.Error(err.Error())
}
core.ReloadReplicationCanaryWriteInterval()
RUNRELOADFUNCS: RUNRELOADFUNCS:
if err := c.Reload(c.reloadFuncsLock, c.reloadFuncs, c.flagConfigs, core); err != nil { if err := c.Reload(c.reloadFuncsLock, c.reloadFuncs, c.flagConfigs, core); err != nil {
c.UI.Error(fmt.Sprintf("Error(s) were encountered during reload: %s", err)) c.UI.Error(fmt.Sprintf("Error(s) were encountered during reload: %s", err))
@@ -1697,9 +1703,6 @@ func (c *ServerCommand) Run(args []string) int {
c.UI.Error(err.Error()) c.UI.Error(err.Error())
} }
if err := core.ReloadCensus(); err != nil {
c.UI.Error(err.Error())
}
select { select {
case c.licenseReloadedCh <- err: case c.licenseReloadedCh <- err:
default: default:

View File

@@ -224,6 +224,9 @@ func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, erro
ClockSkewMillis: core.ActiveNodeClockSkewMillis(), ClockSkewMillis: core.ActiveNodeClockSkewMillis(),
EchoDurationMillis: core.EchoDuration().Milliseconds(), EchoDurationMillis: core.EchoDuration().Milliseconds(),
} }
if standby {
body.ReplicationPrimaryCanaryAgeMillis = core.GetReplicationLagMillisIgnoreErrs()
}
licenseState, err := core.EntGetLicenseState() licenseState, err := core.EntGetLicenseState()
if err != nil { if err != nil {
@@ -254,19 +257,20 @@ type HealthResponseLicense struct {
} }
type HealthResponse struct { type HealthResponse struct {
Initialized bool `json:"initialized"` Initialized bool `json:"initialized"`
Sealed bool `json:"sealed"` Sealed bool `json:"sealed"`
Standby bool `json:"standby"` Standby bool `json:"standby"`
PerformanceStandby bool `json:"performance_standby"` PerformanceStandby bool `json:"performance_standby"`
ReplicationPerformanceMode string `json:"replication_performance_mode"` ReplicationPerformanceMode string `json:"replication_performance_mode"`
ReplicationDRMode string `json:"replication_dr_mode"` ReplicationDRMode string `json:"replication_dr_mode"`
ServerTimeUTC int64 `json:"server_time_utc"` ServerTimeUTC int64 `json:"server_time_utc"`
Version string `json:"version"` Version string `json:"version"`
Enterprise bool `json:"enterprise"` Enterprise bool `json:"enterprise"`
ClusterName string `json:"cluster_name,omitempty"` ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"` ClusterID string `json:"cluster_id,omitempty"`
LastWAL uint64 `json:"last_wal,omitempty"` LastWAL uint64 `json:"last_wal,omitempty"`
License *HealthResponseLicense `json:"license,omitempty"` License *HealthResponseLicense `json:"license,omitempty"`
EchoDurationMillis int64 `json:"echo_duration_ms"` EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"` ClockSkewMillis int64 `json:"clock_skew_ms"`
ReplicationPrimaryCanaryAgeMillis int64 `json:"replication_primary_canary_age_ms"`
} }

View File

@@ -2839,6 +2839,7 @@ func (c *Core) preSeal() error {
close(c.metricsCh) close(c.metricsCh)
c.metricsCh = nil c.metricsCh = nil
} }
var result error var result error
c.stopForwarding() c.stopForwarding()
@@ -4128,15 +4129,16 @@ func (c *Core) ReloadIntrospectionEndpointEnabled() {
} }
type PeerNode struct { type PeerNode struct {
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
APIAddress string `json:"api_address"` APIAddress string `json:"api_address"`
ClusterAddress string `json:"cluster_address"` ClusterAddress string `json:"cluster_address"`
Version string `json:"version"` Version string `json:"version"`
LastEcho time.Time `json:"last_echo"` LastEcho time.Time `json:"last_echo"`
UpgradeVersion string `json:"upgrade_version,omitempty"` UpgradeVersion string `json:"upgrade_version,omitempty"`
RedundancyZone string `json:"redundancy_zone,omitempty"` RedundancyZone string `json:"redundancy_zone,omitempty"`
EchoDuration time.Duration `json:"echo_duration"` EchoDuration time.Duration `json:"echo_duration"`
ClockSkewMillis int64 `json:"clock_skew_millis"` ClockSkewMillis int64 `json:"clock_skew_millis"`
ReplicationPrimaryCanaryAge int64 `json:"replication_primary_canary_age_ms"`
} }
// GetHAPeerNodesCached returns the nodes that've sent us Echo requests recently. // GetHAPeerNodesCached returns the nodes that've sent us Echo requests recently.
@@ -4153,15 +4155,16 @@ func (c *Core) GetHAPeerNodesCached() []PeerNode {
apiAddr = info.nodeInfo.ApiAddr apiAddr = info.nodeInfo.ApiAddr
} }
nodes = append(nodes, PeerNode{ nodes = append(nodes, PeerNode{
Hostname: hostname, Hostname: hostname,
APIAddress: apiAddr, APIAddress: apiAddr,
ClusterAddress: itemClusterAddr, ClusterAddress: itemClusterAddr,
LastEcho: info.lastHeartbeat, LastEcho: info.lastHeartbeat,
Version: info.version, Version: info.version,
UpgradeVersion: info.upgradeVersion, UpgradeVersion: info.upgradeVersion,
RedundancyZone: info.redundancyZone, RedundancyZone: info.redundancyZone,
EchoDuration: info.echoDuration, EchoDuration: info.echoDuration,
ClockSkewMillis: info.clockSkewMillis, ClockSkewMillis: info.clockSkewMillis,
ReplicationPrimaryCanaryAge: info.replicationLagMillis,
}) })
} }
return nodes return nodes

View File

@@ -104,3 +104,7 @@ func (c *Core) SecretsSyncLicensedActivated() bool { return false }
func (c *Core) IsMultisealEnabled() bool { return false } func (c *Core) IsMultisealEnabled() bool { return false }
func (c *Core) SetMultisealEnabled(_ bool) {} func (c *Core) SetMultisealEnabled(_ bool) {}
func (c *Core) ReloadReplicationCanaryWriteInterval() {}
func (c *Core) GetReplicationLagMillisIgnoreErrs() int64 { return 0 }

View File

@@ -118,15 +118,16 @@ func (c *Core) getHAMembers() ([]HAStatusNode, error) {
for _, peerNode := range c.GetHAPeerNodesCached() { for _, peerNode := range c.GetHAPeerNodesCached() {
lastEcho := peerNode.LastEcho lastEcho := peerNode.LastEcho
nodes = append(nodes, HAStatusNode{ nodes = append(nodes, HAStatusNode{
Hostname: peerNode.Hostname, Hostname: peerNode.Hostname,
APIAddress: peerNode.APIAddress, APIAddress: peerNode.APIAddress,
ClusterAddress: peerNode.ClusterAddress, ClusterAddress: peerNode.ClusterAddress,
LastEcho: &lastEcho, LastEcho: &lastEcho,
Version: peerNode.Version, Version: peerNode.Version,
UpgradeVersion: peerNode.UpgradeVersion, UpgradeVersion: peerNode.UpgradeVersion,
RedundancyZone: peerNode.RedundancyZone, RedundancyZone: peerNode.RedundancyZone,
EchoDurationMillis: peerNode.EchoDuration.Milliseconds(), EchoDurationMillis: peerNode.EchoDuration.Milliseconds(),
ClockSkewMillis: peerNode.ClockSkewMillis, ClockSkewMillis: peerNode.ClockSkewMillis,
ReplicationPrimaryCanaryAge: peerNode.ReplicationPrimaryCanaryAge,
}) })
} }

View File

@@ -5783,16 +5783,17 @@ func (b *SystemBackend) handleHAStatus(ctx context.Context, req *logical.Request
} }
type HAStatusNode struct { type HAStatusNode struct {
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
APIAddress string `json:"api_address"` APIAddress string `json:"api_address"`
ClusterAddress string `json:"cluster_address"` ClusterAddress string `json:"cluster_address"`
ActiveNode bool `json:"active_node"` ActiveNode bool `json:"active_node"`
LastEcho *time.Time `json:"last_echo"` LastEcho *time.Time `json:"last_echo"`
Version string `json:"version"` Version string `json:"version"`
UpgradeVersion string `json:"upgrade_version,omitempty"` UpgradeVersion string `json:"upgrade_version,omitempty"`
RedundancyZone string `json:"redundancy_zone,omitempty"` RedundancyZone string `json:"redundancy_zone,omitempty"`
EchoDurationMillis int64 `json:"echo_duration_ms"` EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"` ClockSkewMillis int64 `json:"clock_skew_ms"`
ReplicationPrimaryCanaryAge int64 `json:"replication_primary_canary_age_ms"`
} }
func (b *SystemBackend) handleVersionHistoryList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { func (b *SystemBackend) handleVersionHistoryList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {

View File

@@ -74,26 +74,28 @@ func (s *forwardedRequestRPCServer) ForwardRequest(ctx context.Context, freq *fo
} }
type nodeHAConnectionInfo struct { type nodeHAConnectionInfo struct {
nodeInfo *NodeInformation nodeInfo *NodeInformation
lastHeartbeat time.Time lastHeartbeat time.Time
version string version string
upgradeVersion string upgradeVersion string
redundancyZone string redundancyZone string
localTime time.Time localTime time.Time
echoDuration time.Duration echoDuration time.Duration
clockSkewMillis int64 clockSkewMillis int64
replicationLagMillis int64
} }
func (s *forwardedRequestRPCServer) Echo(ctx context.Context, in *EchoRequest) (*EchoReply, error) { func (s *forwardedRequestRPCServer) Echo(ctx context.Context, in *EchoRequest) (*EchoReply, error) {
incomingNodeConnectionInfo := nodeHAConnectionInfo{ incomingNodeConnectionInfo := nodeHAConnectionInfo{
nodeInfo: in.NodeInfo, nodeInfo: in.NodeInfo,
lastHeartbeat: time.Now(), lastHeartbeat: time.Now(),
version: in.SdkVersion, version: in.SdkVersion,
upgradeVersion: in.RaftUpgradeVersion, upgradeVersion: in.RaftUpgradeVersion,
redundancyZone: in.RaftRedundancyZone, redundancyZone: in.RaftRedundancyZone,
localTime: in.Now.AsTime(), localTime: in.Now.AsTime(),
echoDuration: in.LastRoundtripTime.AsDuration(), echoDuration: in.LastRoundtripTime.AsDuration(),
clockSkewMillis: in.ClockSkewMillis, clockSkewMillis: in.ClockSkewMillis,
replicationLagMillis: in.ReplicationPrimaryCanaryAgeMillis,
} }
if in.ClusterAddr != "" { if in.ClusterAddr != "" {
s.core.clusterPeerClusterAddrsCache.Set(in.ClusterAddr, incomingNodeConnectionInfo, 0) s.core.clusterPeerClusterAddrsCache.Set(in.ClusterAddr, incomingNodeConnectionInfo, 0)
@@ -150,12 +152,13 @@ func (c *forwardingClient) startHeartbeat() {
defer metrics.MeasureSinceWithLabels([]string{"ha", "rpc", "client", "echo"}, time.Now(), labels) defer metrics.MeasureSinceWithLabels([]string{"ha", "rpc", "client", "echo"}, time.Now(), labels)
req := &EchoRequest{ req := &EchoRequest{
Message: "ping", Message: "ping",
ClusterAddr: clusterAddr, ClusterAddr: clusterAddr,
NodeInfo: &ni, NodeInfo: &ni,
SdkVersion: c.core.effectiveSDKVersion, SdkVersion: c.core.effectiveSDKVersion,
LastRoundtripTime: durationpb.New(echoDuration), LastRoundtripTime: durationpb.New(echoDuration),
ClockSkewMillis: serverTimeDelta, ClockSkewMillis: serverTimeDelta,
ReplicationPrimaryCanaryAgeMillis: c.core.GetReplicationLagMillisIgnoreErrs(),
} }
if raftBackend := c.core.getRaftBackend(); raftBackend != nil { if raftBackend := c.core.getRaftBackend(); raftBackend != nil {

View File

@@ -50,7 +50,8 @@ type EchoRequest struct {
// last_roundtrip_time is the time taken for the last echo request // last_roundtrip_time is the time taken for the last echo request
LastRoundtripTime *durationpb.Duration `protobuf:"bytes,13,opt,name=last_roundtrip_time,json=lastRoundtripTime,proto3" json:"last_roundtrip_time,omitempty"` LastRoundtripTime *durationpb.Duration `protobuf:"bytes,13,opt,name=last_roundtrip_time,json=lastRoundtripTime,proto3" json:"last_roundtrip_time,omitempty"`
// clock_skew_millis is the server time minus the local time // clock_skew_millis is the server time minus the local time
ClockSkewMillis int64 `protobuf:"varint,14,opt,name=clock_skew_millis,json=clockSkewMillis,proto3" json:"clock_skew_millis,omitempty"` ClockSkewMillis int64 `protobuf:"varint,14,opt,name=clock_skew_millis,json=clockSkewMillis,proto3" json:"clock_skew_millis,omitempty"`
ReplicationPrimaryCanaryAgeMillis int64 `protobuf:"varint,15,opt,name=replication_primary_canary_age_millis,json=replicationPrimaryCanaryAgeMillis,proto3" json:"replication_primary_canary_age_millis,omitempty"`
} }
func (x *EchoRequest) Reset() { func (x *EchoRequest) Reset() {
@@ -183,6 +184,13 @@ func (x *EchoRequest) GetClockSkewMillis() int64 {
return 0 return 0
} }
func (x *EchoRequest) GetReplicationPrimaryCanaryAgeMillis() int64 {
if x != nil {
return x.ReplicationPrimaryCanaryAgeMillis
}
return 0
}
type EchoReply struct { type EchoReply struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -574,7 +582,7 @@ var file_vault_request_forwarding_service_proto_rawDesc = []byte{
0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x1d, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x2f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x1a, 0x1d, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x2f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
0x69, 0x6e, 0x67, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x69, 0x6e, 0x67, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
0xef, 0x04, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xc1, 0x05, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75,
0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
@@ -613,77 +621,82 @@ var file_vault_request_forwarding_service_proto_rawDesc = []byte{
0x70, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
0x6b, 0x65, 0x77, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x6b, 0x65, 0x77, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03,
0x52, 0x0f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x52, 0x0f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x4d, 0x69, 0x6c, 0x6c, 0x69,
0x73, 0x22, 0xaa, 0x02, 0x0a, 0x09, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x73, 0x12, 0x50, 0x0a, 0x25, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x5f,
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03,
0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x21, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x69,
0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2b, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x41, 0x67, 0x65, 0x4d, 0x69, 0x6c,
0x0a, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x6c, 0x69, 0x73, 0x22, 0xaa, 0x02, 0x0a, 0x09, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x70, 0x6c,
0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63,
0x61, 0x66, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03,
0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x72, 0x61, 0x66, 0x74, 0x41, 0x70, 0x70, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x73,
0x6c, 0x69, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x61, 0x66, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x72, 0x65, 0x70,
0x0a, 0x72, 0x61, 0x66, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x09, 0x6e, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a,
0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x12, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x69, 0x6e,
0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x72, 0x61, 0x66, 0x74, 0x41,
0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x72,
0x12, 0x2c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x66, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x09, 0x52, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x33, 0x0a,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x22, 0xc5, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
0x01, 0x0a, 0x0f, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e,
0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x61, 0x64, 0x64, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x41, 0x64, 0x64, 0x72, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77,
0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x22, 0xc5, 0x01, 0x0a, 0x0f, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,
0x6d, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73,
0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x61,
0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x41, 0x64,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69,
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12,
0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73,
0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x72, 0x65, 0x70, 0x6c,
0x28, 0x0c, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08,
0x52, 0x01, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x64, 0x22, 0x1a, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x65,
0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x22, 0xe9, 0x01, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
0x0a, 0x1b, 0x50, 0x65, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x02,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x28, 0x0c, 0x52, 0x01, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x52, 0x01, 0x64, 0x22, 0x1a, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64,
0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x22,
0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0xe9, 0x01, 0x0a, 0x1b, 0x50, 0x65, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45,
0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x69, 0x6d, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x61, 0x72, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x17, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
0x0a, 0x07, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x06, 0x63, 0x61, 0x43, 0x65, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30,
0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6c, 0x0a, 0x14, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72,
0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72,
0x61, 0x75, 0x6c, 0x74, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x32, 0xf0, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x0c, 0x52, 0x06, 0x63, 0x61, 0x43, 0x65, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69,
0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a,
0x3d, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x63, 0x6c,
0x74, 0x12, 0x13, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79,
0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x32, 0xf0, 0x01, 0x0a, 0x11,
0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x12, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e,
0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x76, 0x61, 0x75, 0x67, 0x12, 0x3d, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75,
0x6c, 0x74, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x6c, 0x65, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
0x0a, 0x21, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61,
0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x65, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x12, 0x2e, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x12, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74,
0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x76,
0x6e, 0x70, 0x75, 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x50, 0x65, 0x72, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00,
0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6c, 0x0a, 0x21, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x53,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x22, 0x5a, 0x20, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x50, 0x65,
0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x50,
0x65, 0x72, 0x66, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x22,
0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x61, 0x75,
0x6c, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -33,6 +33,7 @@ message EchoRequest {
google.protobuf.Duration last_roundtrip_time = 13; google.protobuf.Duration last_roundtrip_time = 13;
// clock_skew_millis is the server time minus the local time // clock_skew_millis is the server time minus the local time
int64 clock_skew_millis = 14; int64 clock_skew_millis = 14;
int64 replication_primary_canary_age_millis = 15;
} }
message EchoReply { message EchoReply {