13 – Flow Control (conflation under backpressure)

A high-frequency SSE feed that conflates under backpressure: it reads $scope->{'pagi.transport'} and, when the client falls behind, skips stale readings so a slow client always gets the freshest one instead of a growing backlog. pagi.transport is the server-side analogue of the browser's WebSocket.bufferedAmount.

This is the conflation recipe from PAGI::Cookbook ("Flow Control"), shown over SSE so you can try it with curl. The cookbook's version uses WebSocket; the pattern is identical.

Quick Start

1. Start the server:

pagi-server --app examples/13-flow-control/app.pl --port 5000

2. Fast client — the feed stays healthy (nothing skipped):

curl -N -H "Accept: text/event-stream" http://localhost:5000/

The server log shows [healthy] sent=… skipped=0.

3. Slow client — watch it conflate. Throttle the reader so it falls behind (here with pv, ~2 KB/sec). After a few seconds the client's read backlog builds and the server log flips to CONFLATING, with the skipped count climbing:

curl -N -H "Accept: text/event-stream" http://localhost:5000/ | pv -qL 2000
[CONFLATING] sent=12 skipped=137 buffered=33792

The client keeps receiving fresh readings; the stale ones in between are dropped rather than queued. (No pv? Any slow consumer works — e.g. pipe into a script that sleeps between reads.)

How it works

buffered_amount reports the bytes queued for the client but not yet on the wire. The app skips a send whenever that exceeds half of high_water_mark, so it never even reaches the point where the server would block the send. The same handle also offers on_high_water / on_drain callbacks for sources you can't pace by skipping — see the cookbook.

Spec References