NAME
PAGI::Server::TransportState - Outbound flow-control introspection for a connection
SYNOPSIS
# Built by the server from an outbound-buffer source (not by the app):
my $transport = PAGI::Server::TransportState->new(
measure => sub { $conn->_get_write_buffer_size },
high => sub { $conn->{write_high_watermark} },
low => sub { $conn->{write_low_watermark} },
arm_drain => sub { my $fire = shift; $conn->_wait_for_drain->on_ready($fire) },
);
# Read by the application via the scope:
my $transport = $scope->{'pagi.transport'};
# Bytes queued for the client but not yet written to the network
my $pending = $transport->buffered_amount;
# The backpressure band (sends block at high, resume at low)
my $ceiling = $transport->high_water_mark;
my $floor = $transport->low_water_mark;
DESCRIPTION
PAGI::Server::TransportState is the object placed in the pagi.transport scope key. It gives an application a synchronous, read-only view of outbound flow control -- how much data the server has queued for the client but not yet written to the network -- so it can conflate, coalesce, shed load, or disconnect a slow client instead of only blocking until the buffer drains. It is the server-side analogue of the browser WebSocket API's bufferedAmount.
The handle is source-agnostic: it measures the outbound buffer through coderefs supplied by the server, never by reaching into a connection itself. That lets the same hysteresis logic serve different transports -- under HTTP/1.1 the source reads the shared TCP write buffer, while under HTTP/2 it reads a per-stream send queue. All reads are live: each call invokes the source and reports its current state. See the "Transport Flow Control" section in PAGI::Spec::Www for the full specification.
METHODS
new
my $transport = PAGI::Server::TransportState->new(
measure => sub { ... }, # current buffered bytes
high => $bytes, # high-water mark (value or coderef)
low => $bytes, # low-water mark (value or coderef)
arm_drain => sub { my $fire = shift; ... },
);
Creates a transport-state handle. This is built by the server, not the application -- apps receive the finished handle via the pagi.transport scope key. The arguments describe the outbound buffer source:
measure-- coderef returning the current buffered byte count.undef/missing is treated as0.high/low-- the backpressure band. Each may be a plain value or a coderef returning the current mark;undefmeans unavailable.arm_drain-- coderef invoked when the buffer crosses the high mark. It receives a single$firecallback and must invoke it exactly once when the buffer next falls below the low mark, soon_drainfires and the cycle re-arms.
buffered_amount
my $pending = $transport->buffered_amount;
Returns the number of bytes queued for the client but not yet written to the network, as an integer; 0 when the send buffer is fully drained (or once the underlying connection has gone away). A synchronous, non-blocking, non-destructive read.
high_water_mark
my $ceiling = $transport->high_water_mark;
Returns the buffered-byte threshold at or above which the server applies backpressure (a $send that would exceed it blocks until the buffer drains), or undef if unavailable. Applications use it to threshold relative to the ceiling rather than hard-coding a byte count.
low_water_mark
my $floor = $transport->low_water_mark;
Returns the buffered-byte threshold the buffer must fall back to before the server releases backpressure (the drain point), or undef if unavailable.
on_high_water
$transport->on_high_water(sub { $source->pause });
Registers a callback invoked when the outbound buffer reaches or exceeds "high_water_mark" (backpressure engaged). Edge-triggered: it fires once when the buffer crosses up, and not again until the buffer has drained below the low mark and crossed up again. If the buffer is already at or above the mark when the callback is registered, it is invoked immediately. Multiple callbacks may be registered; they are invoked in registration order with no arguments. Returns the handle for chaining.
on_drain
$transport->on_drain(sub { $source->resume });
Registers a callback invoked when the outbound buffer falls back below "low_water_mark" after having reached the high mark (backpressure released). It is not invoked merely because the buffer is below the low mark when registered -- only on an actual high-then-low transition. Multiple callbacks may be registered; they are invoked in registration order with no arguments. Returns the handle for chaining.
_check_watermarks
$transport->_check_watermarks;
Internal method - Called by the server after an application send. Detects a high-water crossing and fires on_high_water, then arms drain detection (via the source's arm_drain coderef) so on_drain fires once the buffer falls below the low mark. Edge-triggered and idempotent while above.
SEE ALSO
PAGI::Spec::Www - "Transport Flow Control" specification
PAGI::Server::ConnectionState - HTTP disconnect-state introspection (sibling handle)
PAGI::Server::Connection - Per-connection state machine (internal)