Skip to content
This repository was archived by the owner on Sep 25, 2018. It is now read-only.

Plugin API for SCION 2.0 branch

Jacob Beard edited this page Apr 17, 2017 · 8 revisions

This document proposes a plugin API for SCION.

In SCXML the following tags allow platform-specific extensions:

  1. Custom io processor (send/@type)
  2. Custom invoke type (invoke/@type)
  3. Custom action tags

This document describes an API for registering custom action tags on SCION.

The API for registering custom io processor is here.

Custom Action Tags

Custom action tags are described in the SCXML specification:

Custom Action Elements can be defined in other specifications/namespaces and are responsible for performing actions on behalf of custom components. Logically Custom Action Elements can be thought of as a collection of actions and handlers to perform specific tasks.

http://www.w3.org/TR/scxml/#custom_action

This section describes a custom action element, and an example implementation using SCION's proposed plugin API.

HTTP GET Example

Consider a custom action tag that does an HTTP GET request to a URL, and sends an event to the state machine when the HTTP request completes.

<scxml 
  xmlns="http://www.w3.org/2005/07/scxml" 
  xmlns:ext="http://foo.bar/"
  name="custom-action-tag-example-1" 
  datamodel="ecmascript" 
  version="1.0">
  <state id="fetching">
    <ext:get url="http://google.com"/>
    <transition event="response.success" target="succeeded"/>
    <transition event="response.failure" target="failed"/>
  </state>
  <state id="succeeded"/>
  <state id="failed"/>
</scxml>

SCION Plugin API

scxml.registerCustomActionTags({
  namespace : {
    tagName : function template(action){
    }
  }
});

For example, the HTTP GET example would look like:

scxml.registerCustomActionTags({
   "http://foo.bar/" : {
    "get" : function (action) {
        return "http.get(" + JSON.stringify(action.url) + ",function(res){" +
        "  this.send(res.statusCode === 200 ? 'response.success' : 'response.failure', res);" +
        "}.bind(this));"
    }
  }
});

This would generate in the action code the following:

    function $get_line_8_column_40(_event){
        http.get("http://google.com",function(res){
          this.send(res.statusCode === 200 ? 'response.success' : 'response.failure', res);
        }.bind(this));
    }

Action Parameter

The action parameter of the above template contains the following schema:

{
  $line : integer
  $column : integer
  $type: string
}

It also contains an attribute for each attribute key-value pair from the source XML.

Referencing the datamodel

Consider an extension to the above example where the URL for the GET is dynamic. The <get> tag would need to reference the datamodel via a urlexpr attribute:

<scxml 
  xmlns="http://www.w3.org/2005/07/scxml" 
  xmlns:ext="http://foo.bar/"
  name="custom-action-tag-example-1" 
  datamodel="ecmascript" 
  version="1.0">
  <datamodel>
    <data id="foo" expr="'http://google.com'"/>
  </datamodel>
  <state id="fetching">
    <ext:get urlexpr="foo"/>
    <transition event="response.success" target="succeeded"/>
    <transition event="response.failure" target="failed"/>
  </state>
  <state id="succeeded"/>
  <state id="failed"/>
</scxml>

For example, the HTTP GET example would look like:

scxml.registerCustomActionTags({
   "http://foo.bar/" : {
    "get" : function (action) {
        return "http.get(" + (action.url ? JSON.stringify(action.url) : action.urlexpr) + ",function(res){" +
        "  this.send(res.statusCode === 200 ? 'response.success' : 'response.failure', res);" +
        "}.bind(this));"
    }
  }
});

This would generate in the action code the following:

    function $get_line_8_column_40(_event){
        http.get(foo, function(res){
          this.send(res.statusCode === 200 ? 'response.success' : 'response.failure', res);
        }.bind(this));
    }

urlexpr is exposed as a local variable to the $get_line_8_column_40 function.

Extend Runtime

The above example references a platform-specific http variable. The best approach to this is to add the http module to the executionContext sandbox object argument passed to model.prepare.

Packaging

npm can be used as infrastructure to package, version and distribute libraries of SCXML tags. An SCXML document can use a package.json to specify the particular tag library versions used in the associated SCXML.

Clone this wiki locally