Initial commit
[yaffs-website] / node_modules / orchestrator / README.md
1 [![Build Status](https://secure.travis-ci.org/robrich/orchestrator.svg?branch=master)](https://travis-ci.org/robrich/orchestrator)\r
2 [![Dependency Status](https://david-dm.org/robrich/orchestrator.svg)](https://david-dm.org/robrich/orchestrator)\r
3 \r
4 Orchestrator\r
5 ============\r
6 \r
7 A module for sequencing and executing tasks and dependencies in maximum concurrency\r
8 \r
9 Usage\r
10 -----\r
11 \r
12 ### 1. Get a reference:\r
13 \r
14 ```javascript\r
15 var Orchestrator = require('orchestrator');\r
16 var orchestrator = new Orchestrator();\r
17 ```\r
18 \r
19 ### 2. Load it up with stuff to do:\r
20 \r
21 ```javascript\r
22 orchestrator.add('thing1', function(){\r
23   // do stuff\r
24 });\r
25 orchestrator.add('thing2', function(){\r
26   // do stuff\r
27 });\r
28 ```\r
29 \r
30 ### 3. Run the tasks:\r
31 \r
32 ```javascript\r
33 orchestrator.start('thing1', 'thing2', function (err) {\r
34   // all done\r
35 });\r
36 ```\r
37 \r
38 API\r
39 ---\r
40 \r
41 ### orchestrator.add(name[, deps][, function]);\r
42 \r
43 Define a task\r
44 \r
45 ```javascript\r
46 orchestrator.add('thing1', function(){\r
47   // do stuff\r
48 });\r
49 ```\r
50 \r
51 #### name\r
52 Type: `String`\r
53 \r
54 The name of the task.\r
55 \r
56 #### deps\r
57 Type: `Array`\r
58 \r
59 An array of task names to be executed and completed before your task will run.\r
60 \r
61 ```javascript\r
62 orchestrator.add('mytask', ['array', 'of', 'task', 'names'], function() {\r
63   // Do stuff\r
64 });\r
65 ```\r
66 \r
67 **Note:** Are your tasks running before the dependencies are complete?  Make sure your dependency tasks\r
68 are correctly using the async run hints: take in a callback or return a promise or event stream.\r
69 \r
70 #### fn\r
71 Type: `function`\r
72 \r
73 The function that performs the task's operations.  For asynchronous tasks, you need to provide a hint when the task is complete:\r
74 \r
75 - Take in a callback\r
76 - Return a stream or a promise\r
77 \r
78 #### examples:\r
79 \r
80 **Accept a callback:**\r
81 \r
82 ```javascript\r
83 orchestrator.add('thing2', function(callback){\r
84   // do stuff\r
85   callback(err);\r
86 });\r
87 ```\r
88 \r
89 **Return a promise:**\r
90 \r
91 ```javascript\r
92 var Q = require('q');\r
93 \r
94 orchestrator.add('thing3', function(){\r
95   var deferred = Q.defer();\r
96 \r
97   // do async stuff\r
98   setTimeout(function () {\r
99     deferred.resolve();\r
100   }, 1);\r
101 \r
102   return deferred.promise;\r
103 });\r
104 ```\r
105 \r
106 **Return a stream:** (task is marked complete when stream ends)\r
107 \r
108 ```javascript\r
109 var map = require('map-stream');\r
110 \r
111 orchestrator.add('thing4', function(){\r
112   var stream = map(function (args, cb) {\r
113     cb(null, args);\r
114   });\r
115   // do stream stuff\r
116   return stream;\r
117 });\r
118 ```\r
119 \r
120 **Note:** By default, tasks run with maximum concurrency -- e.g. it launches all the tasks at once and waits for nothing.\r
121 If you want to create a series where tasks run in a particular order, you need to do two things:\r
122 \r
123 - give it a hint to tell it when the task is done,\r
124 - and give it a hint that a task depends on completion of another.\r
125 \r
126 For these examples, let's presume you have two tasks, "one" and "two" that you specifically want to run in this order:\r
127 \r
128 1. In task "one" you add a hint to tell it when the task is done.  Either take in a callback and call it when you're\r
129 done or return a promise or stream that the engine should wait to resolve or end respectively.\r
130 \r
131 2. In task "two" you add a hint telling the engine that it depends on completion of the first task.\r
132 \r
133 So this example would look like this:\r
134 \r
135 ```javascript\r
136 var Orchestrator = require('orchestrator');\r
137 var orchestrator = new Orchestrator();\r
138 \r
139 // takes in a callback so the engine knows when it'll be done\r
140 orchestrator.add('one', function (cb) {\r
141     // do stuff -- async or otherwise\r
142     cb(err); // if err is not null or undefined, the orchestration will stop, and note that it failed\r
143 });\r
144 \r
145 // identifies a dependent task must be complete before this one begins\r
146 orchestrator.add('two', ['one'], function () {\r
147     // task 'one' is done now\r
148 });\r
149 \r
150 orchestrator.start('one', 'two');\r
151 ```\r
152 \r
153 ### orchestrator.hasTask(name);\r
154 \r
155 Have you defined a task with this name?\r
156 \r
157 #### name\r
158 Type: `String`\r
159 \r
160 The task name to query\r
161 \r
162 ### orchestrator.start(tasks...[, cb]);\r
163 \r
164 Start running the tasks\r
165 \r
166 #### tasks\r
167 Type: `String` or `Array` of `String`s\r
168 \r
169 Tasks to be executed. You may pass any number of tasks as individual arguments.\r
170 \r
171 #### cb\r
172 Type: `function`: `function (err) {`\r
173 \r
174 Callback to call after run completed.\r
175 \r
176 Passes single argument: `err`: did the orchestration succeed?\r
177 \r
178 **Note:** Tasks run concurrently and therefore may not complete in order.\r
179 **Note:** Orchestrator uses `sequencify` to resolve dependencies before running, and therefore may not start in order.\r
180 Listen to orchestration events to watch task running.\r
181 \r
182 ```javascript\r
183 orchestrator.start('thing1', 'thing2', 'thing3', 'thing4', function (err) {\r
184   // all done\r
185 });\r
186 ```\r
187 ```javascript\r
188 orchestrator.start(['thing1','thing2'], ['thing3','thing4']);\r
189 ```\r
190 \r
191 **FRAGILE:** Orchestrator catches exceptions on sync runs to pass to your callback\r
192 but doesn't hook to process.uncaughtException so it can't pass those exceptions\r
193 to your callback\r
194 \r
195 **FRAGILE:** Orchestrator will ensure each task and each dependency is run once during an orchestration run\r
196 even if you specify it to run more than once. (e.g. `orchestrator.start('thing1', 'thing1')`\r
197 will only run 'thing1' once.) If you need it to run a task multiple times, wait for\r
198 the orchestration to end (start's callback) then call start again.\r
199 (e.g. `orchestrator.start('thing1', function () {orchestrator.start('thing1');})`.)\r
200 Alternatively create a second orchestrator instance.\r
201 \r
202 ### orchestrator.stop()\r
203 \r
204 Stop an orchestration run currently in process\r
205 \r
206 **Note:** It will call the `start()` callback with an `err` noting the orchestration was aborted\r
207 \r
208 ### orchestrator.on(event, cb);\r
209 \r
210 Listen to orchestrator internals\r
211 \r
212 #### event\r
213 Type: `String`\r
214 \r
215 Event name to listen to:\r
216 - start: from start() method, shows you the task sequence\r
217 - stop: from stop() method, the queue finished successfully\r
218 - err: from stop() method, the queue was aborted due to a task error\r
219 - task_start: from _runTask() method, task was started\r
220 - task_stop: from _runTask() method, task completed successfully\r
221 - task_err: from _runTask() method, task errored\r
222 - task_not_found: from start() method, you're trying to start a task that doesn't exist\r
223 - task_recursion: from start() method, there are recursive dependencies in your task list\r
224 \r
225 #### cb\r
226 Type: `function`: `function (e) {`\r
227 \r
228 Passes single argument: `e`: event details\r
229 \r
230 ```javascript\r
231 orchestrator.on('task_start', function (e) {\r
232   // e.message is the log message\r
233   // e.task is the task name if the message applies to a task else `undefined`\r
234   // e.err is the error if event is 'err' else `undefined`\r
235 });\r
236 // for task_end and task_err:\r
237 orchestrator.on('task_stop', function (e) {\r
238   // e is the same object from task_start\r
239   // e.message is updated to show how the task ended\r
240   // e.duration is the task run duration (in seconds)\r
241 });\r
242 ```\r
243 \r
244 **Note:** fires either *stop or *err but not both.\r
245 \r
246 ### orchestrator.onAll(cb);\r
247 \r
248 Listen to all orchestrator events from one callback\r
249 \r
250 #### cb\r
251 Type: `function`: `function (e) {`\r
252 \r
253 Passes single argument: `e`: event details\r
254 \r
255 ```javascript\r
256 orchestrator.onAll(function (e) {\r
257   // e is the original event args\r
258   // e.src is event name\r
259 });\r
260 ```\r
261 \r
262 LICENSE\r
263 -------\r
264 \r
265 (MIT License)\r
266 \r
267 Copyright (c) 2013-2015 [Richardson & Sons, LLC](http://richardsonandsons.com/)\r
268 \r
269 Permission is hereby granted, free of charge, to any person obtaining\r
270 a copy of this software and associated documentation files (the\r
271 "Software"), to deal in the Software without restriction, including\r
272 without limitation the rights to use, copy, modify, merge, publish,\r
273 distribute, sublicense, and/or sell copies of the Software, and to\r
274 permit persons to whom the Software is furnished to do so, subject to\r
275 the following conditions:\r
276 \r
277 The above copyright notice and this permission notice shall be\r
278 included in all copies or substantial portions of the Software.\r
279 \r
280 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
281 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
282 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
283 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
284 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
285 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
286 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r