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

IO Processor Plugin API Specification for SCION 2.0 branch

Jacob Beard edited this page Jul 15, 2015 · 24 revisions

This specification describes an API for registering custom SCXML IO processors

This is described in the SCXML specification:

SCION Plugin API

scxml.registerIOProcessor({
  "http://foo.bar/#MyCustomProcessor" : {
    generateOriginUri : function(sessionid){
    },
    doSend : function(_event, sendOptions){
    }
  }
});

function generateOriginUri

Used to populate the io processor's location in built-in variable _ioprocessors.

This function would be called on session instantiation.

This is the example _ioprocessors value from the SCXML specification:

  "_ioprocessors" : {
    "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" : {
        "location" : "http://example.com/scxml-http/12345"
    }
    "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" :  {
      "location" : "http://example.com/scxml-http/23456"
    }
  }

Example

The HTTPBasicEventProcessor might be implemented as follows:

scxml.registerIOProcessor({
  "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" : {
    generateOriginUri : function(sessionid){
      return process.env.HOST + / + _sessionid;
    },
    doSend : function(_event, sendOptions){
      //...
    }
  }
});

Where process.env.HOST might be "http://example.com/scxml-http/".

Considerations

, when SCION model in initialized. This function does not provide access to SCXML datamodel.

sessionid is of type string.

function doSend

function doSend(_event, sendOptions){
}

event object

The SCXML specification states that the event object should have the following fields:

name. This is a character string giving the name of the event. The SCXML Processor must set the name field to the name of this event. It is what is matched against the 'event' attribute of <transition>. Note that transitions can do additional tests by using the value of this field inside boolean expressions in the 'cond' attribute.
type. This field describes the event type. The SCXML Processor must set it to: "platform" (for events raised by the platform itself, such as error events), "internal" (for events raised by <raise> and <send> with target '_internal') or "external" (for all other events).
sendid. If the sending entity has specified a value for this, the Processor must set this field to that value (see C Event I/O Processors for details). Otherwise, in the case of error events triggered by a failed attempt to send an event, the Processor must set this field to the send id of the triggering <send> element. Otherwise it must leave it blank.
origin. This is a URI, equivalent to the 'target' attribute on the <send> element. For external events, the SCXML Processor should set this field to a value which, when used as the value of 'target', will allow the receiver of the event to <send> a response back to the originating entity via the Event I/O Processor specified in 'origintype'. For internal and platform events, the Processor must leave this field blank.
origintype. This is equivalent to the 'type' field on the <send> element. For external events, the SCXML Processor should set this field to a value which, when used as the value of 'type', will allow the receiver of the event to <send> a response back to the originating entity at the URI specified by 'origin'. For internal and platform events, the Processor must leave this field blank.
invokeid. If this event is generated from an invoked child process, the SCXML Processor must set this field to the invoke id of the invocation that triggered the child process. Otherwise it must leave it blank.
data. This field contains whatever data the sending entity chose to include in this event. The receiving SCXML Processor should reformat this data to match its data model, but must not otherwise modify it. If the conversion is not possible, the Processor must leave the field blank and must place an error 'error.execution' in the internal event queue.

This corresponds to the follow JavaScript object, in JSON schema:

{
  type : "object",
  properties : {
    name : {
      "type" : "string"
    },
    type : {
      "type" : "string"
    },
    sendid : {
      "type" : "string"
    },
    origin : {
      "type" : "string"
    },
    origintype : {
      "type" : "string"
    },
    invokeid : {
      "type" : "string"
    },
    data : {
      "type" : "object"
      TODO: extensible
    }
  }
}

Note that invokeid will always be null in SCION, until <invoke> implementation is complete. TODO: cite Github issue.

The ioprocessor location generated by generateOriginUri is used to populate _event.origin.

object sendOptions

{
  "type" : "object",
  "properties" : {
    "delay" : {
      "type" : "number" 
      "description" : "Send delay, in milliseconds"
    },
    "sendid" : {
      "type" : "string"
      "description" : "The sendid of the send"
    }
  }
}

Example

The HTTPBasicEventProcessor could be implemented as follows.

The SCXML specification describes the following special targets:

#_internal. If the target is the special term '#_internal', the Processor must add the event to the internal event queue of the sending session.
#_scxml_sessionid. If the target is the special term '#_scxml_sessionid', where sessionid is the id of an SCXML session that is accessible to the Processor, the Processor must add the event to the external queue of that session. The set of SCXML sessions that are accessible to a given SCXML Processor is platform-dependent.
#_parent. If the target is the special term '#_parent', the Processor must add the event to the external event queue of the SCXML session that invoked the sending session, if there is one. See 6.4 <invoke> for details.
#_invokeid. If the target is the special term '#_invokeid', where invokeid is the invokeid of an SCXML session that the sending session has created by <invoke>, the Processor must add the event to the external queue of that session. See 6.4 <invoke> for details.

Ignoring _invokeid and _parent for now, as both require working <invoke> implementation and are out-of-scope for this document.

scxml.registerIOProcessor({
  "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" : {
    generateOriginUri : function(sessionid){
      //...
    },
    doSend : function(_event, sendOptions){
      var targetUrl;
      var scxmlSessionMatch = event.target && event.target.match(/^#_scxml_(.*)$/);
      if(!event.target){
        targetUrl = _event.origin;
      }else if(event.target === '_#internal'){
        return this._interpreter._raise(event);
      }else if(scxmlSessionMatch){
        var targetSessionid = scxmlSessionMatch[1]; 
        targetUrl = process.env.HOST + '/' + targetSessionid;
      }else if(event.target){
        targetUrl = event.target;
      }

      function _doSend(){
        request({
          method : 'POST',
          json : event,
          url : targetUrl
        }, function(error, response, body ) {
          if(error){ 
            //Enqueue error.communication to external queue (event though SCXML spec says inner queue).
            //we need to enqueue to outer queue because request may be handled asynchronously.
            return this._interpreter.gen({name : "error.communication", data : error);
          }

          //ignore the success response
        }.bind(this);
      };
    }

    if(sendOptions.delay){
      setTimeout(_doSend, sendOptions.delay);
    }else {
      _doSend();
    }
  }
});
Clone this wiki locally