Sblurp

Events

ServerService.Subscribe streams events to a client. One stream carries everything for one member. Clients act with unary calls; the stream only receives.

Sequence numbers

Every saved event has a server-wide seq that only goes up. The client keeps the last seq it applied.

  1. Call GetState. Its seq is the snapshot point.
  2. Call Subscribe with afterSeq set to it.
  3. The server first replays every event after that seq that you may see, then streams live ones.
  4. After a disconnect, subscribe again with the last seq you applied. Nothing is missed.

Typing, presence and heartbeat events are not saved. Their seq is 0.

Heartbeats

The server sends a heartbeat at once, so the response starts without delay, and then every 25 seconds. It keeps proxies from closing the stream.

Resync

The server keeps the newest 10,000 events, and anything newer than 7 days. If you ask for a seq it no longer has, or a seq from the future, the first event that is not a heartbeat is resync. Call GetState and continue from its seq. The stream stays open.

Falling behind

A subscriber more than 512 events behind is dropped with resource_exhausted. Reconnect with the last seq.

Who gets what

Each event is stored with who may see it, and replay uses the same rule as live delivery:

  • Public: every member. For example, member_joined.
  • One channel's members: message events, and channel events for that channel. A member never receives traffic for a channel they cannot see.
  • One member: read_state, and channel_created when they are added to a channel.

Event kinds

Each Event has seq, at_ms and exactly one of these:

Kind Carries When
message_created Message A new message or thread reply.
message_updated Message An edit, a reaction, or a new reply count on a thread root.
message_deleted Message A message was deleted.
channel_created Channel A channel you can now see. Add it.
channel_updated Channel A channel changed. Treat it as an upsert.
channel_deleted channel id A channel is gone for you. Drop it.
member_joined Member Someone joined.
member_updated Member Profile, permission or roles changed.
member_left member id Someone left, was kicked or was banned.
read_state ReadState Your read state changed, for example on another device.
typing TypingEvent Someone is typing. Not saved.
presence PresenceEvent Someone came online, went away or went offline. Not saved.
heartbeat true Every 25 seconds. Not saved.
resync true Call GetState again.
role_updated Role A role was made or changed.
role_deleted role id Drop it from members and channels.
channel_mode_changed ChannelMode The community switched between roles and opt-in mode.
server_updated true Description, banner or icon changed. Call GetServerInfo.
emoji_changed true Custom emoji were added or deleted. Fetch GET /emoji again.

When a change hides a channel from a member, they get channel_deleted. When a change lets them in, they get channel_created. Members who still see it get channel_updated.

Unread counts

  • Unread counts start when a member joined, so old history is not unread.
  • unread_count counts top-level messages by others, not thread replies.
  • mention_count counts <@member_id> mentions in any message, thread replies too, and every message in a DM.
  • To tell if a message is new, compare its created_seq with last_read_seq. Do not use seq, which edits, reactions and replies bump.
  • MarkRead with seq 0 marks everything read. It sends read_state to all of that member's streams.

Tools and agents can read every call and type from schema.json.