bitxhub/pkg/order/etcdraft/config.go

105 lines
3.8 KiB
Go

package etcdraft
import (
"path/filepath"
"time"
"github.com/coreos/etcd/raft"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
type RAFTConfig struct {
RAFT RAFT
}
type MempoolConfig struct {
BatchSize uint64 `mapstructure:"batch_size"`
PoolSize uint64 `mapstructure:"pool_size"`
TxSliceSize uint64 `mapstructure:"tx_slice_size"`
TxSliceTimeout time.Duration `mapstructure:"tx_slice_timeout"`
}
type SyncerConfig struct {
SyncBlocks uint64 `mapstructure:"sync_blocks"`
SnapshotCount uint64 `mapstructure:"snapshot_count"`
}
type RAFT struct {
BatchTimeout time.Duration `mapstructure:"batch_timeout"`
TickTimeout time.Duration `mapstructure:"tick_timeout"`
ElectionTick int `mapstructure:"election_tick"`
HeartbeatTick int `mapstructure:"heartbeat_tick"`
MaxSizePerMsg uint64 `mapstructure:"max_size_per_msg"`
MaxInflightMsgs int `mapstructure:"max_inflight_msgs"`
CheckQuorum bool `mapstructure:"check_quorum"`
PreVote bool `mapstructure:"pre_vote"`
DisableProposalForwarding bool `mapstructure:"disable_proposal_forwarding"`
MempoolConfig MempoolConfig `mapstructure:"mempool"`
SyncerConfig SyncerConfig `mapstructure:"syncer"`
}
func defaultRaftConfig() raft.Config {
return raft.Config{
ElectionTick: 10, // ElectionTick is the number of Node.Tick invocations that must pass between elections.(s)
HeartbeatTick: 1, // HeartbeatTick is the number of Node.Tick invocations that must pass between heartbeats.(s)
MaxSizePerMsg: 1024 * 1024, // 1024*1024, MaxSizePerMsg limits the max size of each append message.
MaxInflightMsgs: 500, // MaxInflightMsgs limits the max number of in-flight append messages during optimistic replication phase.
PreVote: true, // PreVote prevents reconnected node from disturbing network.
CheckQuorum: true, // Leader steps down when quorum is not active for an electionTimeout.
DisableProposalForwarding: true, // This prevents blocks from being accidentally proposed by followers
}
}
func generateEtcdRaftConfig(id uint64, repoRoot string, logger logrus.FieldLogger, ram MemoryStorage) (*raft.Config, time.Duration, error) {
readConfig, err := readConfig(repoRoot)
if err != nil {
return &raft.Config{}, 100 * time.Millisecond, nil
}
defaultConfig := defaultRaftConfig()
defaultConfig.ID = id
defaultConfig.Storage = ram
defaultConfig.Logger = logger
if readConfig.RAFT.ElectionTick > 0 {
defaultConfig.ElectionTick = readConfig.RAFT.ElectionTick
}
if readConfig.RAFT.HeartbeatTick > 0 {
defaultConfig.HeartbeatTick = readConfig.RAFT.HeartbeatTick
}
if readConfig.RAFT.MaxSizePerMsg > 0 {
defaultConfig.MaxSizePerMsg = readConfig.RAFT.MaxSizePerMsg
}
if readConfig.RAFT.MaxInflightMsgs > 0 {
defaultConfig.MaxInflightMsgs = readConfig.RAFT.MaxInflightMsgs
}
defaultConfig.PreVote = readConfig.RAFT.PreVote
defaultConfig.CheckQuorum = readConfig.RAFT.CheckQuorum
defaultConfig.DisableProposalForwarding = readConfig.RAFT.DisableProposalForwarding
return &defaultConfig, readConfig.RAFT.TickTimeout, nil
}
func generateRaftConfig(repoRoot string) (*RAFTConfig, error) {
readConfig, err := readConfig(repoRoot)
if err != nil {
return nil, err
}
return readConfig, nil
}
func readConfig(repoRoot string) (*RAFTConfig, error) {
v := viper.New()
v.SetConfigFile(filepath.Join(repoRoot, "order.toml"))
v.SetConfigType("toml")
if err := v.ReadInConfig(); err != nil {
return nil, err
}
config := &RAFTConfig{}
if err := v.Unmarshal(config); err != nil {
return nil, err
}
return config, nil
}