-
Notifications
You must be signed in to change notification settings - Fork 32
/
tasks.js
150 lines (134 loc) · 4.33 KB
/
tasks.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
/*
* raft.js: Raft consensus algorithm in JavaScript
* Copyright (C) 2013 Joel Martin
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for description and usage instructions.
*/
"use strict";
if (typeof module === 'undefined') {
var tasks = {},
exports = tasks;
}
// An Task/Event Queue system. The primary methods are scheduling
// a task (schedule, scheduleRand), cancelling a task (cancel), and
// executing the next task.
// The opts map take the following keys:
// - verbose: enable/disable verbose loggin
// - scheduleCallback: called when a task is scheduled. Passed the
// new task.
// - cancelCallback: called when a task is cancelled. Passed the
// cancelled task.
// - startCallback: called right before a task is executed. Passed
// the task that is about to run.
// - finishCallback: called right after a task is executed. Passed
// the task that just ran.
// Tasks are stored as an array of:
// {id: TASK_ID,
// action: ACTION_FUNCTION,
// time: MS_TIME,
// data: MAP_OF_DATA_ATTRIBUTES}
function Tasks(opts) {
var nextId = 1,
curTime = 0,
tasks = [],
api = {};
opts = opts || {};
// Find the chronological position in the tasks queue for this
// new task and insert it there. Returns the unique ID of this
// task (for use with cancel).
api.schedule = function(action, timeOffset, data) {
var idx = tasks.length,
tid = nextId++,
time = curTime + timeOffset,
task = {id: tid,
action: action,
time: time,
data: data};
// TODO: this should be binary search
for (; idx > 0; idx--) {
if (tasks[idx-1].time <= time) {
break;
}
}
tasks.splice(idx, 0, task);
if (opts.scheduleCallback) {
opts.scheduleCallback(task);
}
return tid;
};
// Like schedule but picks a random timeOffset between min and max
api.scheduleRand = function(action, min, max, data) {
var timeOffset = Math.floor(Math.random() * (max - min) + min);
return api.schedule(action, timeOffset, data);
};
// Remove the task with ID id from the tasks queue
api.cancel = function(id) {
var task = null;
if (opts.verbose) {
console.log("Cancelling task ID " + id);
}
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].id === id) {
task = tasks[i];
tasks.splice(i,1);
break;
}
}
if (opts.cancelCallback && task) {
opts.cancelCallback(task);
}
};
// Return the task at the front of the tasks queue without
// removing it
api.current = function() {
return tasks[0];
};
// Return the task queue
api.dump = function() {
return tasks;
};
// Return the task queue
api.show = function() {
console.log("Current time: " + curTime + "ms");
for (var i = 0; i < tasks.length; i++) {
var t = tasks[i],
type = t.data.type || t.action.name,
msg = t.time + "ms: " + t.id + " " + " [" + type + "]";
if (t.data.desc) { msg += " " + t.data.desc; }
console.log(msg);
}
};
// Return the current time
api.currentTime = function() {
return curTime;
};
//api.start(factor) {}
//api.stop() {}
// Advanced the time to the next task in the queue, remove it,
// and execute it's action. Returns the new "current" time.
api.step = function() {
if (tasks.length === 0) {
console.warn("Step called on empty tasks queue");
return null;
}
var task = tasks.shift(),
msg = "Executing task ID " + task.id;
if (opts.startCallback) {
opts.startCallback(task);
}
if (task.data.type) { msg += " [" + task.data.type + "]"; }
if (task.data.desc) { msg += " " + task.data.desc; }
if (opts.verbose) {
console.log(msg);
}
curTime = task.time;
task.action();
if (opts.finishCallback) {
opts.finishCallback(task);
}
return curTime;
};
return api;
}
exports.Tasks = Tasks;