plushie/bridge

Bridge actor: manages the Erlang Port to the Rust binary.

The bridge is a stable entity that outlives individual renderer processes. When the renderer crashes, the bridge stays alive, queues transient messages during the restart window, and reopens the port after an exponential backoff delay.

Message classification during restart

Messages are classified as rebuildable or transient:

Transport modes

Wire framing

Types

Messages the bridge actor handles.

pub type BridgeMessage {
  Send(data: BitArray)
  SendTransient(data: BitArray)
  PortData(data: dynamic.Dynamic)
  PortLineData(line_data: renderer_port.LineData)
  PortExit(status: dynamic.Dynamic)
  IoStreamData(data: BitArray)
  IoStreamClosed
  HeartbeatTimeout
  RegisterRuntime(process.Subject(RuntimeNotification))
  ResyncComplete
  RestartPort
  Shutdown
}

Constructors

  • Send(data: BitArray)

    Send pre-encoded rebuildable wire bytes (settings, snapshot, patch, subscribe, window_op). Dropped when the port is down since the runtime rebuilds these during resync.

  • SendTransient(data: BitArray)

    Send pre-encoded transient wire bytes (effect, widget_op, image_op, widget command, interact, advance_frame, stub registration). Queued when the port is down or awaiting resync, flushed after ResyncComplete.

  • PortData(data: dynamic.Dynamic)

    Port data received from the Rust binary (via selector).

  • PortLineData(line_data: renderer_port.LineData)

    Line data received from the Rust binary in JSON mode (via selector).

  • PortExit(status: dynamic.Dynamic)

    Port closed/exited (via selector).

  • IoStreamData(data: BitArray)

    Data received from an iostream adapter.

  • IoStreamClosed

    The iostream adapter closed the transport.

  • HeartbeatTimeout

    Heartbeat watchdog timer fired (no renderer messages within interval).

  • Register the runtime’s notification subject. Sent by the runtime after it starts under the supervisor. Any events received before this message are buffered and flushed on receipt.

  • ResyncComplete

    Runtime has finished resync (settings, snapshot, subscriptions, windows). The bridge flushes any queued transient messages.

  • RestartPort

    Internal: bridge’s own restart timer fired.

  • Shutdown

    Graceful shutdown request.

Internal bridge state.

pub opaque type BridgeState

Messages sent to an iostream adapter process. The adapter must handle these messages to integrate with a custom transport (TCP, WebSocket, SSH, etc.).

pub type IoStreamMessage {
  IoStreamBridge(bridge: process.Subject(BridgeMessage))
  IoStreamSend(data: BitArray)
}

Constructors

  • IoStreamBridge(bridge: process.Subject(BridgeMessage))

    The bridge is registering itself. The adapter should send IoStreamData messages to the bridge subject.

  • IoStreamSend(data: BitArray)

    The bridge wants to send data over the transport.

Notifications sent from bridge to runtime.

pub type RuntimeNotification {
  InboundEvent(decode.InboundMessage)
  RendererExited(exit: renderer_exit.RendererExit)
  RendererRestarted
}

Constructors

  • InboundEvent(decode.InboundMessage)

    A decoded inbound message from the Rust binary.

  • RendererExited(exit: renderer_exit.RendererExit)

    The Rust binary process exited.

  • RendererRestarted

    The bridge successfully reopened the port after a crash. The runtime should resync state and then send ResyncComplete.

Transport mode for the bridge.

pub type Transport {
  TransportSpawn
  TransportStdio
  TransportIoStream(adapter: process.Subject(IoStreamMessage))
}

Constructors

  • TransportSpawn

    Spawn the renderer binary as a child process.

  • TransportStdio

    Use the BEAM’s own stdin/stdout.

  • TransportIoStream(adapter: process.Subject(IoStreamMessage))

    Use a custom iostream adapter process.

Values

pub fn start(
  binary_path: String,
  format: protocol.Format,
  runtime: process.Subject(RuntimeNotification),
  session: String,
  renderer_args: List(String),
) -> Result(process.Subject(BridgeMessage), actor.StartError)

Start the bridge actor with spawn transport (default).

Opens a port to the plushie binary and begins forwarding messages. Inbound wire data is decoded and sent as RuntimeNotification values to the provided runtime subject.

pub fn start_supervised(
  name: process.Name(BridgeMessage),
  binary_path: String,
  format: protocol.Format,
  session: String,
  renderer_args: List(String),
  transport: Transport,
) -> Result(
  actor.Started(process.Subject(BridgeMessage)),
  actor.StartError,
)

Start the bridge under a supervisor with a registered name.

The runtime subject is not available yet; the runtime will send a RegisterRuntime message after it starts. Events received before registration are buffered and flushed automatically.

pub fn start_with_transport(
  binary_path: String,
  format: protocol.Format,
  runtime: process.Subject(RuntimeNotification),
  session: String,
  renderer_args: List(String),
  transport: Transport,
) -> Result(process.Subject(BridgeMessage), actor.StartError)

Start the bridge actor with an explicit transport mode.

Search Document