For developers

Quick start

To get started with jIO, clone one of the repositories linked in Download & Fork.

To build the library you have to:

  • Install NodeJS (including NPM)

  • Install Grunt command line with npm.

    # npm -g install grunt-cli

  • Install dev dependencies.

    $ npm install

  • Compile JS/CC parser.

    $ make (until we find how to compile it with grunt)

  • Run build.

    $ grunt

The repository also includes the built ready-to-use files, so in case you do not want to build jIO yourself, just use jio.js as well as complex_queries.js plus the storages and dependencies you need and you will be good to go.

Naming Conventions

All the code follows these JavaScript Naming Conventions.

How to design your own jIO Storage Library

Create a constructor:

function MyStorage(storage_description) {
  this._value = storage_description.value;
  if (typeof this._value !== 'string') {
    throw new TypeError("'value' description property is not a string");
  }
}

Create 10 methods: post, put, putAttachment, get, getAttachment, remove, removeAttachment, allDocs, check and repair.

MyStorage.prototype.post = function (command, metadata, option) {
  var document_id = metadata._id;
  // [...]
};

MyStorage.prototype.get = function (command, param, option) {
  var document_id = param._id;
  // [...]
};

MyStorage.prototype.putAttachment = function (command, param, option) {
  var document_id = param._id;
  var attachment_id = param._attachment;
  var attachment_data = param._blob;
  // [...]
};

// [...]

(To help you design your methods, some tools are provided by jIO.util.)

The first parameter command provides some methods to act on the jIO job:

  • success, to tell jIO that the job is successfully terminated

    command.success(status[Text], [{custom key to add to the response}]);

  • resolve, is equal to success

  • error, to tell jIO that the job cannot be done

    command.error(status[Text], [reason], [message], [{custom key to add to the response}])

  • retry, to tell jIO that the job cannot be done now, but can be retried later. (same API than error)

  • reject, to tell jIO that the job cannot be done, let jIO to decide whether to retry or not. (same API than error)

The second parameter metadata or param is the first parameter provided by the jIO user.

The third parameter option is the option parameter provided by the jIO user.

Methods should return the following objects:

  • post –> success(“created”, {“id”: new_generated_id})

  • put, remove, putAttachment or removeAttachment –> success(204)

  • get –> success(“ok”, {“data”: document_metadata})

  • getAttachment –>

    success(“ok”, {“data”: binary_string, “content_type”: content_type}) // or success(“ok”, {“data”: new Blob([data], {“type”: content_type})})

  • allDocs –> success(“ok”, {“data”: row_object})

  • check –>

    // if metadata provides "_id" -> check document state
    // if metadata doesn't promides "_id" -> check storage state
    success("no_content")
    // or
    error("conflict", "corrupted", "incoherent document or storage")
    
  • repair –>

    // if metadata provides "_id" -> repair document state
    // if metadata doesn't promides "_id" -> repair storage state
    success("no_content")
    // or
    error("conflict", "corrupted", "impossible to repair document or storage")
    // DON'T DESIGN STORAGES IF THEIR IS NO WAY TO REPAIR INCOHERENT STATES
    

After creating all methods, your storage must be added to jIO. This is done with the jIO.addStorage() method, which requires two parameters: the storage type (string) and a constructor (function). It is called like this:

// add custom storage to jIO
jIO.addStorage('mystoragetype', MyStorage);

Please refer to localstorage.js implementation for a good example on how to setup a storage and what methods are required.

Also keep in mind that jIO is a job-based library: whenever you trigger a method, a job is created, which will later return a response, after being processed.

Job rules

The jIO job manager follows several rules set at the creation of a new jIO instance. When you try to call a method, jIO will create a job and will make sure the job is really necessary and will be executed. Thanks to these job rules, jIO knows what to do with the new job before adding it to the queue. You can also add your own rules, as we’re going to see now.

These are the jIO default rules:

var jio_instance = jIO.createJIO(storage_description, {
  "job_rules": [{
    "code_name": "readers update",
    "conditions": [
      "sameStorageDescription",
      "areReaders",
      "sameMethod",
      "sameParameters",
      "sameOptions"
    ],
    "action": "update"
  }, {
    "code_name": "metadata writers update",
    "conditions": [
      "sameStorageDescription",
      "areWriters",
      "useMetadataOnly",
      "sameMethod",
      "haveDocumentIds",
      "sameParameters"
    ],
    "action": "update"
  }, {
    "code_name": "writers wait",
    "conditions": [
      "sameStorageDescription",
      "areWriters",
      "haveDocumentIds",
      "sameDocumentId"
    ],
    "action": "wait"
  }]
});

The following actions can be used:

  • ok - accept the job
  • wait - wait until the end of the selected job
  • update - bind the selected job to this one
  • deny - reject the job

The following condition function can be used:

  • sameStorageDescription - check if the storage descriptions are different.
  • areWriters - check if the commands are post, put, putAttachment, remove, removeAttachment, or repair.
  • areReaders - check if the commands are get, getAttachment, allDocs or check.
  • useMetadataOnly - check if the commands are post, put, get, remove or allDocs.
  • sameMethod - check if the commands are equal.
  • sameDocumentId - check if the document ids are equal.
  • sameParameters - check if the metadata or param are equal (deep comparison).
  • sameOptions - check if the command options are equal.
  • haveDocumentIds - test if the two commands contain document ids.

Create Job Condition

You can create two types of function: job condition, and job comparison.

// Job Condition
// Check if the job is a get command
jIO.addJobRuleCondition("isGetMethod", function (job) {
  return job.method === 'get';
});

// Job Comparison
// Check if the jobs have the same 'title' property only if they are strings
jIO.addJobRuleCondition("sameTitleIfString", function (job, selected_job) {
  if (typeof job.kwargs.title === 'string' &&
      typeof selected_job.kwargs.title === 'string') {
    return job.kwargs.title === selected_job.kwargs.title;
  }
  return false;
});

Add job rules

You just have to define job rules in the jIO options:

// Do not accept to post or put a document which title is equal to another
// already running post or put document title
var jio_instance = jIO.createJIO(storage_description, {
  "job_rules": [{
    "code_name": "avoid similar title",
    "conditions": [
      "sameStorageDescription",
      "areWriters",
      "sameTitleIfString"
    ],
    "action": "deny",
    "before": "writers update" // optional
    // "after": also exists
  }]
});

Clear/Replace default job rules

If a job’s code_name is equal to readers update, then adding this rule will replace it:

var jio_instance = jIO.createJIO(storage_description, {
  "job_rules": [{
    "code_name": "readers update",
    "conditions": [
      "sameStorageDescription",
      "areReaders",
      "sameMethod",
      "haveDocumentIds"
      "sameParameters"
      // sameOptions is removed
    ],
    "action": "update"
  }]
});

Or you can just clear all rules before adding new ones:

var jio_instance = jIO.createJIO(storage_description, {
  "clear_job_rules": true,
  "job_rules": [{
    // ...
  }]
});