Skip to content

Commit b68a949

Browse files
docs(client): pin intentional go-dqlite divergences with source comments
Post-audit documentation pass. The cross-package audit flagged two spots where we intentionally diverge from go-dqlite and where a future reader might "helpfully" realign us to Go and regress the behavior: - find_leader shuffles within role class before sorting. Go's connector iterates nodes in deterministic stored order, which would stampede the same node across parallel callers. Add a block comment warning future maintainers not to drop the shuffle without adding stampede avoidance elsewhere. - handshake generates a random client_id per connection. Go leaves the default. We randomize for per-client server observability (logs, traces, metrics). Add a comment noting the intentional divergence and the 63-bit + "or 1" rationale. Neither is a behavior change. Pure source-level annotation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a521cf7 commit b68a949

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

src/dqliteclient/cluster.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ async def find_leader(self) -> str:
9292
# then stable-sort by role so voters come before non-voters.
9393
# Standby/spare nodes can never become leader (their LEADER
9494
# response is always (0, "")), so probing them first wastes RTTs.
95+
#
96+
# Deliberate divergence from go-dqlite: the Go connector iterates
97+
# nodes in their stored order (deterministic) and relies on role
98+
# to decide candidacy. We shuffle within role class to avoid
99+
# stampeding a single node across parallel callers. Do not
100+
# "fix" this toward Go's deterministic behavior without adding
101+
# an explicit stampede-avoidance mechanism elsewhere.
95102
nodes = list(nodes)
96103
random.shuffle(nodes)
97104
nodes.sort(key=lambda n: 0 if n.role == 0 else 1)

src/dqliteclient/protocol.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ async def handshake(self, client_id: int | None = None) -> int:
111111
from the server.
112112
"""
113113
if client_id is None:
114+
# Deliberate divergence from go-dqlite: Go leaves the default
115+
# client_id; we randomize so each connection is distinguishable
116+
# in server logs, traces, and per-client metrics. 63 bits
117+
# avoids sign-extension pitfalls if an intermediate layer
118+
# treats the id as int64. The ``or 1`` guards against the
119+
# (astronomically unlikely) all-zero draw.
114120
client_id = secrets.randbits(63) or 1
115121
# Send protocol version + client registration together
116122
request = ClientRequest(client_id=client_id)

0 commit comments

Comments
 (0)