Skip to content

Commit 0314276

Browse files
author
Victor Hernández
committed
docs(realtime): document presence and auto-reconnect
Add Presence and Auto-reconnect subsections to the README Realtime section. Presence documents onPresenceSync/onPresenceJoin/onPresenceLeave, track(), untrack(), and presenceState(). Auto-reconnect documents the ClientOptions flags (realtimeAutoReconnect, realtimeReconnectBaseDelay, realtimeReconnectMaxDelay) and the behaviour of run() vs poll(). Remove presence and automatic reconnection from the "out of scope" note. Extend ReadmeRealtimeTest with assertions for onPresenceSync and realtimeAutoReconnect. Add Unreleased CHANGELOG entries for both features.
1 parent 270d7a7 commit 0314276

3 files changed

Lines changed: 73 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ backward-compatible features and patch releases contain fixes.
99

1010
## [Unreleased]
1111

12+
### Added
13+
- **Realtime — Presence**: `Channel` now supports `onPresenceSync(callable)`,
14+
`onPresenceJoin(callable)`, `onPresenceLeave(callable)`, `track(array $payload)`,
15+
`untrack()`, and `presenceState(): array<string, list<array<string, mixed>>>`.
16+
The server sends `presence_state` (full sync) and `presence_diff` (join/leave
17+
deltas) Phoenix frames; the `Presence` class merges them and fires the registered
18+
callbacks. Presence is opt-in: passing `presence_key` in channel params or
19+
registering any presence callback enables it in the `phx_join` config.
20+
- **Realtime — Auto-reconnect**: opt-in via
21+
`ClientOptions(realtimeAutoReconnect: true, realtimeReconnectBaseDelay: 1.0,
22+
realtimeReconnectMaxDelay: 30.0)`. When enabled, `run()` detects connection
23+
drops, waits with exponential backoff (capped at `realtimeReconnectMaxDelay`),
24+
reconnects, and re-subscribes all channels that were `joined` or `joining`.
25+
`poll()` users remain responsible for their own reconnection.
26+
1227
## [0.5.2] - 2026-06-28
1328

1429
### Added

README.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,60 @@ $realtime->disconnect();
168168
Prefer your own loop? Call `poll(float $timeout)` repeatedly instead of `run()`,
169169
and `stop()` to break out of `run()` from inside a callback.
170170

171+
### Presence
172+
173+
Track which clients are online and get notified when they join or leave. Register
174+
callbacks with `onPresenceSync`, `onPresenceJoin`, and `onPresenceLeave` before
175+
calling `subscribe()`, then call `track()` to broadcast your own state:
176+
177+
```php
178+
$channel = $realtime->channel('room-1')
179+
->onPresenceSync(function (): void {
180+
// Fired every time the full presence state is (re)synced — on join and
181+
// after every diff. Read the current snapshot with presenceState().
182+
})
183+
->onPresenceJoin(function (string $key, array $currentPresences, array $newPresences): void {
184+
// A client started tracking; $newPresences lists their state payloads.
185+
})
186+
->onPresenceLeave(function (string $key, array $currentPresences, array $leftPresences): void {
187+
// A client stopped tracking.
188+
})
189+
->subscribe();
190+
191+
// Announce your own state (any serialisable array):
192+
$channel->track(['user_id' => 42, 'online_at' => time()]);
193+
194+
// Read the current snapshot:
195+
// array<string, list<array<string, mixed>>> (keyed by presence_ref)
196+
$state = $channel->presenceState();
197+
198+
// Stop broadcasting (leaves the channel's presence):
199+
$channel->untrack();
200+
```
201+
202+
### Auto-reconnect
203+
204+
By default the client does not reconnect after a dropped connection. Pass
205+
`realtimeAutoReconnect: true` to make `run()` reconnect with exponential backoff
206+
and automatically re-subscribe all active channels:
207+
208+
```php
209+
$client = new Client('https://YOUR-PROJECT.supabase.co', 'YOUR-ANON-KEY', new ClientOptions(
210+
webSocketFactory: new MyWebSocketConnectionFactory(),
211+
realtimeAutoReconnect: true,
212+
realtimeReconnectBaseDelay: 1.0, // initial retry delay in seconds (default)
213+
realtimeReconnectMaxDelay: 30.0, // cap on retry delay in seconds (default)
214+
));
215+
216+
$realtime = $client->realtime();
217+
$realtime->connect();
218+
// ... subscribe channels ...
219+
$realtime->run(); // loops forever; reconnects + re-subscribes if the socket drops
220+
```
221+
222+
When driving the loop yourself with `poll()`, reconnection is not automatic.
223+
After a receive error, call `connect()` again and re-subscribe your channels.
224+
171225
### Implementing `WebSocketConnection`
172226

173227
`WebSocketConnection` is a small contract you back with any WebSocket client.
@@ -246,8 +300,7 @@ handshake, adds headers, applies a read timeout on every `receive()` call, and
246300
auto-responds to WebSocket-level ping frames via phrity's `PingResponder`
247301
middleware.
248302

249-
> Out of scope for this release: presence, automatic reconnection, and automatic
250-
> access-token refresh. Recreate the connection on disconnect to reconnect.
303+
> Out of scope for this release: automatic access-token refresh.
251304
252305
## Auth (GoTrue)
253306

tests/Realtime/ReadmeRealtimeTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@
1313
->and($readme)->toContain('webSocketFactory')
1414
->and($readme)->toContain('onPostgresChanges')
1515
->and($readme)->not->toContain('**Planned:**')
16-
->and($readme)->toContain('Realtime (postgres changes & broadcast)');
16+
->and($readme)->toContain('Realtime (postgres changes & broadcast)')
17+
->and($readme)->toContain('onPresenceSync')
18+
->and($readme)->toContain('realtimeAutoReconnect');
1719
});

0 commit comments

Comments
 (0)