gate-executor 3.0.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/gate-executor.d.ts +2 -0
- package/gate-executor.js +274 -344
- package/gate-executor.js.map +1 -0
- package/gate-executor.min.js +1 -0
- package/gate-executor.ts +374 -0
- package/package.json +26 -22
- package/dist/gate-executor.min.js +0 -1
package/gate-executor.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// Core modules.
|
|
6
|
-
var Assert = require('assert')
|
|
7
|
-
Assert = 'function' === typeof Assert ? Assert : function () {}
|
|
8
|
-
/* $lab:coverage:on$ */
|
|
9
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (c) 2014-2021 Richard Rodger, MIT License */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
4
|
// Create root instance. Exported as module.
|
|
11
5
|
// * `options` (object): instance options as key-value pairs.
|
|
12
6
|
//
|
|
@@ -14,351 +8,287 @@ Assert = 'function' === typeof Assert ? Assert : function () {}
|
|
|
14
8
|
// * `interval` (integer): millisecond interval for timeout checks. Default: 111.
|
|
15
9
|
// * `timeout` (integer): common millisecond timeout.
|
|
16
10
|
// Can be overridden by work item options. Default: 2222.
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Assert('object' === typeof options)
|
|
23
|
-
Assert('number' === typeof options.interval)
|
|
24
|
-
Assert('number' === typeof options.timeout)
|
|
25
|
-
Assert(0 < options.interval)
|
|
26
|
-
Assert(0 < options.timeout)
|
|
27
|
-
|
|
28
|
-
return new GateExecutor(options, 0)
|
|
11
|
+
function MakeGateExecutor(options) {
|
|
12
|
+
options = options || {};
|
|
13
|
+
options.interval = null == options.interval ? 111 : options.interval;
|
|
14
|
+
options.timeout = null == options.timeout ? 2222 : options.timeout;
|
|
15
|
+
return GateExecutor(options, 0);
|
|
29
16
|
}
|
|
30
|
-
|
|
31
17
|
// Create a new instance.
|
|
32
18
|
// * `options` (object): instance options as key-value pairs.
|
|
33
19
|
// * `instance_counter` (integer): count number of instances created;
|
|
34
20
|
// used as identifier.
|
|
35
21
|
function GateExecutor(options, instance_counter) {
|
|
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
|
-
firstclear: null,
|
|
82
|
-
|
|
83
|
-
// Timeout interval reference value returned by `setInterval`.
|
|
84
|
-
// Timeouts are not checked using `setTimeout`, as it is more
|
|
85
|
-
// efficient, and more than sufficient, to check timeouts periodically.
|
|
86
|
-
tm_in: null,
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Process the next work item.
|
|
90
|
-
function processor() {
|
|
91
|
-
// If not running, don't process any work items.
|
|
92
|
-
if (!s.running) {
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// The timeout interval check is stopped and started only as needed.
|
|
97
|
-
if (!self.isclear() && !s.tm_in) {
|
|
98
|
-
s.tm_in = setInterval(timeout_check, options.interval)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Process the next work item, returning `true` if there was one.
|
|
102
|
-
do {
|
|
103
|
-
var next = false
|
|
104
|
-
var work = null
|
|
105
|
-
|
|
106
|
-
// Remove next work item from the front of the work queue.
|
|
107
|
-
if (!s.gate) {
|
|
108
|
-
work = q.shift()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (work) {
|
|
112
|
-
Assert('object' === typeof work)
|
|
113
|
-
Assert('string' === typeof work.id)
|
|
114
|
-
Assert('function' === typeof work.fn)
|
|
115
|
-
|
|
116
|
-
// Add work item to the work-in-progress set.
|
|
117
|
-
progress.lookup[work.id] = work
|
|
118
|
-
progress.history.push(work)
|
|
119
|
-
|
|
120
|
-
// If work item is a gate, set the state of the instance as
|
|
121
|
-
// gated. This work item will need to complete before later
|
|
122
|
-
// work items in the queue can be processed.
|
|
123
|
-
s.gate = work.gate
|
|
124
|
-
|
|
125
|
-
// Call the work item function (which does the real work),
|
|
126
|
-
// passing a callback. This callback has no arguments
|
|
127
|
-
// (including no error!). It is called only to indicate
|
|
128
|
-
// completion of the work item. Work items must handle their
|
|
129
|
-
// own errors and results.
|
|
130
|
-
work.start = Date.now()
|
|
131
|
-
work.callback = make_work_fn_callback(work)
|
|
132
|
-
|
|
133
|
-
timeout_checklist.push(work)
|
|
134
|
-
work.fn(work.callback)
|
|
135
|
-
|
|
136
|
-
next = true
|
|
137
|
-
}
|
|
138
|
-
} while (next)
|
|
139
|
-
// Keep processing work items until none are left or a gate is reached.
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Create the callback for the work function
|
|
143
|
-
function make_work_fn_callback(work) {
|
|
144
|
-
return function work_fn_callback() {
|
|
145
|
-
if (work.done) {
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Remove the work item from the work-in-progress set. As
|
|
150
|
-
// work items may complete out of order, prune the history
|
|
151
|
-
// from the front until the first incomplete work
|
|
152
|
-
// item. Later complete work items will eventually be
|
|
153
|
-
// reached on another processing round.
|
|
154
|
-
work.done = true
|
|
155
|
-
delete progress.lookup[work.id]
|
|
156
|
-
|
|
157
|
-
while (progress.history[0] && progress.history[0].done) {
|
|
158
|
-
progress.history.shift()
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
while (timeout_checklist[0] && timeout_checklist[0].done) {
|
|
162
|
-
timeout_checklist.shift()
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// If the work item was a gate, it is now complete, and the
|
|
166
|
-
// instance can be ungated, allowing later work items in the
|
|
167
|
-
// queue to be processed.
|
|
168
|
-
if (work.gate) {
|
|
169
|
-
s.gate = false
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// If work queue and work-in-progress set are empty, then
|
|
173
|
-
// call the registered clear functions.
|
|
174
|
-
if (0 === q.length && 0 === progress.history.length) {
|
|
175
|
-
clearInterval(s.tm_in)
|
|
176
|
-
s.tm_in = null
|
|
177
|
-
|
|
178
|
-
if (s.firstclear) {
|
|
179
|
-
var fc = s.firstclear
|
|
180
|
-
s.firstclear = null
|
|
181
|
-
fc()
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (s.clear) {
|
|
185
|
-
s.clear()
|
|
22
|
+
let self = {};
|
|
23
|
+
self.id = ++instance_counter;
|
|
24
|
+
self.options = options;
|
|
25
|
+
// Work queue.
|
|
26
|
+
let q = [];
|
|
27
|
+
// Work-in-progress set.
|
|
28
|
+
let progress = {
|
|
29
|
+
// Lookup work by id.
|
|
30
|
+
lookup: {},
|
|
31
|
+
// Work history - a list of work items in the order executed.
|
|
32
|
+
history: [],
|
|
33
|
+
};
|
|
34
|
+
// List of work items to check for timeouts.
|
|
35
|
+
let timeout_checklist = [];
|
|
36
|
+
// Internal state.
|
|
37
|
+
let s = {
|
|
38
|
+
// Count of work items added to this instance. Used as generated work identifier.
|
|
39
|
+
work_counter: 0,
|
|
40
|
+
// When `true`, the instance is in a gated state, and work cannot proceed
|
|
41
|
+
// until the gated in-progress work item is completed.
|
|
42
|
+
gate: false,
|
|
43
|
+
// When `true`, the instance processes work items as they arrive.
|
|
44
|
+
// When `false`, no processing happens, and the instance must be started by
|
|
45
|
+
// calling the `start` method.
|
|
46
|
+
running: false,
|
|
47
|
+
// A function called when the work queue and work-in-progress set
|
|
48
|
+
// are empty. Set by calling the `clear` method. Will be called
|
|
49
|
+
// each time the instance empty.
|
|
50
|
+
clear: null,
|
|
51
|
+
// A function called once only when the work queue and
|
|
52
|
+
// work-in-progress set are first emptied after each start. Set as
|
|
53
|
+
// an optional argument to the `start` method.
|
|
54
|
+
firstclear: null,
|
|
55
|
+
// Timeout interval reference value returned by `setInterval`.
|
|
56
|
+
// Timeouts are not checked using `setTimeout`, as it is more
|
|
57
|
+
// efficient, and more than sufficient, to check timeouts periodically.
|
|
58
|
+
tm_in: null,
|
|
59
|
+
hw_tmc: 0,
|
|
60
|
+
hw_hst: 0,
|
|
61
|
+
};
|
|
62
|
+
// Process the next work item.
|
|
63
|
+
function processor() {
|
|
64
|
+
// If not running, don't process any work items.
|
|
65
|
+
if (!s.running) {
|
|
66
|
+
return;
|
|
186
67
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
setImmediate(processor)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// To be run periodically via setInterval. For timed out work items,
|
|
195
|
-
// calls the done callback to allow work queue to proceed, and marks
|
|
196
|
-
// the work item as finished. Work items can receive notification of
|
|
197
|
-
// timeouts by providing an `ontm` callback property in the
|
|
198
|
-
// work definition object. Work items must handle timeout errors
|
|
199
|
-
// themselves, gate-executor cares only for the fact that a timeout
|
|
200
|
-
// happened, so it can continue processing.
|
|
201
|
-
function timeout_check() {
|
|
202
|
-
var now = Date.now()
|
|
203
|
-
var work = null
|
|
204
|
-
|
|
205
|
-
for (var i = 0; i < timeout_checklist.length; ++i) {
|
|
206
|
-
work = timeout_checklist[i]
|
|
207
|
-
|
|
208
|
-
if (!work.gate && !work.done && work.tm < now - work.start) {
|
|
209
|
-
if (work.ontm) {
|
|
210
|
-
work.ontm(work.tm, work.start, now)
|
|
68
|
+
// The timeout interval check is stopped and started only as needed.
|
|
69
|
+
if (!self.isclear() && !s.tm_in) {
|
|
70
|
+
s.tm_in = setInterval(timeout_check, options.interval);
|
|
211
71
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// Submit a function that will be called each time there are no more
|
|
248
|
-
// work items to process. Multiple calls to this method will replace
|
|
249
|
-
// the previously registered clear function.
|
|
250
|
-
self.clear = function (done) {
|
|
251
|
-
Assert('function' === typeof done)
|
|
252
|
-
s.clear = done
|
|
253
|
-
return self
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Returns `true` when there are no more work items to process.
|
|
257
|
-
self.isclear = function () {
|
|
258
|
-
return 0 === q.length && 0 === progress.history.length
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Add a work item. This is an object with fields:
|
|
262
|
-
// * `fn` (function): the function that performs the work. Takes a
|
|
263
|
-
// single argument, the callback function to call when the work is
|
|
264
|
-
// complete. THis callback does **not** accept errors or
|
|
265
|
-
// results. It's only purpose is to indicate that the work is
|
|
266
|
-
// complete (whether failed or not). The work function itself must
|
|
267
|
-
// handle callbacks to the application. Required.
|
|
268
|
-
// * `id` (string): identifier for the work item. Optional.
|
|
269
|
-
// * `tm` (integer): millisecond timeout specific to this work item,
|
|
270
|
-
// overrides general timeout. Optional.
|
|
271
|
-
// * `ontm` (function): callback to indicate work item timeout. Optional.
|
|
272
|
-
// * `dn` (string): description of the work item, used in the
|
|
273
|
-
// state description. Optional.
|
|
274
|
-
self.add = function (work) {
|
|
275
|
-
Assert('object' === typeof work)
|
|
276
|
-
Assert('function' === typeof work.fn)
|
|
277
|
-
Assert(null == work.id || 'string' === typeof work.id)
|
|
278
|
-
Assert(null == work.tm || 'number' === typeof work.tm)
|
|
279
|
-
Assert(null == work.dn || 'string' === typeof work.dn)
|
|
280
|
-
|
|
281
|
-
s.work_counter += 1
|
|
282
|
-
work.id = work.id || '' + s.work_counter
|
|
283
|
-
work.ge = self.id
|
|
284
|
-
work.tm = null == work.tm ? options.timeout : work.tm
|
|
285
|
-
|
|
286
|
-
work.dn = work.dn || work.fn.name || '' + Date.now()
|
|
287
|
-
|
|
288
|
-
// Used by calling code to store additional context.
|
|
289
|
-
work.ctxt = {}
|
|
290
|
-
|
|
291
|
-
q.push(work)
|
|
292
|
-
|
|
293
|
-
if (s.running) {
|
|
294
|
-
// Work items are **not** processed in the current execution path!
|
|
295
|
-
// This prevents lockup, and avoids false positives in unit tests.
|
|
296
|
-
// Work items are assumed to be inherently asynchronous.
|
|
297
|
-
setImmediate(processor)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return self
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Create a new gate. Returns a new `GateExecutor` instance. All
|
|
304
|
-
// work items added to the new instance must complete before the
|
|
305
|
-
// gate is cleared, and work items in the queue can be processed. A
|
|
306
|
-
// gate is cleared when the new instance is **first** cleared. Work
|
|
307
|
-
// items subsequently added to the new instance are not considered
|
|
308
|
-
// part of the gate. Gates can extend to any depth and form a tree
|
|
309
|
-
// structure that requires breadth-first traversal in terms of the
|
|
310
|
-
// work item queue. Gates do not have timeouts, and can only be
|
|
311
|
-
// cleared when all added work items complete.
|
|
312
|
-
self.gate = function () {
|
|
313
|
-
var ge = new GateExecutor(options, instance_counter)
|
|
314
|
-
|
|
315
|
-
var fn = function gate(done) {
|
|
316
|
-
// This is the work function of the gate, which starts the new
|
|
317
|
-
// instance, and considers the gate work item complete when the
|
|
318
|
-
// work queue clears for the first time.
|
|
319
|
-
ge.start(done)
|
|
72
|
+
// Process the next work item, returning `true` if there was one.
|
|
73
|
+
let next = false;
|
|
74
|
+
do {
|
|
75
|
+
next = false;
|
|
76
|
+
let work = null;
|
|
77
|
+
// Remove next work item from the front of the work queue.
|
|
78
|
+
if (!s.gate) {
|
|
79
|
+
work = q.shift();
|
|
80
|
+
}
|
|
81
|
+
if (work) {
|
|
82
|
+
// Add work item to the work-in-progress set.
|
|
83
|
+
progress.lookup[work.id] = work;
|
|
84
|
+
progress.history.push(work);
|
|
85
|
+
s.hw_hst =
|
|
86
|
+
progress.history.length > s.hw_hst ? progress.history.length : s.hw_hst;
|
|
87
|
+
// If work item is a gate, set the state of the instance as
|
|
88
|
+
// gated. This work item will need to complete before later
|
|
89
|
+
// work items in the queue can be processed.
|
|
90
|
+
s.gate = work.gate;
|
|
91
|
+
// Call the work item function (which does the real work),
|
|
92
|
+
// passing a callback. This callback has no arguments
|
|
93
|
+
// (including no error!). It is called only to indicate
|
|
94
|
+
// completion of the work item. Work items must handle their
|
|
95
|
+
// own errors and results.
|
|
96
|
+
work.start = Date.now();
|
|
97
|
+
work.callback = make_work_fn_callback(work);
|
|
98
|
+
timeout_checklist.push(work);
|
|
99
|
+
s.hw_tmc =
|
|
100
|
+
timeout_checklist.length > s.hw_tmc ? timeout_checklist.length : s.hw_tmc;
|
|
101
|
+
work.fn(work.callback);
|
|
102
|
+
next = true;
|
|
103
|
+
}
|
|
104
|
+
} while (next);
|
|
105
|
+
// Keep processing work items until none are left or a gate is reached.
|
|
320
106
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
107
|
+
// Create the callback for the work function
|
|
108
|
+
function make_work_fn_callback(work) {
|
|
109
|
+
return function work_fn_callback() {
|
|
110
|
+
if (work.done) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
work.end = Date.now();
|
|
114
|
+
// Remove the work item from the work-in-progress set. As
|
|
115
|
+
// work items may complete out of order, prune the history
|
|
116
|
+
// from the front until the first incomplete work
|
|
117
|
+
// item. Later complete work items will eventually be
|
|
118
|
+
// reached on another processing round.
|
|
119
|
+
work.done = true;
|
|
120
|
+
delete progress.lookup[work.id];
|
|
121
|
+
while (progress.history[0] && progress.history[0].done) {
|
|
122
|
+
progress.history.shift();
|
|
123
|
+
}
|
|
124
|
+
while (timeout_checklist[0] && timeout_checklist[0].done) {
|
|
125
|
+
timeout_checklist.shift();
|
|
126
|
+
}
|
|
127
|
+
// If the work item was a gate, it is now complete, and the
|
|
128
|
+
// instance can be ungated, allowing later work items in the
|
|
129
|
+
// queue to be processed.
|
|
130
|
+
if (work.gate) {
|
|
131
|
+
s.gate = false;
|
|
132
|
+
}
|
|
133
|
+
// If work queue and work-in-progress set are empty, then
|
|
134
|
+
// call the registered clear functions.
|
|
135
|
+
if (0 === q.length && 0 === progress.history.length) {
|
|
136
|
+
clearInterval(s.tm_in);
|
|
137
|
+
s.tm_in = null;
|
|
138
|
+
if (s.firstclear) {
|
|
139
|
+
let fc = s.firstclear;
|
|
140
|
+
s.firstclear = null;
|
|
141
|
+
fc();
|
|
142
|
+
}
|
|
143
|
+
if (s.clear) {
|
|
144
|
+
s.clear();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Process each work item on next tick to avoid lockups.
|
|
148
|
+
setImmediate(processor);
|
|
149
|
+
};
|
|
339
150
|
}
|
|
340
|
-
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
151
|
+
// To be run periodically via setInterval. For timed out work items,
|
|
152
|
+
// calls the done callback to allow work queue to proceed, and marks
|
|
153
|
+
// the work item as finished. Work items can receive notification of
|
|
154
|
+
// timeouts by providing an `ontm` callback property in the
|
|
155
|
+
// work definition object. Work items must handle timeout errors
|
|
156
|
+
// themselves, gate-executor cares only for the fact that a timeout
|
|
157
|
+
// happened, so it can continue processing.
|
|
158
|
+
function timeout_check() {
|
|
159
|
+
let now = Date.now();
|
|
160
|
+
let work = null;
|
|
161
|
+
for (let i = 0; i < timeout_checklist.length; ++i) {
|
|
162
|
+
work = timeout_checklist[i];
|
|
163
|
+
if (!work.gate && !work.done && work.tm < now - work.start) {
|
|
164
|
+
if (work.ontm) {
|
|
165
|
+
work.ontm(work.tm, work.start, now);
|
|
166
|
+
}
|
|
167
|
+
work.callback();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
357
170
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
171
|
+
// Start processing work items. Must be called to start processing.
|
|
172
|
+
// Can be called at anytime, interspersed with calls to other
|
|
173
|
+
// methods, including `add`. Takes a function as argument, which is
|
|
174
|
+
// called only once on the next time the queues are clear.
|
|
175
|
+
self.start = function (firstclear) {
|
|
176
|
+
// Allow API chaining by not starting in current execution path.
|
|
177
|
+
setImmediate(function () {
|
|
178
|
+
s.running = true;
|
|
179
|
+
if (firstclear) {
|
|
180
|
+
s.firstclear = firstclear;
|
|
181
|
+
}
|
|
182
|
+
processor();
|
|
183
|
+
});
|
|
184
|
+
return self;
|
|
185
|
+
};
|
|
186
|
+
// Pause the processing of work items. Newly added items, and items
|
|
187
|
+
// not yet started, will not proceed, but items already in progress
|
|
188
|
+
// will complete, and the clear function will be called once all in
|
|
189
|
+
// progress items finish.
|
|
190
|
+
self.pause = function () {
|
|
191
|
+
s.running = false;
|
|
192
|
+
};
|
|
193
|
+
// Submit a function that will be called each time there are no more
|
|
194
|
+
// work items to process. Multiple calls to this method will replace
|
|
195
|
+
// the previously registered clear function.
|
|
196
|
+
self.clear = function (done) {
|
|
197
|
+
s.clear = done;
|
|
198
|
+
return self;
|
|
199
|
+
};
|
|
200
|
+
// Returns `true` when there are no more work items to process.
|
|
201
|
+
self.isclear = function () {
|
|
202
|
+
return 0 === q.length && 0 === progress.history.length;
|
|
203
|
+
};
|
|
204
|
+
// Add a work item. This is an object with fields:
|
|
205
|
+
// * `fn` (function): the function that performs the work. Takes a
|
|
206
|
+
// single argument, the callback function to call when the work is
|
|
207
|
+
// complete. THis callback does **not** accept errors or
|
|
208
|
+
// results. It's only purpose is to indicate that the work is
|
|
209
|
+
// complete (whether failed or not). The work function itself must
|
|
210
|
+
// handle callbacks to the application. Required.
|
|
211
|
+
// * `id` (string): identifier for the work item. Optional.
|
|
212
|
+
// * `tm` (integer): millisecond timeout specific to this work item,
|
|
213
|
+
// overrides general timeout. Optional.
|
|
214
|
+
// * `ontm` (function): callback to indicate work item timeout. Optional.
|
|
215
|
+
// * `dn` (string): description of the work item, used in the
|
|
216
|
+
// state description. Optional.
|
|
217
|
+
self.add = function (work) {
|
|
218
|
+
s.work_counter += 1;
|
|
219
|
+
work.id = work.id || '' + s.work_counter;
|
|
220
|
+
work.ge = self.id;
|
|
221
|
+
work.tm = null == work.tm ? options.timeout : work.tm;
|
|
222
|
+
work.dn = work.dn || work.fn.name || '' + Date.now();
|
|
223
|
+
// Used by calling code to store additional context.
|
|
224
|
+
work.ctxt = {};
|
|
225
|
+
q.push(work);
|
|
226
|
+
if (s.running) {
|
|
227
|
+
// Work items are **not** processed in the current execution path!
|
|
228
|
+
// This prevents lockup, and avoids false positives in unit tests.
|
|
229
|
+
// Work items are assumed to be inherently asynchronous.
|
|
230
|
+
setImmediate(processor);
|
|
231
|
+
}
|
|
232
|
+
return self;
|
|
233
|
+
};
|
|
234
|
+
// Create a new gate. Returns a new `GateExecutor` instance. All
|
|
235
|
+
// work items added to the new instance must complete before the
|
|
236
|
+
// gate is cleared, and work items in the queue can be processed. A
|
|
237
|
+
// gate is cleared when the new instance is **first** cleared. Work
|
|
238
|
+
// items subsequently added to the new instance are not considered
|
|
239
|
+
// part of the gate. Gates can extend to any depth and form a tree
|
|
240
|
+
// structure that requires breadth-first traversal in terms of the
|
|
241
|
+
// work item queue. Gates do not have timeouts, and can only be
|
|
242
|
+
// cleared when all added work items complete.
|
|
243
|
+
self.gate = function () {
|
|
244
|
+
let ge = GateExecutor(options, instance_counter);
|
|
245
|
+
let fn = function gate(done) {
|
|
246
|
+
// This is the work function of the gate, which starts the new
|
|
247
|
+
// instance, and considers the gate work item complete when the
|
|
248
|
+
// work queue clears for the first time.
|
|
249
|
+
ge.start(done);
|
|
250
|
+
};
|
|
251
|
+
self.add({ gate: ge, fn: fn });
|
|
252
|
+
return ge;
|
|
253
|
+
};
|
|
254
|
+
// Return a data structure describing the current state of the work
|
|
255
|
+
// queues, and organised as a tree structure indicating the gating
|
|
256
|
+
// relationships.
|
|
257
|
+
self.state = function () {
|
|
258
|
+
let out = [];
|
|
259
|
+
// First list any in-progress work items.
|
|
260
|
+
for (let hI = 0; hI < progress.history.length; ++hI) {
|
|
261
|
+
let pe = progress.history[hI];
|
|
262
|
+
if (!pe.done) {
|
|
263
|
+
out.push({ s: 'a', ge: pe.ge, dn: pe.dn, id: pe.id });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Then list any waiting work items.
|
|
267
|
+
for (let qI = 0; qI < q.length; ++qI) {
|
|
268
|
+
let qe = q[qI];
|
|
269
|
+
if (qe.gate) {
|
|
270
|
+
// Go down a level when there's a gate.
|
|
271
|
+
out.push(qe.gate.state());
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
out.push({ s: 'w', ge: qe.ge, dn: qe.dn, id: qe.id });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
out.internal = {
|
|
278
|
+
qlen: q.length,
|
|
279
|
+
hlen: progress.history.length,
|
|
280
|
+
klen: Object.keys(progress.lookup).length,
|
|
281
|
+
tlen: timeout_check.length,
|
|
282
|
+
hw_hst: s.hw_hst,
|
|
283
|
+
hw_tmc: s.hw_tmc,
|
|
284
|
+
};
|
|
285
|
+
return out;
|
|
286
|
+
};
|
|
287
|
+
return self;
|
|
361
288
|
}
|
|
362
|
-
|
|
363
289
|
// The module function
|
|
364
|
-
|
|
290
|
+
exports.default = MakeGateExecutor;
|
|
291
|
+
if (undefined != typeof (module.exports)) {
|
|
292
|
+
module.exports = MakeGateExecutor;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=gate-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-executor.js","sourceRoot":"","sources":["gate-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).GateExecutor=t()}}((function(){var t,e,n,r,i=(t=function(t,e){(function(t,n){(function(){var r=o.nextTick,i=(Function.prototype.apply,Array.prototype.slice),l={},u=0;function c(t,e){this._id=t,this._clearFn=e}c.prototype.unref=c.prototype.ref=function(){},c.prototype.close=function(){this._clearFn.call(window,this._id)},e.setImmediate="function"==typeof t?t:function(t){var n=u++,o=!(arguments.length<2)&&i.call(arguments,1);return l[n]=!0,r((function(){l[n]&&(o?t.apply(null,o):t.call(null),e.clearImmediate(n))})),n},e.clearImmediate="function"==typeof n?n:function(t){delete l[t]}}).call(this)}).call(this,i({}).setImmediate,i({}).clearImmediate)},function(n){return e||t(e={exports:{},parent:n},e.exports),e.exports}),o={},l=o={};function u(){throw new Error("setTimeout has not been defined")}function c(){throw new Error("clearTimeout has not been defined")}function a(t){if(n===setTimeout)return setTimeout(t,0);if((n===u||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:u}catch(e){n=u}try{r="function"==typeof clearTimeout?clearTimeout:c}catch(e){r=c}}();var s,f=[],h=!1,d=-1;function p(){h&&s&&(h=!1,s.length?f=s.concat(f):d=-1,f.length&&m())}function m(){if(!h){var t=a(p);h=!0;for(var n=f.length;n;){for(s=f,f=[];++d<n;)s&&s[d].run();d=-1,n=f.length}s=null,h=!1,function(t){if(r===clearTimeout)return clearTimeout(t);if((r===c||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(t);try{r(t)}catch(e){try{return r.call(null,t)}catch(e){return r.call(this,t)}}}(t)}}function g(t,e){this.fun=t,this.array=e}function y(){}l.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];f.push(new g(t,e)),1!==f.length||h||a(m)},g.prototype.run=function(){this.fun.apply(null,this.array)},l.title="browser",l.browser=!0,l.env={},l.argv=[],l.version="",l.versions={},l.on=y,l.addListener=y,l.once=y,l.off=y,l.removeListener=y,l.removeAllListeners=y,l.emit=y,l.prependListener=y,l.prependOnceListener=y,l.listeners=function(t){return[]},l.binding=function(t){throw new Error("process.binding is not supported")},l.cwd=function(){return"/"},l.chdir=function(t){throw new Error("process.chdir is not supported")},l.umask=function(){return 0};var w={};return function(t){(function(){"use strict";function e(e){return(e=e||{}).interval=null==e.interval?111:e.interval,e.timeout=null==e.timeout?2222:e.timeout,function e(n,r){let i={};i.id=++r,i.options=n;let o=[],l={lookup:{},history:[]},u=[],c={work_counter:0,gate:!1,running:!1,clear:null,firstclear:null,tm_in:null,hw_tmc:0,hw_hst:0};function a(){if(!c.running)return;i.isclear()||c.tm_in||(c.tm_in=setInterval(f,n.interval));let t=!1;do{t=!1;let e=null;c.gate||(e=o.shift()),e&&(l.lookup[e.id]=e,l.history.push(e),c.hw_hst=l.history.length>c.hw_hst?l.history.length:c.hw_hst,c.gate=e.gate,e.start=Date.now(),e.callback=s(e),u.push(e),c.hw_tmc=u.length>c.hw_tmc?u.length:c.hw_tmc,e.fn(e.callback),t=!0)}while(t)}function s(e){return function(){if(!e.done){for(e.end=Date.now(),e.done=!0,delete l.lookup[e.id];l.history[0]&&l.history[0].done;)l.history.shift();for(;u[0]&&u[0].done;)u.shift();if(e.gate&&(c.gate=!1),0===o.length&&0===l.history.length){if(clearInterval(c.tm_in),c.tm_in=null,c.firstclear){let t=c.firstclear;c.firstclear=null,t()}c.clear&&c.clear()}t(a)}}}function f(){let t=Date.now(),e=null;for(let n=0;n<u.length;++n)e=u[n],!e.gate&&!e.done&&e.tm<t-e.start&&(e.ontm&&e.ontm(e.tm,e.start,t),e.callback())}return i.start=function(e){return t((function(){c.running=!0,e&&(c.firstclear=e),a()})),i},i.pause=function(){c.running=!1},i.clear=function(t){return c.clear=t,i},i.isclear=function(){return 0===o.length&&0===l.history.length},i.add=function(e){return c.work_counter+=1,e.id=e.id||""+c.work_counter,e.ge=i.id,e.tm=null==e.tm?n.timeout:e.tm,e.dn=e.dn||e.fn.name||""+Date.now(),e.ctxt={},o.push(e),c.running&&t(a),i},i.gate=function(){let t=e(n,r);return i.add({gate:t,fn:function(e){t.start(e)}}),t},i.state=function(){let t=[];for(let e=0;e<l.history.length;++e){let n=l.history[e];n.done||t.push({s:"a",ge:n.ge,dn:n.dn,id:n.id})}for(let e=0;e<o.length;++e){let n=o[e];n.gate?t.push(n.gate.state()):t.push({s:"w",ge:n.ge,dn:n.dn,id:n.id})}return t.internal={qlen:o.length,hlen:l.history.length,klen:Object.keys(l.lookup).length,tlen:f.length,hw_hst:c.hw_hst,hw_tmc:c.hw_tmc},t},i}(e,0)}Object.defineProperty(w,"__esModule",{value:!0}),w.default=e,null!=typeof w&&(w=e)}).call(this)}.call(this,i({}).setImmediate),w}));
|
package/gate-executor.ts
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
/* Copyright (c) 2014-2021 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
type Work = {
|
|
5
|
+
id: string // Identifier
|
|
6
|
+
ge: string // GateExecutor identifier
|
|
7
|
+
tm: number // Timeout
|
|
8
|
+
dn: string // Description
|
|
9
|
+
fn: (callback: () => void) => void
|
|
10
|
+
start: number
|
|
11
|
+
end: number
|
|
12
|
+
gate?: any
|
|
13
|
+
callback: () => void
|
|
14
|
+
ctxt: { [key: string]: any }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// Create root instance. Exported as module.
|
|
20
|
+
// * `options` (object): instance options as key-value pairs.
|
|
21
|
+
//
|
|
22
|
+
// The options are:
|
|
23
|
+
// * `interval` (integer): millisecond interval for timeout checks. Default: 111.
|
|
24
|
+
// * `timeout` (integer): common millisecond timeout.
|
|
25
|
+
// Can be overridden by work item options. Default: 2222.
|
|
26
|
+
function MakeGateExecutor(options?: any) {
|
|
27
|
+
options = options || {}
|
|
28
|
+
options.interval = null == options.interval ? 111 : options.interval
|
|
29
|
+
options.timeout = null == options.timeout ? 2222 : options.timeout
|
|
30
|
+
|
|
31
|
+
return GateExecutor(options, 0)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Create a new instance.
|
|
35
|
+
// * `options` (object): instance options as key-value pairs.
|
|
36
|
+
// * `instance_counter` (integer): count number of instances created;
|
|
37
|
+
// used as identifier.
|
|
38
|
+
function GateExecutor(this: any, options: any, instance_counter: number) {
|
|
39
|
+
let self: any = {}
|
|
40
|
+
|
|
41
|
+
self.id = ++instance_counter
|
|
42
|
+
self.options = options
|
|
43
|
+
|
|
44
|
+
// Work queue.
|
|
45
|
+
let q: Work[] = []
|
|
46
|
+
|
|
47
|
+
// Work-in-progress set.
|
|
48
|
+
let progress: any = {
|
|
49
|
+
// Lookup work by id.
|
|
50
|
+
lookup: {},
|
|
51
|
+
|
|
52
|
+
// Work history - a list of work items in the order executed.
|
|
53
|
+
history: [],
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// List of work items to check for timeouts.
|
|
57
|
+
let timeout_checklist: any[] = []
|
|
58
|
+
|
|
59
|
+
// Internal state.
|
|
60
|
+
let s: any = {
|
|
61
|
+
// Count of work items added to this instance. Used as generated work identifier.
|
|
62
|
+
work_counter: 0,
|
|
63
|
+
|
|
64
|
+
// When `true`, the instance is in a gated state, and work cannot proceed
|
|
65
|
+
// until the gated in-progress work item is completed.
|
|
66
|
+
gate: false,
|
|
67
|
+
|
|
68
|
+
// When `true`, the instance processes work items as they arrive.
|
|
69
|
+
// When `false`, no processing happens, and the instance must be started by
|
|
70
|
+
// calling the `start` method.
|
|
71
|
+
running: false,
|
|
72
|
+
|
|
73
|
+
// A function called when the work queue and work-in-progress set
|
|
74
|
+
// are empty. Set by calling the `clear` method. Will be called
|
|
75
|
+
// each time the instance empty.
|
|
76
|
+
clear: null,
|
|
77
|
+
|
|
78
|
+
// A function called once only when the work queue and
|
|
79
|
+
// work-in-progress set are first emptied after each start. Set as
|
|
80
|
+
// an optional argument to the `start` method.
|
|
81
|
+
firstclear: null,
|
|
82
|
+
|
|
83
|
+
// Timeout interval reference value returned by `setInterval`.
|
|
84
|
+
// Timeouts are not checked using `setTimeout`, as it is more
|
|
85
|
+
// efficient, and more than sufficient, to check timeouts periodically.
|
|
86
|
+
tm_in: null,
|
|
87
|
+
|
|
88
|
+
hw_tmc: 0,
|
|
89
|
+
hw_hst: 0,
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
// Process the next work item.
|
|
96
|
+
function processor() {
|
|
97
|
+
// If not running, don't process any work items.
|
|
98
|
+
if (!s.running) {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The timeout interval check is stopped and started only as needed.
|
|
103
|
+
if (!self.isclear() && !s.tm_in) {
|
|
104
|
+
s.tm_in = setInterval(timeout_check, options.interval)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Process the next work item, returning `true` if there was one.
|
|
108
|
+
let next = false
|
|
109
|
+
do {
|
|
110
|
+
next = false
|
|
111
|
+
let work = null
|
|
112
|
+
|
|
113
|
+
// Remove next work item from the front of the work queue.
|
|
114
|
+
if (!s.gate) {
|
|
115
|
+
work = q.shift()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (work) {
|
|
119
|
+
// Add work item to the work-in-progress set.
|
|
120
|
+
progress.lookup[work.id] = work
|
|
121
|
+
progress.history.push(work)
|
|
122
|
+
|
|
123
|
+
s.hw_hst =
|
|
124
|
+
progress.history.length > s.hw_hst ? progress.history.length : s.hw_hst
|
|
125
|
+
|
|
126
|
+
// If work item is a gate, set the state of the instance as
|
|
127
|
+
// gated. This work item will need to complete before later
|
|
128
|
+
// work items in the queue can be processed.
|
|
129
|
+
s.gate = work.gate
|
|
130
|
+
|
|
131
|
+
// Call the work item function (which does the real work),
|
|
132
|
+
// passing a callback. This callback has no arguments
|
|
133
|
+
// (including no error!). It is called only to indicate
|
|
134
|
+
// completion of the work item. Work items must handle their
|
|
135
|
+
// own errors and results.
|
|
136
|
+
work.start = Date.now()
|
|
137
|
+
work.callback = make_work_fn_callback(work)
|
|
138
|
+
|
|
139
|
+
timeout_checklist.push(work)
|
|
140
|
+
s.hw_tmc =
|
|
141
|
+
timeout_checklist.length > s.hw_tmc ? timeout_checklist.length : s.hw_tmc
|
|
142
|
+
|
|
143
|
+
work.fn(work.callback)
|
|
144
|
+
|
|
145
|
+
next = true
|
|
146
|
+
}
|
|
147
|
+
} while (next)
|
|
148
|
+
// Keep processing work items until none are left or a gate is reached.
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Create the callback for the work function
|
|
152
|
+
function make_work_fn_callback(work: any) {
|
|
153
|
+
return function work_fn_callback() {
|
|
154
|
+
if (work.done) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
work.end = Date.now()
|
|
159
|
+
|
|
160
|
+
// Remove the work item from the work-in-progress set. As
|
|
161
|
+
// work items may complete out of order, prune the history
|
|
162
|
+
// from the front until the first incomplete work
|
|
163
|
+
// item. Later complete work items will eventually be
|
|
164
|
+
// reached on another processing round.
|
|
165
|
+
work.done = true
|
|
166
|
+
delete progress.lookup[work.id]
|
|
167
|
+
|
|
168
|
+
while (progress.history[0] && progress.history[0].done) {
|
|
169
|
+
progress.history.shift()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
while (timeout_checklist[0] && timeout_checklist[0].done) {
|
|
173
|
+
timeout_checklist.shift()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// If the work item was a gate, it is now complete, and the
|
|
177
|
+
// instance can be ungated, allowing later work items in the
|
|
178
|
+
// queue to be processed.
|
|
179
|
+
if (work.gate) {
|
|
180
|
+
s.gate = false
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// If work queue and work-in-progress set are empty, then
|
|
184
|
+
// call the registered clear functions.
|
|
185
|
+
if (0 === q.length && 0 === progress.history.length) {
|
|
186
|
+
clearInterval(s.tm_in)
|
|
187
|
+
s.tm_in = null
|
|
188
|
+
|
|
189
|
+
if (s.firstclear) {
|
|
190
|
+
let fc = s.firstclear
|
|
191
|
+
s.firstclear = null
|
|
192
|
+
fc()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (s.clear) {
|
|
196
|
+
s.clear()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Process each work item on next tick to avoid lockups.
|
|
201
|
+
setImmediate(processor)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// To be run periodically via setInterval. For timed out work items,
|
|
206
|
+
// calls the done callback to allow work queue to proceed, and marks
|
|
207
|
+
// the work item as finished. Work items can receive notification of
|
|
208
|
+
// timeouts by providing an `ontm` callback property in the
|
|
209
|
+
// work definition object. Work items must handle timeout errors
|
|
210
|
+
// themselves, gate-executor cares only for the fact that a timeout
|
|
211
|
+
// happened, so it can continue processing.
|
|
212
|
+
function timeout_check() {
|
|
213
|
+
let now = Date.now()
|
|
214
|
+
let work = null
|
|
215
|
+
|
|
216
|
+
for (let i = 0; i < timeout_checklist.length; ++i) {
|
|
217
|
+
work = timeout_checklist[i]
|
|
218
|
+
|
|
219
|
+
if (!work.gate && !work.done && work.tm < now - work.start) {
|
|
220
|
+
if (work.ontm) {
|
|
221
|
+
work.ontm(work.tm, work.start, now)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
work.callback()
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Start processing work items. Must be called to start processing.
|
|
230
|
+
// Can be called at anytime, interspersed with calls to other
|
|
231
|
+
// methods, including `add`. Takes a function as argument, which is
|
|
232
|
+
// called only once on the next time the queues are clear.
|
|
233
|
+
self.start = function(firstclear: any) {
|
|
234
|
+
// Allow API chaining by not starting in current execution path.
|
|
235
|
+
setImmediate(function() {
|
|
236
|
+
s.running = true
|
|
237
|
+
|
|
238
|
+
if (firstclear) {
|
|
239
|
+
s.firstclear = firstclear
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
processor()
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
return self
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Pause the processing of work items. Newly added items, and items
|
|
249
|
+
// not yet started, will not proceed, but items already in progress
|
|
250
|
+
// will complete, and the clear function will be called once all in
|
|
251
|
+
// progress items finish.
|
|
252
|
+
self.pause = function() {
|
|
253
|
+
s.running = false
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Submit a function that will be called each time there are no more
|
|
257
|
+
// work items to process. Multiple calls to this method will replace
|
|
258
|
+
// the previously registered clear function.
|
|
259
|
+
self.clear = function(done: any) {
|
|
260
|
+
s.clear = done
|
|
261
|
+
return self
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Returns `true` when there are no more work items to process.
|
|
265
|
+
self.isclear = function() {
|
|
266
|
+
return 0 === q.length && 0 === progress.history.length
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Add a work item. This is an object with fields:
|
|
270
|
+
// * `fn` (function): the function that performs the work. Takes a
|
|
271
|
+
// single argument, the callback function to call when the work is
|
|
272
|
+
// complete. THis callback does **not** accept errors or
|
|
273
|
+
// results. It's only purpose is to indicate that the work is
|
|
274
|
+
// complete (whether failed or not). The work function itself must
|
|
275
|
+
// handle callbacks to the application. Required.
|
|
276
|
+
// * `id` (string): identifier for the work item. Optional.
|
|
277
|
+
// * `tm` (integer): millisecond timeout specific to this work item,
|
|
278
|
+
// overrides general timeout. Optional.
|
|
279
|
+
// * `ontm` (function): callback to indicate work item timeout. Optional.
|
|
280
|
+
// * `dn` (string): description of the work item, used in the
|
|
281
|
+
// state description. Optional.
|
|
282
|
+
self.add = function(work: Work) {
|
|
283
|
+
s.work_counter += 1
|
|
284
|
+
work.id = work.id || '' + s.work_counter
|
|
285
|
+
work.ge = self.id
|
|
286
|
+
work.tm = null == work.tm ? options.timeout : work.tm
|
|
287
|
+
|
|
288
|
+
work.dn = work.dn || work.fn.name || '' + Date.now()
|
|
289
|
+
|
|
290
|
+
// Used by calling code to store additional context.
|
|
291
|
+
work.ctxt = {}
|
|
292
|
+
|
|
293
|
+
q.push(work)
|
|
294
|
+
|
|
295
|
+
if (s.running) {
|
|
296
|
+
// Work items are **not** processed in the current execution path!
|
|
297
|
+
// This prevents lockup, and avoids false positives in unit tests.
|
|
298
|
+
// Work items are assumed to be inherently asynchronous.
|
|
299
|
+
setImmediate(processor)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return self
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Create a new gate. Returns a new `GateExecutor` instance. All
|
|
306
|
+
// work items added to the new instance must complete before the
|
|
307
|
+
// gate is cleared, and work items in the queue can be processed. A
|
|
308
|
+
// gate is cleared when the new instance is **first** cleared. Work
|
|
309
|
+
// items subsequently added to the new instance are not considered
|
|
310
|
+
// part of the gate. Gates can extend to any depth and form a tree
|
|
311
|
+
// structure that requires breadth-first traversal in terms of the
|
|
312
|
+
// work item queue. Gates do not have timeouts, and can only be
|
|
313
|
+
// cleared when all added work items complete.
|
|
314
|
+
self.gate = function() {
|
|
315
|
+
let ge: any = GateExecutor(options, instance_counter)
|
|
316
|
+
|
|
317
|
+
let fn = function gate(done: any) {
|
|
318
|
+
// This is the work function of the gate, which starts the new
|
|
319
|
+
// instance, and considers the gate work item complete when the
|
|
320
|
+
// work queue clears for the first time.
|
|
321
|
+
ge.start(done)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
self.add({ gate: ge, fn: fn })
|
|
325
|
+
|
|
326
|
+
return ge
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Return a data structure describing the current state of the work
|
|
330
|
+
// queues, and organised as a tree structure indicating the gating
|
|
331
|
+
// relationships.
|
|
332
|
+
self.state = function() {
|
|
333
|
+
let out: any = []
|
|
334
|
+
|
|
335
|
+
// First list any in-progress work items.
|
|
336
|
+
for (let hI = 0; hI < progress.history.length; ++hI) {
|
|
337
|
+
let pe = progress.history[hI]
|
|
338
|
+
if (!pe.done) {
|
|
339
|
+
out.push({ s: 'a', ge: pe.ge, dn: pe.dn, id: pe.id })
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Then list any waiting work items.
|
|
344
|
+
for (let qI = 0; qI < q.length; ++qI) {
|
|
345
|
+
let qe = q[qI]
|
|
346
|
+
if (qe.gate) {
|
|
347
|
+
// Go down a level when there's a gate.
|
|
348
|
+
out.push(qe.gate.state())
|
|
349
|
+
} else {
|
|
350
|
+
out.push({ s: 'w', ge: qe.ge, dn: qe.dn, id: qe.id })
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
out.internal = {
|
|
355
|
+
qlen: q.length,
|
|
356
|
+
hlen: progress.history.length,
|
|
357
|
+
klen: Object.keys(progress.lookup).length,
|
|
358
|
+
tlen: timeout_check.length,
|
|
359
|
+
hw_hst: s.hw_hst,
|
|
360
|
+
hw_tmc: s.hw_tmc,
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return out
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return self
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// The module function
|
|
370
|
+
export default MakeGateExecutor
|
|
371
|
+
|
|
372
|
+
if (undefined != typeof (module.exports)) {
|
|
373
|
+
module.exports = MakeGateExecutor
|
|
374
|
+
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gate-executor",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "A work queue that can be gated, stopping to wait for sub-queues to complete.",
|
|
5
5
|
"main": "gate-executor.js",
|
|
6
|
-
"browser": "
|
|
6
|
+
"browser": "gate-executor.min.js",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"types": "gate-executor.d.ts",
|
|
7
9
|
"scripts": {
|
|
8
|
-
"test": "
|
|
9
|
-
"test-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"repo-
|
|
10
|
+
"test": "jest --coverage --no-cache",
|
|
11
|
+
"test-some": "jest --no-cache -t",
|
|
12
|
+
"test-watch": "jest --coverage --watchAll",
|
|
13
|
+
"watch": "tsc -w -d",
|
|
14
|
+
"build": "tsc -d && cp gate-executor.js gate-executor.min.js && browserify -o gate-executor.min.js -e gate-executor.js -s @GateExecutor -im -i assert -p tinyify",
|
|
15
|
+
"reset": "npm run clean && npm i && npm run build && npm test",
|
|
16
|
+
"clean": "rm -rf node_modules yarn.lock package-lock.json",
|
|
17
|
+
"repo-tag": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION && git push && git tag v$REPO_VERSION && git push --tags;",
|
|
18
|
+
"repo-publish": "npm run clean && npm i && npm run repo-publish-quick",
|
|
19
|
+
"repo-publish-quick": "npm run build && npm run test && npm run repo-tag && npm publish --access public --registry https://registry.npmjs.org "
|
|
16
20
|
},
|
|
17
21
|
"repository": {
|
|
18
22
|
"type": "git",
|
|
@@ -26,13 +30,12 @@
|
|
|
26
30
|
"files": [
|
|
27
31
|
"LICENSE",
|
|
28
32
|
"README.md",
|
|
29
|
-
"gate-executor
|
|
30
|
-
"dist"
|
|
33
|
+
"gate-executor.*"
|
|
31
34
|
],
|
|
32
35
|
"engines": {
|
|
33
|
-
"node": ">=
|
|
36
|
+
"node": ">=12.0.0"
|
|
34
37
|
},
|
|
35
|
-
"author": "Richard Rodger (
|
|
38
|
+
"author": "Richard Rodger (https://richardrodger.com)",
|
|
36
39
|
"contributors": [
|
|
37
40
|
"Jacob Pruitt (http://javascriptjake.com)",
|
|
38
41
|
"Wyatt Preul (http://jsgeek.com)"
|
|
@@ -44,13 +47,14 @@
|
|
|
44
47
|
"homepage": "https://github.com/senecajs/gate-executor",
|
|
45
48
|
"dependencies": {},
|
|
46
49
|
"devDependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
50
|
+
"@types/jest": "^30.0.0",
|
|
51
|
+
"browserify": "^17.0.1",
|
|
52
|
+
"esbuild": "^0.27.1",
|
|
53
|
+
"esbuild-jest": "^0.5.0",
|
|
54
|
+
"jest": "^30.2.0",
|
|
55
|
+
"tinyify": "^4.0.0",
|
|
56
|
+
"ts-jest": "^29.4.6",
|
|
57
|
+
"typescript": "^5.9.3",
|
|
58
|
+
"util.promisify": "^1.1.3"
|
|
55
59
|
}
|
|
56
60
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).GateExecutor=t()}}((function(){var t={exports:{}};return function(e){!function(n){"object"==typeof t.exports?t.exports=n():("undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:this).GateExecutor=n()}((function(){var t={exports:{}};return function(e){!function(n){"object"==typeof t.exports?t.exports=n():("undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:this).GateExecutor=n()}((function(){var t={exports:{}};return function(e){!function(n){"object"==typeof t.exports?t.exports=n():("undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:this).GateExecutor=n()}((function(){var t,e,n,o,i=(t=function(t,e){(function(t,n){var o=u.nextTick,i=(Function.prototype.apply,Array.prototype.slice),r={},f=0;function l(t,e){this._id=t,this._clearFn=e}l.prototype.unref=l.prototype.ref=function(){},l.prototype.close=function(){this._clearFn.call(window,this._id)},e.setImmediate="function"==typeof t?t:function(t){var n=f++,u=!(arguments.length<2)&&i.call(arguments,1);return r[n]=!0,o((function(){r[n]&&(u?t.apply(null,u):t.call(null),e.clearImmediate(n))})),n},e.clearImmediate="function"==typeof n?n:function(t){delete r[t]}}).call(this,i({}).setImmediate,i({}).clearImmediate)},function(n){return e||t(e={exports:{},parent:n},e.exports),e.exports}),r={},u={},f=u={};function l(){throw new Error("setTimeout has not been defined")}function c(){throw new Error("clearTimeout has not been defined")}function a(t){if(n===setTimeout)return setTimeout(t,0);if((n===l||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:l}catch(e){n=l}try{o="function"==typeof clearTimeout?clearTimeout:c}catch(e){o=c}}();var s,d=[],p=!1,h=-1;function y(){p&&s&&(p=!1,s.length?d=s.concat(d):h=-1,d.length&&m())}function m(){if(!p){var t=a(y);p=!0;for(var n=d.length;n;){for(s=d,d=[];++h<n;)s&&s[h].run();h=-1,n=d.length}s=null,p=!1,function(t){if(o===clearTimeout)return clearTimeout(t);if((o===c||!o)&&clearTimeout)return o=clearTimeout,clearTimeout(t);try{o(t)}catch(e){try{return o.call(null,t)}catch(e){return o.call(this,t)}}}(t)}}function w(t,e){this.fun=t,this.array=e}function g(){}f.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];d.push(new w(t,e)),1!==d.length||p||a(m)},w.prototype.run=function(){this.fun.apply(null,this.array)},f.title="browser",f.browser=!0,f.env={},f.argv=[],f.version="",f.versions={},f.on=g,f.addListener=g,f.once=g,f.off=g,f.removeListener=g,f.removeAllListeners=g,f.emit=g,f.prependListener=g,f.prependOnceListener=g,f.listeners=function(t){return[]},f.binding=function(t){throw new Error("process.binding is not supported")},f.cwd=function(){return"/"},f.chdir=function(t){throw new Error("process.chdir is not supported")},f.umask=function(){return 0};var v={};return function(t){"use strict";function e(n,o){var i=this;r("object"==typeof n),r("number"==typeof o),i.id=++o,i.options=n;var u=[],f={lookup:{},history:[]},l=[],c={work_counter:0,gate:!1,running:!1,clear:null,firstclear:null,tm_in:null};function a(){if(c.running){i.isclear()||c.tm_in||(c.tm_in=setInterval(d,n.interval));do{var t=!1,e=null;c.gate||(e=u.shift()),e&&(r("object"==typeof e),r("string"==typeof e.id),r("function"==typeof e.fn),f.lookup[e.id]=e,f.history.push(e),c.gate=e.gate,e.start=Date.now(),e.callback=s(e),l.push(e),e.fn(e.callback),t=!0)}while(t)}}function s(e){return function(){if(!e.done){for(e.done=!0,delete f.lookup[e.id];f.history[0]&&f.history[0].done;)f.history.shift();for(;l[0]&&l[0].done;)l.shift();if(e.gate&&(c.gate=!1),0===u.length&&0===f.history.length){if(clearInterval(c.tm_in),c.tm_in=null,c.firstclear){var n=c.firstclear;c.firstclear=null,n()}c.clear&&c.clear()}t(a)}}}function d(){for(var t=Date.now(),e=null,n=0;n<l.length;++n)!(e=l[n]).gate&&!e.done&&e.tm<t-e.start&&(e.ontm&&e.ontm(e.tm,e.start,t),e.callback())}i.start=function(e){return r(null==e||"function"==typeof e),t((function(){c.running=!0,e&&(c.firstclear=e),a()})),i},i.pause=function(){c.running=!1},i.clear=function(t){return r("function"==typeof t),c.clear=t,i},i.isclear=function(){return 0===u.length&&0===f.history.length},i.add=function(e){return r("object"==typeof e),r("function"==typeof e.fn),r(null==e.id||"string"==typeof e.id),r(null==e.tm||"number"==typeof e.tm),r(null==e.dn||"string"==typeof e.dn),c.work_counter+=1,e.id=e.id||""+c.work_counter,e.ge=i.id,e.tm=null==e.tm?n.timeout:e.tm,e.dn=e.dn||e.fn.name||""+Date.now(),e.ctxt={},u.push(e),c.running&&t(a),i},i.gate=function(){var t=new e(n,o);return i.add({gate:t,fn:function(e){t.start(e)}}),t},i.state=function(){for(var t=[],e=0;e<f.history.length;++e){var n=f.history[e];n.done||t.push({s:"a",ge:n.ge,dn:n.dn,id:n.id})}for(var o=0;o<u.length;++o){var i=u[o];i.gate?t.push(i.gate.state()):t.push({s:"w",ge:i.ge,dn:i.dn,id:i.id})}return t.internal={qlen:u.length,hlen:f.history.length,klen:Object.keys(f.lookup).length,tlen:d.length},t}}r="function"==typeof r?r:function(){},v=function(t){return(t=t||{}).interval=null==t.interval?111:t.interval,t.timeout=null==t.timeout?2222:t.timeout,r("object"==typeof t),r("number"==typeof t.interval),r("number"==typeof t.timeout),r(0<t.interval),r(0<t.timeout),new e(t,0)}}.call(this,i({}).setImmediate),v}))}.call(this,void 0!==e?e:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{}),t=t.exports}))}.call(this,void 0!==e?e:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{}),t=t.exports}))}.call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{}),t=t.exports}));
|