Skip to content

Instantly share code, notes, and snippets.

@dapetcu21
Created December 15, 2014 14:52
Show Gist options
  • Save dapetcu21/9583e356d7567b22ec91 to your computer and use it in GitHub Desktop.
Save dapetcu21/9583e356d7567b22ec91 to your computer and use it in GitHub Desktop.

Build Status

Orchestrator-like task management with event stream integration.

Gulp advocates the philosophy that disk I/O should be kept to the minimum: the initial read and the final write. To this end, it popularized event streams and the stream piping pattern.

Unfortunately, orchestrator is blatantly stream-unaware. A .pipe() chain can only be contained to one orchestrator task and in most complex gulpfiles, you end up with either huge or function-fragmented tasks, either tasks that write temporary files (or to global variables).

Affluent tries to solve this issue by treating tasks as streams. Tasks can be run in sequence with access to the previous tasks' output and merged. Also, tasks don't have to wait for their dependencies to finish their whole .pipe() chain, as they can add themselves to it.

Affluent also solves the issue of extendability of tasks. Tasks can be discovered with wildcards (globs) to create hook points in your .pipe() chains.

Installation

$ npm install --save affluent

Usage

1. Get a reference:

var Affluent = require('affluent');
var affluent = new Affluent();

2. Create some tasks:

affluent.task('thing1', function (input){
  // do stuff
  return stream1;
});
affluent.task('thing2', function (input){
  // do stuff
  return stream2;
});
affluent.task('thing3', function (input){
  // do stuffin
  return stream3;
});

Tasks will recieve a readable stream as input and it's usual to also return a readable stream.

Tasks can return:

  1. a readable stream
  2. a promise to a readable stream
  3. a promise to anything else
  4. anything else

3. Run the tasks:

affluent.run(['thing1', 'thing2', 'thing3']);

This will run thing1, then .pipe its result into thing2, then pipe its result into thing3.

The return value of run() will also be a stream that you can pipe into as input to the first task in the sequence.

Behaviour is a bit different depending on what do the tasks return.

  1. If the tasks are streams, they will be piped together sequentially.
  2. If any of the tasks returns a promise, a buffered stream will be used to delay the next pipe until the promise resolves.
  3. If any of the tasks returns anything else, they will be skipped from the pipe chain.

4. Use globs:

Affluent uses globs for task names everywhere. The above example could have been written as:

affluent.run('thing*');

Since run() returns a stream, you can create tasks that customize their behaviour depending on what other tasks are installed:

affluent.task('html', function (input) {
  return input
    // do stuff with the input
    .pipe(affluent.run('html-filter:*'));
});

The above example would process the HTML content given to it, then pass it through all the installed HTML filters (which could be named html-filter:minify, html-filter:censor-bad-words, etc.) The sequence's order is defined as the order of the creation of the tasks.

5. Merging streams

affluent.merge([stream1, stream2, 'task4', 'globs:*'])

Returns a single readable stream by joining the event streams from an array (with event_stream.merge) Task names and globs can also be passed instead of streams. They will be called with an empty stream as input.

The joined stream will also pass through whatever is written to it, to enable setups like this:

someStream.pipe(affluent.merge(['some', 'tasks']));

6. Dependencies:

affluent.task('thing', ['dependencies', 'of', 'current', '*task*'], function (deps, of, current, task, input) {
   // do stuff
});

Dependencies of a task will be executed before the current task (with an empty stream as input). Their return values are then passed along as arguments to the current task. Glob matches are merge()-d together before they are passed along.

License

MPL v2.0 (c) ReadForward

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment