Chapter 5
Channels


5.1 Introduction

In Chapter 4, we introduced datasets; and we saw how they can be used to organize data, share data among worksheets, and enable persistent storage.

In this chapter, we look at channels. Channels are similar to datasets in many ways; the main difference is that channels focus on changes rather than state. As we shall see, this adds structure to message handling, it allows us to create persistent activity logs, and it facilitates private communication among worksheets.

5.2 Channels

Each channel on a worksheet must have a suitable declaration in the HTML file for that worksheet. The format of the declaration is similar to that used in defining datasets. The HTML fragment shown below defines two channels, one named pro and the other named con.

<channel id='pro'></channel> <channel id='con'></channel>

A message is written to a channel by specifying a corresponding message factoid on the right hand side as a conclusion in an operation definition. The first rule below adds a message of the form a(X,Y) to the pro channel whenever the users selects value Y for the X selector. The second rule below adds a message of the form d(X,Y) to the con channel whenever the users deselects value Y from the X selector.

select(X,Y) :: message(a(X,Y),pro)
deselect(X,Y) :: message(d(X,Y),con)

A message can be read from a channel by defining the message operation for the channel. The first rule below says what happens on receipt of an a(X,Y) message on the pro. The second rule below says what happens on receipt of a message of the form d(X,Y) on the con channel.

message(a(X,Y),pro) :: value(X,Y)
message(d(X,Y),con) :: ~value(X,Y)

Of course the effects of these rules can be obtained without the use of channels by directly connecting the select and deselect actions with the corresponding value factoids. Almost. One difference is that, with these rules, the value factoids will be added / deleted on the next time step rather than the current time step.

Note that messages make it possible to implement ongoing processes. For example, if we had a channel called pc, we could build a counter by writing the following rules.

message(step,pc) :: value(counter,M) & evaluate(plus(M,1),N)
==> ~value(counter,M) & value(counter,N) & message(step,pc)

Finally, note that channels differ from datasets in several other ways. First of all, channels are lists of messages, not sets. The upshot is that the same message can appear in a channel more than once. Second, the messages are ephemeral, i.e. once they are processed, they are removed from the channel.

5.3 Logs

One of the benefits of channels is that they provide a way of recording changes on a worksheet as files in secondary storage or in the cloud. This can be used for tracking user activity for the purposes of analysis. It also provides an indirect but efficient way of implementing persistence (by recording just changes rather than writing all of the data on a worksheet on each change).

In order to enable logging using the Worksheets cloud storage, we simply annotate a channel with the name of a file as the value of the src attribute of the channel and we list the direction of the channel as outbound. For example, the following HTML fragment specified a source file for the channel named mylog. (The use of inbound channels is discussed in the next section.)

<channel id='log' src='mylog' direction='outbound'></channel>

If a channel is listed as outbound, then any message that is written to that channel is automatically appended to the end of the file specified as its src attribute.

To see how this works, consider a worksheet with the rules shown below.

select(X,Y) :: message(select(X,Y),mylog)
deselect(X,Y) :: message(deselect(X,Y),mylog)

The effect of these rules is to write a message to the mylog channel whenever a user selects or deselects a value. Since the channel has a src attribute and is outbound, all such messages will be appended to the end of the mylog file, effectively creating a log of the user's selections and deselections.

5.4 Communication

As we saw in Chapter 4, it is possible for worksheets to exchange data by sharing datasets. Although this is a simple and reliable mechanism, it has some disadvantages.

One downside of implementing communication in this way is that it can be expensive if the amount of data in the shared datasets is large. Implementing communication with channels can be more efficient since only changes are exchanged.

A second downside of using datasets for communication is that worksheets must share all of the data in those datasets and this may not always be desirable. Implementing communication with channels means that only changes need to be communicated and other data can be reserved.

In order to use channels for communication, we must be able to read as well as write messages. This is accomplished by having both incoming and outgoing channels. The following HTML fragment defines an inbound channel names inbox and an outbound channel named outbox.

<channel id='log' src='inbox' direction='inbound'></channel> <channel id='log' src='outbox' direction='outbound'></channel>

Given these channels, we can write rules to read as well as write messages. For example, the following rules have the effect of sending selection information to other worksheets via the outbox channel and receiving selections from other worksheets via the inbox channel.

select(X,Y) :: message(select(X,Y),outbox)
deselect(X,Y) :: message(deselect(X,Y),outbox)
 
message(select(X,Y),inbox) :: value(X,Y)
message(deselect(X,Y),inbox) :: ~value(X,Y)

In keeping with the ephemeral nature of channel data, messages in channels are processed just once. As soon as one recipient has read a message, it is removed from the channel. The upshot is that it is not possible to communicate the same message to several other worksheets without replicating the message or using multiple channels.