Tutorial3 (Drink Responsibly)

In Tutorial3 we build a slightly more complex mix introducing alternative responses, a request/reply operation and a new service.

This new service is the very responsible Barman service who suddenly starts wondering who the car in front of the pub belongs to.

You once again send a message containing the field BEER to SPARKL.

This time the field you send is an empty flag field, as you only indicate your intention.

In this case, alas, there are two possible responses depending on the goodwill of the Bartender service.

SPARKL will return a response message containing either the alcoholic or the nonalcoholic field.

The mix

The mix in Tutorial3 comprises a solicit/response and a request/reply operation.

The solicit/response operation is used to kick off the transaction in SPARKL.

The service that processes the transaction, using the initial solicit as its starting point, is the Sequencer service.

The Sequencing Graph is derived from all the operations in the mix.

The mix has the following components:

Sequencer
Sequencer, a service provisioned using the Sequencer extension processes the transaction starting with the initial operation.
Bartender
A service provisioned using the Expressions extension. It supports the request/reply operation and is invoked on demand by the Sequencer.
GetBeer/Alcoholic/NonAlcoholic
An operation comprising a solicit with two possible responses, implemented by the Sequencer.
DoYouDrive/Yes/No
An operation comprising a request with two possible replies, implemented by the Bartender service.
BEER
A flag field sent to and from the operations. A flag field has no value and serves only sequencing purposes.
nonalcoholic, alcoholic
Fields sent to and from the operations. They contain data in the form of a string.
Client, Server
Folders separating operations. Folders are optional and can be used to separate various components of a mix.

Figure: Tutorial3 - The mix


Explanation

The Sequencing Graph is generated from the operations of the mix.

The first vertex is generated by the solicit/response operation.

The other two vertices, and the edges connecting them with the first vertex, are generated by the two request/reply operations.

When a transaction is triggered by the solicit, the Sequencer can start toward either of the other two vertices.

As it will have either the BEER and alcoholic, or the BEER and nonalcoholic fields, the Sequencer can satisfy only one of the goal events.

Nevertheless, the Sequencer makes no distinction which goal vertex it traverses first.

Assuming the Sequencer will get the BEER and alcoholic fields, it can just as well traverse the BEER - nonalcoholic vertex first.

See Figure 3 and Table 1 for a better understanding.

Figure: Tutorial3 - The graph


Table 1. Tutorial3 - Component roles
Component Markup Description
GetBeer
<solicit 
  name="GetBeer" 
  service="Sequencer" 
  fields="BEER">
  <response 
    name="Alcoholic" 
    fields="alcoholic"/>
  <response 
    name="NonAlcoholic" 
    fields="nonalcoholic"/>
</solicit>
Once it receives the single field BEER, the Sequencer creates a new transaction and uses the solicit as its starting point.

The Sequencer looks at the Sequencing Graph to find the closest goal it can satisfy.

As it happens, there are two such goals: the two responses which are equally close to the solicit point.

However, both responses require a field (alcoholic or nonalcoholic) which does not exist at this point.

DoYouDrive
<request 
  name="DoYouDrive" 
  service="Bartender" 
  fields="BEER">
  <prop 
    name="expr.bind.out" 
    Alcoholic="alcoholic" 
    Nonalcoholic="nonalcoholic"/>
  <prop 
    name="expr.src" 
    content-type="text/x-erlang"><![CDATA[
Nonalcoholic = "Foster's Low-Alcohol",
Alcoholic = "Guinness",

case rand:uniform() > 0.5 of
  true ->
        "No";
  false ->
	 "Yes"
end.
  ]]></prop>
  <reply 
    name="Yes" 
    fields="nonalcoholic"/>
  <reply 
    name="No" 
    fields="alcoholic"/>
</request>
In order to generate either of these fields, the Sequencer calls for the DoYouDrive operation. Once invoked, this request/reply operation generates a new field which will be added to the fields known to the Sequencer.

The two possible replies output either the alcoholic or the nonalcoholic field.

An Erlang expression executing in the DoYouDrive operation decides which reply is sent. The fields alcoholic and nonalcoholic are bound to the Erlang variables Alcoholic and Nonalcoholic, which are assigned a value in the expression.

The Sequencer now has either BEER and alcoholic or BEER and nonalcoholic. Whichever set of fields it has, the Sequencer is able to satisfy either the NonAlcoholic or the Alcoholic response goal event. The Sequencer can satisfy only one of the two goal events.

Once it satisfied one of these (either at first or second attempt, depending on which vertex it traversed first) and realised it cannot satisfy the other, the Sequencer discards the fields and the transaction ends.

Bartender
<service 
  name="Bartender" 
  provision="expr"/>
The service implementing the DoYouDrive operation is the Bartender service. As it is provisioned using the Expressions extension, operations on it can contain Erlang expressions.