{"_id":"plan","_rev":"20-479dc8e6265e60300509b1d134ab8325","name":"plan","description":"execute a complicated dependency graph of tasks with smooth progress events","dist-tags":{"latest":"0.1.5"},"versions":{"0.0.0":{"name":"plan","version":"0.0.0","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"index.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","readmeFilename":"README.md","devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"# node-plan\n\nWORK IN PROGRESS. NOT READY FOR USE.\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\n```js\n\nvar s3 = require('s3')\n  , path = require('path');\n\nvar s3DowloadTask = {\n  start: function(done) {\n    var self = this;\n    var client = s3.createClient({\n      key: \"s3 key\",\n      secret: \"s3 secret\",\n      bucket: \"s3 bucket\"\n    });\n    this.info.bucket = this.settings.s3_bucket;\n    this.emit('update');\n    var s3_url = this.context.s3_url;\n    delete this.context.s3_url;\n    var ext = path.extname(s3_url);\n    this.context.temp_path = this.context.makeTemp({\n      suffix: ext\n    });\n    var downloader = client.download(s3_url, this.context.temp_path);\n    downloader.on('error', done);\n    downloader.on('progress', function(amount_done, amount_total){\n      self.info.amount_done = amount_done;\n      self.info.amount_total = amount_total;\n      self.emit('progress');\n    });\n    downloader.on('end', done);\n  },\n};\n```\n\n### Execute a plan\n\n```js\nvar Plan = require('planner').Plan;\n\nvar plan = new Plan();\nplan.addTask(task);\nplan.addDependency(task, task2);\nplan.on('error', function(err) {\n  console.log(\"error:\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.info);\n});\nplan.on('end', function() {\n  console.log(\"done\");\n});\nplan.start();\n```\n\n## Documentation\n\n### Creating a Task\n\n### Executing a Plan\n","_id":"plan@0.0.0","dist":{"shasum":"b65b447d5dc095ce37438f5348b540d91b05fe9d","tarball":"https://registry.npmjs.org/plan/-/plan-0.0.0.tgz","integrity":"sha512-0HnmRZCgiTL3SrcpuD8tZ7bQ7TBin7KXRD1j4C3iOvxi3FWgAD2wBjEFJl/DIfA85TQFSFd0EmE82UvrA93QgA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHmdw9EVyn/xrwNtFAJPLLjHtKfSUOIvmsVpzd1KCj/ZAiBt+JXlFciaQy7uyZzYx68DKJ6oFtqbZTOV39Zg6sD12g=="}]},"_npmVersion":"1.1.66","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.0.1":{"name":"plan","version":"0.0.1","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":">=0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n\n### Execute a plan\n\n```js\nvar Plan = require('plan');\nvar plan = new Plan();\nplan.addTask(task);\nplan.addDependency(task, task2);\nplan.on('error', function(err) {\n  console.log(\"error:\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.info);\n});\nplan.on('end', function() {\n  console.log(\"done\");\n});\ncontext = {blah: \"foo\"};\nplan.start(context);\n```\n\n## Documentation\n\n### Creating a Task\n\n#### context\n\n#### options\n\n#### emitting update events\n\n#### emitting progress events\n\n#### CPU Bound Tasks\n\n### Executing a Plan\n","readmeFilename":"README.md","_id":"plan@0.0.1","dist":{"shasum":"8755cff31d3bab570687593bd0d4bf5dca0e475c","tarball":"https://registry.npmjs.org/plan/-/plan-0.0.1.tgz","integrity":"sha512-UsFYC+NULQGAXV1g60Oo3tLkEO/kNy+iHb/8eKSi0fTWHQiQF3ZBe9Cq8OQMJNuCKzl0VI8kfpYx9rVPlVg2Tg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD3tW2Hs+hQUuP0Gn+RTA4z16crw6Qk6xAYakqdeaWJdAIgBj8r4DTioQvu0NwIzzAY5LjKpmjv7WPCtnosEu7SulQ="}]},"_npmVersion":"1.1.66","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.0":{"name":"plan","version":"0.1.0","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":"~0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err) {\n  console.log(\"error:\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function() {\n  console.log(\"done\");\n});\ncontext = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.0","dist":{"shasum":"59701d34264a8105a15cc09da792c6fe266b2fb3","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.0.tgz","integrity":"sha512-6N9TrPEa5KUMG6mYIgFDq+26XrcQmFMa+UFjVxzaIP9i2UpSbeqxAf72IYQo2Dtv2gpEDsQdnnwOSytSBiP8mA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEUf3J+QahTCYtfp8UWvXkGq9dUVJ2C/N5VznRVpgtXRAiAte5YIN5I9Uxm1tBVZHR8Cz50C8gbd7SpZL/obhJCqLg=="}]},"_npmVersion":"1.1.66","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.1":{"name":"plan","version":"0.1.1","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":"~0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err, task) {\n  console.log(\"task\", task.name, \"error\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function(context) {\n  console.log(\"done\", context);\n});\nvar context = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.1","dist":{"shasum":"9833864f4df4c08732d6a451067a23c930b82d79","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.1.tgz","integrity":"sha512-M91yNKYpCdnZyL6lVyqbTp4jqEfhJSm1nU3vf8+N9lSzHAQcb/fMexP2VmyYKlbGs4+j7ZS81uWkvaqbER9yRQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHHAYt1HGEjY7+hnHzBdJRTje+f5Q5l0pmRZkZTqkXVSAiAsJ456AzYXymBRAcNQSJGTKO1cuyGObq2NwBPXqoaYsQ=="}]},"_npmVersion":"1.1.66","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.2":{"name":"plan","version":"0.1.2","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":"~0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err, task) {\n  console.log(\"task\", task.name, \"error\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function(context) {\n  console.log(\"done\", context);\n});\nvar context = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.2","dist":{"shasum":"0ef80e5b64c7bc29ca6e652b1e3a85f616b8f8d6","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.2.tgz","integrity":"sha512-sVkQZwYRP/8j2ltDt74u6vVrbEUMkxhAfXcVPOHPySvBbjy0xYIj1qHCUGlSk54+D9YONn/KdhRTB3f0BJlQNA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF0Z/JF7LYivZXb5HUcVL1b2m/E47nx5vDRbdPxIv+sFAiEAruS9O+yoI/zQz3L+5Ws8ToIsn2C8z3gbacOlchJamJg="}]},"_npmVersion":"1.1.66","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.3":{"name":"plan","version":"0.1.3","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":">=0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.2.1","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err, task) {\n  console.log(\"task\", task.name, \"error\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function(context) {\n  console.log(\"done\", context);\n});\nvar context = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n### What would I use this for?\n\nCreating a service such as [TransloadIt](https://transloadit.com/).\n\n[Mediablast](https://github.com/superjoe30/mediablast) is an open source\nservice such as this running on node-plan.\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.3","dist":{"shasum":"609ce6ad6d09bb578c6be1dc9d0128a01b85039f","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.3.tgz","integrity":"sha512-nOM4VmSRtlg3EQysiPtKdwVTvf5MnngR4D7dPMBFBc2CqXgXzw260Lp6RkTUaDVE6TRLLbjCjtiRFQqQNJkyGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDb5nI8ogJTo/wvIps2oCD1kYqy3EbeFyeqQRHbaTu7KAIgKsQEHwB/fDA5bYylUdwqY85F8PmMVQyMV5Nld9gJsec="}]},"_from":".","_npmVersion":"1.2.14","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.4":{"name":"plan","version":"0.1.4","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":">=0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.3.2","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err, task) {\n  console.log(\"task\", task.name, \"error\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function(context) {\n  console.log(\"done\", context);\n});\nvar context = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n### What would I use this for?\n\nCreating a service such as [TransloadIt](https://transloadit.com/).\n\n[Mediablast](https://github.com/superjoe30/mediablast) is an open source\nservice such as this running on node-plan.\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.4","dist":{"shasum":"1b09ec410ef597f200f0fe3f5307379e13d037b1","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.4.tgz","integrity":"sha512-9S+fmhFQR1upIIXmt7xJUwuPdqMr4gEt1x2zi3tcXpwZKdlZUPtIRV9FVu3Kz7HlqwCjc8HC0lzFvWC6upXVzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwnWr66fjyB3matXyuKESCDF24lGaKMo1TonvZLUGEzwIhAIIINJp2RaE4puhsN2lGiwnHKVpPdXu00h+Xc8ejM+xw"}]},"_from":".","_npmVersion":"1.2.17","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]},"0.1.5":{"name":"plan","version":"0.1.5","description":"execute a complicated dependency graph of tasks with smooth progress events","main":"lib/plan.js","scripts":{"test":"mocha"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"keywords":["dependency","graph","async","plan","planner","emit","smooth","progress"],"author":{"name":"Andrew Kelley"},"license":"BSD","engines":{"node":">=0.8.0"},"devDependencies":{"mocha":"~1.7.2"},"dependencies":{"batch":"~0.3.2","node-uuid":"~1.4.0"},"readme":"[![Build Status](https://secure.travis-ci.org/superjoe30/node-plan.png?branch=master)](https://travis-ci.org/superjoe30/node-plan)\n\n# node-plan\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\nHere are some examples:\n\n * [waveform](https://github.com/superjoe30/node-plan-waveform)\n * [callback](https://github.com/superjoe30/node-plan-callback)\n * [s3-upload](https://github.com/superjoe30/node-plan-s3-upload)\n * [s3-download](https://github.com/superjoe30/node-plan-s3-download)\n * [thumbnail](https://github.com/superjoe30/node-plan-thumbnail)\n * [transcode](https://github.com/superjoe30/node-plan-transcode)\n\n### Execute a plan\n\nIn this example, we will download a song from s3, generate a waveform image\nand preview audio, and upload each generated thing to s3, all the while\nreporting smooth and accurate processing progress to the end user.\n\n```js\nvar Plan = require('plan')\n  , WaveformTask = require('plan-waveform')\n  , TranscodeTask = require('plan-transcode')\n  , UploadS3Task = require('plan-s3-upload')\n  , DownloadS3Task = require('plan-s3-download')\n\nvar downloadTask = Plan.createTask(DownloadS3Task, \"download\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar waveformTask = Plan.createTask(WaveformTask, \"waveform\", {\n  width: 1000,\n  height: 200,\n});\nvar previewTask = Plan.createTask(TranscodeTask, \"preview\", {\n  format: 'mp3'\n});\nvar uploadWaveformTask = Plan.createTask(UploadS3Task, \"upload-waveform\", {\n  url: \"/{uuid}/waveform{ext}\"\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\nvar uploadPreviewTask = Plan.createTask(UploadS3Task, \"upload-preview\", {\n  s3Key: '...',\n  s3Bucket: '...',\n  s3Secret: '...',\n})\n\n// planId is used to index progress statistics. Same with the 2nd parameter\n// to `Plan.createTask` above. Next time we run the same planId, node-plan\n// uses the gathered stats to inform the progress events, so that they will\n// be much more accurate and smooth.\nvar planId = \"process-audio\";\n\nvar plan = new Plan(planId);\nplan.addTask(uploadPreviewTask);\nplan.addDependency(uploadPreviewTask, previewTask);\nplan.addDependency(previewTask, downloadTask);\nplan.addTask(uploadWaveformTask);\nplan.addDependency(uploadWaveformTask, waveformTask);\nplan.addDependency(waveformTask, downloadTask);\nplan.on('error', function(err, task) {\n  console.log(\"task\", task.name, \"error\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.exports);\n});\nplan.on('end', function(context) {\n  console.log(\"done\", context);\n});\nvar context = {\n  s3Url: '/the/file/to/download',\n  makeTemp: require('temp').path\n};\nplan.start(context);\n```\n\n### What would I use this for?\n\nCreating a service such as [TransloadIt](https://transloadit.com/).\n\n[Mediablast](https://github.com/superjoe30/mediablast) is an open source\nservice such as this running on node-plan.\n\n## Documentation\n\n### Creating a Task Definition\n\n```js\nvar TaskDefinition = {};\n```\n\n#### start\n\n```js\nTaskDefinition.start = function(done) {\n  ...\n};\n```\n\n`start` is your main entry point. When you are finished processing, call \n`done`. In this scope, `this` points to the task instance.\n\nIf your task encounters an error, call done with the error object as\nthe first parameter.\n\n#### context\n\n`context` acts as your input as well as your output. Sometimes it makes\nsense to delete the parameter that you are using; sometimes it does not.\n\nAccess `context` via `this.context` in the `start` function.\n\n#### exports\n\n`exports` is output that is tied to the task instance and is not passed to\nthe next task in the dependency graph.\n\nThere are some special fields on `exports` that you should be wary of:\n\nFields you should write to:\n\n * `exports.amountTotal` - as soon as you find out how long executing this\n   task is going to take, set `amountTotal`. If the task is unable to emit\n   progress, node-plan will guess based on previous statistics.\n * `exports.amountDone` - this number will change based on progress whereas\n   `amountTotal` should not.\n\nWhenever you update `amountDone` or `amountTotal`, you should emit a\n`progress` event: `this.emit('progress')`. Don't worry about emitting\nan `update` event for this case.\n\nFields you should not write to:\n\n * `exports.startDate` - the date the task instance started\n * `exports.endDate` - the date the task instance completed\n * `exports.state` - one of ['queued', 'skipped', 'processing', 'complete']\n   * `queued` - this task has not yet been started\n   * `skipped` - this task has been skipped, because one or more of its\n     dependencies emitted an error, and `ignoreDependencyErrors` is not \n     set to `true`.\n   * `processing` - this task is currently in progress\n   * `complete` - this task has completed, possibly unsuccessfully.\n\nYou are free to add as many other `exports` fields as you wish.\n\nWhenever you change something in `exports`, you should emit a `update`\nevent: `this.emit('update')`.\n\nAccess `exports` via `this.exports` in the `start` function.\n\n#### options\n\n`options` are per-task-instance configuration values. It is the third\nparameter of `Plan.createTask(definition, name, options)`.\n\nAccess `options` via `this.options` in the `start` function.\n\n#### CPU Bound Tasks\n\nIf your task spawns a CPU-intensive process and waits for it to complete,\nyou should mark your task as `cpuBound`:\n\n```js\nTaskDefinition.cpuBound = true;\n```\n\nnode-plan pools all `cpuBound` tasks, defaulting to a worker count equal\nto the number of CPU cores on your machine.\n\n### Executing a Plan\n\n#### new Plan(planId)\n\n`planId` is used for the progress heuristics. when you're building a\nsimilar plan, use the same `planId` and progress events will use\npast statistics for accuracy and smoothness.\n\n#### Plan.setWorkerCap(count)\n\nSet this to limit the number of simultaneous CPU-bound tasks.\n\n#### Plan.createTask(definition, name, options)\n\n * `definition` - task definition described above\n * `name` - a string, used to store statistics data. If you're doing a similar\n   task, use the same name.\n * `options` - an object which is passed to the task instance to configure it.\n   In addition to the options which the task definition recognizes, all tasks\n   have these additional built-in options:\n   * `ignoreDependencyErrors` - if set to true, the task will execute even if\n     one or more of its dependencies did not suceed. default false.\n\n#### Plan.prototype.addTask(task)\n\nThis adds a root node to the dependency graph. If you imagine a tree, where\nthe plan instance itself is the root node, `addTask` adds a task to the root node.\n\n#### Plan.prototype.addDependency(targetTask, dependencyTask)\n\nThis is how you specify dependencies. `dependencyTask` becomes a leaf node of\n`targetTask`.\n\n#### Plan.prototype.start(context)\n\nExecutes the plan. `context` is cloned and passed to all leaf nodes. Task\ninstances modify `context` and pass a clone to the next task in the tree.\n\n#### Plan 'end' event (context)\n\nThe plan has completed executing successfully. `context` is a merged result\nobject of the tasks that were added with `addTask`.\n\n#### Plan 'error' event (err)\n\nOne or more tasks returned an error. `err` is the error object.\n\n#### Plan 'progress' event (amountDone, amountTotal)\n\nTells you how far along the execution of the plan is.\n\n#### Plan 'update' event\n\nOccurs when a task instance's `exports` have updated.\n","readmeFilename":"README.md","_id":"plan@0.1.5","dist":{"shasum":"361f47897f3a2e481e2099c2f96db1b8eb3fc20e","tarball":"https://registry.npmjs.org/plan/-/plan-0.1.5.tgz","integrity":"sha512-jejIRMchs5YDEg8xOUMDd6rV1XH1pHp4IAp5/OmUpkyksJxA0ddnKsxHio6FCGLNgsFvm/ZCEJpy6DbXa4WD7Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMxbxHWz+H1k8tHarSP1mHIR7LlPwXSeDULJ84gr1z/QIgfas5U0WzVhxNH4370dE7drO6pyY+9nfofVZrTxww2Xo="}]},"_from":".","_npmVersion":"1.2.17","_npmUser":{"name":"superjoe","email":"superjoe30@gmail.com"},"maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}]}},"readme":"# node-plan\n\nWORK IN PROGRESS. NOT READY FOR USE.\n\nExecute a complicated dependency graph of tasks with smooth progress events.\n\n## Usage\n\n### Create tasks\n\n```js\n\nvar s3 = require('s3')\n  , path = require('path');\n\nvar s3DowloadTask = {\n  start: function(done) {\n    var self = this;\n    var client = s3.createClient({\n      key: \"s3 key\",\n      secret: \"s3 secret\",\n      bucket: \"s3 bucket\"\n    });\n    this.info.bucket = this.settings.s3_bucket;\n    this.emit('update');\n    var s3_url = this.context.s3_url;\n    delete this.context.s3_url;\n    var ext = path.extname(s3_url);\n    this.context.temp_path = this.context.makeTemp({\n      suffix: ext\n    });\n    var downloader = client.download(s3_url, this.context.temp_path);\n    downloader.on('error', done);\n    downloader.on('progress', function(amount_done, amount_total){\n      self.info.amount_done = amount_done;\n      self.info.amount_total = amount_total;\n      self.emit('progress');\n    });\n    downloader.on('end', done);\n  },\n};\n```\n\n### Execute a plan\n\n```js\nvar Plan = require('planner').Plan;\n\nvar plan = new Plan();\nplan.addTask(task);\nplan.addDependency(task, task2);\nplan.on('error', function(err) {\n  console.log(\"error:\", err);\n});\nplan.on('progress', function(amountDone, amountTotal) {\n  console.log(\"progress\", amountDone, amountTotal);\n});\nplan.on('update', function(task) {\n  console.log(\"update\", task.info);\n});\nplan.on('end', function() {\n  console.log(\"done\");\n});\nplan.start();\n```\n\n## Documentation\n\n### Creating a Task\n\n### Executing a Plan\n","maintainers":[{"name":"superjoe","email":"superjoe30@gmail.com"}],"time":{"modified":"2022-06-24T02:26:31.916Z","created":"2012-11-29T09:04:29.598Z","0.0.0":"2012-11-29T09:04:30.907Z","0.0.1":"2012-12-05T19:41:27.533Z","0.1.0":"2012-12-11T02:26:26.426Z","0.1.1":"2012-12-12T17:45:09.107Z","0.1.2":"2012-12-12T17:56:11.181Z","0.1.3":"2013-03-12T04:44:58.813Z","0.1.4":"2013-04-09T16:16:48.368Z","0.1.5":"2013-04-10T16:58:22.153Z"},"author":{"name":"Andrew Kelley"},"repository":{"type":"git","url":"git://github.com/superjoe30/node-plan.git"},"users":{"edin-m":true}}