4: Socket monitoring
Because every connection passes through your hooks, you can see and manage sockets with ordinary Phlo models, no special tooling required.
4.1: Presence
Track who is connected by writing a row in wsConnect and deleting it in wsClose:
function wsConnect($wsHost, $wsToken, $wsSocket){
type_presence::create(socket: $wsSocket, token: substr((string)$wsToken, 0, 8), since: time())
return true
}
function wsClose($wsHost, $wsToken, $wsSocket){
type_presence::delete('socket=?', $wsSocket)
}
The live count is then just count(type_presence::records()), which you can broadcast to everyone on each change.
4.2: A connect/disconnect feed
Append every lifecycle event to a log model and you have an audit trail and a live feed. The demo's /monitor page renders the log and updates the online count and the feed through wsCast as sockets come and go.
| Want | Use |
|---|---|
| Online count | count(type_presence::records()) |
| Per-user sockets | filter presence by token |
| Event history | a wslog model, newest first |
| Targeted push | wsCast(wsTarget: $socketOrToken, ...) |
4.3: Health
A GET /health on the daemon (e.g. 127.0.0.1:3001) reports both the connection side and the worker pools in one place, since they are one process:
{
"status": "ok",
"workers": 5,
"cap": 7,
"pools": {
"/var/www/app/release/www/app.php": { "workers": 4, "busy": 2, "queued": 0 }
},
"sockets": {
"app.example.com": { "tokens": 5, "sockets": 12 }
},
"registered": ["app.example.com", "dev.example.com"]
}
sockets counts the live connections per host (tokens and sockets); pools is the per-app worker stats, where busy is the workers currently handling an event and queued the events waiting for a free worker; workers/cap is the live total against the ceiling. The pool grows itself toward the cap and reaps idle workers, so a busy that sits at the cap with a growing queued means the node is at capacity.
4.4: Limitations
Phlo Realtime is the daemon's built-in WebSocket layer: one process owns the sockets and runs the PHP. In one-shot mode (a build: true app) the daemon boots a handler per event, so there is a small per-event cost compared to a process that holds state in memory; run the host as a release build and the daemon serves it from its resident pool, removing that cost and scaling throughput. Either way you keep the same stateless model as the rest of Phlo and no extra language. For very high-frequency streaming (many events per second per socket) a dedicated streaming server may still fit better.