How to use mix components

Best practices on how to or how not to use specific operations and patterns to meet your specific needs.

Using fields

Fields normally carry data that can be of different type. Fields are also used for ensuring sequencing.

Use FLAGs instead of unrelated fields

FLAGS are fields without type that are not supplied to services in a data event. They can be used for sequencing purposes instead of regular fields that are not related to a sequence. The unrelated field could be removed at a later time, thus changing or breaking the sequence. In such cases, FLAGs can ensure the sequencing stays the same.

Table 1. Use FLAGs instead of unrelated fieldsThe left column shows the GetInfo operation that may be changed to no longer produce the field doAInfo. In this case, the consume operation would also have to be modified.
Undesirable Idiomatic
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="doAInfo" 
    type="string"/>  
  <field name="doZInfo" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <request name="GetInfo" 
      fields="field1">      
      <reply name="Ok" 
        fields="doAInfo doZInfo"/>    
    </request>    
    <consume name="DoOpB" 
      fields="doAInfo field2"/>  
  </mix>
</folder>
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="doAInfo" 
    type="string"/>  
  <field name="doZInfo" 
    type="string"/>  
  <field name="DO_B"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <request name="GetInfo" 
      fields="field1">      
      <reply name="Ok" 
      fields="doAInfo doZInfo DO_B"/>    
    </request>    
    <consume name="DoOpB" 
      fields="DO_B field2"/>  
  </mix>
</folder>

Do not overuse FLAGs

Use FLAGs only if regular fields are not enough to enforce sequencing.

Table 2. Unnecessary FLAGIn the left column the FLAG field DO_A is unnecessary. The field doAInfo already enforces the sequencing. This piece of data is produced by the request operation, and is necessary for the consume operation to proceed.
Undesirable Idiomatic
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="doAInfo" 
    type="string"/>  
  <field name="DO_A"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <request name="GetAInfo" 
      fields="field1">      
      <reply name="Ok" 
        fields="doAInfo DO_A"/>    
    </request>    
    <consume name="DoOpA" 
      fields="doAInfo DO_A field2"/>  
  </mix>
</folder> 
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="doAInfo" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <request name="GetAInfo" 
      fields="field1">      
      <reply name="Ok" 
        fields="doAInfo"/>    
    </request>    
    <consume name="DoOpA" 
      fields="doAInfo field2"/>  
  </mix>
</folder>

Using operations

There are four types of operations in SPARKL that make possible different patterns and combinations. Find here some pieces of advice on where and how to apply particular operations.

Do not use request/reply operations that are not needed to satisfy a goal

Requests are not themselves goals. They only get sequenced if they help the Sequencer reach a goal. Goals in SPARKL are to generate responses to solicits, and to satisfy consume operations.

Table 3. Requests are not themselves goals - sometimes a consume is neededThe request operation in the left column does not get sequenced as the reply fields are not expected by a response or consume. In the right column the consume gets sequenced as it forms a goal.
Undesirable Idiomatic
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="field1"/>    
    <request fields="field1">      
      <reply name="Ok" 
        fields="field2"/>    
    </request>    
    ...  
  </mix>
</folder>
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="field1"/>    
    <consume fields="field1">      
      <reply name="Ok" 
        fields="field2"/>    
    </consume>    
    ...  
  </mix>
</folder>

Use consume operations instead of request operations when there is overlap between input fields and fields of at least one reply

Field data is immutable in SPARKL unless it crosses a consume boundary. One purpose of consume/reply operations is to allow mutability for fields. A consume/reply creates a parallel thread of execution.

Table 4. Using consume/reply operations to effect field data changeThe request in the left column cannot change the data carried by myField. If a consume expected myField, the request operation would not even be invoked as this field is already known to SPARKL.
Undesirable Idiomatic
<folder name="myFolder">  
  <field name="myField" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="myField"/>    
    <request fields="myField">      
      <reply name="Ok" 
        fields="myField"/>    
    </request>    
    ...  
  </mix>
</folder>
<folder name="myFolder">  
  <field name="myField" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="myField"/>    
    <consume fields="myField">      
      <reply name="Ok" 
        fields="myField"/>    
    </consume>    
    ...  
  </mix>
</folder>

Parallel threads of execution

A consume/reply creates a parallel thread of execution, whether we have used it as a goal in itself, or simply to allow mutability of field data. Goal events behave differently in that a response can be satisfied once per transaction while a consume can be satisfied once per thread.

Table 5. Response vs Consume
Operation Satisfied
Response
  • It may be satisfied in any of the ongoing threads
  • It can be satisfied only once per transaction
  • Once satisfied it is not considered a goal in other threads
Consume
  • It can be satisfied in every ongoing threads
  • It can be satisfied multiple times per transaction
  • Is considered a goal in every consecutive thread

Be careful how you want consume operations to fire around solicits, particularly when the solicit has already been satisfied.

Also, be careful that even though more than one of the threads could satisfy the solicit, it can be satisfied only by the one that "gets there first".

You may use FLAGs to ensure a response is sent only at the right time, in the right thread.

Tie unnecessary parallel threads created by consume/reply operations

A consume/reply creates a consequent field set, thus a parallel thread of execution. If your only goal is to allow for mutability in fields, make sure that only the new thread continues.

Table 6. Consume/reply operations and parallel threadsThe right column shows an example on how to do this by using a FLAG field that gets created in the new field set and is expected by the myRequest operation.
Tip: See the Primes example on a possible use of a consume/reply.
Undesirable Idiomatic
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="field3" 
    type="string"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <consume name="ConsumeA" 
      fields="field1">      
      <reply name="Ok" 
        fields="field1"/>    
    </consume>    
    <request name="myRequest" 
      fields="field2">      
      <reply name="Ok" 
        fields="field3"/>    
    </request>    
    <consume name="ConsumeB" 
      fields="field3"/>  
  </mix>
</folder>   
<folder name="myFolder">  
  <field name="field1" 
    type="string"/>  
  <field name="field2" 
    type="string"/>  
  <field name="field3" 
    type="string"/>  
  <field name="AFLAG"/>  
  <mix name="myMix">    
    <notify fields="field1 field2"/>    
    <consume name="ConsumeA" 
      fields="field1">      
      <reply name="Ok" 
        fields="field1 AFLAG"/>    
    </consume>    
    <request name="myRequest" 
      fields="AFLAG field2">      
      <reply name="Ok" 
        fields="field3"/>    
    </request>    
    <consume name="ConsumeB" 
      fields="field3"/>  
  </mix>
</folder>