Parity pass on the other three language templates. Same guarantees as
go/: survive server restart, client restart, half-open TCP, and long
outages; rejoin and drain prime-side backlog on reconnect, without
the user writing any of this in process.*.
python/main.py:
- grpc.keepalive_time_ms=10000, keepalive_timeout_ms=3000,
keepalive_permit_without_calls=1 on the channel. Half-open TCP is
detected within ~13s instead of the OS default ~2h.
- Exponential backoff with jitter; max_backoff_seconds config ceiling
(default 120). Attempts counter resets after a session runs
healthy for 60s so transient restarts don't escalate the delay.
- chain_id added as a required config field and sent as the
x-chain-id gRPC metadata header (prime rejects streams without it).
typescript/src/main.ts:
- Same keepalive options on the @grpc/grpc-js client.
- Same exponential backoff + jitter logic.
- chain_id added to Config + metadata.
bash/:
- Config + README updated. The bash template uses Python's main.py
as its runtime, so the behavioural changes above flow through
without a separate main per language.
Docs: each README gains a "Durability guarantees" section so contract
authors see the invariants without reading the runtime code.
Three related fixes that turn the go template into a client that
survives the full matrix of server restart, client restart, network
blip, half-open TCP, and long outages (hours → months) — without the
user writing a line of reconnect logic in process.go.
1. gRPC keepalive: Time=10s, Timeout=3s, PermitWithoutStream=true.
Half-open TCP (silent server restart, resumed laptop, NAT drop)
is detected within ~13s. Previously the OS TCP keepalive took
~2h to notice, leaving the client as a ghost stream while prime
logged "no active gRPC connection" for every skipped transaction.
2. Exponential backoff with jitter on reconnect. Effective delay =
min(max_backoff_seconds, reconnect_delay_seconds * 2^attempts)
+ random(0, reconnect_delay_seconds). The attempts counter resets
after any session that runs healthy for 60+ seconds. Jitter
desynchronises clients so a server restart doesn't trigger a
thundering herd. New max_backoff_seconds config field, default 120.
3. Unified error signalling: the sender goroutine now tears down the
stream's context when it hits a Send error. Previously only Recv
errors triggered a reconnect — a stale stream where only Send was
broken could sit there indefinitely.
Also: chain_id is a required config field now and goes in the
x-chain-id gRPC metadata header alongside x-api-key and
x-smart-contract-id. Prime rejects streams without it with "missing
chain ID", which was silently breaking every template-based client
until users discovered it the hard way. README documents the
durability contract so contract authors know they don't have to
reimplement any of it.