Stock SMS example

In this example we combine a set of subroutine mixes to grab the price of a stock from a particular stock exchange and text the information to A mobile phone.

Figure: Text Stock example - The mix


Tip: Get the code from the SPARKL public repository.
Table 1. Text Stock example - The markup
Markup Description
<folder name="StockSMS">
  <field name="mobile" 
    type="string"/>
  <field name="stock" 
    type="string"/>
  <field name="time" 
    type="string"/>
  <field name="error"
    type="string"/>
  <field name="price" 
    type="float"/>
  <field name="OK"/>
  <field name="message" 
    type="string"/>
  <service name="Rest" 
    provision="rest"/>
  <service name="Expr" 
    provision="expr"/>
  <service name="Sequencer" 
    provision="sequencer"/>
  <service name="LibSMS" 
    provision="subr">
    <prop name="subr.import" 
      key="lib.sms.SMS"
      user="demo_lib@sparkl.com"/>
  </service>
  <service name="LibStocks" 
    provision="subr">
    <prop name="subr.import" 
      key="lib.stocks.Stocks"
      user="demo_lib@sparkl.com"/>
  </service>
  <mix name="Mix">
    ...
  </mix>
</folder>
This example comprises the following:
  • A bunch of fields sent to and from the operations
  • Rest, a service that supports rest calls to this mix
  • Expr, a service provisioned using the Expressions extension. Operations implemented by this extension can use Erlang expressions
  • Sequencer, a service provisioned using the Sequencer extension. It is responsible for carrying out transactions
  • Two services provisioned using the Subroutine extension. These services are used to import so called libraries - subroutine mixes - that are run as slave processes to carry out subtasks
    • LibSMS imports a SPARKL configuration, which integrates a Twilio application, to send a text to a specified phone number
      Tip: See this mix on GitHub.
    • LibStocks imports a SPARKL configuration, which integrates a Google finance API, to retrieve the latest price of a specific stock traded on a specific stock exchange
      Tip: See this mix on GitHub.
    The starting operation of each slave process is bound to an operation in the master mix, as described in Table 2.
Table 2. Text Stock example - The operations
Markup Description
<solicit name="Solicit" 
  service="Sequencer" 
  clients="Rest" 
  fields="stock mobile">
  <response name="Error" 
    fields="error"/>
  <response name="Ok" 
    fields="OK"/>
</solicit>
Solicit starts a transaction by outputting the following fields:
  • stock - a valid stock code. For example: nyse:ddd
  • mobile - a valid phone number. For example: +447777777777
This operation is on the Rest client. It means it can be fired by an external application through a rest call.

Once Solicit is fired, the Sequencer service, which implements this operation, sets out to collect the fields needed to satisfy one of the responses.

Depending on the fields collected, either of the responses is sent, which concludes the transaction:

  • Error with the ERROR FLAG - either the stock code or the phone number is invalid
  • Ok with the OK FLAG and the message field - a text is successfully sent with some information on the stock
<request name="GetPrice" 
  service="LibStocks" 
  fields="stock">
  <prop name="subr.spec" 
    Stock="stock" 
    Price="price" 
    Time="time"
    Error="error"/>
  <reply name="Error" 
    fields="error"/>
  <reply name="Ok" 
    fields="price time"/>
</request>
GetPrice tries to look up the stock it received in the stock field.

Depending on whether the stock code is valid, GetPrice sends either of the replies:

  • Error, with the FLAG ERROR
  • Ok, with the fields price and time, which are the last latest price and date of the stock
GetPrice is implemented by the LibStocks service. The subr.spec property on GetPrice is used to match the operation to a subroutine solicit that starts a slave process.
<request name="BuildMessage" 
  service="Expr" 
  fields="price stock time">
  <prop name="expr.bind.in" 
    Price="price" 
    Stock="stock" 
    Time="time"/>
  <prop name="expr.bind.out" 
    Message="message"/>
  <prop name="expr.src" 
    content-type="text/x-erlang"><![CDATA[
Message =
  lists:flatten(
    io_lib:format(
      "Stock ~s price ~.4f on ~s", [
        string:to_upper(Stock), Price, Time])),
    "Ok".
  ]]></prop>
  <reply name="Ok" 
    fields="message"/>
</request>
BuildMessage constructs and sends a message from the content of its income fields.

The properties expr.bind.in and expr.bind.out bind the input and output fields of the operation to Erlang variables.

The expressions in the expr.src property:

  1. Construct the message from the input fields
  2. Send the Ok reply
BuildMessage is implemented by Expr, a service provisioned using the Expressions extension.
<request name="SendMessage" 
  service="LibSMS" 
  fields="message mobile">
  <prop name="subr.spec" 
    To="mobile" 
    Message="message"
    Error="error"/>
  <reply name="Error" 
    fields="error"/>
  <reply name="Ok" 
    fields="OK"/>
</request>
SendMessage tries to send the message constructed by BuildMessage to the phone number it receives in the mobile field.

Depending on whether the number is valid, SendMessage sends either of the replies:

  • Error, with the FLAG ERROR
  • Ok, with the FLAG Ok
SendMessage is implemented by the LibSMS service. The subr.spec property on SendMessage is used to match the operation to a subroutine solicit that starts a slave process.

Figure: Text Stock example - Sample SMS