Documentation

Presence

List connections in a segment and observe presence notifications without treating them as a complete user roster.

Before you start: complete Messaging. Use its channel and chat handles in web/app.js, with credentials granting read access to chat. Register listeners before connecting; request a listing only after the channel is connected.

Presence describes connections, not unique people. A user with three tabs can appear three times, each with its own connectionId.

1. Register a listener and hold presence interest

Add this setup before the Connect button handler:

const stopPresence = chat.onPresence((event) => {
  console.log(
    event.joined ? "Joined" : "Left",
    event.tokenReference,
    event.connectionId
  );
});
const presenceSubscription = chat.subscribePresence();

onPresence() registers a local callback; subscribePresence() requests notifications. Keep both until this part of your application is finished. event.joined is a boolean, and event.timestamp is a bigint. The identifiers are strings.

A presence subscription also joins the segment for messages. Cancelling presence does not by itself leave that message membership.

2. Fetch a snapshot

After connecting, request the first page. Use ordinary JavaScript numbers for page and perPage:

try {
  const result = await chat.presenceList({ page: 1, perPage: 25 });
  console.log("Connections:", result.total);
  console.log("Page:", result.currentPage);
  for (const connection of result.connections) {
    console.log(connection.tokenReference, connection.connectionId);
  }
} catch (error) {
  console.error("Presence query failed:", error.name, error.message);
}

A query does not require a held presence-event subscription, but it does require an established connection and read permission.

Read the result according to its field types:

FieldJavaScript typeMeaning
totalnumberReported connection count
perPagenumberPage size reported by the server
currentPagenumberCurrent page number
from, tonumberRange reported for this page
connectionsarrayConnection records, not unique users
connections[i].timestampbigintExact timestamp on that connection record

Counts and page figures can be compared, added, or passed to Math functions directly. They do not need Number() or BigInt() conversion. A record's timestamp is different: keep its bigint value, or use a decimal string when serializing it to JSON.

Expected: with both Quickstart tabs connected, the listing includes two connections with the same demo identity and different connection IDs.

3. Paginate and handle failures

Both request fields must be integer numbers: page from 1 to 2,147,483,647 and perPage from 1 to 100. Strings, bigint values, fractions, and out-of-range values are rejected with ConfigurationError, not converted or clamped.

To inspect a small segment across multiple pages, run this in a connected handler instead of the one-page query above:

async function listConnections(segment) {
  const connections = [];
  let page = 1;
  const perPage = 25;

  while (true) {
    const result = await segment.presenceList({ page, perPage });
    connections.push(...result.connections);
    if (result.connections.length === 0 || result.to >= result.total) break;
    if (page === 2_147_483_647) break;
    page += 1;
  }

  return connections;
}

try {
  const connections = await listConnections(chat);
  console.log("Records fetched:", connections.length);
} catch (error) {
  console.error("Presence listing failed:", error.name, error.message);
}

Only one query may be in flight per channel, even if the queries target different segments. Await the first query before starting another.

A server refusal or failure rejects the relevant presenceList() directly, not also through onError. Timeout and cancellation free the query slot without closing the connection; a late response is ignored.

The default query timeout is ten seconds. Queries are not automatically retried. After an actual connection loss, issue a new query once recovered; see Reconnection and Recovery.

Past the last page, connections may be empty with from > to. Do not interpret that as a protocol error.

Listings aggregate across the cluster, but pages are not an atomic snapshot. Connections can join or leave between requests, so a multi-page result can omit or repeat records. Presence events are emitted only on the acting connection's server node; events alone may miss connections on another node. Refresh listings when current state matters, and do not treat presence as a durable user roster.

4. Release presence resources

presenceSubscription.cancel();
stopPresence();

Close the channel when its owner no longer needs it. A connection to default has automatic message membership, but still needs subscribePresence() to request presence events.

Expected: closing one demo connection removes it from a later listing. Cancelling your presence subscription stops notifications without closing the channel.

Next: Errors and troubleshooting.

We use Google Analytics cookies to understand how people use Celeris, only if you allow it. See our Cookie Policy.