- 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
or write
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:
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.
- [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.