Skip to content

Rework on the previous version spec. #21

@yuanyan

Description

@yuanyan

Current spec is more simple, some work on previous version:

var Promise = require('es6-promise').Promise;
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var _ = require('lodash');

var Status = {
    PENDING:  0, // Indicates that the task has not been executed yet.
    RUNNING:  1, // Indicates that the task is running.
    REJECTED: 2, // Indicates that the task has completed without errors.
    RESOLVED: 3, // Indicates that the task not completed.
    FINISHED: 4, // Indicates that the task has finished.
    FAULTED: 5   // Indicates that the task finished due to an unhandled exception.
};

function Task (config) {
    if (!(this instanceof Task)) return new Task(config);
    this.setOptions(config.options);
    this._status = Status.PENDING;
    _.extend(this, config);
    EventEmitter.call(this);
}

util.inherits(Task, EventEmitter);

Task.Status = Status;


/**
 * Task name must be a combination of one or more digits, letters a–z, underscores, and/or dashes,
 * satisfying the following regular expression: [0-9a-zA-Z\-\_]+
 * @type {String}
 */
Task.prototype.name = null;
Task.prototype.timeout = null;
Task.prototype.force = false;
Task.prototype.options = {};

Task.prototype._parseOptions = function (options) {
    var defaults = _.merge({}, this.options, options, function(d, o) {
        return o.defaultValue || o;
    });
    return _.extend(defaults, this._options || {});
};

Task.prototype.getOptions = function(){
    return this._options;
};

Task.prototype.setOptions = function(options){
    return this._options = this._parseOptions(options);
}

Task.prototype.getStatus = function(){
    return this._status;
};

Task.prototype.getInput = function(){
    return this._input;
};

Task.prototype.setTimeout = function(msecs, callback) {
    if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) {
        this.timeout = msecs;
        if (callback) {
            this.on('timeout', callback);
            this._timeoutHandler = callback;
        }
    } else if (msecs === 0) {
        this.clearTimeout(callback);
    }
};

Task.prototype.clearTimeout = function(callback){
    this.timeout = null;
    if (this._timer) {
        clearTimeout(this._timer);
    }
    callback = callback || this._timeoutHandler;
    if (callback) {
        this.removeListener('timeout', callback);
    }
};

/**
 * Main entry point for task.
 * @param input
 * @returns {*}
 */
Task.prototype.run = function (input) {
    this._input = !_.isArray(input)? [input]: input;
    return this._run();

};

Task.prototype._run = function(resolve, reject){
    var self = this;
    if(this.timeout){
        this._timer = setTimeout(function(){
            self.emit('timeout');
        }, this.timeout)
    }
    var promise = Promise.resolve();
    return promise.then(this._setup.bind(self))
        .then(this._execute.bind(self))
        .then(this._teardown.bind(self))
        .catch(this._error.bind(self));
}

/**
 * Thenable
 */
Task.prototype.then = function(resolve, reject){
    return this._run(resolve, reject);
};

Task.prototype._setup = function () {
    var self = this;
    return new Promise(function (resolve, reject) {
        self.emit('setup');
        self.setup(resolve, reject);
    });
};

Task.prototype._execute = function(){
    var self = this;
    return new Promise(function (resolve, reject) {
        self.emit('execute');
        self._status = Status.RUNNING;
        self.execute(function(){
            self._status = Status.RESOLVED;
            resolve.apply(self, arguments);
        }, function(){
            self._status = Status.REJECTED;
            reject.apply(self. arguments);
        });
    });
};

Task.prototype._teardown = function(res){
    this.emit('teardown');
    this._status = Status.FINISHED;
    return Promise.resolve(this.teardown(res));
};

Task.prototype._error = function(err){
    this._status = Status.FAULTED;
    this.emit('error', err);
    return this.error(err);
}

/*
When an task is run, the task goes through 3 steps:
1. setup(Params...), invoked before the task is executed. This step is normally used to setup the task.
2. execute(Params...), invoked immediately after setup() finishes executing.
   This step is used to perform task that can take a long time.The parameters of the task are passed to this step.
   The result of the task must be returned by this step and will be passed back to the last step.
3. teardown(Result), invoked after execute() finishes. The result of the execute() is passed to this step as a parameter.
*/

Task.prototype.setup = function (resolve, reject) {
    resolve();
};

Task.prototype.execute = function (resolve, reject) {
    // var input = this.getInput();
    // input.isStream();
};

Task.prototype.teardown = function (res) {
    return res;
};

Task.prototype.error = function (err) {
    return err;
};

module.exports = Task;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions