// NewSequencerControl creates a new instance of SequencerControl. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// NewOpConductor creates a new OpConductor instance.
funcNewOpConductor(
ctxcontext.Context,
cfg*Config,
loglog.Logger,
versionstring,
ctrlclient.SequencerControl,
consconsensus.Consensus,
hmonhealth.HealthMonitor,
)(*OpConductor,error){
iferr:=cfg.Check();err!=nil{
iferr:=cfg.Check();err!=nil{
returnnil,errors.Wrap(err,"invalid config")
returnnil,errors.Wrap(err,"invalid config")
}
}
oc:=&OpConductor{
oc:=&OpConductor{
log:log,
log:log,
version:version,
version:version,
cfg:cfg,
cfg:cfg,
pauseCh:make(chanstruct{}),
pauseDoneCh:make(chanstruct{}),
resumeCh:make(chanstruct{}),
resumeDoneCh:make(chanstruct{}),
actionCh:make(chanstruct{},1),
ctrl:ctrl,
cons:cons,
hmon:hmon,
}
}
oc.actionFn=oc.action
// explicitly set all atomic.Bool values
oc.leader.Store(false)// upon start, it should not be the leader unless specified otherwise by raft bootstrap, in that case, it'll receive a leadership update from consensus.
oc.healthy.Store(true)// default to healthy unless reported otherwise by health monitor.
oc.seqActive.Store(false)// explicitly set to false by default, the real value will be reported after sequencer control initialization.
returnerrors.Wrap(err,"failed to create node rpc client")
}
node:=sources.NewRollupClient(nc)
pc,err:=rpc.DialContext(ctx,c.cfg.NodeRPC)
iferr!=nil{
returnerrors.Wrap(err,"failed to create p2p rpc client")
}
p2p:=opp2p.NewClient(pc)
c.hmon=health.NewSequencerHealthMonitor(
c.log,
c.cfg.HealthCheck.Interval,
c.cfg.HealthCheck.SafeInterval,
c.cfg.HealthCheck.MinPeerCount,
&c.cfg.RollupCfg,
node,
p2p,
)
returnnil
}
// OpConductor represents a full conductor instance and its resources, it does:
// OpConductor represents a full conductor instance and its resources, it does:
// 1. performs health checks on sequencer
// 1. performs health checks on sequencer
// 2. participate in consensus protocol for leader election
// 2. participate in consensus protocol for leader election
// 3. and control sequencer state based on leader and sequencer health status.
// 3. and control sequencer state based on leader, sequencer health and sequencer active status.
//
//
// OpConductor has three states:
// OpConductor has three states:
// 1. running: it is running normally, which executes control loop and participates in leader election.
// 1. running: it is running normally, which executes control loop and participates in leader election.
// 2. paused: control loop (sequencer start/stop) is paused, but it still participates in leader election.
// 2. paused: control loop (sequencer start/stop) is paused, but it still participates in leader election, and receives health updates.
// it is paused for disaster recovery situation
// 3. stopped: it is stopped, which means it is not participating in leader election and control loop. OpConductor cannot be started again from stopped mode.
// 3. stopped: it is stopped, which means it is not participating in leader election and control loop. OpConductor cannot be started again from stopped mode.
typeOpConductorstruct{
typeOpConductorstruct{
loglog.Logger
loglog.Logger
...
@@ -98,21 +185,169 @@ type OpConductor struct {
...
@@ -98,21 +185,169 @@ type OpConductor struct {
ctrlclient.SequencerControl
ctrlclient.SequencerControl
consconsensus.Consensus
consconsensus.Consensus
hmonhealth.HealthMonitor
leaderatomic.Bool
healthyatomic.Bool
seqActiveatomic.Bool
actionFnfunc()// actionFn defines the action to be executed to bring the sequencer to the desired state.
// NewConsensus creates a new instance of Consensus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// NewHealthMonitor creates a new instance of HealthMonitor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.