mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-25 16:19:07 +02:00
[management] Keep an established claim when its re-read is inconclusive
SaveProxy upserts on the proxy ID, so on a reconnect the row Connect just wrote is the claim the account has held since its first connect, and the session guard on DeleteProxy matches because the upsert wrote the new session. Withdrawing that row whenever the post-write re-read errored surrendered an established claim on a transient store error — a window in which any other account could take the address — where the pre-existing code left the row untouched. An inconclusive re-read still refuses the connect, but marks the session disconnected instead of deleting the row; only a conclusive answer that the address is claimed withdraws it. The write-then-re-read argument moves to the doc of the exported ErrClusterAddressUnavailable, where the API needs it, and both helpers point there instead of carrying it twice. Store-backed tests drive the re-read through the real queries — a reconnect keeps its row, the account's own pin is not a competing claim, another account's is — since the whole path now depends on the store excluding the account's own claims. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sa3DsBDP3VciAi4PPG17L6
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
e6c69f674d
commit
d80f0ff031
@@ -10,12 +10,23 @@ const (
|
||||
StatusDisconnected = "disconnected"
|
||||
)
|
||||
|
||||
// ErrClusterAddressUnavailable is returned by Manager.Connect when the
|
||||
// cluster address turned out to be claimed by someone else once the proxy's
|
||||
// own row was written — a conflicting proxy row or another account's agent
|
||||
// network gateway pin that landed between the availability check and the
|
||||
// write. The proxy's row has been withdrawn by then; the caller reports the
|
||||
// address as taken, exactly as if the pre-write check had caught it.
|
||||
// ErrClusterAddressUnavailable is returned by Manager.Connect when the cluster
|
||||
// address turns out to be claimed by someone else once the proxy's own row is
|
||||
// written: a conflicting proxy row, or another account's agent network gateway
|
||||
// pinned to the address. The row has been withdrawn by then, and the caller
|
||||
// reports the address as taken exactly as if the pre-write check had caught it.
|
||||
//
|
||||
// Both kinds of claim are made the same way, write then re-read then withdraw,
|
||||
// and the re-read is the whole mechanism. Each side's availability check and
|
||||
// its write are separate autocommit statements, so two concurrent claimants
|
||||
// can each pass their check with neither row committed yet. Because both write
|
||||
// before they re-read, of two concurrent claims at least one re-reads after
|
||||
// the other has committed and backs off; each statement sees every commit
|
||||
// before it on sqlite, postgres and mysql alike. Both may back off, which
|
||||
// costs a retry; neither keeps a claim the other holds. No lock spans the
|
||||
// proxies and settings tables portably, and a claims table would be more
|
||||
// machinery than the property needs. The gateway side of the same protocol is
|
||||
// agentnetwork's confirmGatewayClusterOwnership.
|
||||
var ErrClusterAddressUnavailable = errors.New("cluster address is not available")
|
||||
|
||||
// Capabilities describes what a proxy can handle, as reported via gRPC.
|
||||
|
||||
Reference in New Issue
Block a user