@@ -11,6 +11,7 @@ import (
1111 "path/filepath"
1212 "slices"
1313 "strings"
14+ "sync/atomic"
1415 "time"
1516
1617 "github.com/hashicorp/raft"
@@ -47,7 +48,7 @@ type Config struct {
4748// FSM implements raft.FSM for block state
4849type FSM struct {
4950 logger zerolog.Logger
50- state * RaftBlockState
51+ state * atomic. Pointer [ RaftBlockState ]
5152 applyCh chan <- RaftApplyMsg
5253}
5354
@@ -63,9 +64,11 @@ func NewNode(cfg *Config, clusterClient clusterClient, logger zerolog.Logger) (*
6364 raftConfig .HeartbeatTimeout = cfg .HeartbeatTimeout
6465 raftConfig .LeaderLeaseTimeout = cfg .HeartbeatTimeout / 2
6566
67+ startPointer := new (atomic.Pointer [RaftBlockState ])
68+ startPointer .Store (& RaftBlockState {})
6669 fsm := & FSM {
6770 logger : logger .With ().Str ("component" , "raft-fsm" ).Logger (),
68- state : & RaftBlockState {} ,
71+ state : startPointer ,
6972 }
7073
7174 logStore , err := raftboltdb .NewBoltStore (filepath .Join (cfg .RaftDir , "raft-log.db" ))
@@ -131,6 +134,7 @@ func (n *Node) Start(ctx context.Context) error {
131134 if n .GetState ().Height != 0 {
132135 return nil
133136 }
137+ time .Sleep (time .Second / 10 )
134138 }
135139 }
136140 }
@@ -158,7 +162,6 @@ func (n *Node) Start(ctx context.Context) error {
158162 }
159163 n .logger .Info ().Msg ("bootstrapped raft cluster" )
160164 return nil
161-
162165}
163166
164167func (n * Node ) awaitToBeClusterMember (ctx context.Context , nodeID raft.ServerID ) error {
@@ -246,8 +249,8 @@ func (n *Node) Broadcast(_ context.Context, state *RaftBlockState) error {
246249}
247250
248251// GetState returns the current replicated state
249- func (n * Node ) GetState () * RaftBlockState {
250- return n .fsm .state
252+ func (n * Node ) GetState () RaftBlockState {
253+ return * n .fsm .state . Load ()
251254}
252255
253256// AddPeer adds a peer to the raft cluster
@@ -304,10 +307,10 @@ func (f *FSM) Apply(log *raft.Log) interface{} {
304307 f .logger .Error ().Err (err ).Msg ("unmarshal block state" )
305308 return err
306309 }
307- if err := f .state .assertValid (state ); err != nil {
310+ if err := f .state .Load (). assertValid (state ); err != nil {
308311 return err
309312 }
310- f .state = & state
313+ f .state . Store ( & state )
311314 f .logger .Debug ().Uint64 ("height" , state .Height ).Msg ("received block state" )
312315
313316 if f .applyCh != nil {
@@ -323,7 +326,7 @@ func (f *FSM) Apply(log *raft.Log) interface{} {
323326
324327// Snapshot implements raft.FSM
325328func (f * FSM ) Snapshot () (raft.FSMSnapshot , error ) {
326- return & fsmSnapshot {state : f .state }, nil
329+ return & fsmSnapshot {state : * f .state . Load () }, nil
327330}
328331
329332// Restore implements raft.FSM
@@ -335,13 +338,13 @@ func (f *FSM) Restore(rc io.ReadCloser) error {
335338 return fmt .Errorf ("decode snapshot: %w" , err )
336339 }
337340
338- f .state = & state
341+ f .state . Store ( & state )
339342 f .logger .Info ().Uint64 ("height" , state .Height ).Msg ("restored from snapshot" )
340343 return nil
341344}
342345
343346type fsmSnapshot struct {
344- state * RaftBlockState
347+ state RaftBlockState
345348}
346349
347350func (s * fsmSnapshot ) Persist (sink raft.SnapshotSink ) error {
0 commit comments