UNPKG

usher

Version:

Simple DSL for composing decision workflows for AWS Simple Workflow

232 lines (176 loc) 7.16 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: decider/version.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: decider/version.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/*! * Usher * Copyright(c) 2014 meltmedia &lt;mike@meltmedia.com> */ /* jshint camelcase:false */ 'use strict'; var winston = require('winston'), util = require('util'), _ = require('lodash'), swf = require('aws-swf'), AWS = require('aws-sdk'), usherUtil = require('../util'), Context = require('./context'), Fragment = require('./fragment'), WorkflowState = require('./state'), WorkflowExecution = require('./execution'); module.exports = WorkflowVersion; /** * Represents a single, named workflow, where all activities and decisions are defined. * @constructor * @extends {Fragment} * @param {string} name - The name of the workflow. * @param {string} version - Version(s) this workflow can handle (conforms to v2.0 of http://semver.org) * @param {string} domain - The AWS SWF domain name to execute this workflow in. * @param {object} [options] - Additional SWF options used when creating and executing this workflow * (taskList, tagList, childPolicy, executionStartToCloseTimeout, taskStartToCloseTimeout) */ function WorkflowVersion(name, version, domain, options) { if (!(this instanceof WorkflowVersion)) { return new WorkflowVersion(name, version, domain, options); } Fragment.call(this, name); if (!_.isString(domain)) { throw new Error('A `domain` is required'); } this.version = version; this.domain = domain; this.options = options || {}; } // Make Workflow an extention of Fragment util.inherits(WorkflowVersion, Fragment); /** * Execute a new run of this workflow * @returns {WorkflowVersion} This workflow so you can chain commands. */ WorkflowVersion.prototype.execute = function execute(input, tags, cb) { // Callback and tags are optional cb = cb || (_.isFunction(tags) ? tags : function () {}); tags = _.isFunction(tags) ? [] : (tags || []); var config = usherUtil.workflowConfig(this.name, this.version, input, this.options); // Merge local tags with global tags config.tagList = _.isArray(config.tagList) ? config.tagList.concat(tags) : tags; // The domain is not always needed so it's not set by the workflow config config.domain = this.domain; var workflow = new swf.Workflow(config, new AWS.SWF()); var workflowExecution = workflow.start({ input: JSON.stringify(input) }, function (err, runId) { if (err) { return cb(err); } cb(null, runId, workflowExecution.workflowId); }); return this; // chainable }; /** * Validate this workflow * @returns {WorkflowVersion} This workflow version so you can chain commands. */ WorkflowVersion.prototype.validate = function validate() { // This will throw if there are issues this.sequencedTasks(); // If we got here, everything validated fine return true; }; /** @private */ WorkflowVersion.prototype._handleTask = function _handleTask(decisionTask) { var context, execution, self = this; decisionTask.workflowState = new WorkflowState(decisionTask); // When something goes wrong and we can't make a decision function handleFailure(err) { // Respond back to SWF failing the workflow winston.log('error', 'An problem occured in the execution of workflow: %s, failing due to: ', self.name, err.stack); decisionTask.response.fail('Workflow failed', err, function (err) { if (err) { winston.log('error', 'Unable to mark workflow: %s as failed due to: %s', self.name, JSON.stringify(err)); return; } }); } // When we have made a decision function handleSuccess() { // If any activities failed, we need to fail the workflow if (context.failed()) { winston.log('warn', 'One of more activities failed in workflow: %s, marking workflow as failed', self.name); // Respond back to SWF failing the workflow decisionTask.response.fail('Activities failed', { failures: context.errorMessages }, function (err) { if (err) { winston.log('error', 'Unable to mark workflow: %s as failed due to: %s', self.name, JSON.stringify(err)); return; } }); } else { // Check to see if we are done with the workflow if (context.done()) { winston.log('info', 'Workflow: %s has completed successfuly', self.name); // Stop the workflow decisionTask.response.stop({ result: JSON.stringify(context.results) }); } // If no decisions made this round, skip if (!decisionTask.response.decisions) { winston.log('debug', 'No decision can be made this round for workflow: %s', self.name); // Record our state when we can't make a decision to help in debugging // decisionTask.response.add_marker('current-state', JSON.stringify(context.currentStatus())); decisionTask.response.wait(); } // Respond back to SWF with all decisions decisionTask.response.respondCompleted(decisionTask.response.decisions, function (err) { if (err) { winston.log('error', 'Unable to respond to workflow: %s with decisions due to: %s', self.name, JSON.stringify(err)); return; } }); } } /** * Run Workflow */ winston.log('debug', 'Handling new decision task for workflow: %s', this.name); try { execution = new WorkflowExecution(this.sequencedTasks()); context = new Context(decisionTask); execution.execute(context, function (err) { if (err) { return handleFailure(err); } handleSuccess(); }); } catch (e) { handleFailure(e); } }; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="Accumulator.html">Accumulator</a></li><li><a href="ActivityPoller.html">ActivityPoller</a></li><li><a href="ActivityTask.html">ActivityTask</a></li><li><a href="DecisionPoller.html">DecisionPoller</a></li><li><a href="Fragment.html">Fragment</a></li><li><a href="Loop.html">Loop</a></li><li><a href="Usher.html">Usher</a></li><li><a href="WhileLoop.html">WhileLoop</a></li><li><a href="WorkflowVersion.html">WorkflowVersion</a></li></ul> </nav> <br clear="both"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Mon Sep 12 2016 14:59:00 GMT-0700 (MST) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>