-
Notifications
You must be signed in to change notification settings - Fork 28
Task chain
##Introduction
the task (or tasks) chain is a hook up line of actions that should be executed in the files of a framework. Each task takes the input from the previous task, do some possible manipulations on the files and pass the result on to the next task in the chain. The tasks can be combined to match the demands of the concrete building problem. A developer can specify the sequence of the tasks and also implement new ones.
This diagram shows the primary steps to build and attache a chain of tasks to a framework, included here are the involved Espresso components.
Application flow Status: 19.11.2010
The workflow of defining and using a custom task chain is not fully convenient at the moment. At the current status of Espresso, a task chain is only used internal for building the "The-M-Project" core. Nevertheless the task chain will working just the same way for custom or build-in task chains. Its only a matter of abstraction to provide a elegant way of defining a custom chain, like in the projects config, by using JSON syntax or something else.
So, here is how it works:
(1)
It all starts within the App
. The app takes the task chain definition and passes it over to the TaskManager
.
This is done by calling: new TaskManager(['T1',''T2','T4','T3']).getTaskChain();
. The order of the task names represents the sequence in which the tasks shall be executed.
(2)
The TaskManager will, make a look up to in his managed tasks to find a entry for the given task name from App. If all names references to valid tasks, the manager will hook the tasks up to a chain and returning the first task in the chain.
(3)
The app taks the return value! Here you have the free choice what to do with the task chain. As for the internal use, during the build for "The-M-Project" core. The task chain is bound to the framework, that serves as a representation of the core system.
Look at the Code snippet in the App, which is responsible for loading the core system :
App.prototype.loadTheMProject = function(options) {
var that = this, _theMProject;
_theMProject = ['core'].map(function(module) {
var _frameworkOptions = {};
_frameworkOptions.path = that.pathName+'/frameworks/Mproject/modules/' + module;
_frameworkOptions.name = module;
/* Definition of standard build chain for The-M-Project´s core files*/
_frameworkOptions.taskChain = new TaskManager(["dependency","..."]).getTaskChain();
return new Framework(_frameworkOptions);
});
this.addFrameworks(_theMProject);
};
##Task definition
Each concrete task uses the Task prototype. The prototype defines the functions and properties that every task should have, to work in a task chain. A shortened overview of the Task prototype is shown here:
Task = exports.Task = function() {
this.framework;
this.name;
this.next;
};
[...]
/**
* The run function, defined here for any task.
* @param framework the framework, this task is working with
* @param callback the function, that should be called after the all tasks finished there job.
*/
Task.prototype.run = function(framework,callback){
var that = this;
that.duty(framework,function(fr){
if (that.next === undefined){
callback(fr);
}else{
that.next.run(fr,callback);
}
});
};
/**
* This function should be overridden by any Task implementation.
* The duty() function contains the implementation of the action, provided by this task.
*
* @param framework the framework, this task is working with
* @param callback the function, that should be called after the all tasks finished there job.
*/
Task.prototype.duty = function(framework,callback){
// concrete tasks code goes here.
};
The important functions are: run()
which shall not be touched by a concrete task implementation using this prototype and duty()
. The run()
function implements the execution of the task itself, and then call the next task in the chain. The action of the task is implemented in the duty()
function, and is overridden by any concrete task that uses this prototype.
Here is a example of a concrete task implementation. Note: the using of the Task prototype by first:
- referencing the prototype
Task = require('./Task').Task;
- and then using it:
T1.prototype = new Task;
.
var _l = {},
myTask,
Task = require('./Task').Task;
_l.sys = require('sys');
myTask = exports.myTask = function() {
/* Properties */
this.name = 'myTask';
};
/**
* Using Task prototype
*/
myTask.prototype = new Task;
/**
* The duty of this task. Overridden from prototype
*/
myTask.prototype.duty = function(framework,callback) {
// duty of this tasks.
// execute callback, to pass on to the next task, when done.
callback(framework);
};
##The managed tasks
After implementing the concrete task, the task manager needs to know about this task. To tell the manager about the task, a entry in managed_tasks has to be made. The managed tasks are look up table of the manager to get a object instance of a tasks. The file: managed_tasks.js
is located in the tasks folder: espresso/tasks
. The necessary values are the: tasks name
, under which the task should be know to the manager and the person who specifies the task chain. In fact when defining a task chain the names for the tasks are the ones that are specified in the manage tasks.
The second values is the include of the task itself -> here the task.
var ManagedTasks
ManagedTasks = exports.ManagedTasks = {};
ManagedTasks.Tasks = new Array();
/*
* The Tasks
*/
ManagedTasks.Tasks['dependency'] = require('./dependencyTask').Task_Dependency;
ManagedTasks.Tasks['jslint'] = require('./jslintTask').Task_JSLINT;
ManagedTasks.Tasks['myTask'] = require('./myTask.js').myTask;
ManagedTasks.Tasks['T1'] = require('./t1.js').T1;
ManagedTasks.Tasks['T2'] = require('./t2.js').T2;