Follow-ups to #681: decision count for a stopped view, regression tests, and cleanups
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- go
- Domain
- distributed-systems
Research direction
Start by reading #681 and the controller and view changer code around Controller.decide, run, sync, and commitInFlightProposal; the issue does not name source or test file paths. Check completion_signal_test.go and trace how aborts interact with buffered decisions and in-flight Decide or Sync calls. Done means fixing the stopped-current-view decision count, adding tests that fail on the old behavior, and addressing the listed cleanups; the optional late-result recovery is a separate improvement.
Written by the indexing model from the issue text.
Description
Written by Claude (Anthropic's AI assistant) on behalf of Hagar Meir.
These are the points left open in the review of #681 (avoid blocking on completion signals when the waiter has left). They should be done in a separate PR once #681 is merged.
1. Decision count when the deciding view is still current but stopped (possible small bug)
In Controller.decide, isRunningCurrentView(d.view) returns false in two different cases:
- The view was replaced. Skipping all of the view bookkeeping is right.
- The view is still current but already stopped, for example when the run loop handles
abortViewChanbefore the decision buffered indecisionChan. The decision was delivered in this view, and the checkpoint moved to its sequence, butincrementCurrentDecisionsInViewis skipped.
In the second case, if the node then syncs and finds nothing newer, it restarts the same view with a count that is one too low:
runcallschangeView(c.getCurrentViewNumber(), vs.ProposalSeq, c.getCurrentDecisionsInView()), orsynckeepsnewDecisionsInView = c.getCurrentDecisionsInView()when the latest decision is at the controller's sequence.
With leader rotation on, getLeaderID can then give this node a different leader from the other nodes, until the next view change resets the count.
This is not a regression: before #681, the send on deliverChan failed in the same case and the increment was skipped too.
Proposed fix: when d.view is the current view but stopped, still call incrementCurrentDecisionsInView, and skip only checkIfRotate/changeView and acquireLeaderToken, the steps that could race the pending view change. Add a test for it.
2. Regression tests that fail on the old code
The tests added in #681 (completion_signal_test.go) pass on the old code as well:
decidenow only closesd.delivered, andclosenever blocks;- the in-flight tests call
decideInFlightandsyncInFlightdirectly, and their non-blocking sends never block either.
Tests that reproduce the original hangs would catch a regression:
- controller:
Decidereturns through the view's abort channel while the decision is still buffered indecisionChan, and the run loop must keep processing later events; - view changer:
commitInFlightProposaltimes out or is stopped, and the deferredinFlightView.Abort()must not hang on a lateDecideorSyncfrom the in-flight view.
3. Inconsistent nil checks
decide checks d.delivered != nil, but Decide always sets it. Meanwhile a nil d.view panics in isRunningCurrentView. The two fields are always set together, so both checks can be removed.
4. Comments in decide
- "the current view must not be rotated or lead because of it" is unclear. It could say that the leader token is not acquired.
- It could also say why skipping
acquireLeaderTokenis fine for a replaced view: the new view'sstartViewacquires the token when needed.
5. Optional: in-flight attempt result after a late decision
If the in-flight attempt times out or is stopped while the in-flight view is delivering its decision, the deferred Abort() waits for the delivery to finish, so the proposal was committed. commitInFlightProposal still returns false, and the node waits for the next view change. Since decideCh is buffered, a non-blocking receive on it after the abort could return true instead. This only affects how quickly the node recovers, not correctness.
- Dominant language
- Go
- Stars
- 110
- Forks
- 40
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 14
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from hyperledger/SmartBFT
-
Set up a pr projectOpen
Difficulty 4/5 3-5 days Newbie friendliness 25/100
hyperledger/SmartBFT#666 · 4 comments ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
hyperledger/SmartBFT#628 · 12 comments ·
Maintainers usually reply within 1 day
-
Recording library runtime for bug analysis by developersMay be free again @HagarMeir claimed this 1733 days ago, and no pull request is open. Open
hyperledger/SmartBFT#487 · 1 assignee ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 15/100
hyperledger/SmartBFT#439 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
hyperledger/SmartBFT#420 ·
Maintainers usually reply within 1 day
All issues in hyperledger/SmartBFT
Similar issues
-
area/security kind/bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
agent-substrate/substrate#2935 ·
Maintainers usually reply within 1 day
-
automation models
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
Guardian health server binds :8080 and collides with the Voltron proxyPossibly taken @denislemire claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
projectcalico/calico#14341 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
blinklabs-io/dingo#5368 ·
Maintainers usually reply within 1 day
-
OpenAI compat: assistant tool_calls attached to previous message when content is an empty arrayPossibly taken @ShryukGrandhi claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day