phase 5: Node.call() gen_server protocol
Node wraps EPMD lookup + handshake + Channel into a single client
object. Constructor eagerly opens the dist connection; call() runs the
synchronous $gen_call protocol against a registered name on the peer:
caller -> {'$gen_call', {FromPid, Ref}, Request} (REG_SEND)
server -> {Ref, Reply} (SEND)
Synthesized FromPid and a Node-lifetime Ref counter route replies back
to us; mismatched Ref or unexpected control op raises CallProtocolError.
Reply timeout raises CallTimeout (also covers Erlang's silent-drop case
when the registered name doesn't exist).
Tests against an erl peer running a $gen_call-aware loop:
- {ping, X} -> {pong, X}
- {add, A, B} -> {ok, A + B}
- five sequential calls with monotonically increasing Refs
- server error response surfaces as Python tuple
- slow responder triggers CallTimeout
- unknown registered name surfaces as CallTimeout
- ref uniqueness across 100 synthesized refs
111 tests green across 10 consecutive runs, lint clean.
This commit is contained in:
parent
776efaead3
commit
ac4636e00c
4 changed files with 383 additions and 4 deletions
|
|
@ -62,11 +62,22 @@ if we hit a peer that requires it.
|
|||
process: EPMD → handshake → REG_SEND → recv reply, payload matches
|
||||
- Survives an outbound tick before the reply
|
||||
|
||||
## Phase 5 — gen_call convenience layer
|
||||
## Phase 5 — gen_call convenience layer ✅
|
||||
|
||||
- `Node.call(name_or_pid, request, timeout=5.0)` → reply term
|
||||
- Wraps the `$gen_call` protocol used by `:gen_server`
|
||||
- Idempotency-key handling lives in the caller; we just pass the term
|
||||
- `Node(our_name, peer_name, cookie)` lazy-connects: EPMD lookup +
|
||||
TCP connect + v6 handshake on construction
|
||||
- `Node.call(target_name, request, timeout=5.0)` implements
|
||||
the `$gen_call` protocol:
|
||||
```
|
||||
caller -> {'$gen_call', {FromPid, Ref}, Request} (REG_SEND)
|
||||
server -> {Ref, Reply} (SEND)
|
||||
```
|
||||
- Unique Ref per call, matched on receive — protocol violations
|
||||
surface as `CallProtocolError`, timeouts as `CallTimeout`
|
||||
- Tests: `{ping, X} -> {pong, X}`, `{add, A, B} -> {ok, A+B}`,
|
||||
sequential calls without crosstalk, timeout against a slow
|
||||
responder, drop-on-the-floor against an unknown registered name,
|
||||
Ref uniqueness across the Node lifetime
|
||||
|
||||
## Phase 6 — TLS dist
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue