6 library(http/hub): Manage a hub for websockets
- To be done
- The current design does not use threads to perform tasks for multiple hubs. This implies that the design scales rather poorly for hosting many hubs with few users.
This library manages a hub that consists of clients that are connected using a websocket. Messages arriving at any of the websockets are sent to the event queue of the hub. In addition, the hub provides a broadcast interface. A typical usage scenario for a hub is a chat server A scenario for realizing an chat server is:
- Create a new hub using hub_create/3.
- Create one or more threads that listen to Hub.queues.event from the
created hub. These threads can update the shared view of the world. A
message is a dict as returned by ws_receive/2
or a hub control message. Currently, the following control messages are
defined:
- hub{
error
:Error,left
:ClientId,reason
:Reason} - A client left us because of an I/O error. Reason is
read
orwrite
and Error is the Prolog I/O exception. - hub{
joined
:ClientId} - A new client has joined the chatroom.
The
thread(s)
can talk to clients using two predicates:- hub_send/2 sends a message to a specific client
- hub_broadcast/2 sends a message to all clients of the hub.
- hub{
A hub consists of (currenty) four message queues and a simple dynamic fact. Threads that are needed for the communication tasks are created on demand and die if no more work needs to be done.
- [det]hub_create(+Name, -Hub, +Options)
- Create a new hub. Hub is a dict containing the following
public information:
- Hub
.
name
- The name of the hub (the Name argument)
queues
.
event
- Message queue to which the hub
thread(s)
can listen.
After creating a hub, the application normally creates a thread that listens to Hub.queues.event and exposes some mechanisms to establish websockets and add them to the hub using hub_add/3.
- See also
- http_upgrade_to_websocket/3 establishes a websocket from the SWI-Prolog webserver.
- Hub
- [nondet]current_hub(?Name, ?Hub)
- True when there exists a hub Hub with Name.
- [det]hub_add(+Hub, +WebSocket, ?Id)
- Add a WebSocket to the hub. Id is used to identify this user. It may be provided (as a ground term) or is generated as a UUID.
- [nondet]hub_member(?HubName, ?Id)
- True when Id is a member of the hub HubName.
- [semidet]hub_send(+ClientId, +Message)
- Send message to the indicated ClientId. Fails silently if ClientId
does not exist.
Message is either a single message (as accepted by ws_send/2) or a list of such messages. - [det]hub_broadcast(+Hub, +Message)
- [det]hub_broadcast(+Hub, +Message, :Condition)
- Send Message to all websockets associated with Hub
for which
call(Condition, Id)
succeeds. Note that this process is asynchronous: this predicate returns immediately after putting all requests in a broadcast queue. If a message cannot be delivered due to a network error, the hub is informed through io_error/3.