Repository navigation
Conversation
| // holdView keeps the controller from starting the given view again until the | ||
| // view changer asks for a new one. | ||
| func (c *Controller) holdView(view uint64) { | ||
| c.currViewLock.Lock() | ||
| defer c.currViewLock.Unlock() | ||
|
|
||
| c.minRestartView = max(c.minRestartView, view+1) | ||
| } |
There was a problem hiding this comment.
minRestartView is only set while viewChangeLock is held, and changeView already waits on that lock. ReleaseViewWrite then resets it to 0, so isViewHeld never returns true outside the unit test that calls holdView directly. Could it be removed? If it's meant to stay, the holdView comment ("until the view changer asks for a new one") doesn't match what it does.
(Written by Claude Code.)
| case <-view.AbortChan(): | ||
| // The view is stopping while the controller is busy with a long sync or | ||
| // delivery. Do not block the view, or the abort would wait for it, but do | ||
| // not drop the decision either: hand it to the controller in the background. | ||
| go c.enqueueDecision(d) | ||
| return |
There was a problem hiding this comment.
The goroutine can put an aborted view's decision on decisionChan after the next view has started, or after the view changer has committed the same in-flight proposal. Is double delivery ruled out somewhere? A decision left in the buffered channel could already do this before the PR, so this may be fine.
(Written by Claude Code.)
27a0018 to
7a2ac06
Compare
|
@HagarMeir fixed |
|
Thanks for the fixes. This is a lot of concurrency change in one PR, and I find it hard to follow. Could you split it? Something like:
Each one would then come with its own tests. Also, (Written by Claude Code.) |
7a2ac06 to
4f4b3c3
Compare
Please take a look, I've simplified the code. But if you think you need to split it into several pull requests, I'll do it. |
yes please try to split the work |
06afc1d to
1b363c2
Compare
693c5c8 to
2c2da71
Compare
2c2da71 to
2c5146f
Compare
AbortView stopped the current view, but the controller could restart it through the sync path before the view changer wrote its record. That allowed a commit to land after a NewView or ViewChange record, leaving a WAL sequence that recovery rejects ([NewView, Commit] or [PP, ViewChange, Commit]).
Add AbortViewAndHold/ReleaseViewWrite and a viewChangeLock so no view can be started or write between the abort and the record write. Also enqueue a decision instead of dropping it when the view is aborted, and let AbortView return without waiting for the controller loop.
#736