Stateful Services pattern

State variable bindings allow the svc_expr service to act as a stateful service, where values are persisted in the service instance.

Using service states

Procedure

  1. Specify the expr.state property on the service
    1. Specify a state variable
    2. Specify a state variable that updates the state
    <prop name="expr.state" Mode="NewMode"/>
    Note: The sample configuration is taken from the No Rum for Two tutorial.
  2. Give the state an initial value by either:
    • Using the expr.init property on the service. For example:
      <prop name="expr.init"
          Mode="sober"/>
    • Using the expr.src property on the service. For example:
      <prop name="expr.src"
        content-type="text/x-erlang"><![CDATA[
       NewMode="sober".
      ]]></prop>
      Note: This method leads to a state change, as opposed to using expr.init.
  3. Use request/reply and consume operations to update the service state.
    <consume name="DrinkRum" 
      service="WilliamKidd" 
      fields="rum">
      <prop name="expr.src" 
        content-type="text/x-erlang"><![CDATA[
    NewMode = "Drunk".
      ]]></prop>
    </consume>
    Important: Only request/reply and consume operations can update the state of a service. You can use states and state changes to conditionalize the triggering and firing of notify operations but they cannot change the state of services themselves.

Stateful Services pattern example

In the example in Table 1, svc_expr is used for initialising a state variable and incrementing it on each execution of the request/reply.

Table 1. Stateful services
Example Description
<field name="count"  
  type="integer"/>
<field name="INCREMENT"/>  

<service name="Expr"  
  provision="expr">  
  <prop name="expr.state"    
    Count="NewCount"/>  
  <prop name="expr.init"
    Count = "0"/>
</service>  

<request name="Increment"  
  service="Expr"  
  fields="INCREMENT">  
  <prop name="expr.bind.out"    
    Count="count"/>  
  <prop name="expr.src"
    content-type="text/x-erlang"><![CDATA[
NewCount = Count + 1,
"Ok".  
  ]]></prop>  
  <reply name="Ok"    
    fields="count"/>
</request>
The expr.state property declares that:
  • Count is a state variable
  • The value of the NewCount variable updates Count when an operation script completes

The service property expr.init initialises the Count variable to zero.

The operation property expr.bind.out binds the field count to the state variable Count.

The operation property expr.src defines the value of the NewCount variable and sends the reply set "Ok".
Tip: An expression in expr.src can also initialise a state variable. For example, NewFoo = 0. This leads to a state change, as opposed to using expr.init, with the attribute Foo="0".

Every time the operation is implemented, it updates the service state with the value of NewCount that updates the Count state variable.

Note: Do not manually type the <![CDATA...]]> delimiters. The Editor automatically renders text content as XML CDATA sections.

Serializing Stateful Operations

The svc_expr extension automatically serializes state updates.

It does this by queuing all operations on the service such that only one operation at a time can execute, thus ensuring that state updates are atomic even if they affect several state variables per operation.

This queuing does not occur across operations on an svc_expr service that has no state variables defined.