-
-
Notifications
You must be signed in to change notification settings - Fork 53
Rooms
- You want a subset of clients inside a namespace (a chat room, a game match, a document being collaboratively edited).
- You need to broadcast to that subset without sending to every other client in the namespace.
- You're listing room members or counting them.
A room is a dynamic, named group of NSConns within a single namespace. Where namespaces are static (declared up-front), rooms are created and destroyed at runtime based on what clients want to join.
| Property | Namespace | Room |
|---|---|---|
| Declared up-front | ✓ | — |
| Lives as long as | the server | the last member |
| Scoped under | the connection | a namespace |
| Created by | Conn.Connect |
NSConn.JoinRoom |
A Room always belongs to exactly one NSConn. A client must be connected to the namespace before joining any of its rooms.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
room, err := nsConn.JoinRoom(ctx, "lobby")
if err != nil {
return err
}Server-side handlers can deny the join by returning a non-nil error from OnRoomJoin:
neffos.Events{
neffos.OnRoomJoin: func(c *neffos.NSConn, msg neffos.Message) error {
if msg.Room == "vip" && !isVIP(c.Conn) {
return errors.New("vip room is restricted")
}
return nil
},
}Inside the namespace, broadcast to the room:
room.Emit("chat", []byte("hi everyone"))This goes to every member of lobby in this namespace, including the sender. If you only want to send to the other members, use the namespace-level helper:
c.BroadcastOthers(neffos.Message{
Room: "lobby",
Event: "chat",
Body: []byte("hi"),
})(Namespace is filled automatically from the NSConn.)
room := nsConn.Room("lobby") // *Room or nil
rooms := nsConn.Rooms() // []*Room snapshot, slice-copiedRooms() returns a snapshot of joined rooms taken under the lock — safe to iterate after the call returns.
Neffos does not store an explicit "members of room X" index — for memory reasons, since most rooms have few members and most servers many rooms. To list members, combine Server.GetConnectionsByNamespace with NSConn.Room:
func MembersOfRoom(server *neffos.Server, namespace, room string) []string {
var ids []string
for id, ns := range server.GetConnectionsByNamespace(namespace) {
if ns.Room(room) != nil {
ids = append(ids, id)
}
}
return ids
}GetConnectionsByNamespace is not designed for hot paths — it materializes the entire map. Use it for occasional inspection or debugging.
err := room.Leave(ctx)Or leave every room at once:
err := nsConn.LeaveAll(ctx)LeaveAll asks the server to leave each joined room sequentially under the lock and fires the local OnRoomLeave / OnRoomLeft events. If any leave fails the operation stops and the error propagates back.
sequenceDiagram
autonumber
participant C as Client (NSConn)
participant S as Server (NSConn)
C->>C: fire OnRoomJoin (local)
C->>S: Ask(OnRoomJoin)
S->>S: fire OnRoomJoin (remote)
alt accepted
S-->>C: empty reply (wait token)
C->>C: rooms[name] = new Room
C->>C: fire OnRoomJoined
S->>S: rooms[name] = new Room
S->>S: fire OnRoomJoined
else denied
S-->>C: error in msg.Err
end
Rooms exist independently on each side of the wire: the client's Room and the server's Room are not the same object, just two sides of a shared name. Either side can refuse a join or a leave by returning an error from the corresponding OnRoomJoin / OnRoomLeave event.
- Namespaces — rooms are scoped to namespaces
-
Broadcast —
Message.Roomtargets a room - The ask method — join/leave use Ask under the hood
Home | About | Project | Getting Started | Technical Docs | Copyright © 2019-2023 Gerasimos Maropoulos. Documentation terms of use.
Getting started
Concepts
Messaging
Production
Scale out