Reply Matching Rules (Client Implementation)
Since responses may arrive out of order relative to requests (a response to an acquire that waited arrives once its turn comes), the client must pair responses to requests using the following rules — a demultiplexing scheme that sorts the responses interleaved on one connection back to their requests.
| Rule | Detail |
|---|---|
| Matching key | The echoed (op, key, identifier). Acquire-side (A/T/B) matches the request's owner; release-side (R/N) matches the request's token |
| Multiple requests with the same (op, key) | Never assume FIFO — always pin it down by identifier. See below |
| Registration timing | The waiter is registered before the request is sent (to prevent a race where the response arrives first) |
Handling N/T | Returned as non-error values ("didn't exist" / "timed out") |
Handling B | Correlated queue/server-capacity rejection: return Busy immediately; no internal retry |
Handling M | Store only an allowlisted address as a leader hint and close that connection; it has no owner/key to correlate with sent pending requests |
Handling L | Updates the leader hint only and keeps the connection — it's a server-initiated notice, not a response to a request |
E no_leader / E not_active / E auth_failed | Close and apply error-specific backoff (no_leader also invalidates the leader hint) |
Other E / malformed / oversized / unknown response | Uncorrelatable, therefore connection-fatal; every acquire already sent becomes Indeterminate |
| Response with no matching waiter | Protocol/session mismatch: close. If it is A, send the known exact token to the reserved release lane |
Why Match by Identifier and Not FIFO
Even for one key, an immediately successful request, a queued request, and a request rejected with B can complete at different times. Requests for multiple keys are also pipelined on one connection. Never match FIFO; verify the echoed identifier, op, and key.
Aborted Requests and Orphaned Locks
If an aborted request had already been granted, the lock may remain on the server. Once any request byte was sent, a missing definitive response is Indeterminate; never resend A with the same owner as though it were a status query. Only when the token has already been parsed may the client send a best-effort exact-token R. An unknown grant is reclaimed by lease expiry.
This is also why the connection is closed after cancellation following send or a framing error. Dropping only the pending request can orphan a delivered response. Socket close alone is not proof that a committed grant was released: use exact-token R when known, otherwise remain Indeterminate until lease expiry.