rpc.server
import rpc
Everything here is re-exported by
rpc, soimport rpcis enough and the names are called asrpc.*. Importingrpc.serveron its own works too and reaches the same definitions.
Serving JSON-RPC to many connections at once, over TCP, TLS or a Unix domain socket.
serve() binds a listening socket and spreads the connections it
accepts across a pool of worker isolates. Every connection gets an
Endpoint of its own, and setup gives it
its handlers, so each connection is a full JSON-RPC peer: it answers
what its client asks, and it can call its client and notify it in
return.
Each worker polls the connections it holds rather than blocking on one, so a quiet client occupies a descriptor and not a thread, and one worker serves many long-lived connections side by side.
Re-exported by rpc.
Functions
serve()
rpc.serve(setup, options: ?dict)
Serves JSON-RPC on a listening socket, across a pool of worker isolates, until it is stopped.
setup is called inside a worker for every connection accepted, with
the connection’s own Endpoint and the
client’s address, and gives the endpoint its handlers. A worker shares
nothing with the others or with this isolate, so setup builds whatever
state a connection needs, and is a function of a module, or a function
that uses nothing but its own imports.
import rpc
def setup(endpoint, peer) {
endpoint
.on_request('add', @(params) => params[0] + params[1])
.on_request('whoami', @() => peer.to_string())
}
rpc.serve(setup, { port: 4444, framing: 'line' })
| Option | Meaning | Default |
|---|---|---|
host | the address to listen on | '127.0.0.1' |
port | the port to listen on; 0 picks a free one | 8000 |
path | a Unix domain socket to listen on, in place of host and port | nil |
workers | how many worker isolates serve connections | the number of CPUs |
backlog | how many accepted connections may wait for a worker | workers * 4 |
framing | 'header' for Content-Length headers, 'line' for lines | 'header' |
max_message_size | the largest message accepted, in bytes | 64 MiB |
max_connections_per_worker | the most connections one worker holds | 256 |
idle_timeout | seconds a connection may stay silent before it is closed | nil, never |
read_timeout | seconds a read may wait once a message has begun | 30 |
write_timeout | seconds a write may wait | 30 |
cert_chain, private_key | PEM strings that put every connection behind TLS | nil |
on_ready | called here once bound, with the address and a stop function | nil |
max_connections | stop after accepting this many connections | nil, never |
on_ready is called on this isolate once the socket is bound, with the
address it is bound to, as a SocketAddr or the socket’s path, and a
function that stops the server. Stopping it stops accepting connections;
every worker then finishes the message it is handling, closes its
connections and ends, and serve() returns. Reaching max_connections
stops accepting too, but serves the connections already accepted until
each of them closes, and serve() returns after the last.
A connection whose TLS handshake fails, or whose setup raises, is
closed and nothing else is affected. A connection that cannot be read is
reported to its endpoint’s on_error() handler and closed.
A handler that calls its client with request() holds its worker until
the answer arrives, and every other connection on that worker waits with
it.
The socket file of a Unix domain socket is removed when the server
stops. A file already at path makes binding fail.
A failure accepting connections stops the server as stop would, and
raises from serve() once it has.
Parameters
setup(function(2)) — Called with each connection’s {Endpoint} and the client’s address.options(?dict) — Defaultnil, every option at its default.
Raises ValueError when an option holds a value it cannot take.
Raises Error when the socket cannot be bound.
2026, Richard Ore and Zuri contributors