Skip to main content

Clients, Groups & Users

The server sends messages to clients through self.clients, a typed client proxy, and tracks groups through self.groups.

Sending to everyone

class BroadcastHub(Hub):
async def notify_all(self, text: str) -> None:
await self.clients.all_.send("broadcast", text)

clients.all_ targets every connected client, optionally excluding some:

await self.clients.all_.send("broadcast", text, excluded=frozenset({connection_id}))

clients.others is shorthand for "everyone except the caller":

await self.clients.others.send("broadcast", text)

Sending to specific clients

# One connection
await self.clients.connection(connection_id).send("target", *args)

# Several connections
await self.clients.connections((id_a, id_b)).send("target", *args)

Sending to groups

Groups are named sets of connections managed by the hub:

class RoomHub(Hub):
async def join_room(self, room: str) -> None:
await self.groups.add(room)

async def leave_room(self, room: str) -> None:
await self.groups.remove(room)

async def room_chat(self, room: str, text: str) -> None:
await self.clients.group(room).send("chat", text)
  • groups.add(name) / groups.remove(name) mutate the caller's membership.
  • clients.group(name).send(...) broadcasts to the group.
  • Membership is removed automatically when a connection disconnects.

Sending to users

If connections carry a user id, you can target them:

await self.clients.user(user_id).send("target", *args)
await self.clients.users((uid_a, uid_b)).send("target", *args)

The user_id is read from ctx.context.user_id. The default lifetime manager matches by that value.

Type of send targets

ProxyTarget
all_Every connected client
othersEvery client except the caller
connection(id)A single connection
connections(ids)Several connections
group(name)Members of a group
groups(names)Members of several groups
user(id)Connections with the given user id
users(ids)Connections with the given user ids

Each proxy returns a client handle exposing send(method, *args).

Broadcast encoding

For efficiency, clients.all_.send(...) serializes the message once per protocol and reuses the encoded bytes for every recipient connection (see DefaultHubLifetimeManager._send). When stateful reconnect is enabled, the encoded bytes are also fed through each recipient's message buffer so they are replayed if that client was disconnected at send time.