Rationale
Phoenix Presence is one of Elixir's most-loved batteries: who/what is online per topic, cluster-wide, conflict-free. actor-ts already ships the exact substrate — ORSet/ORMap CRDTs + DistributedPubSub — and the chat example hand-rolls presence on top of them today. Promote the pattern into the framework.
Scope
Presence extension: track(topic, key, metadata), untrack, list(topic), subscribe(topic, diffHandler) with join/leave diffs.
- Multiple presences per key (one user, N devices) with per-entry metadata; heartbeat/TTL eviction for crashed non-graceful clients.
- Built on ORMap + DistributedPubSub; no new dependencies.
const presence = Presence.get(system);
await presence.track('room:42', userId, { device: 'web' });
presence.subscribe('room:42', diff => render(diff.joins, diff.leaves));
console.log(await presence.list('room:42')); // { "u1": [{device:"web"},{device:"ios"}], … }
Documentation
Concept page (EN + DE) + example; migrate the chat example to it; JSDoc; CHANGELOG.
Acceptance
- MultiNodeSpec: presence converges across nodes; TTL eviction on silent node death; diffs delivered to subscribers on join/leave.
Non-goals
Cross-cluster federation; persistence of presence history.
Relates
#186 (wildcard topics). Improvement program M5.
Rationale
Phoenix Presence is one of Elixir's most-loved batteries: who/what is online per topic, cluster-wide, conflict-free. actor-ts already ships the exact substrate — ORSet/ORMap CRDTs + DistributedPubSub — and the chat example hand-rolls presence on top of them today. Promote the pattern into the framework.
Scope
Presenceextension:track(topic, key, metadata),untrack,list(topic),subscribe(topic, diffHandler)with join/leave diffs.Documentation
Concept page (EN + DE) + example; migrate the chat example to it; JSDoc; CHANGELOG.
Acceptance
Non-goals
Cross-cluster federation; persistence of presence history.
Relates
#186 (wildcard topics). Improvement program M5.