Skip to content

beryl/transport

Transport SPI: the contract between beryl core and WebSocket transport implementations such as the beryl_mist and beryl_ewe packages.

beryl/transport/server owns the shared admission, connection, rate, decode, and telemetry pipeline. This low-level SPI keeps only the hooks a transport implementation needs: connection-capacity permits, exact-owner atomic admission, disconnect, text/binary routing, the configured codec, and transport telemetry.

pub type ConnectionPermit

A held connection slot returned by acquire_connection_slot.

Hold it for the connection's lifetime. Pass it to release_connection_slot when the connection closes. When no connection limit is configured, the permit allows all connections. Releasing it does nothing. A configured permit belongs to the acquiring process until bind_connection_slot transfers it to the connection process.

pub type FrameKind {
TextFrame
BinaryFrame
}

WebSocket data frame kinds.

pub type FrameOutcome {
FrameRouted
FrameOversized
FrameRateLimited
FrameDecodeFailed
FrameAdmissionRejected
}

Closed terminal outcomes for inbound frame processing.

pub type Telemetry

A low-cost transport telemetry context.

When telemetry is disabled, operations avoid VM clock calls and event construction.

pub type TelemetryTransport {
Mist
Ewe
}

WebSocket transport implementations in beryl's telemetry schema.

pub type UpgradeOutcome {
UpgradeSucceeded
OriginRejected
VersionRejected
AuthenticationRejected
CapacityRejected
HandshakeFailed
}

Closed terminal outcomes for a matched WebSocket upgrade.

pub type Sockets = beryl.Sockets

A runtime handle for transport implementations.

pub fn acquire_connection_slot(
beryl.Sockets,
String
) -> Result(ConnectionPermit, Nil)

Try to acquire a configured connection slot for a transport.

Pass the real socket peer IP. Do not pass a client-supplied address such as X-Forwarded-For. Return Error(Nil) when the configured per-IP or per-system limit on this node is already reached.

pub fn active_codec(beryl.Sockets) -> codec.Codec

Return the wire codec configured for these sockets.

Transports use it to decode inbound frames in the connection process.

pub fn admit_socket(
sockets: beryl.Sockets,
owner: process.Pid,
socket_id: String,
send: fn(String) -> Result(Nil, Nil),
send_binary: fn(BitArray) -> Result(Nil, Nil),
codec: option.Option(codec.Codec),
seed: socket.ConnectSeed,
close: fn() -> Nil
) -> Result(Nil, Nil)

Register a socket and its closer against the captured connection owner.

Install a monitor for owner before calling this function. Admission succeeds only if that runtime instance processes the registration. A restart cannot redirect it to the next runtime. On Error, this function closes the connection so its bound permit can be released.

pub fn bind_connection_slot(ConnectionPermit) -> Result(Nil, Nil)

Transfer an acquired connection slot to the calling connection process.

Acquisition already monitors the requesting process. This function replaces that monitor without leaving the reservation unowned, so either process dying reclaims the slot at the correct lifecycle stage. Returns Error(Nil) when the reservation was already reclaimed or the limiter cannot acknowledge the transfer. The connection must close on error.

pub fn max_inbound_frame_bytes(beryl.Sockets) -> Int

Return the configured inbound frame size cap for transports.

pub fn release_connection_slot(ConnectionPermit) -> Nil

Release a connection slot acquired by a transport.

pub fn route_binary(
sockets: beryl.Sockets,
socket_id: String,
data: BitArray
) -> Result(Nil, overload.AdmissionError)

Route a raw binary frame for a codec without a binary decoder.

The runtime sends a Binary event to update for each joined topic.

pub fn route_decoded(
sockets: beryl.Sockets,
socket_id: String,
message: codec.Inbound
) -> Result(Nil, overload.AdmissionError)

Route a transport-decoded inbound message to the runtime. Decode in the connection process (see active_codec) so parse cost and malformed input never reach the runtime.

Runtime message-rate limiting applies after routing. If it sheds a heartbeat, that heartbeat does not refresh the socket's deadline; sustained over-rate traffic therefore leads to heartbeat eviction and a call to the closer registered by admit_socket.

pub fn route_decoded_binary(
sockets: beryl.Sockets,
socket_id: String,
message: codec.Inbound
) -> Result(Nil, overload.AdmissionError)

Route a transport-decoded binary message while preserving its binary frame classification for runtime telemetry and rate accounting.

This function supplements route_decoded. The text semantics of route_decoded remain unchanged for third-party transport compatibility.

pub fn runtime_pid(beryl.Sockets) -> Result(process.Pid, Nil)

Return the pid of the runtime that owns transport connections.

On Ok(pid), monitor that exact PID before admission and close the connection on its Down. Error(Nil) means the runtime is unavailable (pre-start or a restart window), so the connection must be refused.

pub fn socket_disconnected(
sockets: beryl.Sockets,
socket_id: String
) -> Nil

Announce that a socket's connection has closed.

pub fn telemetry(
beryl.Sockets,
TelemetryTransport
) -> Telemetry

Create a telemetry context from the channels configuration.

pub fn telemetry_frame_stop(
Telemetry,
Int,
Int,
FrameKind,
FrameOutcome
) -> Nil

Emit exactly one terminal inbound-frame event.

pub fn telemetry_start(Telemetry) -> Int

Start a timed transport operation.

Returns zero when telemetry is disabled.

pub fn telemetry_upgrade_stop(
Telemetry,
Int,
UpgradeOutcome
) -> Nil

Emit exactly one terminal matched-upgrade event.