Skip to content

gtramontina/spring-river

Repository files navigation

spring-river

npm version npm license travis codeclimate score

Disclaimer

This library is my attempt to make a javascript version of Fred George's (@fredgeorge) RapidsRivers following Zeit's Micro simple bootstrap approach. This is just an experiment at this point.

For more information on the Rapids/Rivers/Ponds paradigm, please refer to the links at the bottom of this file.

Usage

If you learn by looking at code first, check out examples directory.

Now onto the step-by-step:

First, you need to install spring-river as a runtime dependency:

npm install spring-river --save

This library requires an amqp-compatible queue. RabbitMQ works perfectly. In order to configure the queue address, you can either set the environment variable ADDRESS or add the --address (or -a) flag when starting your services and set the address as amqp://….

River

If your microservice is the one generating "solutions", add a {"start": "river"} script, like the following, to your package.json:

{
  "main": "index.js",
  "name": "my-microservice-river",
  "scripts": {
    "start": "river"
  }
}

Your index.js will look like the following. It accepts a packet, which is, for all purposes, a plain javascript object with the packet's contents, and a publish function, which can be used to publish conclusions back to the rapids.

module.exports = (packet, publish) => {
  packet.solution = 10;
  publish(packet);
};

To get you service running, all you need to do is to run:

npm start

Spring

If your microservice is the one generating "needs", add a {"start": "spring"} script, like the following, to your package.json:

{
  "main": "index.js",
  "name": "my-microservice-spring",
  "scripts": {
    "start": "spring"
  }
}

Your index.js will look like the following. It accepts a publish function, which can be used to publish conclusions (a need is a conclusion) to the rapids.

module.exports = (publish) => {
  setInterval(() => {
    publish({need: 'rental_car_offer'});
  }, 5000)
};

To get you service running, all you need to do is to run:

npm start

Predicates

By definition, your exported function will be called whenever a packet arrives (this is so we can keep the bus a dumb pipe). In order to filter out and focus only on interesting packets, you can use decorators around your to-be-exported function. E.g.:

const myFilter = require('./my-filter');

module.exports = myFilter((packet, publish) => {
  packet.solution = 10;
  publish(packet);
});

Where my-filter.js could be something that filters only packets that have {need: 'rental_car_offer'}:

module.exports = (next) => (packet, publish) => {
  if (packet.need === 'rental_car_offer') {
    next(packet, publish);
  }
}

This library ships with a few built-in predicates that you might find useful (perhaps these are candidates to be moved out into their own modules, as these are just very simple functions).

`forbid-keys`: filters out packets that contain any of the given keys;

Parameters: (...string): a list of forbidden keys

`require-keys`: filters out packets that _do not_ contain _all_ given keys;

Parameters: (...string): a list of required keys

`require-values`: filters out packets that _do not_ contain _all_ given key-value pairs;

Parameters: (object): the object with the required key-value pairs

Usage

The following example is interested in packets that contain the {need: 'rental_car_offer'} key-value pair and does not have a solution key:

const predicates = require('spring-river/predicates');
const {requireValues, forbidKeys} = predicates;

module.exports = predicates(
  requireValues({need: 'rental_car_offer'}),
  forbidKeys('solution')
)((packet, publish) => {
  packet.solution = 10;
  publish(packet);
});

Credits

First and foremost, everything here is built based on Fred George's (@fredgeorge) Rapids/Rivers/Ponds paradigm, so here's a list of resources if you want to get more familiar with this idea:

The structure of this module was inspired by Zeit's Micro, so bin/index.js borrows a lot from it.

License

This software is licensed under the MIT license.