PusherServer.Backend behaviour (pusher_server v0.1.2)

Copy Markdown View Source

The seam between "one node" and "many nodes".

Everything that has to be shared between servers goes through this behaviour; everything per-connection (the websocket process, its local Registry entry) stays local on every node.

Callers don't use a backend directly — they go through PusherServer.Cluster.

Summary

Callbacks

Called right after a local socket subscribed. true if the channel just became occupied cluster-wide.

Called right after a local socket left. true if the channel just became vacant cluster-wide.

Extra children to supervise for this backend (connections, subscribers, ...).

Names of every channel that currently has at least one subscriber, cluster-wide.

Returns true if this is the first connection for user_id on the channel (cluster-wide).

Unique members as {user_id, user_info} pairs.

Returns {is_last_connection_for_user, user_id}, or {false, nil} if the socket wasn't tracked.

Re-records an already announced presence entry, silently and idempotently. Called by a socket after the shared store lost its data (see PusherServer.Backend.Redis.Janitor). Never announces anything.

Propagate an already-encoded message to the other nodes. The sending node has already delivered it to its own local subscribers.

Total subscribers on a channel across the cluster.

Types

channel()

@type channel() :: String.t()

name()

@type name() :: atom()

socket_id()

@type socket_id() :: String.t()

user_id()

@type user_id() :: String.t()

Callbacks

channel_joined(name, channel)

@callback channel_joined(name(), channel()) :: boolean()

Called right after a local socket subscribed. true if the channel just became occupied cluster-wide.

channel_left(name, channel)

@callback channel_left(name(), channel()) :: boolean()

Called right after a local socket left. true if the channel just became vacant cluster-wide.

child_specs(name, t)

@callback child_specs(name(), PusherServer.Config.t()) :: [Supervisor.child_spec()]

Extra children to supervise for this backend (connections, subscribers, ...).

list_channels(name)

@callback list_channels(name()) :: [channel()]

Names of every channel that currently has at least one subscriber, cluster-wide.

presence_add(name, channel, socket_id, user_id, user_info)

@callback presence_add(name(), channel(), socket_id(), user_id(), user_info :: term()) ::
  boolean()

Returns true if this is the first connection for user_id on the channel (cluster-wide).

presence_members(name, channel)

@callback presence_members(name(), channel()) :: [{user_id(), term()}]

Unique members as {user_id, user_info} pairs.

presence_remove(name, channel, socket_id)

@callback presence_remove(name(), channel(), socket_id()) :: {boolean(), user_id() | nil}

Returns {is_last_connection_for_user, user_id}, or {false, nil} if the socket wasn't tracked.

presence_restore(name, channel, socket_id, user_id, user_info)

@callback presence_restore(name(), channel(), socket_id(), user_id(), user_info :: term()) ::
  :ok

Re-records an already announced presence entry, silently and idempotently. Called by a socket after the shared store lost its data (see PusherServer.Backend.Redis.Janitor). Never announces anything.

publish(name, channel, encoded, exclude_socket_id)

@callback publish(
  name(),
  channel(),
  encoded :: String.t(),
  exclude_socket_id :: String.t() | nil
) :: :ok

Propagate an already-encoded message to the other nodes. The sending node has already delivered it to its own local subscribers.

subscription_count(name, channel)

@callback subscription_count(name(), channel()) :: non_neg_integer()

Total subscribers on a channel across the cluster.