% This LaTeX document was generated using the LaTeX backend of PlDoc,
% The SWI-Prolog documentation system



\section{library(http/hub): Manage a hub for websockets}

\label{sec:hub}

\begin{tags}
    \tag{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.
\end{tags}

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 \textit{event} queue of the hub. In addition, the hub provides a
\textit{broadcast} interface. A typical usage scenario for a hub is a \textit{chat
server} A scenario for realizing an chat server is:

\begin{enumerate}
    \item Create a new hub using \predref{hub_create}{3}.
    \item 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 \predref{ws_receive}{2} or a
hub control message. Currently, the following control messages
are defined:

\begin{description}
\dictitem{hub}{\key{error}:\arg{Error}, \key{left}:\arg{ClientId}, \key{reason}:\arg{Reason}}A client left us because of an I/O error. \arg{Reason} is \const{read}
or \const{write} and \arg{Error} is the Prolog I/O exception.\dictitem{hub}{\key{joined}:\arg{ClientId}}A new client has joined the chatroom.
\end{description}

The \verb$thread(s)$ can talk to clients using two predicates:

\begin{itemize}
    \item \predref{hub_send}{2} sends a message to a specific client
    \item \predref{hub_broadcast}{2} sends a message to all clients of the
hub.
\end{itemize}
\end{enumerate}

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.\vspace{0.7cm}

\begin{description}
    \predicate[det]{hub_create}{3}{+Name, -Hub, +Options}
Create a new hub. \arg{Hub} is a dict containing the following public
information:

\begin{description}
    \infixtermitem{\Sdot}{\arg{Hub}}{\term{name}{}}
The name of the hub (the \arg{Name} argument)
    \infixtermitem{\Sdot}{\term{queues}{}}{\term{event}{}}
Message queue to which the hub \verb$thread(s)$ can listen.
\end{description}

After creating a hub, the application normally creates a thread
that listens to \arg{Hub}.queues.event and exposes some mechanisms to
establish websockets and add them to the hub using \predref{hub_add}{3}.

\begin{tags}
    \tag{See also}
\predref{http_upgrade_to_websocket}{3} establishes a websocket from
the SWI-Prolog webserver.
\end{tags}

    \predicate[nondet]{current_hub}{2}{?Name, ?Hub}
True when there exists a hub \arg{Hub} with \arg{Name}.

    \predicate[det]{hub_add}{3}{+Hub, +WebSocket, ?Id}
Add a \arg{WebSocket} to the hub. \arg{Id} is used to identify this user. It may
be provided (as a ground term) or is generated as a UUID.

    \predicate[semidet]{hub_send}{2}{+ClientId, +Message}
Send message to the indicated \arg{ClientId}. Fails silently if \arg{ClientId}
does not exist.

\begin{arguments}
\arg{Message} & is either a single message (as accepted by
\predref{ws_send}{2}) or a list of such messages. \\
\end{arguments}

    \predicate[det]{hub_broadcast}{2}{+Hub, +Message}
\nodescription
    \predicate[det]{hub_broadcast}{3}{+Hub, +Message, :Condition}
Send \arg{Message} to all websockets associated with \arg{Hub} for which
\verb$call(Condition, Id)$ succeeds. Note that this process is
\textit{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
\predref{io_error}{3}.
\end{description}

