@coherentglobal/wasm-runner 0.0.103 → 0.1.19
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/README.md +137 -222
- package/dist/CancellationToken.js.map +1 -1
- package/dist/browser/logger.js.map +1 -1
- package/dist/browser/template/main.template.js +1 -1
- package/dist/browser/template/main.template.js.map +1 -1
- package/dist/browser/template/runtime.template.js.map +1 -1
- package/dist/browser/template/worker.template.js +7 -4
- package/dist/browser/template/worker.template.js.map +1 -1
- package/dist/browser/template.js +1 -1
- package/dist/browser/template.js.map +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +6 -6
- package/dist/browser.js.map +1 -1
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/error.d.ts +5 -0
- package/dist/error.js +13 -3
- package/dist/error.js.map +1 -1
- package/dist/mockConstants.d.ts +5 -0
- package/dist/mockConstants.js +14 -0
- package/dist/mockConstants.js.map +1 -0
- package/dist/node/logger.d.ts +1 -4
- package/dist/node/logger.js +1 -1
- package/dist/node/logger.js.map +1 -1
- package/dist/node/logger.ts +1 -1
- package/dist/node/template/main.template.ejs +126 -86
- package/dist/node/threads/mockWorkerThread.d.ts +28 -0
- package/dist/node/threads/mockWorkerThread.js +89 -0
- package/dist/node/threads/mockWorkerThread.js.map +1 -0
- package/dist/node/threads/workerPool.d.ts +17 -0
- package/dist/node/threads/workerPool.js +27 -0
- package/dist/node/threads/workerPool.js.map +1 -0
- package/dist/node/threads/workerPool.ts +38 -0
- package/dist/node/threads/workerThread.d.ts +31 -0
- package/dist/node/threads/workerThread.js +91 -0
- package/dist/node/threads/workerThread.js.map +1 -0
- package/dist/node/threads/workerThread.ts +92 -0
- package/dist/node.d.ts +36 -26
- package/dist/node.js +334 -62
- package/dist/node.js.map +1 -1
- package/dist/responseTimeMetric.d.ts +16 -0
- package/dist/responseTimeMetric.js +56 -0
- package/dist/responseTimeMetric.js.map +1 -0
- package/dist/serializer/columnarSerializer.d.ts +3 -2
- package/dist/serializer/columnarSerializer.js +10 -1
- package/dist/serializer/columnarSerializer.js.map +1 -1
- package/dist/types.d.ts +41 -2
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +49 -13
- package/dist/utils.js.map +1 -1
- package/package.json +8 -5
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
/* eslint-disable no-useless-catch */
|
|
4
4
|
/* eslint-disable no-param-reassign */
|
|
5
5
|
/* eslint-disable no-underscore-dangle */
|
|
6
|
-
const
|
|
6
|
+
const WorkerThread = require('<%= modules.workerThread %>').default;
|
|
7
|
+
const { threadId } = require('worker_threads');
|
|
7
8
|
const model = require('<%= runtime %>');
|
|
8
|
-
const externalResolver = require('<%= modules.externalResolver %>');
|
|
9
9
|
const { logger } = require('<%= modules.logger %>');
|
|
10
10
|
const metadata = <%- metadata %>;
|
|
11
11
|
const formspec = <%- formspec %>;
|
|
12
|
-
|
|
13
|
-
var events = require('events');
|
|
14
|
-
var eventEmitter = new events.EventEmitter();
|
|
15
|
-
|
|
16
12
|
const modelName = '<%= modelName %>';
|
|
13
|
+
const DISPATCH_TYPE = {
|
|
14
|
+
SPARK_SERVICE: 0,
|
|
15
|
+
EXTERNAL_API: 1,
|
|
16
|
+
};
|
|
17
17
|
|
|
18
18
|
logger.debug({
|
|
19
19
|
TimeStamp: Date.now(),
|
|
@@ -22,20 +22,24 @@ logger.debug({
|
|
|
22
22
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
let wasm;
|
|
26
25
|
let wb;
|
|
27
|
-
|
|
28
26
|
let isReady = false;
|
|
29
|
-
|
|
30
27
|
let execute = () => { return Promise.resolve(false) };
|
|
31
28
|
let _execute = () => { return Promise.resolve(false) };
|
|
32
|
-
|
|
33
29
|
let modelIsBusy = false;
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Place holder of the worker thread instance.
|
|
33
|
+
* Actual definition happens during Worker initialization.
|
|
34
|
+
*/
|
|
35
|
+
let workerThreadInstance = null;
|
|
36
|
+
|
|
37
|
+
function sleep(ms) {
|
|
38
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const start = Date.now();
|
|
42
|
+
let readyRes = undefined;
|
|
39
43
|
|
|
40
44
|
try {
|
|
41
45
|
logger.debug({
|
|
@@ -62,23 +66,20 @@ try {
|
|
|
62
66
|
const resultData = new Uint8Array(
|
|
63
67
|
instance.HEAPU8.subarray(argPtr, argPtr + argsOffSet)
|
|
64
68
|
);
|
|
65
|
-
const result = dnc.decode(resultData).slice();
|
|
66
69
|
|
|
70
|
+
const result = dnc.decode(resultData).slice();
|
|
67
71
|
const requestData = JSON.parse(result);
|
|
68
72
|
|
|
69
73
|
switch (service) {
|
|
70
74
|
case DISPATCH_TYPE.SPARK_SERVICE: {
|
|
71
|
-
const
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
case DISPATCH_TYPE.EXTERNAL_API: {
|
|
75
|
-
// eslint-disable-next-line no-return-await
|
|
76
|
-
return await externalResolver.externalApi(requestData, ctx);
|
|
75
|
+
const resultSparkService = await workerThreadInstance.requestMessage(requestData, ctx);
|
|
76
|
+
return resultSparkService;
|
|
77
77
|
}
|
|
78
78
|
default: {
|
|
79
79
|
logger.error(
|
|
80
80
|
`Not implemented for service ${service} data ${result}`
|
|
81
81
|
);
|
|
82
|
+
return '';
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
};
|
|
@@ -87,7 +88,7 @@ try {
|
|
|
87
88
|
execute = function (req) {
|
|
88
89
|
try {
|
|
89
90
|
if (req === "isReady") {
|
|
90
|
-
return Promise.resolve(
|
|
91
|
+
return Promise.resolve(readyRes);
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
if (req === "destroy") {
|
|
@@ -95,7 +96,7 @@ try {
|
|
|
95
96
|
return Promise.resolve(true);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
if(!req.request_data) req.request_data = {}
|
|
99
|
+
if (!req.request_data) req.request_data = {}
|
|
99
100
|
|
|
100
101
|
let rawString = false;
|
|
101
102
|
if (req.request_data._raw) {
|
|
@@ -115,7 +116,7 @@ try {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
if(!req.request_meta) req.request_meta = {}
|
|
119
|
+
if (!req.request_meta) req.request_meta = {}
|
|
119
120
|
|
|
120
121
|
if (req.request_meta?._ctx?.correlationId) {
|
|
121
122
|
ctx.correlationId = req.request_meta._ctx.correlationId;
|
|
@@ -149,22 +150,34 @@ try {
|
|
|
149
150
|
delete req.request_meta._ctx.servicemap;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
if(req.request_meta._ctx?.xcallChainId) {
|
|
153
|
+
if (req.request_meta._ctx?.xcallChainId) {
|
|
153
154
|
ctx.xcallChainId = req.request_meta._ctx?.xcallChainId;
|
|
154
155
|
delete req.request_meta._ctx.xcallChainId;
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
if(req.
|
|
158
|
+
if (req.request_meta._ctx?.callId) {
|
|
159
|
+
ctx.callid = req.request_meta._ctx.callId;
|
|
160
|
+
delete req.request_meta._ctx.callId;
|
|
161
|
+
} else if (req.callid) {
|
|
158
162
|
ctx.callid = req.callid;
|
|
159
163
|
delete req.callid;
|
|
160
164
|
}
|
|
161
165
|
|
|
166
|
+
if (!req.request_meta?.allow_range_address) {
|
|
167
|
+
req.request_meta.allow_range_address = false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (req.request_meta?._ctx?.trace) {
|
|
171
|
+
ctx.trace = req.request_meta._ctx.trace;
|
|
172
|
+
delete req.request_meta._ctx.trace;
|
|
173
|
+
}
|
|
174
|
+
|
|
162
175
|
const startTime = Date.now();
|
|
163
176
|
logger.debug({
|
|
164
177
|
TimeStamp: Date.now(),
|
|
165
178
|
EventType: 'Runner.ModelThread.Execute',
|
|
166
|
-
|
|
167
|
-
|
|
179
|
+
threadCallId: ctx.callid,
|
|
180
|
+
correlationId: ctx.correlationId,
|
|
168
181
|
});
|
|
169
182
|
|
|
170
183
|
const input = JSON.stringify(req);
|
|
@@ -191,21 +204,23 @@ try {
|
|
|
191
204
|
[wb, inBuffer, encoded.length, outBuffer],
|
|
192
205
|
{ async: true }
|
|
193
206
|
).then((outPtr) => {
|
|
207
|
+
|
|
194
208
|
var offset = instance.getValue(outBuffer, "i32");
|
|
195
209
|
const resultData = new Uint8Array(instance.HEAPU8.subarray(outPtr, outPtr + offset));
|
|
196
210
|
var result = dnc.decode(resultData).slice();
|
|
211
|
+
|
|
197
212
|
instance._free(inBuffer);
|
|
198
213
|
instance._free(outBuffer);
|
|
199
214
|
instance._free(outPtr);
|
|
200
215
|
|
|
201
|
-
if(isMetadataSubSvc) {
|
|
216
|
+
if (isMetadataSubSvc) {
|
|
202
217
|
result = JSON.parse(result);
|
|
203
|
-
if(!result.response_data) {
|
|
218
|
+
if (!result.response_data) {
|
|
204
219
|
result.response_data = {}
|
|
205
220
|
}
|
|
206
221
|
const hasImageOutputs = metadata?.ImageOutputs ?? []
|
|
207
|
-
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce(
|
|
208
|
-
if(!curr?.ImageName) return prev
|
|
222
|
+
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce((prev, curr) => {
|
|
223
|
+
if (!curr?.ImageName) return prev
|
|
209
224
|
prev[curr.ImageName] = curr?.Base64Content || ""
|
|
210
225
|
return prev
|
|
211
226
|
}, {}) : {}
|
|
@@ -220,14 +235,14 @@ try {
|
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
|
|
223
|
-
if(isFormSpecSubSvc) {
|
|
238
|
+
if (isFormSpecSubSvc) {
|
|
224
239
|
result = JSON.parse(result);
|
|
225
|
-
if(!result.response_data) {
|
|
240
|
+
if (!result.response_data) {
|
|
226
241
|
result.response_data = {}
|
|
227
242
|
}
|
|
228
243
|
|
|
229
244
|
// result.response_data.outputs = Object.assign({}, result.response_data.outputs, formspec);
|
|
230
|
-
|
|
245
|
+
result.response_data.outputs = formspec;
|
|
231
246
|
return rawString ? JSON.stringify(result) : result;
|
|
232
247
|
}
|
|
233
248
|
|
|
@@ -237,6 +252,7 @@ try {
|
|
|
237
252
|
Message: `Complete execute model ${modelName}`,
|
|
238
253
|
innerExecuteDuration: Date.now() - startTime,
|
|
239
254
|
threadCallId: ctx.callid,
|
|
255
|
+
correlationId: ctx.correlationId,
|
|
240
256
|
});
|
|
241
257
|
|
|
242
258
|
return rawString ? result : JSON.parse(result);
|
|
@@ -257,14 +273,14 @@ try {
|
|
|
257
273
|
instance._free(outBuffer);
|
|
258
274
|
instance._free(outPtr);
|
|
259
275
|
|
|
260
|
-
if(isMetadataSubSvc) {
|
|
276
|
+
if (isMetadataSubSvc) {
|
|
261
277
|
result = JSON.parse(result);
|
|
262
|
-
if(!result.response_data) {
|
|
278
|
+
if (!result.response_data) {
|
|
263
279
|
result.response_data = {}
|
|
264
280
|
}
|
|
265
281
|
const hasImageOutputs = metadata?.ImageOutputs ?? []
|
|
266
|
-
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce(
|
|
267
|
-
if(!curr?.ImageName) return prev
|
|
282
|
+
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce((prev, curr) => {
|
|
283
|
+
if (!curr?.ImageName) return prev
|
|
268
284
|
prev[curr.ImageName] = curr?.Base64Content || ""
|
|
269
285
|
return prev
|
|
270
286
|
}, {}) : {}
|
|
@@ -273,17 +289,17 @@ try {
|
|
|
273
289
|
...metadata?.Outputs,
|
|
274
290
|
...imageOutputs,
|
|
275
291
|
}
|
|
276
|
-
result.response_data.outputs = Object.assign({},
|
|
292
|
+
result.response_data.outputs = Object.assign({}, metadataOutput);
|
|
277
293
|
return rawString ? JSON.stringify(result) : result;
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
if(isFormSpecSubSvc) {
|
|
296
|
+
if (isFormSpecSubSvc) {
|
|
281
297
|
result = JSON.parse(result);
|
|
282
|
-
if(!result.response_data) {
|
|
298
|
+
if (!result.response_data) {
|
|
283
299
|
result.response_data = {}
|
|
284
300
|
}
|
|
285
301
|
|
|
286
|
-
|
|
302
|
+
// result.response_data.outputs = Object.assign({}, result.response_data.outputs, formspec);
|
|
287
303
|
result.response_data.outputs = formspec;
|
|
288
304
|
return rawString ? JSON.stringify(result) : result;
|
|
289
305
|
}
|
|
@@ -293,11 +309,11 @@ try {
|
|
|
293
309
|
Message: `Complete execute model ${modelName}`,
|
|
294
310
|
EventType: 'Runner.ModelThread.Execute',
|
|
295
311
|
innerExecuteDuration: Date.now() - startTime,
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
threadCallId: ctx.callid,
|
|
313
|
+
correlationId: ctx.correlationId,
|
|
298
314
|
});
|
|
299
315
|
|
|
300
|
-
return rawString ? result : JSON.parse(result);
|
|
316
|
+
return rawString ? result.concat('') : JSON.parse(result);
|
|
301
317
|
});
|
|
302
318
|
}
|
|
303
319
|
} else {
|
|
@@ -316,14 +332,15 @@ try {
|
|
|
316
332
|
instance._free(outBuffer);
|
|
317
333
|
instance._free(outPtr);
|
|
318
334
|
|
|
319
|
-
|
|
335
|
+
|
|
336
|
+
if (isMetadataSubSvc) {
|
|
320
337
|
result = JSON.parse(result);
|
|
321
|
-
if(!result.response_data) {
|
|
338
|
+
if (!result.response_data) {
|
|
322
339
|
result.response_data = {}
|
|
323
340
|
}
|
|
324
341
|
const hasImageOutputs = metadata?.ImageOutputs ?? []
|
|
325
|
-
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce(
|
|
326
|
-
if(!curr?.ImageName) return prev
|
|
342
|
+
const imageOutputs = hasImageOutputs ? hasImageOutputs.reduce((prev, curr) => {
|
|
343
|
+
if (!curr?.ImageName) return prev
|
|
327
344
|
prev[curr.ImageName] = curr?.Base64Content || null
|
|
328
345
|
return prev
|
|
329
346
|
}, {}) : {}
|
|
@@ -336,13 +353,13 @@ try {
|
|
|
336
353
|
return rawString ? JSON.stringify(result) : result;
|
|
337
354
|
}
|
|
338
355
|
|
|
339
|
-
if(isFormSpecSubSvc) {
|
|
356
|
+
if (isFormSpecSubSvc) {
|
|
340
357
|
result = JSON.parse(result);
|
|
341
|
-
if(!result.response_data) {
|
|
358
|
+
if (!result.response_data) {
|
|
342
359
|
result.response_data = {}
|
|
343
360
|
}
|
|
344
361
|
|
|
345
|
-
|
|
362
|
+
//result.response_data.outputs = Object.assign({}, result.response_data.outputs, formspec);
|
|
346
363
|
result.response_data.outputs = formspec;
|
|
347
364
|
return rawString ? JSON.stringify(result) : result;
|
|
348
365
|
}
|
|
@@ -352,11 +369,11 @@ try {
|
|
|
352
369
|
Message: `Complete execute model ${modelName}`,
|
|
353
370
|
EventType: 'Runner.ModelThread.Execute',
|
|
354
371
|
innerExecuteDuration: Date.now() - startTime,
|
|
355
|
-
|
|
356
|
-
|
|
372
|
+
threadCallId: ctx.callid,
|
|
373
|
+
correlationId: ctx.correlationId,
|
|
357
374
|
});
|
|
358
375
|
|
|
359
|
-
return rawString ? result : JSON.parse(result);
|
|
376
|
+
return rawString ? result.concat('') : JSON.parse(result);
|
|
360
377
|
});
|
|
361
378
|
}
|
|
362
379
|
|
|
@@ -368,34 +385,33 @@ try {
|
|
|
368
385
|
};
|
|
369
386
|
|
|
370
387
|
|
|
371
|
-
_execute = function (req) {
|
|
372
|
-
|
|
373
|
-
if(!modelIsBusy) {
|
|
374
|
-
logger.debug({
|
|
375
|
-
TimeStamp: Date.now(),
|
|
376
|
-
Message: `Execute ${modelName}`,
|
|
377
|
-
EventType: 'Execute',
|
|
378
|
-
})
|
|
388
|
+
_execute = async function (req) {
|
|
389
|
+
while (1) {
|
|
390
|
+
if (!modelIsBusy) {
|
|
379
391
|
modelIsBusy = true;
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
392
|
+
const start = Date.now();
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
return {
|
|
396
|
+
payload: await execute(req),
|
|
397
|
+
memoryUsage: process.memoryUsage().rss,
|
|
398
|
+
threadId,
|
|
399
|
+
time: Date.now() - start
|
|
400
|
+
}
|
|
401
|
+
} catch (err) {
|
|
402
|
+
return {
|
|
403
|
+
error: err,
|
|
404
|
+
memoryUsage: process.memoryUsage().rss,
|
|
405
|
+
threadId,
|
|
406
|
+
time: Date.now() - start
|
|
407
|
+
}
|
|
408
|
+
} finally {
|
|
409
|
+
modelIsBusy = false;
|
|
410
|
+
}
|
|
388
411
|
} else {
|
|
389
|
-
|
|
390
|
-
logger.debug({
|
|
391
|
-
TimeStamp: Date.now(),
|
|
392
|
-
Message: `Execute.wait ${modelName}`,
|
|
393
|
-
EventType: 'Execute.wait',
|
|
394
|
-
});
|
|
395
|
-
execute(req)
|
|
396
|
-
}, 1)
|
|
412
|
+
await sleep(5)
|
|
397
413
|
}
|
|
398
|
-
}
|
|
414
|
+
}
|
|
399
415
|
}
|
|
400
416
|
|
|
401
417
|
logger.debug({
|
|
@@ -412,6 +428,13 @@ try {
|
|
|
412
428
|
});
|
|
413
429
|
|
|
414
430
|
isReady = true;
|
|
431
|
+
readyRes = {
|
|
432
|
+
memoryUsage: process.memoryUsage().rss,
|
|
433
|
+
threadId,
|
|
434
|
+
time: Date.now() - start,
|
|
435
|
+
readyTs: Date.now()
|
|
436
|
+
};
|
|
437
|
+
|
|
415
438
|
return Promise.resolve();
|
|
416
439
|
} catch (err) {
|
|
417
440
|
instance = undefined
|
|
@@ -419,12 +442,29 @@ try {
|
|
|
419
442
|
return Promise.reject(err);
|
|
420
443
|
}
|
|
421
444
|
})
|
|
422
|
-
.catch((err) => logger.error('Instance Error: ', err));
|
|
445
|
+
.catch((err) => logger.error('Instance Error: ' + err.message, err));
|
|
423
446
|
} catch (err) {
|
|
424
447
|
logger.error('Error', err)
|
|
425
448
|
}
|
|
426
449
|
|
|
427
|
-
|
|
450
|
+
/**
|
|
451
|
+
* Main worker function that triggers the `execute` logic which communicates to
|
|
452
|
+
* the WASM functions.
|
|
453
|
+
*
|
|
454
|
+
* @param {String|Object} input
|
|
455
|
+
* Can be 'isReady', JSON String or an Object.
|
|
456
|
+
*
|
|
457
|
+
* @returns {*}
|
|
458
|
+
*/
|
|
459
|
+
async function main(input) {
|
|
460
|
+
// IMPORTANT: `postMessage` from parent also triggers this function, better not to pass `data` from parent
|
|
461
|
+
// and use `pool.execute()` instead.
|
|
462
|
+
if (!input) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Private function init
|
|
467
|
+
workerThreadInstance = this;
|
|
428
468
|
|
|
429
469
|
if (
|
|
430
470
|
typeof input !== "string" &&
|
|
@@ -434,7 +474,7 @@ parentPort.on("message", (input) => {
|
|
|
434
474
|
throw new Error("Param must be a json string or json object");
|
|
435
475
|
}
|
|
436
476
|
|
|
437
|
-
|
|
477
|
+
return _execute(input);
|
|
478
|
+
};
|
|
438
479
|
|
|
439
|
-
|
|
440
|
-
});
|
|
480
|
+
module.exports = new WorkerThread(main);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare class WorkerThread extends ThreadWorker<any, any> {
|
|
2
|
+
constructor(taskFunctions: any, opts: any);
|
|
3
|
+
/**
|
|
4
|
+
* Sends message back to the main thread.
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} message
|
|
7
|
+
*/
|
|
8
|
+
postMessage(message: any): void;
|
|
9
|
+
/**
|
|
10
|
+
* Receives message from the main thread or other threads.
|
|
11
|
+
*
|
|
12
|
+
* @param {Function} callback
|
|
13
|
+
* Function to receive the message data.
|
|
14
|
+
*/
|
|
15
|
+
onMessage(callback: Function): void;
|
|
16
|
+
/**
|
|
17
|
+
* Sends a request to the main thread and waits for a response.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} payload
|
|
20
|
+
* Object or details that needs to be passed to main thread as `payload`.
|
|
21
|
+
*
|
|
22
|
+
* @returns {Promise<Object>}
|
|
23
|
+
* Response from main thread.
|
|
24
|
+
*/
|
|
25
|
+
requestMessage(payload: any, context: any): Promise<any>;
|
|
26
|
+
}
|
|
27
|
+
import { ThreadWorker } from "poolifier";
|
|
28
|
+
export { WorkerThread as default };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const events = require("events");
|
|
2
|
+
const { isMainThread, parentPort } = require("worker_threads");
|
|
3
|
+
const { createId } = require("@paralleldrive/cuid2");
|
|
4
|
+
const { ThreadWorker } = require("poolifier");
|
|
5
|
+
// eslint-disable-next-line import/no-unresolved, import/extensions
|
|
6
|
+
const { THREAD_EVENT_TYPES } = require("../../mockConstants");
|
|
7
|
+
|
|
8
|
+
class WorkerThread extends ThreadWorker {
|
|
9
|
+
// eslint-disable-next-line no-useless-constructor
|
|
10
|
+
constructor(taskFunctions, opts) {
|
|
11
|
+
super(taskFunctions, opts);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Sends message back to the main thread.
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} message
|
|
18
|
+
*/
|
|
19
|
+
postMessage(message) {
|
|
20
|
+
if (isMainThread) {
|
|
21
|
+
throw Error("Failed to post message using main thread.");
|
|
22
|
+
} else {
|
|
23
|
+
parentPort.postMessage(message);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Receives message from the main thread or other threads.
|
|
29
|
+
*
|
|
30
|
+
* @param {Function} callback
|
|
31
|
+
* Function to receive the message data.
|
|
32
|
+
*/
|
|
33
|
+
onMessage(callback) {
|
|
34
|
+
if (isMainThread) {
|
|
35
|
+
throw Error("Failed to receive message using main thread.");
|
|
36
|
+
} else {
|
|
37
|
+
parentPort.on("message", callback);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sends a request to the main thread and waits for a response.
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} payload
|
|
45
|
+
* Object or details that needs to be passed to main thread as `payload`.
|
|
46
|
+
*
|
|
47
|
+
* @returns {Promise<Object>}
|
|
48
|
+
* Response from main thread.
|
|
49
|
+
*/
|
|
50
|
+
async requestMessage(payload, context) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const eventId = createId();
|
|
53
|
+
const eventEmitter = new events.EventEmitter();
|
|
54
|
+
|
|
55
|
+
// Prepare to process the response from parent
|
|
56
|
+
eventEmitter.once(eventId, (response) => {
|
|
57
|
+
eventEmitter.removeAllListeners(eventId);
|
|
58
|
+
if (response.type === THREAD_EVENT_TYPES.ERROR) {
|
|
59
|
+
reject(response?.payload);
|
|
60
|
+
} else {
|
|
61
|
+
resolve(response?.payload);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Send the request to parent
|
|
66
|
+
this.postMessage({
|
|
67
|
+
payload,
|
|
68
|
+
context,
|
|
69
|
+
type: THREAD_EVENT_TYPES.REQUEST_EXECUTE,
|
|
70
|
+
eventId,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Receive the response from parent once ready
|
|
74
|
+
this.onMessage((message) => {
|
|
75
|
+
if (
|
|
76
|
+
message.eventId === eventId &&
|
|
77
|
+
(message?.type === THREAD_EVENT_TYPES.RESPONSE ||
|
|
78
|
+
message?.type === THREAD_EVENT_TYPES.ERROR)
|
|
79
|
+
) {
|
|
80
|
+
eventEmitter.emit(eventId, message);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
default: WorkerThread,
|
|
89
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockWorkerThread.js","sourceRoot":"","sources":["../../../src/node/threads/mockWorkerThread.js"],"names":[],"mappings":";;;;;;;;;AAAA,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACjC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC/D,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACrD,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAC9C,mEAAmE;AACnE,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAE9D,MAAM,YAAa,SAAQ,YAAY;IACrC,kDAAkD;IAClD,YAAY,aAAa,EAAE,IAAI;QAC7B,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,OAAO;QACjB,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,QAAQ;QAChB,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACG,cAAc,CAAC,OAAO,EAAE,OAAO;;YACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;gBAC3B,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBAE/C,8CAA8C;gBAC9C,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;oBACtC,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;oBACzC,IAAI,QAAQ,CAAC,IAAI,KAAK,kBAAkB,CAAC,KAAK,EAAE,CAAC;wBAC/C,MAAM,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,CAAC,CAAC;oBAC5B,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,CAAC,CAAC;oBAC7B,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,6BAA6B;gBAC7B,IAAI,CAAC,WAAW,CAAC;oBACf,OAAO;oBACP,OAAO;oBACP,IAAI,EAAE,kBAAkB,CAAC,eAAe;oBACxC,OAAO;iBACR,CAAC,CAAC;gBAEH,8CAA8C;gBAC9C,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE;oBACzB,IACE,OAAO,CAAC,OAAO,KAAK,OAAO;wBAC3B,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,kBAAkB,CAAC,QAAQ;4BAC5C,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,kBAAkB,CAAC,KAAK,CAAC,EAC7C,CAAC;wBACD,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;KAAA;CACF;AAED,MAAM,CAAC,OAAO,GAAG;IACf,OAAO,EAAE,YAAY;CACtB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FixedThreadPool } from "poolifier";
|
|
2
|
+
import type { ThreadPoolOptions } from "poolifier";
|
|
3
|
+
import { EventResponseData } from "../../types";
|
|
4
|
+
declare class WorkerPool extends FixedThreadPool {
|
|
5
|
+
constructor(numberOfThreads: number, filePath: string, opts?: ThreadPoolOptions, maximumNumberOfThreads?: number);
|
|
6
|
+
/**
|
|
7
|
+
* Sends message to a specific worker thread or broadcasts the message
|
|
8
|
+
* to all running threads.
|
|
9
|
+
*
|
|
10
|
+
* @param message
|
|
11
|
+
* Any data that needs to passed to the worker.
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
postMessage(message: EventResponseData): void;
|
|
15
|
+
}
|
|
16
|
+
export default WorkerPool;
|
|
17
|
+
export type { FixedThreadPool };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const poolifier_1 = require("poolifier");
|
|
4
|
+
class WorkerPool extends poolifier_1.FixedThreadPool {
|
|
5
|
+
constructor(numberOfThreads, filePath, opts, maximumNumberOfThreads) {
|
|
6
|
+
super(numberOfThreads, filePath, opts);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Sends message to a specific worker thread or broadcasts the message
|
|
10
|
+
* to all running threads.
|
|
11
|
+
*
|
|
12
|
+
* @param message
|
|
13
|
+
* Any data that needs to passed to the worker.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
postMessage(message) {
|
|
17
|
+
let workerIndex = -1;
|
|
18
|
+
if (message.threadId) {
|
|
19
|
+
workerIndex = this.workerNodes.findIndex((w) => { var _a; return ((_a = w.info) === null || _a === void 0 ? void 0 : _a.id) === message.threadId; });
|
|
20
|
+
}
|
|
21
|
+
if (workerIndex > -1) {
|
|
22
|
+
this.workerNodes[workerIndex].worker.postMessage(message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.default = WorkerPool;
|
|
27
|
+
//# sourceMappingURL=workerPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workerPool.js","sourceRoot":"","sources":["../../../src/node/threads/workerPool.ts"],"names":[],"mappings":";;AAAA,yCAA4C;AAI5C,MAAM,UAAW,SAAQ,2BAAe;IACtC,YACE,eAAuB,EACvB,QAAgB,EAChB,IAAwB,EACxB,sBAA+B;QAE/B,KAAK,CAAC,eAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED;;;;;;;OAOG;IACH,WAAW,CAAC,OAA0B;QACpC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;QACrB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CACtC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,CAAA,MAAA,CAAC,CAAC,IAAI,0CAAE,EAAE,MAAK,OAAO,CAAC,QAAQ,CAAA,EAAA,CACvC,CAAC;QACJ,CAAC;QAED,IAAI,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF;AAED,kBAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FixedThreadPool } from "poolifier";
|
|
2
|
+
import type { ThreadPoolOptions } from "poolifier";
|
|
3
|
+
import { EventResponseData } from "../../types";
|
|
4
|
+
|
|
5
|
+
class WorkerPool extends FixedThreadPool {
|
|
6
|
+
constructor(
|
|
7
|
+
numberOfThreads: number,
|
|
8
|
+
filePath: string,
|
|
9
|
+
opts?: ThreadPoolOptions,
|
|
10
|
+
maximumNumberOfThreads?: number
|
|
11
|
+
) {
|
|
12
|
+
super(numberOfThreads, filePath, opts);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sends message to a specific worker thread or broadcasts the message
|
|
17
|
+
* to all running threads.
|
|
18
|
+
*
|
|
19
|
+
* @param message
|
|
20
|
+
* Any data that needs to passed to the worker.
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
postMessage(message: EventResponseData) {
|
|
24
|
+
let workerIndex = -1;
|
|
25
|
+
if (message.threadId) {
|
|
26
|
+
workerIndex = this.workerNodes.findIndex(
|
|
27
|
+
(w) => w.info?.id === message.threadId
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (workerIndex > -1) {
|
|
32
|
+
this.workerNodes[workerIndex].worker.postMessage(message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default WorkerPool;
|
|
38
|
+
export type { FixedThreadPool };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ThreadWorker } from "poolifier";
|
|
2
|
+
import type { TaskFunctions, TaskFunction, WorkerOptions } from "poolifier";
|
|
3
|
+
import type { EventRequestData } from "../../types";
|
|
4
|
+
declare class WorkerThread extends ThreadWorker {
|
|
5
|
+
constructor(taskFunctions: TaskFunction<unknown, Response> | TaskFunctions<unknown, Response>, opts?: WorkerOptions);
|
|
6
|
+
/**
|
|
7
|
+
* Sends message back to the main thread.
|
|
8
|
+
*
|
|
9
|
+
* @param {EventRequestData} message
|
|
10
|
+
*/
|
|
11
|
+
postMessage(message: EventRequestData): void;
|
|
12
|
+
/**
|
|
13
|
+
* Receives message from the main thread or other threads.
|
|
14
|
+
*
|
|
15
|
+
* @param {Function} callback
|
|
16
|
+
* Function to receive the message data.
|
|
17
|
+
*/
|
|
18
|
+
onMessage(callback: (value?: any) => void): void;
|
|
19
|
+
private cleanupListener;
|
|
20
|
+
/**
|
|
21
|
+
* Sends a request to the main thread and waits for a response.
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} payload
|
|
24
|
+
* Object or details that needs to be passed to main thread as `payload`.
|
|
25
|
+
*
|
|
26
|
+
* @returns {Promise<Object>}
|
|
27
|
+
* Response from main thread.
|
|
28
|
+
*/
|
|
29
|
+
requestMessage(payload: any, context: any): Promise<unknown>;
|
|
30
|
+
}
|
|
31
|
+
export default WorkerThread;
|