Tutorial5 (With or Without You)

The main difference between this tutorial and the previous one is a new service that is specified as a client for the Order notify operation. This transaction, therefore, can be started by a service (or you via the usual transaction testing).

In Tutorial5 you reach the point where you start talking about painful past relationships.

You need someone to pour your heart out to but the Bartender can only pour out gin and tonic and Gatsby has already left.

In your time of need a new service, Bono, enters and silently sits down beside you.

For simplicity's sake he is content with gin and tonic as well.

Moreover, he has the decency to buy his own drink. However, the Bartender stops serving gin, once he thinks he has served too many already.

The mix

The mix in Tutorial5 is a combination of the previous tutorials.

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 that supports a request/reply operation and a consume operation. It is invoked on demand by the Sequencer. This service is provisioned using the Expressions extension.
Bono
A service that supports consume operations. It is also specified as the client of the Order operation.
Order
An operation comprising a notify, implemented by the Sequencer.
ServeDrink/NonAlcoholic/Alcoholic
An operation comprising a request with two possible replies, implemented by the Bartender service.
NextCustomer
An operation comprising a consume, implemented by the Bartender service.
Drink/KeepDrinking
An operation comprising a consume with one possible reply, implemented by the Bono service.
DrinkSoda
An operation comprising a consume, implemented by the Bono service.
ORDER, ENOUGH
FLAGS sent to and from the operations. A FLAG has no value and serves only sequencing purposes.
gin, tonic
Fields sent to and from the operations. They contain data in the form of a string.
Customer, Bartender
Folders separating operations. Folders are optional and can be used to separate various components of a mix.

Figure: Tutorial5 - The mix


Explanation

This tutorial is a combination of all previous tutorials.

The first and biggest difference is that you finally assign a client that can start transactions.

Figure 3 shows the Sequencing Graph, with:
  • The operations that created the edges
  • The field sets that are available on the vertices

Figure: Tutorial5 - The Sequencing Graph


Table 1 summarises the components of the mix and their role in the transactions.

Table 1. Tutorial5 - Component roles
Component Markup Description
Bono
<service 
  name="Bono" 
  provision="expr"/>
The Bono service is provisioned using the Expressions extension. It is specified as the client of the Order notify.

This means, that depending on the markup in the notify, Bono can trigger and/or fire the notify.

Order
<notify 
  name="Order" 
  service="Sequencer" 
  clients="Bono" 
  fields="ORDER">
  <prop 
    name="expr.auto" 
    count="1"/>
</notify>
The expr.auto property in the notify means that when the Bono service is started, the Order notify is fired once, outputting the ORDER field and starting a new transaction.
Bartender
<service 
  name="Bartender" 
  provision="expr">
  <prop 
    name="expr.state" 
    GinsServed="NewGinsServed"/>
  <prop name="expr.init"
    GinsServed="0"/>
  <prop 
    name="expr.src" 
    content-type="text/x-erlang"><![CDATA[
EnoughGin = 4.
  ]]></prop>
</service>
The Bartender service is also provisioned using the Expressions extension. It has a state variable called GinsServed that can be updated by the NewGinsServed variable.

The state of the service is initialised to 0, meaning it has not served any gin yet.

EnoughGin is a constant that can be referenced by operations on the Bartender service.

ServeDrink
<request 
  name="ServeDrink" 
  service="Bartender" 
  fields="ORDER">
  <prop 
    name="expr.bind.out" 
    Gin="gin" 
    Tonic="tonic"/>
  <prop 
    name="expr.src" 
    content-type="text/x-erlang"><![CDATA[
Gin = "Gordon's",
Tonic = "Schweppes",

case GinsServed < EnoughGin of
  true ->
    NewGinsServed = GinsServed + 1,
    "Alcoholic";
  false ->
    "NonAlcoholic"
end.
  ]]></prop>
  <reply 
    name="NonAlcoholic" 
    fields="ENOUGH tonic"/>
  <reply 
    name="Alcoholic" 
    fields="gin tonic"/>
</request>
ServeDrink is a request operation on the Bartender service.

The reply sent depends on the expression in the operation that is evaluated every time ServeDrink is implemented.

If the Bartender has already served 4 or more gins, which is the value of the EnoughGin constant, the operation sends the NonAlcoholic reply with the ENOUGH and tonic fields.

If the value of the Bartender's GinsServed state is less than 4, the operation sends the Alcoholic reply with the gin and tonic fields.

Drink
<consume 
  name="Drink" 
  service="Bono" 
  fields="gin tonic">
  <reply 
    name="KeepDrinking" 
    fields="ORDER"/>
</consume>
The Drink operation is a consume/reply operation implemented by the Bono service.

Such an operation creates a parallel thread of execution. It does not start a new transaction like a notify or solicit would - instead it starts a new sequence - or a loop, that can be used to satisfy outstanding consume or response goals in the transaction.

Here, every time the fields gin and tonic arrive, the KeepDrinking reply is sent starting a new sequence ending up in new field sets of gin and tonic coming in until the EnoughGin variable is surpassed, and the ServeDrink operation sends the NonAlcoholic reply.

DrinkSoda
<consume 
  name="DrinkSoda" 
  service="Bono" 
  fields="ENOUGH tonic">
</consume>
Once the Bartender has served enough gin, the Bono service can drink only tonic, as the ServeDrink operation will output only the tonic and ENOUGH fields.
NextCustomer
<consume 
  name="NextCustomer" 
  service="Bartender" 
  fields="ENOUGH">
  <prop 
    name="expr.src" 
    content-type="text/x-erlang"><![CDATA[
NewGinsServed = 0.
  ]]></prop>
</consume>
If the Bartender implements the NextCustomer operation, NewGinsServed is set to 0, meaning the next customer can order her maximum four gin and tonics.