diff --git a/README.md b/README.md index 4d81b80..cc41b58 100644 --- a/README.md +++ b/README.md @@ -4,44 +4,122 @@ [![Build Status](https://img.shields.io/travis/Kikobeats/farm-cli/master.svg?style=flat-square)](https://travis-ci.org/Kikobeats/farm-cli) [![Coverage Status](https://img.shields.io/coveralls/Kikobeats/farm-cli.svg?style=flat-square)](https://coveralls.io/github/Kikobeats/farm-cli) [![Dependency status](https://img.shields.io/david/Kikobeats/farm-cli.svg?style=flat-square)](https://david-dm.org/Kikobeats/farm-cli) -[![Dev Dependencies Status](https://img.shields.io/david/dev/Kikobeats/farm-cli.svg?style=flat-square)](https://david-dm.org/Kikobeats/farm-cli#info=devDependencies) [![NPM Status](https://img.shields.io/npm/dm/farm-cli.svg?style=flat-square)](https://www.npmjs.org/package/farm-cli) -[![Donate](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square)](https://paypal.me/Kikobeats) ![](https://i.imgur.com/BKQqOy4.png) -> Launch a farm of workers from your CLI. Based on [worker-farm](https://github.com/rvagg/node-worker-farm). +`farm` allows you create a multi-process architecture from your CLI. It's based on [worker-farm](https://github.com/rvagg/node-worker-farm). -## Install +> **Note**: See [examples](/examples) for common user case. + +## Installation + +First, install the library globally: ```bash $ npm install farm-cli --global ``` -## Usage +Additionally, you can invoke it using `npx`: + +```bash +$ npx farm-cli +``` + +## Getting Started + +### Basic Usage + +You need to specify a file and export a main method as entry point. + +```js +const createLog = n => (...args) => console.log(`[#${n}] ${args}`) +module.exports = function (opts, exit) { + const { isMaster, maxWorkers, worker } = opts + log(`I'm worker ${worker} of ${maxWorkers} ${isMaster ? '(master)' : ''}`) +} ``` -Usage - $ farm [options] -Options - -n, --cores [default=numCPUs] Cores to use for spawn workers. +Finally, invoke the file using `farm`: - -w, --workers [default=1] Workers to spawn per each core. +```bash +$ farm examples/basic + +[#0] Hello I'm worker 1 of 4 (master) +[#1] Hello I'm worker 2 of 4 +[#2] Hello I'm worker 3 of 4 +[#3] Hello I'm worker 4 of 4 +``` - -d, --delay [default=1000ms] Waiting time between spawning workers. +### Creating Your Own Farm - -r, --retries [default=Infinity] Max number of call requeues after unexpected worker termination. +By default, the library will create as many processes as number of CPUs in the machine and a thread per process. -It's possible to load [options] from file, creating '.farmrc' JSON file on the path of . +Let's use the same example but this time specifying multiple theads per process -Examples - $ farm process - $ farm -w 1 -n 1 process - $ farm -w 1 -n 1 process foo=bar +```bash +$ farm examples/basic -w 2 + +[#0] Hello I'm worker 1 of 8 (master) +[#1] Hello I'm worker 2 of 8 +[#2] Hello I'm worker 3 of 8 +[#4] Hello I'm worker 4 of 8 +[#5] Hello I'm worker 5 of 8 +[#6] Hello I'm worker 6 of 8 +[#7] Hello I'm worker 7 of 8 +[#8] Hello I'm worker 8 of 8 ``` -See more at [examples](/examples). +This time the farm has 2 threads per process (2 threads * 4 cores = 8 workers). + +Type `farm --help` to know more. + +### Load Configuration File + +The same things passed to `farm` from a `.farmrc` file created in the same directory. + +```bash +$ ls -al examples/load-config + +-rw-r--r--@ 1 50 Jan 21 2017 .farmrc +-rw-r--r--@ 1 105 Nov 26 2017 README.md +-rw-r--r--@ 1 50 Jan 21 2017 index.js +``` + +### Finishing the Execution + +When you want to finish, call the second argument: + +```js +module.exports = function (opts, exit) { + const { worker } = opts + + setTimeout(() => { + console.log(`[#${worker}] bye bye!`) + exit() + }) +} +``` + +It will finish gracefully when all the threads exit. + +### Passing File Arguments + +The parameters passed after the filename will used as file arguments: + +``` +$ farm examples/fiboniacci --memoize +[#0] Enable memoize mode! +``` + +### Debug Mode + +If you need to debug, enable it passing `DEBUG=farm` as environment variable + +``` +DEBUG=farm examples/fiboniacci --memoize +``` ## License diff --git a/bin/cli/index.js b/bin/cli/index.js index 20dd2b8..5dc5054 100755 --- a/bin/cli/index.js +++ b/bin/cli/index.js @@ -4,7 +4,7 @@ const pkg = require('../../package.json') require('update-notifier')({ pkg }).notify() -const debug = require('debug')(pkg.name) +const debug = require('debug')('farm') const workerFarm = require('worker-farm') const minimist = require('minimist') diff --git a/examples/basic/README.md b/examples/basic/README.md index db6245b..4bc0fc4 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -1,7 +1,7 @@ # Shared memory -An example for illustrating that the memory can be shared between workers in the same core. +An example to illustrate how to shared memory between workers in the same core. ```bash -$ DEBUG=farm-cli farm -n 1 -w 5 -d 0 examples/basic --your-file-flags foo=bar +$ DEBUG=farm farm -n 1 -w 5 -d 0 examples/basic --your-file-flags foo=bar ``` diff --git a/examples/basic/index.js b/examples/basic/index.js index f73410d..286edfb 100644 --- a/examples/basic/index.js +++ b/examples/basic/index.js @@ -11,7 +11,9 @@ module.exports = function (opts, exit) { const log = createLog(worker) log( - `Hello I'm worker ${worker} of ${maxWorkers} ${isMaster ? '(master)' : ''}` + `Hello I'm worker ${worker + 1} of ${maxWorkers} ${ + isMaster ? '(master)' : '' + }` ) shared.push(`#${worker}`) diff --git a/examples/factorial/README.md b/examples/factorial/README.md index 8e3582b..27fab3f 100644 --- a/examples/factorial/README.md +++ b/examples/factorial/README.md @@ -1,5 +1,5 @@ # Basic ```bash -$ DEBUG=farm-cli farm --cores 1 --workers 5 --delay 0 examples/factorial +$ DEBUG=farm farm --cores 1 --workers 5 --delay 0 examples/factorial ``` diff --git a/examples/fibonacci-redis/README.md b/examples/fibonacci-redis/README.md index 449825e..4b4eb29 100644 --- a/examples/fibonacci-redis/README.md +++ b/examples/fibonacci-redis/README.md @@ -9,5 +9,5 @@ $ redis-server Then run the script: ```bash -$ DEBUG=farm-cli farm --cores 2 --workers 1 --delay 0 examples/fibonacci-redis --n 40 +$ DEBUG=farm farm --cores 2 --workers 1 --delay 0 examples/fibonacci-redis --n 40 ``` diff --git a/examples/fibonacci/README.md b/examples/fibonacci/README.md index 15da68a..e023133 100644 --- a/examples/fibonacci/README.md +++ b/examples/fibonacci/README.md @@ -1,5 +1,11 @@ -# Basic - -```bash -$ DEBUG=farm-cli farm --cores 1 --workers 5 --delay 0 examples/fibonacci -``` +# Fibonacci + +This example use many workers in the same core for calculate fibonacci values. + +```bash +$ DEBUG=farm farm --cores 1 --workers 5 --delay 0 examples/fibonacci --n=20 +``` + +Notes you need to specify the number of values to get using `--n`. + +Additionally, you can pass `--memo` for use a memoize implementation. diff --git a/examples/fibonacci/index.js b/examples/fibonacci/index.js index 2da9d8c..7bff9a4 100644 --- a/examples/fibonacci/index.js +++ b/examples/fibonacci/index.js @@ -1,6 +1,6 @@ 'use strict' -const { ensureAsync, waterfall, whilst } = require('async') +const { whilst } = require('async') const mutexify = require('mutexify') const memo = [0, 1] @@ -19,26 +19,25 @@ const fibonacci = num => const lock = mutexify() let index = 0 -module.exports = function (opts, cb) { - const { worker: workerNum, memo, n } = opts +module.exports = function (opts, exit) { + const { isMaster, worker, memo, n } = opts const fn = memo ? fibonacciMemo : fibonacci + if (!n) { + if (isMaster) { + console.log('Ops! You need to specify the number of iteration with `--n`') + } + return exit() + } + whilst( () => index < n, done => - waterfall( - [ - next => lock(release => release(next(null, ++index))), - ensureAsync((num, next) => { - const value = fn(num) - console.log( - `#${workerNum} fibonacci value=${index} result=${value}` - ) - return next() - }) - ], - done - ), - cb + lock(release => { + const value = fn(++index) + console.log(`#${worker} fibonacci value=${index} result=${value}`) + return release(done) + }), + exit ) } diff --git a/examples/load-config/README.md b/examples/load-config/README.md index c70a928..6ff6a40 100644 --- a/examples/load-config/README.md +++ b/examples/load-config/README.md @@ -1,5 +1,5 @@ # Basic ```bash -$ DEBUG=farm-cli farm -w 2 -n 5 -d 0 examples/load-config --your-file-flags foo=bar +$ DEBUG=farm farm -w 2 -n 5 -d 0 examples/load-config --your-file-flags foo=bar ``` diff --git a/examples/throw-error/README.md b/examples/throw-error/README.md index dddd817..9214594 100644 --- a/examples/throw-error/README.md +++ b/examples/throw-error/README.md @@ -3,5 +3,5 @@ If the process throw an error, then the child worker will spawned again. ```bash -$ DEBUG=farm-cli farm -w 1 -n 1 -d 0 examples/throw-error --your-file-flags foo=bar +$ DEBUG=farm farm -w 1 -n 1 -d 0 examples/throw-error --your-file-flags foo=bar ```