Use :frame_handler for session-aware websocket protocols where raw incoming frames are not directly suitable as Broadway payloads.
Typical examples:
- channel-id multiplexing
- subscription acknowledgements that must update connection-local state
- heartbeat frames that should be swallowed but still refresh liveness
Pass an MFA and optional initial state:
frame_handler: {MyApp.Transport, :handle_frame, []},
frame_handler_state: %{subscriptions: %{}}The callback receives:
- the normalized inbound data payload
- the current connection-local handler state
- any extra MFA arguments
It must return one of:
{:emit, [payload, ...], new_state}{:skip, new_state}{:error, reason, new_state}
- queues zero, one, or many payloads downstream
- updates the handler state
- refreshes liveness
- emits nothing downstream
- updates the handler state
- still refreshes liveness
- updates the handler state for the current failure path
- fails the current connection
- follows reconnect/backoff
frame_handler_state is connection-local and resets to its initial baseline on reconnect.
This is important for protocols where session identifiers such as channel ids become invalid after reconnect.