Commit ee5a46ae authored by Jay Guo's avatar Jay Guo
Browse files

[FAB-14075] Use human readable format for TickInterval



Instead of uint64 with unit Millisecond, use string in time
duration for TickInterval for etcdraft chain options, e.g. 500ms

Change-Id: I1549d4278654b04baa6e3ab6a93de1d9c453cdcc
Signed-off-by: default avatarJay Guo <guojiannan1101@gmail.com>
parent 0c4d5c38
......@@ -12,6 +12,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
"github.com/hyperledger/fabric/common/tools/configtxgen/encoder/mock"
genesisconfig "github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
......@@ -21,8 +22,6 @@ import (
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/hyperledger/fabric/protos/orderer/etcdraft"
"github.com/hyperledger/fabric/protos/utils"
"github.com/golang/protobuf/proto"
)
var _ = Describe("Encoder", func() {
......@@ -230,7 +229,7 @@ var _ = Describe("Encoder", func() {
conf.OrdererType = "etcdraft"
conf.EtcdRaft = &etcdraft.Metadata{
Options: &etcdraft.Options{
TickInterval: 5,
TickInterval: "500ms",
},
}
})
......@@ -246,7 +245,7 @@ var _ = Describe("Encoder", func() {
metadata := &etcdraft.Metadata{}
err = proto.Unmarshal(consensusType.Metadata, metadata)
Expect(err).NotTo(HaveOccurred())
Expect(metadata.Options.TickInterval).To(Equal(uint64(5)))
Expect(metadata.Options.TickInterval).To(Equal("500ms"))
})
Context("when the raft configuration is bad", func() {
......
......@@ -194,7 +194,7 @@ var genesisDefaults = TopLevel{
},
EtcdRaft: &etcdraft.Metadata{
Options: &etcdraft.Options{
TickInterval: 500,
TickInterval: "500ms",
ElectionTick: 10,
HeartbeatTick: 1,
MaxInflightMsgs: 256,
......@@ -404,7 +404,7 @@ loop:
second_loop:
for {
switch {
case ord.EtcdRaft.Options.TickInterval == 0:
case ord.EtcdRaft.Options.TickInterval == "":
logger.Infof("Orderer.EtcdRaft.Options.TickInterval unset, setting to %v", genesisDefaults.Orderer.EtcdRaft.Options.TickInterval)
ord.EtcdRaft.Options.TickInterval = genesisDefaults.Orderer.EtcdRaft.Options.TickInterval
......@@ -436,6 +436,10 @@ loop:
}
}
if _, err := time.ParseDuration(ord.EtcdRaft.Options.TickInterval); err != nil {
logger.Panicf("Etcdraft TickInterval (%s) must be in time duration format", ord.EtcdRaft.Options.TickInterval)
}
// validate the specified members for Options
if ord.EtcdRaft.Options.ElectionTick <= ord.EtcdRaft.Options.HeartbeatTick {
logger.Panicf("election tick must be greater than heartbeat tick")
......
......@@ -246,7 +246,7 @@ func TestConsensusSpecificInit(t *testing.T) {
"HeartbeatTick should be set to the default value")
})
t.Run("panic on invalid options", func(t *testing.T) {
t.Run("panic on invalid Heartbeat and Election tick", func(t *testing.T) {
options := &etcdraft.Options{
HeartbeatTick: 2,
ElectionTick: 1,
......@@ -257,6 +257,17 @@ func TestConsensusSpecificInit(t *testing.T) {
profile.completeInitialization(devConfigDir)
})
})
t.Run("panic on invalid TickInterval", func(t *testing.T) {
options := &etcdraft.Options{
TickInterval: "500",
}
profile := makeProfile(consenters, options)
assert.Panics(t, func() {
profile.completeInitialization(devConfigDir)
})
})
})
})
}
......@@ -268,7 +268,7 @@ var _ bool = Describe("Kafka2RaftMigration", func() {
},
},
Options: &protosraft.Options{
TickInterval: 100,
TickInterval: "500ms",
ElectionTick: 10,
HeartbeatTick: 1,
MaxInflightMsgs: 256,
......
......@@ -88,6 +88,7 @@ Profiles:{{ range .Profiles }}
{{- if eq $w.Consensus.Type "etcdraft" }}
EtcdRaft:
Options:
TickInterval: 500ms
SnapshotInterval: 1 KB
Consenters:{{ range .Orderers }}{{ with $w.Orderer . }}
- Host: 127.0.0.1
......
......@@ -179,13 +179,18 @@ func (c *Consenter) HandleChain(support consensus.ConsenterSupport, metadata *co
}
}
tickInterval, err := time.ParseDuration(m.Options.TickInterval)
if err != nil {
return nil, errors.Errorf("failed to parse TickInterval (%s) to time duration", m.Options.TickInterval)
}
opts := Options{
RaftID: id,
Clock: clock.NewClock(),
MemoryStorage: raft.NewMemoryStorage(),
Logger: c.Logger,
TickInterval: time.Duration(m.Options.TickInterval) * time.Millisecond,
TickInterval: tickInterval,
ElectionTick: int(m.Options.ElectionTick),
HeartbeatTick: int(m.Options.HeartbeatTick),
MaxInflightMsgs: int(m.Options.MaxInflightMsgs),
......
......@@ -147,7 +147,7 @@ var _ = Describe("Consenter", func() {
{ServerTlsCert: certBytes},
},
Options: &etcdraftproto.Options{
TickInterval: 500,
TickInterval: "500ms",
ElectionTick: 10,
HeartbeatTick: 1,
MaxInflightMsgs: 256,
......@@ -189,7 +189,7 @@ var _ = Describe("Consenter", func() {
{ServerTlsCert: []byte("cert.orderer1.org1")},
},
Options: &etcdraftproto.Options{
TickInterval: 500,
TickInterval: "500ms",
ElectionTick: 10,
HeartbeatTick: 1,
MaxInflightMsgs: 256,
......@@ -235,6 +235,35 @@ var _ = Describe("Consenter", func() {
Expect(chain).To(BeNil())
Expect(err).To(MatchError("etcdraft options have not been provided"))
})
It("fails to handle chain if tick interval is invalid", func() {
certBytes := []byte("cert.orderer0.org0")
m := &etcdraftproto.Metadata{
Consenters: []*etcdraftproto.Consenter{
{ServerTlsCert: certBytes},
},
Options: &etcdraftproto.Options{
TickInterval: "500",
ElectionTick: 10,
HeartbeatTick: 1,
MaxInflightMsgs: 256,
MaxSizePerMsg: 1048576,
},
}
metadata := utils.MarshalOrPanic(m)
support.SharedConfigReturns(&mockconfig.Orderer{
ConsensusMetadataVal: metadata,
CapabilitiesVal: &mockconfig.OrdererCapabilities{
Kafka2RaftMigVal: false,
},
})
consenter := newConsenter(chainGetter)
chain, err := consenter.HandleChain(support, nil)
Expect(chain).To(BeNil())
Expect(err).To(MatchError("failed to parse TickInterval (500) to time duration"))
})
})
type consenter struct {
......
......@@ -32,7 +32,7 @@ func (m *Metadata) Reset() { *m = Metadata{} }
func (m *Metadata) String() string { return proto.CompactTextString(m) }
func (*Metadata) ProtoMessage() {}
func (*Metadata) Descriptor() ([]byte, []int) {
return fileDescriptor_configuration_030e547fa9cbed9e, []int{0}
return fileDescriptor_configuration_eccf5482c1dcdfdd, []int{0}
}
func (m *Metadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Metadata.Unmarshal(m, b)
......@@ -81,7 +81,7 @@ func (m *Consenter) Reset() { *m = Consenter{} }
func (m *Consenter) String() string { return proto.CompactTextString(m) }
func (*Consenter) ProtoMessage() {}
func (*Consenter) Descriptor() ([]byte, []int) {
return fileDescriptor_configuration_030e547fa9cbed9e, []int{1}
return fileDescriptor_configuration_eccf5482c1dcdfdd, []int{1}
}
func (m *Consenter) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Consenter.Unmarshal(m, b)
......@@ -132,7 +132,7 @@ func (m *Consenter) GetServerTlsCert() []byte {
// Options to be specified for all the etcd/raft nodes. These can be modified on a
// per-channel basis.
type Options struct {
TickInterval uint64 `protobuf:"varint,1,opt,name=tick_interval,json=tickInterval,proto3" json:"tick_interval,omitempty"`
TickInterval string `protobuf:"bytes,1,opt,name=tick_interval,json=tickInterval,proto3" json:"tick_interval,omitempty"`
ElectionTick uint32 `protobuf:"varint,2,opt,name=election_tick,json=electionTick,proto3" json:"election_tick,omitempty"`
HeartbeatTick uint32 `protobuf:"varint,3,opt,name=heartbeat_tick,json=heartbeatTick,proto3" json:"heartbeat_tick,omitempty"`
MaxInflightMsgs uint32 `protobuf:"varint,4,opt,name=max_inflight_msgs,json=maxInflightMsgs,proto3" json:"max_inflight_msgs,omitempty"`
......@@ -148,7 +148,7 @@ func (m *Options) Reset() { *m = Options{} }
func (m *Options) String() string { return proto.CompactTextString(m) }
func (*Options) ProtoMessage() {}
func (*Options) Descriptor() ([]byte, []int) {
return fileDescriptor_configuration_030e547fa9cbed9e, []int{2}
return fileDescriptor_configuration_eccf5482c1dcdfdd, []int{2}
}
func (m *Options) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Options.Unmarshal(m, b)
......@@ -168,11 +168,11 @@ func (m *Options) XXX_DiscardUnknown() {
var xxx_messageInfo_Options proto.InternalMessageInfo
func (m *Options) GetTickInterval() uint64 {
func (m *Options) GetTickInterval() string {
if m != nil {
return m.TickInterval
}
return 0
return ""
}
func (m *Options) GetElectionTick() uint32 {
......@@ -233,7 +233,7 @@ func (m *RaftMetadata) Reset() { *m = RaftMetadata{} }
func (m *RaftMetadata) String() string { return proto.CompactTextString(m) }
func (*RaftMetadata) ProtoMessage() {}
func (*RaftMetadata) Descriptor() ([]byte, []int) {
return fileDescriptor_configuration_030e547fa9cbed9e, []int{3}
return fileDescriptor_configuration_eccf5482c1dcdfdd, []int{3}
}
func (m *RaftMetadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RaftMetadata.Unmarshal(m, b)
......@@ -290,11 +290,11 @@ func init() {
}
func init() {
proto.RegisterFile("orderer/etcdraft/configuration.proto", fileDescriptor_configuration_030e547fa9cbed9e)
proto.RegisterFile("orderer/etcdraft/configuration.proto", fileDescriptor_configuration_eccf5482c1dcdfdd)
}
var fileDescriptor_configuration_030e547fa9cbed9e = []byte{
// 535 bytes of a gzipped FileDescriptorProto
var fileDescriptor_configuration_eccf5482c1dcdfdd = []byte{
// 537 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x93, 0x4d, 0x6b, 0x1b, 0x3d,
0x14, 0x85, 0x99, 0x78, 0xf2, 0xa5, 0x78, 0x5e, 0xdb, 0x7a, 0x37, 0xa6, 0x50, 0x30, 0x6e, 0x9b,
0xba, 0x49, 0x99, 0x81, 0x84, 0x42, 0xe9, 0xb2, 0xa6, 0x05, 0x2f, 0x4c, 0x8b, 0x9a, 0x55, 0x37,
......@@ -310,23 +310,23 @@ var fileDescriptor_configuration_030e547fa9cbed9e = []byte{
0x02, 0xa4, 0xa5, 0xb6, 0x30, 0x94, 0x83, 0xb6, 0xc3, 0xce, 0x28, 0x98, 0x74, 0x49, 0x54, 0xc9,
0x0f, 0x85, 0x99, 0x42, 0xc5, 0x19, 0xd0, 0x5b, 0xd0, 0x07, 0x2e, 0xac, 0xb8, 0x4a, 0xae, 0xb9,
0xf1, 0x9f, 0x00, 0x9d, 0xd7, 0xd1, 0xf0, 0x2b, 0x14, 0x59, 0xc1, 0x57, 0x54, 0xb8, 0x44, 0x5b,
0x56, 0xf8, 0x30, 0x21, 0xe9, 0x3a, 0x71, 0x56, 0x6b, 0x0e, 0x82, 0x02, 0xb8, 0xab, 0xa0, 0xce,
0xa8, 0xd3, 0x75, 0x1b, 0xf1, 0x41, 0xf0, 0x15, 0x7e, 0x83, 0xfe, 0xcb, 0x81, 0x69, 0xbb, 0x00,
0x66, 0x2b, 0xaa, 0xe3, 0xa9, 0xa8, 0x55, 0x3d, 0x76, 0x83, 0x06, 0x6b, 0xb6, 0xa3, 0x42, 0x2e,
0x0b, 0x91, 0xe5, 0x96, 0xae, 0x4d, 0x66, 0x7c, 0xcc, 0x88, 0xf4, 0xd6, 0x6c, 0x37, 0xab, 0xf5,
0xb9, 0xc9, 0x0c, 0x7e, 0x8b, 0xfa, 0x8e, 0x35, 0xe2, 0x11, 0x68, 0x09, 0xda, 0xb1, 0xc3, 0x53,
0x9f, 0x2f, 0x5a, 0xb3, 0xdd, 0x0f, 0xf1, 0x08, 0xdf, 0x41, 0xcf, 0x4d, 0x86, 0x6f, 0xd1, 0xc0,
0x48, 0x56, 0x9a, 0x5c, 0xd9, 0xc3, 0x4d, 0xce, 0x7c, 0xd3, 0x7e, 0x63, 0x34, 0xb7, 0x19, 0xff,
0x3e, 0x41, 0x5d, 0xc2, 0x96, 0xb6, 0x9d, 0xfb, 0xd7, 0x67, 0xe6, 0x7e, 0x7d, 0x98, 0xe2, 0x31,
0x7b, 0x58, 0x02, 0xf3, 0x45, 0x5a, 0xbd, 0xff, 0x67, 0x15, 0x6e, 0xd0, 0x40, 0xc2, 0xce, 0xd2,
0x56, 0xa2, 0x22, 0xf5, 0x4f, 0x15, 0x92, 0x9e, 0x33, 0xda, 0xda, 0x59, 0x8a, 0xdf, 0x23, 0xec,
0x16, 0x93, 0xf2, 0x9c, 0xc9, 0x0c, 0x28, 0x57, 0x1b, 0x69, 0x8d, 0x7f, 0xb1, 0x90, 0xf4, 0x9d,
0x33, 0xf5, 0xc6, 0xd4, 0xeb, 0xf8, 0x25, 0x42, 0x2e, 0x0a, 0x15, 0x32, 0x85, 0x9d, 0x7f, 0xad,
0x90, 0x5c, 0x3a, 0x65, 0xe6, 0x84, 0x17, 0x04, 0xf5, 0x9e, 0xe4, 0xc2, 0x7d, 0xd4, 0x59, 0xc1,
0xbe, 0x9e, 0xa6, 0x3b, 0xe2, 0x77, 0xe8, 0x74, 0xcb, 0x8a, 0x0d, 0xd4, 0x6b, 0xfa, 0xec, 0x62,
0x57, 0xc4, 0xa7, 0x93, 0x8f, 0xc1, 0xe7, 0x0c, 0xc5, 0x4a, 0x67, 0x71, 0xbe, 0x2f, 0x41, 0x17,
0x90, 0x66, 0xa0, 0xe3, 0x25, 0x5b, 0x68, 0xc1, 0xab, 0x2f, 0x64, 0xe2, 0xfa, 0xa3, 0xb5, 0x6d,
0x7e, 0x7e, 0xc8, 0x84, 0xcd, 0x37, 0x8b, 0x98, 0xab, 0x75, 0x72, 0x54, 0x96, 0x54, 0x65, 0x49,
0x55, 0x96, 0x3c, 0xfd, 0x9f, 0x8b, 0x33, 0x6f, 0xdc, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xfb,
0x39, 0x7a, 0xda, 0xba, 0x03, 0x00, 0x00,
0x56, 0xd4, 0x61, 0xba, 0x4e, 0x9c, 0xd5, 0x9a, 0x83, 0xa0, 0x00, 0xee, 0x2a, 0xa8, 0x33, 0xea,
0x74, 0xdd, 0x46, 0x7c, 0x10, 0x7c, 0x85, 0xdf, 0xa0, 0xff, 0x72, 0x60, 0xda, 0x2e, 0x80, 0xd9,
0x8a, 0xea, 0x78, 0x2a, 0x6a, 0x55, 0x8f, 0xdd, 0xa0, 0xc1, 0x9a, 0xed, 0xa8, 0x90, 0xcb, 0x42,
0x64, 0xb9, 0xa5, 0x6b, 0x93, 0x19, 0x1f, 0x33, 0x22, 0xbd, 0x35, 0xdb, 0xcd, 0x6a, 0x7d, 0x6e,
0x32, 0x83, 0xdf, 0xa2, 0xbe, 0x63, 0x8d, 0x78, 0x04, 0x5a, 0x82, 0x76, 0xec, 0xf0, 0x74, 0x14,
0x4c, 0x42, 0x12, 0xad, 0xd9, 0xee, 0x87, 0x78, 0x84, 0xef, 0xa0, 0xe7, 0x26, 0xc3, 0xb7, 0x68,
0x60, 0x24, 0x2b, 0x4d, 0xae, 0xec, 0xe1, 0x26, 0x67, 0xbe, 0x69, 0xbf, 0x31, 0x9a, 0xdb, 0x8c,
0x7f, 0x9f, 0xa0, 0x2e, 0x61, 0x4b, 0xdb, 0xce, 0xfd, 0xeb, 0x33, 0x73, 0xbf, 0x3e, 0x4c, 0xf1,
0x98, 0x3d, 0x2c, 0x81, 0xf9, 0x22, 0xad, 0xde, 0xff, 0xb3, 0x0a, 0x37, 0x68, 0x20, 0x61, 0x67,
0x69, 0x2b, 0x51, 0x91, 0xfa, 0xa7, 0x0a, 0x49, 0xcf, 0x19, 0x6d, 0xed, 0x2c, 0xc5, 0xef, 0x11,
0x76, 0x8b, 0x49, 0x79, 0xce, 0x64, 0x06, 0x94, 0xab, 0x8d, 0xb4, 0xc6, 0xbf, 0x58, 0x48, 0xfa,
0xce, 0x99, 0x7a, 0x63, 0xea, 0x75, 0xfc, 0x12, 0x21, 0x17, 0x85, 0x0a, 0x99, 0xc2, 0xce, 0xbf,
0x56, 0x48, 0x2e, 0x9d, 0x32, 0x73, 0xc2, 0x0b, 0x82, 0x7a, 0x4f, 0x72, 0xe1, 0x3e, 0xea, 0xac,
0x60, 0xef, 0xa7, 0x19, 0x12, 0x77, 0xc4, 0xef, 0xd0, 0xe9, 0x96, 0x15, 0x1b, 0xa8, 0xd7, 0xf4,
0xd9, 0xc5, 0xae, 0x88, 0x4f, 0x27, 0x1f, 0x83, 0xcf, 0x19, 0x8a, 0x95, 0xce, 0xe2, 0x7c, 0x5f,
0x82, 0x2e, 0x20, 0xcd, 0x40, 0xc7, 0x4b, 0xb6, 0xd0, 0x82, 0x57, 0x5f, 0xc8, 0xc4, 0xf5, 0x47,
0x6b, 0xdb, 0xfc, 0xfc, 0x90, 0x09, 0x9b, 0x6f, 0x16, 0x31, 0x57, 0xeb, 0xe4, 0xa8, 0x2c, 0xa9,
0xca, 0x92, 0xaa, 0x2c, 0x79, 0xfa, 0x3f, 0x17, 0x67, 0xde, 0xb8, 0xff, 0x1b, 0x00, 0x00, 0xff,
0xff, 0x16, 0xa4, 0x7e, 0x04, 0xba, 0x03, 0x00, 0x00,
}
......@@ -29,7 +29,7 @@ message Consenter {
// Options to be specified for all the etcd/raft nodes. These can be modified on a
// per-channel basis.
message Options {
uint64 tick_interval = 1; // specified in miliseconds
string tick_interval = 1; // time duration format, e.g. 500ms
uint32 election_tick = 2;
uint32 heartbeat_tick = 3;
uint32 max_inflight_msgs = 4;
......
......@@ -312,10 +312,8 @@ Orderer: &OrdererDefaults
# are the defaults for all new channels and can be modified on a
# per-channel basis via configuration updates.
Options:
# TickInterval is the time interval between two Node.Tick
# invocations.
# Unit: millisecond
TickInterval: 500
# TickInterval is the time interval between two Node.Tick invocations.
TickInterval: 500ms
# ElectionTick is the number of Node.Tick invocations that must pass
# between elections. That is, if a follower does not receive any
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment