NAME
Langertha::Skeid::Proxy::Realtime - One realtime session -- two WebSockets joined, bounded, ended once
VERSION
version 0.004
DESCRIPTION
The relay of the realtime route (skeid k95, ADR 0029). Langertha::Skeid::Proxy answers the handshake -- the client gate, the model, routing, admission, the node's key, the upstream WebSocket, the upgrade -- and then hands both open WebSockets to "start_session". From there a session is two transactions, the client's and the node's, and this module is everything that happens until one of them ends:
Text frames go across both ways in order. The client's are decoded and checked first ("client_frame" in Langertha::Skeid::Protocol::Realtime: a model the key was not granted is refused with an
errorevent, the session's own is rewritten to the served one); the node's are read for usage and relayed as the bytes they came in. A binary frame from the client closes the session1003, like a frame that is no JSON object.Nothing grows without bound. A message above
realtime.max_message_bytescloses the session1009(the transaction's own limit, set per session); bytes written to a peer that has not taken them yet are counted per direction, and pastrealtime.max_queued_bytesthe session closes1013. A session silent forrealtime.idle_timeoutseconds and one older thanrealtime.max_session_secondsare closed1000, by timers (ADR 0005).It ends once. Whichever side closes first, or a limit, the one finish callback runs --
request.finish, the usage event -- and then the other side is closed with the mapped code. Codes that cannot travel on the wire (1005,1006,1015) are mapped: a client that went away closes the node with1000, a node that died closes the client with1011.A graceful stop of the process (the event loop's
finishevent, which the prefork worker emits onSIGQUIT) closes every open session1001first, so its finish callback and its usage event run before the worker exits.
The module does I/O only through the two transactions and Mojo::IOLoop timers, and knows no routing and no usage store: the finish callback is the proxy's.
start_session
my $session = $realtime->start_session(
client => $c->tx, # established server WebSocket transaction
upstream => $up_tx, # established client WebSocket transaction to the node
requested_model => 'house-asr',
served_model => 'whisper-large',
started => time, # when the handshake began
limits => { idle_timeout => 300, max_session_seconds => 3600,
max_message_bytes => 1048576, max_queued_bytes => 4194304 },
finish => sub { my ($result) = @_; ... },
);
Starts the relay. finish is called exactly once, with a hashref: ok, status_code, error_type, error_message (empty for a session that ended well), aborted and rejected (for request.finish), duration_ms, usage (the summed usage blocks, or undef), audio_seconds and content_bytes (absent when nothing measured them) and transcriptions. Returns the number of the session.
open_count
How many sessions are open.
shutdown
$realtime->shutdown;
Closes every open session 1001 ("going away"); their finish callbacks run first. Called from the event loop's finish event.
SEE ALSO
"Realtime route" in Langertha::Skeid::Proxy, Langertha::Skeid::Protocol::Realtime
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-skeid/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.