5: The WebSocket layer
Phlo Realtime is the daemon's built-in WebSocket server: the daemon owns the sockets and runs your PHP hooks in the same process. This is how that fits together, and a good model for how the daemon's features relate.
5.1: In-process, not a separate service
The WebSocket server (the ws library) lives inside the daemon. It holds the connections, the client registry and the /message broadcast bridge, and runs no PHP of its own: for each socket event it dispatches the matching websocket::<hook> target on the daemon's own pool, in-process. So the one-shot-versus-resident choice is just the host's build mode (what the daemon already does for that host), not a separate WebSocket setting; the dispatch path is identical either way.
It resolves each connection's Host to an app through the daemon's registry, the host-to-app map declared in config/daemon.js (the daemon's 4th argument). A host with no entry fails the dispatch, which fails the upgrade.
5.2: The event flow
| Socket event | Dispatched as | Notes |
|---|---|---|
| handshake | websocket::auth |
Runs before the socket is accepted; an explicit false (or a thrown error) refuses it. A missing token cookie refuses it outright. |
| accepted | websocket::connect |
Set-up; a false here closes the socket. |
| message | websocket::receive |
Dispatched with stream: true, so printed lines flow back to the sender as they are produced. |
| disconnect | websocket::close |
Clean-up. |
The engine's websocket resource maps these targets onto your plain wsAuth / wsConnect / wsReceive / wsClose functions; a missing function means "accept and do nothing". This is the full app-side story covered in the WebSocket manual and the WebSocket chapter of the guide.
5.3: Other relationships
- The runtime helpers dispatch by
apppath over HTTP when thedaemonconstant is set (see the previous chapter). - The scheduler is built into the daemon (previous chapter), replacing cron for
tasks::runandfleet::poll. - Phlo WhatsApp stays its own service. A WhatsApp gateway holds a persistent phone session, which is not a worker-pool job, so the daemon does not run it; it is monitored, not absorbed.
5.4: Running it
The daemon is one process. Run it under a supervisor:
pm2 start config.js --name phlo-daemon
pm2 save
It binds to localhost; terminate wss:// at your reverse proxy and forward /websocket to the daemon's port.