Repository navigation
Conversation
|
At our stand, the situation turned out to be that the nodes spread to different views and could not restore their functionality. |
Thanks for this. Before we look at the fix itself, here are some notes on How I checked: I copied
Only two of the six tests fail on
Keep, with fixes
For both: assert each group's view with Tests that don't exercise the fix
Why are these two needed in this PR? They pass both on
If they're meant to document current behaviour, please fix the comments and the recovery check. Otherwise they may not belong in this PR.
General
Flakiness:
I'll comment on the fix itself separately. |
Thank you very much. Don't comment on the correction yet. I need to finalize the split test first. |
961b575 to
9ac3e18
Compare
I've removed the extra tests. I have corrected the remaining ones, please take a look at them or there are more comments on them. |
Thanks, this is a big improvement. The shared setup, the delivery wait that checks for request 2 and stops its goroutines, How I checked: I ran the two tests on this branch, on
So the first test covers the
|
One more suggestion: could we take this one change at a time? I'd start with just the
For the first step, it would help to make Would you be open to splitting it this way? |
I'm willing to do anything to solve the main problem. I won't share the changes yet. I'm afraid that the main situation that I would like to overcome will go away. The nodes were stuck in views n, n + 1, n + 2. and the long waiting time did not lead to the fact that they restored their work and were able to continue calculating transactions. |
9ac3e18 to
b45bcf0
Compare
I changed the test according to your comments. |
Thanks for the update. The tests look good now. The first one builds the views 0/1/2 shape you described, the second runs with all timers ticking, and the setup checks stop the test at the step that went wrong. How I checked: you wanted to know whether each change on its own solves the main problem, so I ran both tests on four builds, 5 rounds each:
Both tests now fail without the fix, every time.
On your question whether each change alone solves the main problem:
So splitting shouldn't lose the main fix. The first PR, with the Two small points on the tests:
|
b45bcf0 to
da65fd3
Compare
no: in the prod, all nodes remained mutually accessible, the network was not completely cut; they got stuck precisely because of the out-of-sync sequences |
A node that fell behind the cluster by exactly the proposal that was in flight could never rejoin, and went silent forever. The numbers that tell a node how far the cluster got were taken from two different frames of reference. ViewSequences held the sequence that had just been decided, while the heartbeat a leader broadcasts, the sequence a node reports when its state is collected, and the sequence a follower compares its own against all refer to the sequence the view is about to propose. A node that syncs in the middle of a proposal is told the cluster is at a sequence it has already decided: it starts the new view at that sequence, waits for a proposal that was already sent once and is never sent again, and never learns that it is behind. Publish the next proposal sequence in ViewSequences as soon as the view moves on to it, so that the heartbeat a leader broadcasts, the sequence a node reports when its state is collected, and the sequence a follower compares its own against are all the same number. The scenario is covered end to end by TestNodeOneSequenceBehindRejoins in test/view_split_test.go. It builds the shape that was seen in production, a cluster of seven spread over three views, and it fails on main every time it is run: the two nodes that stayed behind never deliver the next request. The second half of the problem, a node that never starts a view change because it keeps hearing its leader, is handled by the announcement-triggered sync and by TestNodeBehindOnIdleViewRejoins, which follow in a separate pull request. Signed-off-by: Fedor Partanskiy <fredprtnsk@gmail.com>
da65fd3 to
e7bbcf0
Compare
|
@HagarMeir On your advice, I will divide the pull request into 2. Now the first part will go, after we work it out and accept it, I will send the second one. |
A node that fell behind the cluster by exactly the proposal that was in flight could never
rejoin, and went silent forever.
The numbers that tell a node how far the cluster got were taken from two different frames of
reference. ViewSequences held the sequence that had just been decided, while the heartbeat a
leader broadcasts, the sequence a node reports when its state is collected, and the sequence a
follower compares its own against all refer to the sequence the view is about to propose. A node
that syncs in the middle of a proposal is told the cluster is at a sequence it has already
decided: it starts the new view at that sequence, waits for a proposal that was already sent
once and is never sent again, and never learns that it is behind.
Publish the next proposal sequence in ViewSequences as soon as the view moves on to it, so that
the heartbeat a leader broadcasts, the sequence a node reports when its state is collected, and
the sequence a follower compares its own against are all the same number.
The scenario is covered end to end by TestNodeOneSequenceBehindRejoins in
test/view_split_test.go. It builds the shape that was seen in production, a cluster of seven
spread over three views, and it fails on main every time it is run: the two nodes that stayed
behind never deliver the next request.
The second half of the problem, a node that never starts a view change because it keeps hearing
its leader, is handled by the announcement-triggered sync and by
TestNodeBehindOnIdleViewRejoins, which follow in a separate pull request.