-
Notifications
You must be signed in to change notification settings - Fork 0
/
kuji.js
159 lines (127 loc) · 4.12 KB
/
kuji.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*#######.
kuji.js ########",#:
#########',##".
by KUBE : www.kube.io ##'##'##".##',##.
Created : Jul 23, 2014 6:55PM ## ## ## # ##",#.
Modified : Sep 28, 2014 2:17AM ## ## ## ## ##'
## ## ## :##
## ## ##*/
var Task = function (graph, task) {
var self = this;
var _dependencies = [],
_promises = [],
_started = false;
this.finished = false;
this.isReadyToGo = function () {
for (var i in _dependencies)
if (!_dependencies[i].finished)
return false;
return true;
};
this.addDependency = function (dependency) {
_dependencies.push(dependency);
dependency.addPromise(self);
};
this.addPromise = function (promise) {
_promises.push(promise);
};
// Create Next callback
var next = function () {
// Define task as finished
self.finished = true;
// Run all its promises, if some
if (_promises.length > 0)
for (var i in _promises)
_promises[i].start();
// If no promise, maybe graph has finished its tasks
else
graph.tryFinish();
};
this.start = function () {
if (!_started && self.isReadyToGo()) {
_started = true;
// Run task and pass it the callback
task(next);
}
};
};
var Graph = function (finalCallback) {
var _nodes = [],
_root = [],
_finalCallback;
this.addTask = function (name, task) {
var node = new Task(this, task);
// If task has no dependency add it to the graph root
if (!task.dependencies || task.dependencies.length === 0)
_root.push(node);
// Else add each of its dependencies to the node
else
for (var i in task.dependencies)
node.addDependency(_nodes[task.dependencies[i]]);
_nodes[name] = node;
};
this.start = function () {
// Start all tasks at root
for (var i in _root)
_root[i].start();
};
this.setFinalCallback = function (finalCallback) {
_finalCallback = finalCallback;
};
this.tryFinish = function () {
// Ensure there is a final callback
if (!_finalCallback)
return;
// Check if all nodes have been executed
for (var i in _nodes)
if (!_nodes[i].finished)
return;
_finalCallback();
};
};
var kuji = {
// Helper for adding dependencies to task
_dependsOn: function (dependencies, task) {
task.dependencies = [];
for (var key in dependencies)
task.dependencies.push(dependencies[key]);
return task;
},
// Creates a graph from tasks array and run it
graph: function (tasks, finalCallback) {
var _graph = new Graph();
// Add all tasks to graph
for (var i in tasks)
_graph.addTask(i, tasks[i]);
if (finalCallback)
_graph.setFinalCallback(finalCallback);
_graph.start();
},
parallel: function (tasks, finalCallback) {
var _graph = new Graph();
// Add all tasks to graph
for (var i in tasks) {
delete tasks[i].dependencies;
_graph.addTask(i, tasks[i]);
}
if (finalCallback)
_graph.setFinalCallback(finalCallback);
_graph.start();
},
inline: function (tasks) {
var _graph = new Graph();
// Add all tasks to graph
var previous = null;
for (var i in tasks) {
// Set task dependency to previous task
delete tasks[i].dependencies;
if (previous)
tasks[i].dependencies = [previous];
_graph.addTask(i, tasks[i]);
previous = i;
}
_graph.start();
}
};
module.exports = kuji;