Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous Custom Plugins Startup #96

Open
asnowfix opened this issue Feb 1, 2017 · 3 comments
Open

Asynchronous Custom Plugins Startup #96

asnowfix opened this issue Feb 1, 2017 · 3 comments

Comments

@asnowfix
Copy link

asnowfix commented Feb 1, 2017

TL;DR

The EMG custom plugin API does not allow safe initialization of async (remote or not) resources.

Problem

Custom EMG plugins provide an init() entry point, which synchronously returns a predefined list of other entry points dealing with HTTP traffic. As soon as init() returns, the plugin is expected to be able to deal with inbound HTTP traffic. However, initialization of some resources might require some time. This is the case for example to get a remote public key (to check for JWT token validity), or to open a local database.

Actually, most of the Node.js API being asynchronous, the EMG init() synchronous call forces us to be able to deal with early race condition, while this could be easily avoided.

module.exports.init = function(config, logger, stats) {
  return {
    ondata_response: function(req, res, data, next) {
      debug('***** plugin ondata_response');
      next(null, null);
    },
    onend_response: function(req, res, data, next) {
      debug('***** plugin onend_response');
      next(null, "Hello, World!\n\n");
    }
  };
}

Our Recommendation

Add an optional 4th parameter "next" to the init() call, being a Node.js callback:

  1. If absent (function arity === 3), then init() synchronously returns the expected list of HTTP handler. This is the current API & the current behavior: it maintains backward compatibility.
  2. If present (function arity === 4), init() returns nothing and calls next() with error or data payload, depending on the initialization success, according to the Node.js callback model.

Example custom plugin source code using async init():

 module.exports.init = function(config, logger, stats, next) {
  db.open('./mydb.sql', function(err, mydb) {
    if (err) {
      next(err); 
    } else {
      next(null, {
        ondata_response: function(req, res, data, next) {
          debug('***** plugin ondata_response');
          next(null, null);
        },
        onend_response: function(req, res, data, next) {
          debug('***** plugin onend_response');
         next(null, "Hello, World!\n\n");
        }
      }
   });
};
@f1erro
Copy link
Contributor

f1erro commented Feb 11, 2017

Nice idea, let's get this into the next release @mdobson

@mdobson
Copy link
Contributor

mdobson commented Feb 12, 2017

We'll keep this in mind for upcoming backlog discussions.

@dschniepp
Copy link

Any update on this topic, I guess it seems still to be an issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants