fix(clients): push bulk client changes to nodes only after the commit lands - #6181
Open
n0ctal wants to merge 1 commit into
Open
fix(clients): push bulk client changes to nodes only after the commit lands#6181n0ctal wants to merge 1 commit into
n0ctal wants to merge 1 commit into
Conversation
n0ctal
force-pushed
the
upstream-node-push-after-commit
branch
from
August 8, 2026 02:10
ab5b2ab to
0503192
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Move the node-side client push in
bulkAdjustInboundClientsandbulkDelInboundClientsso it runs after the database transaction commits, and let the existing dirty-node reconcile converge instead of pushing eagerly.Why
Both bulk paths pushed the mutated client set to the remote node before
runSerializedTxwrote the inbound. If that transaction then failed — a serialization retry giving up, a constraint violation, the traffic poll holding the lock — the node had already applied changes the panel never recorded.From that point the two disagree, and they disagree silently: the node serves expiry and quota values that exist nowhere in the database, while the panel believes the operation did not happen. Nothing marks the divergence, because each half individually reported success. It surfaces later as a client whose limits do not match the panel, with no event to trace it back to.
This is an ordering bug rather than a race — the push is unconditionally sequenced before the write, so no amount of retrying changes the outcome.
Scope
bulkAdjustInboundClients: drop the pre-commit push block and push after a successful commit, keeping the existingflowChangedandnodeBulkPushThresholdconditions unchanged.bulkDelInboundClients: same reordering. The deletion path now runs throughrunSerializedTxwithMarkNodeDirtyTx, so a push that fails converges through reconcile instead of leaving the node ahead of the panel.prevSettings/advancePushedInboundbookkeeping that existed only to compensate for the early push.Validation
go build ./internal/...clean.go test ./internal/web/service/green onmainatece16559with this applied.mainwithout conflict.Risk
Low. A failed push now leaves the node marked dirty and is picked up by the existing reconcile pass rather than retried inline — the same mechanism that already covers batches above
nodeBulkPushThresholdand flow changes. No schema, API, or configuration change.