Remote actor module
Talk to an @prelude/actor that lives on the other side of a
message boundary — a worker, a MessagePort, a socket — through the same
send/ask interface as a local one.
serve(actor, transport)answers frames from the transport.new RemoteActor(transport)is aRef:send,ask(withtimeoutandsignal),close.- Frames are plain data; any transport that can carry JSON or structured clones
works.
fromPortadapts MessagePort-like objects,pair()connects two ends in memory,channelmultiplexes several actors over one transport. - Remote handler errors reject
askwith aRemoteErrorcarrying the remote error'sname,messageandcode.
Usage
npm i -E @prelude/remote-actor
Serving side (e.g. inside a worker):
import * as Actor from '@prelude/actor'
import * as Remote from '@prelude/remote-actor'
const counter = Actor.of(() => ({ count: 0 }), (message: Message, state) => { /* … */ })
Remote.serve(counter, Remote.fromPort(self))
Calling side:
import * as Remote from '@prelude/remote-actor'
const counter = new Remote.RemoteActor<Message, number>(Remote.fromPort(worker))
await counter.send({ type: 'inc', value: 5 })
console.log(await counter.ask({ type: 'get' }, { timeout: 1000 })) // 5
counter.close()
Several actors over one connection:
Remote.serve(users, Remote.channel(port, 'users'))
Remote.serve(orders, Remote.channel(port, 'orders'))
const users = new Remote.RemoteActor(Remote.channel(port, 'users'))
Transport
interface Transport {
post(frame: Frame): void | Promise<void>
subscribe(listener: (frame: Frame) => void): () => void
}
Implement it over anything ordered and bidirectional. RemoteActor and serve
ignore frames they do not understand, so a transport may carry other traffic.
Semantics
sendresolves when the transport has accepted the frame; delivery is not acknowledged. A message to a stopped remote actor is dead-lettered there.askresolves with the handler's return value or rejects with aRemoteError(code: 'remote'), anActorError(code: 'timeout'), the abort reason, or aRemoteError(code: 'closed') if the client is closed.- Frames from one client stay in issue order.
- One
RemoteActorper served actor (or perchannelkey); two clients sharing a channel would collide on ask ids.
License
This package is dedicated to the public domain under CC0 1.0.