npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

arch-orchestrator

v1.4.9

Published

Orchestrator for large node.js applications

Downloads

25

Readme

arch-orchestrator

Build Status

Orchestrator architectural pattern for large node.js applications

Installation

npm install arch-orchestrator

Motivation

Managing architecture or big node.js applications can be challenging. With orchestrator approach you can improve structure of your node.js application by decoupling different tasks on system. Let's see typical architecture after moving to orchestrator approach.

alt tag

Now let's clarify some parts of this architecture:

Participants

Route handler
  • Function which knows which orchestrator method needs to call, in order to deliver requested resource.
Orchestrator
  • Object which know how to construct chain of tasks. This object should know about each task. In order to deliver chain (or direct results) to route handler, he needs to construct appropriate chain of tasks.
Task
  • Function which knows how to finish some specific task. Tasks don't know anything about each other. They have also small additional responsability. When action on task is finished, task needs to call next function in order to deliver results to next part of task chain. Next step will have some another responsability, and so on, until end of chain. When end of chain is reached, result will be available. Note that if you use arch-orchestrator next function will be called automatically for you.

So, central point of this system is orchestrator, and there is power of architecture this type. Orchestrator can decide to change order of actions in chain, can decide to add new steps to chain, can decide to remove some steps from chain, etc. All these actions should not hit any of tasks, because task don't know anything about who is sending data to task, or to who task is delivering data. That is completely dynamic.

Example

Okey, let's look some practical example of this architecture, using arch-orchestrator module.

Without orchestrator pattern

Let' define few simple functions which do some actions in some order.

function add(arg) {
  return multiply(arg + 10);
}

function substract(arg) {
  return divide(arg - 10);
}

function multiply(arg) {
  return substract(arg * 10);
}

function divide(arg) {
  return arg / 10;
}

I suppose this situation is familiar to you. This is really tightly coupled situation. If you want to change order of actions in this architecture, you will hit each function. Or imagine that you want to keep current order of actions, but you want to reuse functions in order (for example) divide -> add -> substract. Hmmmm, yes, that can end with dirty code.

With orchestrator pattern

First let's define few tasks.

// each task accepts result(s) from previous action(s).
function add(arg) {
  // each task need to call next function
  // next function will call next part of chain, which is dynamic,
  // and defined by orchestrator
  // here ``arch-orchestrator`` is calling ``next`` function for us,
  return arg + 10;
}

function substract(arg) {
  return arg - 10;
}

function multiply(arg) {
  return arg * 10;
}

function divide(arg) {
  return arg / 10;
}

Now we can define chain for out tasks. Orchestrator is responsable for that.

var orchestrator = require('arch-orchestrator');

function doMagic() {
  return orchestrator()
    .setNext(add)
    .setNext(multiply)
    .setNext(substract)
    .setNext(divide)
    .end();
};

This chain is not very usefull, but it shows you idea of this approach. I belive you can see that you can easily remove/add/change order of tasks in chain, wihout hitting actual task. So if you want to do that, you could simply say for example:

function doMagic() {
  return orchestrator()
    .setNext(divide)
    .setNext(add)
    .setNext(substract)
    .end();
};

And at the end some route handler should ask orchestrator for chain of methods.

function (req, res) {
  var chain = doMagic();
  console.log(chain(100));
}

NOTE: You can use generators as you chain parts. Your chain can consist of only generators, only of normal functions, or combination of generators and functions.

API

setNext(Function)

Method adds new function to chain. You can pass normal or generator function to chain.

end()

Method ends current chain, and compose chain of functions for you. All passed functions to setNext will be part of chain.

asResult()

If you want to use result of some specific chain step as final, you should mark that chain step with asResult method.

Example:
var fn = orchestrator()
  .setNext(add)
  .setNext(multiply).asResult()
  .setNext(substract)
  .setNext(divide)
  .end();

var result = fn(100)

In this case result will be returned from add and multiply methods. All other methods bellow will execute normally, but final result will be used from add and multiply methods.

argsTo([Function...])

With this method you can redirect arguments of some function which is part of chain to some other.

Example:
var fn = orchestrator()
  .setNext(add).argsTo(substract)
  .setNext(multiply)
  .setNext(substract)
  .setNext(divide)
  .end();

In this example you will execute add method normally, but you will also say that method substract will accept the same argument values as method add. So method substract won't use passed values from multiply, it will use the same arguments as add method.

resultTo([Function...])

With this method you set result of some chain function to be argument of some other chain function.

Example:
var fn = orchestrator()
  .setNext(add).resultTo(substract)
  .setNext(multiply)
  .setNext(substract)
  .setNext(divide)
  .end();

You can call resultTo and argsTo multiple times, or even combine them.

Example:
var fn = orchestrator()
  .setNext(fn1).argsTo(fn4)
  .setNext(fn2).resultTo(fn4)
  .setNext(fn3)
  .setNext(fn4)
  .end();

In this case arguments on fn4 will be available in order as functions argsTo and resultTo are called, so fn4 can look like:

function fn4(argFromArgsTo, argFromResultTo) {
  // do something awesome
}

Breaking chain

At some point you will maybe want to be able to break chain. So instead of downstreaming result, you will want to return from chain immediately. In that case you just need return object from some chain function.

That object should have at least breakChain property with true value.

return {
  breakChain: true
}

You can also add some additional fields, so you can consume retuned additional fields, for example:

return {
  breakChain: true,
  message: 'this is some message which explains reason of chain break'
}

License

MIT