1.3.0 • Published 5 years ago

fofx v1.3.0

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

F of X ( or fofx, for short)

What is this?

fofx aims to be a way for solo developers or teams to develop tiny pieces of software that is easily deployed, powerful enough to do stuff and easily pluginable.

Basically, think of fofx as a sort of serverless (OMG, buzzword alert) product you can use as easy as npm install.

Installation

Installing the main cli tool (this is the repo of the main cli tool, BTW) is as easy as npm install --global fofx. However, you're probably going to want to run some code with that nifty fofx you've heard so much about. Read on, then.

Abstract

A good fofx setup is composed of two kinds of entities:

  • Plugins are the components that let fofx know when to trigger your services, and how to handle their output. An Input Plugin produces the parameter that is passed to your service. An Output Plugin is called with your service's result value.
  • Nanos are your bits of code, named so since they are basically nanoservices (is this a buzzword yet?). Your nanos should export a single function (async, or not) and may return a value. These functions will run on every input event, and pass their results to their respective outputs.

Setup

Once you've installed the cli, you should create a new directory. Lets call ours demo. In it, create 2 JSON files: plugins.json and nanos.json. These serve as your "package.json"s, as we shall soon see. Recap:

demo/
|--plugins.json
|--nanos.json

Now, go into plugins.json. This is where you list your plugins (duh). A plugin can either be listed as its package name (if npm install accets it, fofx accepts it, as a rule), or as a more complex object:

[
  {
    "name": "fofx-web",
    "params": {
      "port": 5000
    }
  },
  "fofx-cron"
]

As you may have noticed, the complex form accepts a params key, which is an object passed to the plugin's factory function. You can read more on these on individual plugins' READMEs.

We'll skip nanos.json for now. First, let's create our first nano.

Our first nano

Open a new terminal tab. Create a new node project, however you like. It should have a package.json and main file (usually, index.js). Make sure the packe name is unique - this is your nano's name! Now, go ahead and create a nano.json file, too. Recap:

nano-test/
|--package.json
|--index.js
|--nano.json

We'll disregard the package.json for now, and start with our nano.json file:

{
  "input": {
    "type": "cron",
    "cron": "*/20 * * * * *"
  },
  "output": {
    "type": "web",
    "method": "POST",
    "url": "http://localhost:5000/api/bar"
  }
}

This file must have a hash with the input key, and may also have an output key. These represent the plugins that feed/accept data from your nano. In our example, our nano is triggered by the Crontab Plugin (fofx-cron), as indicated by the type key (every plugin has a declared, unique type) This plugin also needs a valid cron key in order to succefully schedule tasks. In our example, this nano will run every 20 seconds. By the output key, we can tell that the result of the nano will be sent as a POST request to the url http://localhost:5000/api/bar, via the Web Plugin (fofx-web).

New In version 1.3.0: Your nano.json file may have a useState key with a boolean value. If this key is set to true, your nano may use state, even across workers. See Stateful Nanos, below.

This is all we need to write in order to create a schduled task that sends HTTP requests.

As to our index.js:

/* our function accepts no arguments, since crontab delivers no valuable info.
Other plugins, such as web input, might pass one argument (e.g. a web request object).
*/
module.exports = function() {
  // We were called!

  // every nano can hook into fofx log :)
  // available methods are: doc, debug, info, warn, error and fatal
  this.log.info('I have a dedicated log! Yay!');
  return {
    timestamp: Date.now(),
  };
};

And we have our first nano! Now we just have to make sure it's installable (you can publish to npm, store it on a git server or even just npm link it).

Stateful Nanos

Sometimes, you may wish your nano to have a state that persists between runs. Since fofx may run across different workers, you shouldn't rely on a module level variable for this. To enable persistent state, please set "useState" to true in your nano.json file, and then use it like so:

module.exports = async function() {
  const state = (await this.state.get()) || {};
  if (!state.foo) {
    state.foo = 0;
  }
  state.foo++;
  await this.state.set(state);
  return state;
};

Back to our nanos.json

Now we can simply list our nanos by their instabllable names (just like with the plugins file - if npm install accepts it, so should fofx). No complex forms this time:

["nano-test"]

Setup is done!

Run

Assuming your CWD is our demo directory, run: fofx

This should install your plugins and nanos in a directory named modules under demo:

demo/
|--plugins.json
|--nanos.json
|--modules/
|----plugins/
|------package-lock.json
|------node_modules/
|----nanos/
|------package-lock.json
|------node_modules/
|----cache/

If and when you use git to manage your fofx setup, you should set the .gitignore to ignore the modules directory.

And there you have it - a running platform for your nanoservices.

You can view a demo setup here.

Distributed Run

Run fofx with the --broker=<redis_connection_string> flag. This runs the main platform without nano execution responsibilities. You should then run fofx-worker with the same --broker flag, with either an identical copy of your enviornment, or the same one, using the --dry flag to make sure you don't re-download your nanos.

Official Plugins

  • fofx-web - An input/output plugin for HTTP requests
  • fofx-cron - An input plugin for crontab-flavoured scheduled tasks
  • fofx-mongodb - An input/output plugin for MongoDB

Roadmap

  • Scalable/distributed
  • Watch changes to plugins/nanos and reload