@@ -2,6 +2,7 @@ package driver
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"time"
6
7
7
8
"github.com/NethermindEth/juno/consensus/db"
@@ -62,16 +63,40 @@ func (d *Driver[V, H, A]) Run(ctx context.Context) error {
62
63
}
63
64
}()
64
65
65
- d .stateMachine .ReplayWAL ()
66
+ if err := d .replay (ctx ); err != nil {
67
+ return err
68
+ }
69
+
70
+ return d .listen (ctx )
71
+ }
72
+
73
+ func (d * Driver [V , H , A ]) replay (ctx context.Context ) error {
74
+ for walEntry , err := range d .db .LoadAllEntries () {
75
+ if err != nil {
76
+ return fmt .Errorf ("failed to load WAL entries: %w" , err )
77
+ }
66
78
79
+ if _ , err := d .execute (ctx , true , d .stateMachine .ProcessWAL (walEntry )); err != nil {
80
+ return err
81
+ }
82
+ }
83
+
84
+ return nil
85
+ }
86
+
87
+ func (d * Driver [V , H , A ]) listen (ctx context.Context ) error {
67
88
for {
68
89
select {
69
90
case <- ctx .Done ():
70
91
return nil
71
92
default :
72
93
}
94
+
73
95
actions := d .stateMachine .ProcessStart (0 )
74
- isCommitted := d .execute (ctx , actions )
96
+ isCommitted , err := d .execute (ctx , false , actions )
97
+ if err != nil {
98
+ return err
99
+ }
75
100
76
101
// Todo: check message signature everytime a message is received.
77
102
// For the time being it can be assumed the signature is correct.
@@ -100,46 +125,69 @@ func (d *Driver[V, H, A]) Run(ctx context.Context) error {
100
125
actions = d .stateMachine .ProcessPrecommit (p )
101
126
}
102
127
103
- isCommitted = d .execute (ctx , actions )
128
+ isCommitted , err = d .execute (ctx , false , actions )
129
+ if err != nil {
130
+ return err
131
+ }
104
132
}
105
133
}
106
134
}
107
135
108
136
// This function executes the actions returned by the stateMachine.
109
137
// It returns true if a commit action was executed. This is to notify the caller to start a new height with round 0.
138
+ // Note: `WriteWAL` actions are generated as part of processing the event itself, so there's no
139
+ // need to write them to the WAL again here. `isReplaying` is used to disable the writing of WAL.
110
140
func (d * Driver [V , H , A ]) execute (
111
141
ctx context.Context ,
112
- executingActions []actions.Action [V , H , A ],
113
- ) (isCommitted bool ) {
114
- for _ , action := range executingActions {
142
+ isReplaying bool ,
143
+ resultActions []actions.Action [V , H , A ],
144
+ ) (isCommitted bool , err error ) {
145
+ for _ , action := range resultActions {
146
+ if ! isReplaying && action .RequiresWALFlush () {
147
+ if err := d .db .Flush (); err != nil {
148
+ return false , fmt .Errorf ("failed to flush WAL: %w" , err )
149
+ }
150
+ }
151
+
115
152
switch action := action .(type ) {
153
+ case * actions.WriteWAL [V , H , A ]:
154
+ if ! isReplaying {
155
+ if err := d .db .SetWALEntry (action .Entry ); err != nil {
156
+ return false , fmt .Errorf ("failed to write WAL: %w" , err )
157
+ }
158
+ }
159
+
116
160
case * actions.BroadcastProposal [V , H , A ]:
117
161
d .broadcasters .ProposalBroadcaster .Broadcast (ctx , (* types.Proposal [V , H , A ])(action ))
162
+
118
163
case * actions.BroadcastPrevote [H , A ]:
119
164
d .broadcasters .PrevoteBroadcaster .Broadcast (ctx , (* types.Prevote [H , A ])(action ))
165
+
120
166
case * actions.BroadcastPrecommit [H , A ]:
121
167
d .broadcasters .PrecommitBroadcaster .Broadcast (ctx , (* types.Precommit [H , A ])(action ))
168
+
122
169
case * actions.ScheduleTimeout :
123
- d .scheduledTms [types .Timeout (* action )] = time .AfterFunc (d .getTimeout (action .Step , action .Round ), func () {
124
- select {
125
- case <- ctx .Done ():
126
- case d .timeoutsCh <- types .Timeout (* action ):
127
- }
128
- })
129
- case * actions.Commit [V , H , A ]:
130
- if err := d .db .Flush (); err != nil {
131
- d .log .Fatalf ("failed to flush WAL during commit" , "height" , action .Height , "round" , action .Round , "err" , err )
132
- }
170
+ d .setTimeout (ctx , types .Timeout (* action ))
133
171
172
+ case * actions.Commit [V , H , A ]:
134
173
d .log .Debugw ("Committing" , "height" , action .Height , "round" , action .Round )
135
174
d .commitListener .OnCommit (ctx , action .Height , * action .Value )
136
175
137
176
if err := d .db .DeleteWALEntries (action .Height ); err != nil {
138
- d . log . Errorw ("failed to delete WAL messages during commit" , "height" , action . Height , "round" , action . Round , "err " , err )
177
+ return true , fmt . Errorf ("failed to delete WAL messages during commit: %w " , err )
139
178
}
140
179
141
- return true
180
+ return true , nil
142
181
}
143
182
}
144
- return false
183
+ return false , nil
184
+ }
185
+
186
+ func (d * Driver [V , H , A ]) setTimeout (ctx context.Context , timeout types.Timeout ) {
187
+ d .scheduledTms [timeout ] = time .AfterFunc (d .getTimeout (timeout .Step , timeout .Round ), func () {
188
+ select {
189
+ case <- ctx .Done ():
190
+ case d .timeoutsCh <- timeout :
191
+ }
192
+ })
145
193
}
0 commit comments