Skip to content

How STREAM Works

Guide Home | Previous: Handlers and Message Processing | Next: How Session Binding Works

What you get from this chapter

You can follow the order in which a packet on one connection reaches the session callback, what happens when processing falls behind, how a reply is matched to its request, and where errors and connection close go.

STREAM went as far as accepting a connection and answering one packet. This chapter walks through what the framework does in between, in order.

1. The Order One Connection Goes Through

↗ View larger

When a client connects, the framework creates that connection's session and runs the connected callback. After that, one packet is handled in this order.

  1. The framework secures one slot in the host's processing queue.
  2. Only after securing the slot does it take one packet from Core.
  3. It decodes the header and puts the packet name, metadata, request information, and the packet's Actor into the dispatch context. The packet's Actor is present only when the client sent through an Actor handle and that slot is a current binding — How Session Binding Works covers this.
  4. It passes the dispatch context and the not-yet-converted payload to the session callback. Inside the session callback, the payload is read as the type you want through the common decode surface.

When the connection drops, the framework runs the disconnected callback. What identifies a connection is the routing ID that Core attaches to each connection, and it reaches the session callback unchanged.

2. When Processing Falls Behind — Order and Backpressure

2.1 Client → Server

While the processing queue is full, complete packets aren't dropped but stay in Core, and once processing resumes they reach the session callback once each, in per-connection order. A packet with bad or incomplete framing isn't passed to the callback; the connection is closed.

When the processing queue has no free slot, the framework doesn't take the next packet. A packet not taken stays in Core's receive buffer, and when that buffer reaches its limit (HWM), Core stops reading from that connection's socket. TCP flow control then fills the send buffer of the client's socket and the client's sends slow down. When a slot frees up, the held packets flow again in order. The queue slots are shared by the whole host, so this applies to every connection on the host, not just one. Limits and state transitions are covered in Backpressure.

2.2 Server → Client

Replies and pushes the server sends to a session queue up in Core's send buffer per connection. When the server sends faster than that connection actually drains and the buffer reaches its limit (HWM), a send to that connection waits until space frees up. Sends to other connections aren't affected. The wait has no time limit or caller cancellation. Connection termination while pending ends with Unavailable; socket close or runtime shutdown ends with ShuttingDown. The framework does not resend the same content.

The client connector uses the runtime's own socket and keeps reading whatever arrives without a limit, so slow processing in the client application doesn't hold back the server's sends. Pushes (send) pile up in the client's unbounded receive queue, while replies and error replies skip that queue and complete the waiting request. The server's send waits when the network is slow or the client can't read its socket. The receive size limit (§4) doesn't apply in this direction.

3. The Lifetime of a Reply Token

To answer a request you use the current dispatch's single-use reply token. The token is valid only for the current request and can be submitted once. Even if sending fails through a timeout or cancellation, the same token can't be used again.

A reply carries the request's sequence back unchanged, and the client uses that sequence to find the request it was waiting on. A reply carries no packet name. The type the reply is read as is the type the client named when it made the request. An error reply comes back under the same sequence.

When the server sends first to a client that has no pending request, it uses a send (push), not a reply.

4. Size Limit on Received Messages

The limit for one message a client sends (header plus payload, excluding the 6-byte length prefix) is 64 KiB by default. It doesn't apply to messages the server sends. A message over the limit reaches the session callback not even in part; the server records EMSGSIZE and closes the connection. The client receives no error code and sees only the connection close. Setting it to 0 removes the framework limit.

5. Where Errors Go

The session error callback receives only transport errors that belong to that session. Everything else goes elsewhere.

Error Where it goes
A transport error of that session The session error callback
Handshake failure Runtime observation. There's no session yet to call
Socket- or node-level error Runtime observation. It can't be pinned to one session
Application handler exception The handler exception path

6. When a Connection Closes

Once a connection starts closing, the framework accepts no new packets on it, completes or cancels the reads and writes in progress, and then releases the TCP, TLS, or WebSocket resources. A transport completion that arrives late after that doesn't touch released resources. What happens to the Actors bound to that connection is covered in How Session Binding Works.

7. Settings Refused Before Startup

A stream node registration is defined by the node name, the bind endpoint, and the session type. The following setting errors aren't deferred to the first connection; they are refused before the host starts.

Condition
The node name is empty
The same node name was registered twice
There is no bind endpoint
The same session type was registered on more than one node of a host
More than one session was registered on one node
TLS is on but the certificate path is empty
TLS is on but the key path is empty
A client certificate is required without configuring a TLS server
The message size limit is negative

When you turn TLS on, set the certificate and key paths together. Requiring a client certificate is off by default; when on, a connection that fails verification is refused before a session is created.