Guides

Subscriptions

Client-side subscriptions with options - recovery, resume from a position, delta compression, join/leave.

A subscription belongs to the current client. Channels from connect({ channels }) are subscribed with default options; add more at any time after connect():

import {
  addSubscription, addSubscriptionWithOptions, removeSubscription,
  removeAllSubscriptions, getSubscriptions,
} from "tauri-plugin-centrifugo-api";

await addSubscription("news");                       // default options
await addSubscriptionWithOptions({ channel: "chat:42", recoverable: true, joinLeave: true });

await getSubscriptions();     // { news: true, "chat:42": false }  true = subscribed now
await removeSubscription("news");
await removeAllSubscriptions();

addSubscription* resolve once the subscription is created; the result arrives as subscribing → subscribed (or error / unsubscribed) events. Adding a channel that is already added rejects with { RequestError: "duplicate subscription" }. removeSubscription of an unknown channel does nothing.

disconnect() drops every subscription. A new connect() subscribes only its own channels, so add the dynamic ones again after it (for example in onConnected, or keep them in channels).

Options

OptionMeaningServer side
channelChannel name.
tokenSubscription JWT for a private channel; refreshed through need_sub_token, see Tokens.token HMAC/RSA key
recoverableAfter a reconnect, get the publications missed while offline.history (history_size, history_ttl); force_recovery makes it the default
positionedThe server checks the stream position and resubscribes the client on a gap.history
joinLeaveGet join / leave events.join_leave (and presence)
deltaFossil delta compression of publications.allowed_delta_types: ["fossil"]
sinceStart from a saved stream position, see below.history

Server option names are the Centrifugo v5 channel options; v6 groups them differently.

Recovery

With recoverable: true the SDK remembers the stream position. After a reconnect it asks the server for what it missed; the subscribed event tells how it went:

await onSubscribed(({ payload }) => {
  if (payload.wasRecovering && !payload.recovered) {
    // Too many publications missed (history is shorter): reload the state from your backend.
  }
});

Recovered publications arrive as normal publication events right after subscribed.

Resume from a saved position

The position also survives an app restart if you store it. subscribed carries streamPosition ({ offset, epoch }) for recoverable and positioned subscriptions (after a recovery, the position it recovered from); the offset of each publication moves it forward.

import { addSubscriptionWithOptions, onPublication, onSubscribed } from "tauri-plugin-centrifugo-api";

let epoch = localStorage.getItem("chat.epoch");
await onSubscribed(({ payload }) => {
  if (payload.channel === "chat" && payload.streamPosition) {
    epoch = payload.streamPosition.epoch;
    localStorage.setItem("chat.epoch", epoch);
    localStorage.setItem("chat.offset", String(payload.streamPosition.offset));
  }
});
await onPublication(({ payload }) => {
  if (payload.channel === "chat" && payload.offset != null) localStorage.setItem("chat.offset", String(payload.offset));
});

const offset = localStorage.getItem("chat.offset");
await addSubscriptionWithOptions({
  channel: "chat",
  recoverable: true,
  since: epoch && offset ? { offset: Number(offset), epoch } : undefined,
});

since makes the subscription start by recovering from that position (wasRecovering: true).

Delta compression

delta: true asks for fossil deltas: the server sends only the difference to the previous publication and the SDK restores the full data, so publication events look the same. Useful for big, slowly changing payloads. The channel must allow it (allowed_delta_types).

Join / leave

With joinLeave: true (and join/leave enabled for the channel) you get join and leave events with the client info. There is no helper; use onCentrifugoEvent("join", ...), see Events. For who is online now use presence.