@e-mc/core 0.11.8 → 0.12.0
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 +101 -13
- package/index.d.ts +3 -1
- package/index.js +715 -190
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a
|
|
3
|
-
exports.Module = exports.Permission = exports.AbortComponent = exports.ClientDb = exports.Client = exports.Host = void 0;
|
|
2
|
+
var _a;
|
|
3
|
+
exports.Module = exports.Permission = exports.AbortComponent = exports.WorkerChannel = exports.WorkerGroup = exports.ClientDb = exports.Client = exports.Host = void 0;
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const fs = require("node:fs");
|
|
6
|
+
const os = require("node:os");
|
|
6
7
|
const pm = require("picomatch");
|
|
7
8
|
const ipaddr = require("ipaddr.js");
|
|
9
|
+
const EventEmitter = require("node:events");
|
|
10
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
11
|
+
const node_url_1 = require("node:url");
|
|
8
12
|
const types_1 = require("@e-mc/types");
|
|
9
13
|
const module_1 = require("@e-mc/module");
|
|
10
14
|
exports.Module = module_1;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const kFreeze = Symbol('freeze');
|
|
15
|
-
const kDone = Symbol('done');
|
|
16
|
-
const kLogState = Symbol('logState');
|
|
17
|
-
const kCacheDir = Symbol('cacheDir');
|
|
18
|
-
const kDiskRead = Symbol('diskRead');
|
|
19
|
-
const kDiskWrite = Symbol('diskWrite');
|
|
20
|
-
const kUncRead = Symbol('uncRead');
|
|
21
|
-
const kUncWrite = Symbol('uncWrite');
|
|
15
|
+
const kHost = Symbol.for('host:constructor');
|
|
16
|
+
const kClient = Symbol.for('client:constructor');
|
|
17
|
+
const kClientDb = Symbol.for('clientdb:constructor');
|
|
22
18
|
const CACHE_USER = {};
|
|
23
19
|
const CACHE_SOURCE = {};
|
|
24
20
|
const CACHE_SESSION = Object.create(null);
|
|
@@ -33,9 +29,7 @@ const HOST = {
|
|
|
33
29
|
QUEUED: 0,
|
|
34
30
|
REJECTED: 0,
|
|
35
31
|
KILLED: 0,
|
|
36
|
-
|
|
37
|
-
CIPHER_KEY: undefined,
|
|
38
|
-
CIPHER_IV: undefined,
|
|
32
|
+
CIPHER: null,
|
|
39
33
|
ADMIN_USERS: [],
|
|
40
34
|
ADMIN_PRIVATE: false,
|
|
41
35
|
THREAD_LIMIT: Infinity,
|
|
@@ -48,10 +42,20 @@ const HOST = {
|
|
|
48
42
|
LOG_PROGRESS_QUEUE: new WeakSet(),
|
|
49
43
|
LOG_PROGRESS_PAUSED: new Set()
|
|
50
44
|
};
|
|
51
|
-
const
|
|
45
|
+
const WORKER_GROUP = {
|
|
46
|
+
MAX: (0, types_1.supported)(19, 4) || (0, types_1.supported)(18, 14, true) ? os.availableParallelism() : os.cpus().length,
|
|
47
|
+
TIMEOUT: Infinity,
|
|
48
|
+
LOCKED: true
|
|
49
|
+
};
|
|
50
|
+
const WORKER_CHANNEL = {
|
|
51
|
+
MIN: 0,
|
|
52
|
+
MAX: Math.max(WORKER_GROUP.MAX / 2, 2),
|
|
53
|
+
TIMEOUT: 300 * 1000,
|
|
54
|
+
VERBOSE: true
|
|
55
|
+
};
|
|
52
56
|
let STORE_RESULT_COUNT = 0;
|
|
53
57
|
let PICOMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32 };
|
|
54
|
-
let MINIMATCH_OPTIONS = {
|
|
58
|
+
let MINIMATCH_OPTIONS = {};
|
|
55
59
|
let MINIMATCH;
|
|
56
60
|
let PERMISSION;
|
|
57
61
|
function closeHostThread(host) {
|
|
@@ -70,7 +74,7 @@ function closeHostThread(host) {
|
|
|
70
74
|
}
|
|
71
75
|
if (HOST.QUEUE.length > 0 && HOST.DONE.size < HOST.THREAD_LIMIT) {
|
|
72
76
|
const queue = HOST.QUEUE.shift();
|
|
73
|
-
|
|
77
|
+
HOST.DONE.set(queue.instance, HOST.PID++);
|
|
74
78
|
resumeHostQueue(queue);
|
|
75
79
|
HOST.QUEUE.forEach((item, index) => {
|
|
76
80
|
notifyHostQueue(item.instance, index, item.priority, true);
|
|
@@ -104,10 +108,6 @@ function resumeHostLog(host) {
|
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
|
-
function addHostThread(host) {
|
|
108
|
-
HOST.DONE.set(host, HOST.PID++);
|
|
109
|
-
host[kQueued] = false;
|
|
110
|
-
}
|
|
111
111
|
function notifyHostQueue(host, position, priority, broadcast) {
|
|
112
112
|
if (!broadcast || host.broadcastId) {
|
|
113
113
|
host.formatMessage(2, 'QUEUE', ["Thread limit exceeded" + ` (position #${position + 1})`, host.username], 'Priority: ' + priority, { type: 2, ...module_1.LOG_STYLE_WARN });
|
|
@@ -156,27 +156,8 @@ function resumeHostQueue(item, aborted) {
|
|
|
156
156
|
}
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
|
-
function
|
|
160
|
-
return HOST.
|
|
161
|
-
}
|
|
162
|
-
function matchPermission(permission, pathname) {
|
|
163
|
-
const { enabled, value } = permission;
|
|
164
|
-
return enabled === true && (0, types_1.isString)(pathname) && (value === '**/*' || value === '**' || Permission.match(pathname, value));
|
|
165
|
-
}
|
|
166
|
-
function setPermission(name, pathname, enabled) {
|
|
167
|
-
if (typeof enabled === 'boolean' && (!this[kFreeze] || this[name].enabled === null) && (!enabled || (pathname = Permission.toPosix(pathname)))) {
|
|
168
|
-
if (enabled && Array.isArray(pathname)) {
|
|
169
|
-
switch (pathname.length) {
|
|
170
|
-
case 1:
|
|
171
|
-
pathname = pathname[0];
|
|
172
|
-
break;
|
|
173
|
-
case 0:
|
|
174
|
-
enabled = false;
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
this[name] = Object.freeze({ enabled, value: enabled ? Object.freeze(pathname) : '' });
|
|
179
|
-
}
|
|
159
|
+
function encryptText(data, iv) {
|
|
160
|
+
return HOST.CIPHER && (0, types_1.isString)(data) && (0, types_1.encryptUTF8)(HOST.CIPHER.algorithm, HOST.CIPHER.key, iv, data) || '';
|
|
180
161
|
}
|
|
181
162
|
function clearSourceResult(data) {
|
|
182
163
|
const result = data[1];
|
|
@@ -246,25 +227,24 @@ function asPosix(value) {
|
|
|
246
227
|
return path.normalize(value);
|
|
247
228
|
}
|
|
248
229
|
function parseIp(value, kind) {
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
ip = ip.toIPv4MappedAddress();
|
|
230
|
+
if (value) {
|
|
231
|
+
try {
|
|
232
|
+
let ip = ipaddr.parse(value);
|
|
233
|
+
if (ip.kind() === 'ipv4') {
|
|
234
|
+
if (kind === 6) {
|
|
235
|
+
ip = ip.toIPv4MappedAddress();
|
|
236
|
+
}
|
|
257
237
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
238
|
+
else if (kind === 4) {
|
|
239
|
+
if (!ip.isIPv4MappedAddress()) {
|
|
240
|
+
return '';
|
|
241
|
+
}
|
|
242
|
+
ip = ip.toIPv4Address();
|
|
262
243
|
}
|
|
263
|
-
|
|
244
|
+
return ip.toNormalizedString();
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
264
247
|
}
|
|
265
|
-
return ip.toNormalizedString();
|
|
266
|
-
}
|
|
267
|
-
catch {
|
|
268
248
|
}
|
|
269
249
|
return '';
|
|
270
250
|
}
|
|
@@ -272,6 +252,7 @@ const readable = (value) => (0, types_1.isString)(value) || (0, types_1.isArray)
|
|
|
272
252
|
const expireTime = (value) => Date.now() + value * 1000;
|
|
273
253
|
const convertSeconds = (value) => typeof value === 'string' && Math.ceil((0, types_1.parseTime)(value) / 1000) || 0;
|
|
274
254
|
class Host extends module_1 {
|
|
255
|
+
static [kHost] = true;
|
|
275
256
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
276
257
|
return parent ? super.purgeMemory(percent, limit) : 0;
|
|
277
258
|
}
|
|
@@ -304,76 +285,101 @@ class Host extends module_1 {
|
|
|
304
285
|
if (perm.settings) {
|
|
305
286
|
const { picomatch: pico, minimatch: mini } = perm.settings;
|
|
306
287
|
if ((0, types_1.isPlainObject)(pico)) {
|
|
307
|
-
PICOMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32,
|
|
288
|
+
PICOMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32, ...pico };
|
|
308
289
|
}
|
|
309
290
|
if ((0, types_1.isPlainObject)(mini)) {
|
|
310
291
|
try {
|
|
311
|
-
const
|
|
312
|
-
MINIMATCH =
|
|
313
|
-
MINIMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32,
|
|
292
|
+
const { minimatch } = require('minimatch');
|
|
293
|
+
MINIMATCH = minimatch;
|
|
294
|
+
MINIMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32, ...mini };
|
|
314
295
|
}
|
|
315
296
|
catch {
|
|
316
297
|
}
|
|
317
298
|
}
|
|
318
299
|
}
|
|
319
300
|
}
|
|
320
|
-
if (proc
|
|
321
|
-
const {
|
|
322
|
-
{
|
|
323
|
-
|
|
324
|
-
if (limit && (limit = Math.floor(+limit)) > 0) {
|
|
325
|
-
HOST.THREAD_LIMIT = limit;
|
|
326
|
-
}
|
|
327
|
-
if (expires && (expires = (0, types_1.parseTime)(expires)) > 0) {
|
|
328
|
-
HOST.THREAD_EXPIRES = expires;
|
|
329
|
-
}
|
|
301
|
+
if (proc) {
|
|
302
|
+
const { cipher, thread } = proc;
|
|
303
|
+
if (cipher?.iv && cipher.key) {
|
|
304
|
+
HOST.CIPHER = Object.freeze({ algorithm: cipher.algorithm || 'aes-256-gcm', key: cipher.key, iv: cipher.iv });
|
|
330
305
|
}
|
|
331
|
-
if (
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
HOST.QUEUE_EXPIRES = expires;
|
|
338
|
-
}
|
|
339
|
-
if (priority) {
|
|
340
|
-
let { min = -1, max = 0, bypass } = priority;
|
|
341
|
-
if ((min = Math.floor(+min)) >= 0) {
|
|
342
|
-
HOST.PRIORITY_MIN = min;
|
|
343
|
-
}
|
|
344
|
-
if ((max = Math.floor(+max)) > 0) {
|
|
345
|
-
HOST.PRIORITY_MAX = max;
|
|
306
|
+
if (thread) {
|
|
307
|
+
const { queue, admin, worker } = thread;
|
|
308
|
+
{
|
|
309
|
+
let { limit, expires } = thread;
|
|
310
|
+
if (limit && (limit = Math.floor(+limit)) > 0) {
|
|
311
|
+
HOST.THREAD_LIMIT = limit;
|
|
346
312
|
}
|
|
347
|
-
if (
|
|
348
|
-
HOST.
|
|
313
|
+
if (expires && (expires = (0, types_1.parseTime)(expires)) > 0) {
|
|
314
|
+
HOST.THREAD_EXPIRES = expires;
|
|
349
315
|
}
|
|
350
|
-
|
|
351
|
-
|
|
316
|
+
}
|
|
317
|
+
if (queue) {
|
|
318
|
+
let { limit, expires, priority } = queue;
|
|
319
|
+
if (limit !== undefined && (limit = Math.floor(+limit)) >= -1) {
|
|
320
|
+
HOST.QUEUE_LIMIT = limit >= 0 ? limit : Infinity;
|
|
352
321
|
}
|
|
353
|
-
|
|
354
|
-
|
|
322
|
+
if (expires && (expires = (0, types_1.parseTime)(expires)) > 0) {
|
|
323
|
+
HOST.QUEUE_EXPIRES = expires;
|
|
355
324
|
}
|
|
356
|
-
if (
|
|
357
|
-
|
|
325
|
+
if (priority) {
|
|
326
|
+
let { min = -1, max = 0, bypass } = priority;
|
|
327
|
+
if ((min = Math.floor(+min)) >= 0) {
|
|
328
|
+
HOST.PRIORITY_MIN = min;
|
|
329
|
+
}
|
|
330
|
+
if ((max = Math.floor(+max)) > 0) {
|
|
331
|
+
HOST.PRIORITY_MAX = max;
|
|
332
|
+
}
|
|
333
|
+
if (HOST.PRIORITY_MAX < HOST.PRIORITY_MIN) {
|
|
334
|
+
HOST.PRIORITY_MAX = HOST.PRIORITY_MIN + 1;
|
|
335
|
+
}
|
|
336
|
+
if (bypass !== undefined && (bypass = Math.floor(+bypass)) && (bypass < HOST.PRIORITY_MIN || bypass > HOST.PRIORITY_MAX)) {
|
|
337
|
+
HOST.PRIORITY_BYPASS = bypass;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
bypass = HOST.PRIORITY_BYPASS;
|
|
341
|
+
}
|
|
342
|
+
if (bypass !== undefined && bypass >= HOST.PRIORITY_MIN && bypass <= HOST.PRIORITY_MAX) {
|
|
343
|
+
HOST.PRIORITY_BYPASS = undefined;
|
|
344
|
+
}
|
|
358
345
|
}
|
|
359
346
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const algorithm = cipher.algorithm || 'aes-256-gcm';
|
|
365
|
-
HOST.ADMIN_USERS = admin.users.map(value => (0, types_1.encryptUTF8)(algorithm, HOST.CIPHER_KEY, HOST.CIPHER_IV, value)).filter(value => value);
|
|
366
|
-
if (HOST.ADMIN_USERS.length > 0) {
|
|
367
|
-
HOST.CIPHER_ALGORITHM = algorithm;
|
|
347
|
+
if (admin) {
|
|
348
|
+
if (HOST.CIPHER && (0, types_1.isArray)(admin.users)) {
|
|
349
|
+
const { algorithm, key, iv } = HOST.CIPHER;
|
|
350
|
+
HOST.ADMIN_USERS = admin.users.map(value => (0, types_1.encryptUTF8)(algorithm, key, iv, value)).filter(value => value);
|
|
368
351
|
}
|
|
369
|
-
|
|
370
|
-
HOST.
|
|
371
|
-
HOST.CIPHER_KEY = null;
|
|
372
|
-
HOST.CIPHER_IV = null;
|
|
352
|
+
if (typeof admin.private === 'boolean') {
|
|
353
|
+
HOST.ADMIN_PRIVATE = admin.private;
|
|
373
354
|
}
|
|
374
355
|
}
|
|
375
|
-
if (
|
|
376
|
-
|
|
356
|
+
if (worker) {
|
|
357
|
+
let { max = 0, locked, max_expires, channel } = worker;
|
|
358
|
+
if ((max = Math.floor(+max)) > 1) {
|
|
359
|
+
WORKER_GROUP.MAX = max;
|
|
360
|
+
}
|
|
361
|
+
if (max_expires && (max_expires = (0, types_1.parseExpires)(max_expires)) > 0) {
|
|
362
|
+
WORKER_GROUP.TIMEOUT = WorkerGroup.checkTimeout(max_expires, false);
|
|
363
|
+
}
|
|
364
|
+
if (typeof locked === 'boolean') {
|
|
365
|
+
WORKER_GROUP.LOCKED = locked;
|
|
366
|
+
}
|
|
367
|
+
if (channel) {
|
|
368
|
+
let { min: a = -1, max: b = 0, expires, verbose } = channel;
|
|
369
|
+
if ((a = Math.floor(+a)) >= 0) {
|
|
370
|
+
WORKER_CHANNEL.MIN = a;
|
|
371
|
+
}
|
|
372
|
+
if ((b = Math.floor(+b)) >= 0) {
|
|
373
|
+
WORKER_CHANNEL.MAX = b;
|
|
374
|
+
WORKER_CHANNEL.MIN = Math.min(WORKER_CHANNEL.MIN, b);
|
|
375
|
+
}
|
|
376
|
+
if (expires && (expires = (0, types_1.parseExpires)(expires)) > 0) {
|
|
377
|
+
WORKER_CHANNEL.TIMEOUT = WorkerGroup.checkTimeout(expires, false);
|
|
378
|
+
}
|
|
379
|
+
if (typeof verbose === 'boolean') {
|
|
380
|
+
WORKER_CHANNEL.VERBOSE = verbose;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
385
|
}
|
|
@@ -390,11 +396,15 @@ class Host extends module_1 {
|
|
|
390
396
|
return permission;
|
|
391
397
|
}
|
|
392
398
|
static isPermission(value) {
|
|
393
|
-
return value instanceof Permission || (0, types_1.isObject)(value) &&
|
|
399
|
+
return value instanceof Permission || (0, types_1.isObject)(value) && typeof value.diskRead === 'boolean' && typeof value.diskWrite === 'boolean';
|
|
394
400
|
}
|
|
395
401
|
static kill(username, iv, pid) {
|
|
402
|
+
if (typeof iv === 'boolean' || typeof iv === 'number' || Array.isArray(iv)) {
|
|
403
|
+
pid = iv;
|
|
404
|
+
iv = false;
|
|
405
|
+
}
|
|
396
406
|
let result = 0;
|
|
397
|
-
if (HOST.ADMIN_USERS.includes(
|
|
407
|
+
if (HOST.ADMIN_USERS.includes(username) || iv && HOST.ADMIN_USERS.includes(encryptText(username, iv))) {
|
|
398
408
|
for (const [host, id] of HOST.DONE) {
|
|
399
409
|
if (pid === true || id === pid || Array.isArray(pid) && pid.includes(id)) {
|
|
400
410
|
cancelHostThread(host, 'pid: ' + id.toString());
|
|
@@ -413,7 +423,7 @@ class Host extends module_1 {
|
|
|
413
423
|
username = undefined;
|
|
414
424
|
break;
|
|
415
425
|
case 'string':
|
|
416
|
-
if (!
|
|
426
|
+
if (!(HOST.ADMIN_USERS.includes(username) || iv && HOST.ADMIN_USERS.includes(encryptText(username, iv)))) {
|
|
417
427
|
username = undefined;
|
|
418
428
|
}
|
|
419
429
|
full = true;
|
|
@@ -479,27 +489,29 @@ class Host extends module_1 {
|
|
|
479
489
|
static getPermissionFromSettings() {
|
|
480
490
|
return PERMISSION;
|
|
481
491
|
}
|
|
492
|
+
restartable = true;
|
|
493
|
+
modules = new Set();
|
|
494
|
+
subProcesses = new Set();
|
|
495
|
+
startTime = Date.now();
|
|
496
|
+
_threadable = true;
|
|
497
|
+
_logExclude = false;
|
|
498
|
+
_logLevel = 0;
|
|
499
|
+
_logDelayed = null;
|
|
500
|
+
_usingObjects = new Set();
|
|
501
|
+
#done = false;
|
|
502
|
+
#logState = 1;
|
|
503
|
+
#username = '';
|
|
504
|
+
#config;
|
|
482
505
|
constructor(config = {}) {
|
|
483
506
|
super();
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
this._logLevel = 0;
|
|
491
|
-
this._logDelayed = null;
|
|
492
|
-
this._usingObjects = new Set();
|
|
493
|
-
this[_a] = false;
|
|
494
|
-
this[_b] = false;
|
|
495
|
-
this[_c] = 1;
|
|
496
|
-
const { broadcastId, log, username, priority } = config;
|
|
497
|
-
if ((0, types_1.isString)(username)) {
|
|
498
|
-
HOST_USERNAME.set(this, username);
|
|
499
|
-
}
|
|
500
|
-
if (broadcastId) {
|
|
501
|
-
this.broadcastId = broadcastId;
|
|
507
|
+
if ((0, types_1.isString)(config.username)) {
|
|
508
|
+
const cipher = HOST.CIPHER;
|
|
509
|
+
this.#username = cipher ? (0, types_1.decryptUTF8)(cipher.algorithm, cipher.key, cipher.iv, config.username) || '' : config.username;
|
|
510
|
+
}
|
|
511
|
+
if (config.broadcastId) {
|
|
512
|
+
this.broadcastId = config.broadcastId;
|
|
502
513
|
}
|
|
514
|
+
const { log, priority } = config;
|
|
503
515
|
let showProgress;
|
|
504
516
|
if ((0, types_1.isPlainObject)(log)) {
|
|
505
517
|
const { enabled, level, exclude, useColor, silent } = log;
|
|
@@ -523,7 +535,7 @@ class Host extends module_1 {
|
|
|
523
535
|
else if (log !== undefined) {
|
|
524
536
|
this.ignoreLog(typeof log === 'boolean' ? !log : log);
|
|
525
537
|
}
|
|
526
|
-
this
|
|
538
|
+
this.#config = Object.freeze({ ...config });
|
|
527
539
|
if (HOST.DONE.size < HOST.THREAD_LIMIT || this.username && typeof priority === 'number' && priority === HOST.PRIORITY_BYPASS) {
|
|
528
540
|
HOST.DONE.set(this, HOST.PID++);
|
|
529
541
|
if (HOST.LOG_PROGRESS) {
|
|
@@ -535,7 +547,6 @@ class Host extends module_1 {
|
|
|
535
547
|
}
|
|
536
548
|
}
|
|
537
549
|
else if (typeof priority === 'number' && priority >= HOST.PRIORITY_MIN && priority <= HOST.PRIORITY_MAX && HOST.QUEUE.length < HOST.QUEUE_LIMIT && typeof this.resumeThread === 'function') {
|
|
538
|
-
this[kQueued] = true;
|
|
539
550
|
addHostQueue({ instance: this, priority, startTime: Date.now() });
|
|
540
551
|
notifyHostQueue(this, HOST.QUEUE.findIndex(item => item.instance === this), priority);
|
|
541
552
|
}
|
|
@@ -546,8 +557,11 @@ class Host extends module_1 {
|
|
|
546
557
|
restart(...args) { }
|
|
547
558
|
updateProgress(name, ...args) { }
|
|
548
559
|
isFatal(err) {
|
|
549
|
-
|
|
550
|
-
|
|
560
|
+
if (err instanceof Error) {
|
|
561
|
+
const fatal = this.config.error?.fatal;
|
|
562
|
+
return fatal ?? super.isFatal(err);
|
|
563
|
+
}
|
|
564
|
+
return false;
|
|
551
565
|
}
|
|
552
566
|
using(...items) {
|
|
553
567
|
const data = this._usingObjects;
|
|
@@ -655,11 +669,11 @@ class Host extends module_1 {
|
|
|
655
669
|
this._logDelayed ||= [];
|
|
656
670
|
HOST.LOG_PROGRESS_PAUSED.add(this);
|
|
657
671
|
}
|
|
658
|
-
this
|
|
672
|
+
this.#logState = 0;
|
|
659
673
|
}
|
|
660
674
|
resumeLog(type) {
|
|
661
675
|
if (!type || this.hasLog(type) || type === 'progress' && !HOST.LOG_PROGRESS) {
|
|
662
|
-
this
|
|
676
|
+
this.#logState = 1;
|
|
663
677
|
const log = this._logDelayed;
|
|
664
678
|
if (log?.length) {
|
|
665
679
|
const trailing = {};
|
|
@@ -723,7 +737,6 @@ class Host extends module_1 {
|
|
|
723
737
|
}
|
|
724
738
|
if (reject) {
|
|
725
739
|
HOST.QUEUE.splice(index, 1);
|
|
726
|
-
addHostThread(this);
|
|
727
740
|
return false;
|
|
728
741
|
}
|
|
729
742
|
if (Array.isArray(args)) {
|
|
@@ -742,10 +755,10 @@ class Host extends module_1 {
|
|
|
742
755
|
return null;
|
|
743
756
|
}
|
|
744
757
|
get config() {
|
|
745
|
-
return this
|
|
758
|
+
return this.#config;
|
|
746
759
|
}
|
|
747
760
|
get username() {
|
|
748
|
-
return
|
|
761
|
+
return this.#username;
|
|
749
762
|
}
|
|
750
763
|
get ipV4() {
|
|
751
764
|
return parseIp(this.config.remoteIp, 4);
|
|
@@ -755,33 +768,34 @@ class Host extends module_1 {
|
|
|
755
768
|
}
|
|
756
769
|
set done(value) {
|
|
757
770
|
if (value) {
|
|
758
|
-
this
|
|
771
|
+
this.#done = true;
|
|
759
772
|
closeHostThread(this);
|
|
760
773
|
}
|
|
761
774
|
}
|
|
762
775
|
get done() {
|
|
763
|
-
return this
|
|
776
|
+
return this.#done || this.aborted;
|
|
764
777
|
}
|
|
765
778
|
get queued() {
|
|
766
|
-
return this
|
|
779
|
+
return !!HOST.QUEUE.find(item => item.instance === this);
|
|
767
780
|
}
|
|
768
781
|
get logState() {
|
|
769
|
-
return this
|
|
782
|
+
return this.#logState;
|
|
770
783
|
}
|
|
771
784
|
get errorCount() {
|
|
772
785
|
return Array.from(this.modules).reduce((a, b) => a + b.errors.length, this.errors.length);
|
|
773
786
|
}
|
|
774
787
|
}
|
|
775
788
|
exports.Host = Host;
|
|
776
|
-
_a = kDone, _b = kQueued, _c = kLogState;
|
|
777
789
|
class Client extends module_1 {
|
|
790
|
+
static [kClient] = true;
|
|
778
791
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
779
792
|
return parent ? super.purgeMemory(percent, limit) : 0;
|
|
780
793
|
}
|
|
794
|
+
module;
|
|
795
|
+
_extensions = null;
|
|
796
|
+
#cacheDir = '';
|
|
781
797
|
constructor(data) {
|
|
782
798
|
super();
|
|
783
|
-
this._extensions = null;
|
|
784
|
-
this[_d] = '';
|
|
785
799
|
this.module = (0, types_1.isPlainObject)(data) ? data : {};
|
|
786
800
|
}
|
|
787
801
|
init(...args) {
|
|
@@ -827,11 +841,11 @@ class Client extends module_1 {
|
|
|
827
841
|
}
|
|
828
842
|
set cacheDir(value) {
|
|
829
843
|
if (path.isAbsolute(value) && module_1.isDir(value)) {
|
|
830
|
-
this
|
|
844
|
+
this.#cacheDir = value;
|
|
831
845
|
}
|
|
832
846
|
}
|
|
833
847
|
get cacheDir() {
|
|
834
|
-
return this
|
|
848
|
+
return this.#cacheDir;
|
|
835
849
|
}
|
|
836
850
|
get settings() {
|
|
837
851
|
return (this.module.settings ||= {});
|
|
@@ -846,8 +860,11 @@ class Client extends module_1 {
|
|
|
846
860
|
}
|
|
847
861
|
}
|
|
848
862
|
exports.Client = Client;
|
|
849
|
-
_d = kCacheDir;
|
|
850
863
|
class ClientDb extends Client {
|
|
864
|
+
database;
|
|
865
|
+
static [kClientDb] = true;
|
|
866
|
+
static STORE_RESULT_PARTITION_SIZE = 16;
|
|
867
|
+
static STORE_RESULT_PARTITION_MULT = 2;
|
|
851
868
|
static get TRANSACTION_ACTIVE() {
|
|
852
869
|
return 1;
|
|
853
870
|
}
|
|
@@ -880,8 +897,9 @@ class ClientDb extends Client {
|
|
|
880
897
|
if ((0, types_1.isPlainObject)(item) && 'enabled' in item) {
|
|
881
898
|
const key = name + '_' + source;
|
|
882
899
|
const stored = CACHE_SOURCE[key];
|
|
883
|
-
|
|
900
|
+
const { enabled, limit = 0, min = 0, max = 0 } = item;
|
|
884
901
|
if (enabled && limit > 0) {
|
|
902
|
+
let percent = item.percent || 0;
|
|
885
903
|
if ((0, types_1.isString)(percent)) {
|
|
886
904
|
percent = percent.includes('%') ? parseFloat(percent) / 100 : parseFloat(percent);
|
|
887
905
|
}
|
|
@@ -939,7 +957,7 @@ class ClientDb extends Client {
|
|
|
939
957
|
return result > 0 ? result : 0;
|
|
940
958
|
}
|
|
941
959
|
static findResult(source, credential, queryString, timeout, sessionKey, renewCache) {
|
|
942
|
-
const userKey = this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential));
|
|
960
|
+
const userKey = credential ? this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential)) : undefined;
|
|
943
961
|
if (!userKey) {
|
|
944
962
|
return;
|
|
945
963
|
}
|
|
@@ -968,7 +986,7 @@ class ClientDb extends Client {
|
|
|
968
986
|
return result;
|
|
969
987
|
}
|
|
970
988
|
try {
|
|
971
|
-
return JSON.parse(fs.readFileSync(result, '
|
|
989
|
+
return JSON.parse(fs.readFileSync(result, 'utf8'));
|
|
972
990
|
}
|
|
973
991
|
catch {
|
|
974
992
|
}
|
|
@@ -983,6 +1001,9 @@ class ClientDb extends Client {
|
|
|
983
1001
|
}
|
|
984
1002
|
}
|
|
985
1003
|
static storeResult(source, credential, queryString, result, options, sessionKey, sessionExpires) {
|
|
1004
|
+
if (!credential) {
|
|
1005
|
+
return result;
|
|
1006
|
+
}
|
|
986
1007
|
let cache, cacheDir;
|
|
987
1008
|
if ((0, types_1.isObject)(sessionKey)) {
|
|
988
1009
|
({ cacheDir, sessionKey, sessionExpires } = sessionKey);
|
|
@@ -1115,10 +1136,10 @@ class ClientDb extends Client {
|
|
|
1115
1136
|
}
|
|
1116
1137
|
return source + '_' + (result || this.asString(credential, true));
|
|
1117
1138
|
}
|
|
1139
|
+
cacheExpires = 600000;
|
|
1118
1140
|
constructor(data, database = []) {
|
|
1119
1141
|
super(data);
|
|
1120
1142
|
this.database = database;
|
|
1121
|
-
this.cacheExpires = 600000;
|
|
1122
1143
|
}
|
|
1123
1144
|
init(config) {
|
|
1124
1145
|
let { cache_dir, session_expires: expires } = this.settings;
|
|
@@ -1167,6 +1188,9 @@ class ClientDb extends Client {
|
|
|
1167
1188
|
return this.settingsOf(source, 'coerce', component) === true || component === 'options' && this.settingsOf(source, 'coerce') === true;
|
|
1168
1189
|
}
|
|
1169
1190
|
getQueryResult(source, credential, queryString, options, renewCache) {
|
|
1191
|
+
if (!credential) {
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1170
1194
|
let sessionKey, value, exclusiveOf;
|
|
1171
1195
|
switch (typeof options) {
|
|
1172
1196
|
case 'boolean':
|
|
@@ -1205,12 +1229,12 @@ class ClientDb extends Client {
|
|
|
1205
1229
|
if (!Array.isArray(result)) {
|
|
1206
1230
|
result = result === undefined ? [] : [result];
|
|
1207
1231
|
}
|
|
1208
|
-
if (!(0, types_1.isString)(queryString)) {
|
|
1232
|
+
if (!credential || !(0, types_1.isString)(queryString)) {
|
|
1209
1233
|
return result;
|
|
1210
1234
|
}
|
|
1211
1235
|
const uuidKey = ClientDb.extractUUID(credential);
|
|
1212
1236
|
let options;
|
|
1213
|
-
if (
|
|
1237
|
+
if (this.hasPermission('memory')) {
|
|
1214
1238
|
let value, exclusiveOf;
|
|
1215
1239
|
if ((0, types_1.isObject)(sessionKey)) {
|
|
1216
1240
|
({ value, sessionKey, exclusiveOf } = sessionKey);
|
|
@@ -1291,12 +1315,473 @@ class ClientDb extends Client {
|
|
|
1291
1315
|
}
|
|
1292
1316
|
}
|
|
1293
1317
|
exports.ClientDb = ClientDb;
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1318
|
+
class WorkerGroup {
|
|
1319
|
+
static checkTimeout(value, active = true) {
|
|
1320
|
+
if (value === Infinity && WORKER_GROUP.TIMEOUT === Infinity) {
|
|
1321
|
+
return active ? module_1.MAX_TIMEOUT : Infinity;
|
|
1322
|
+
}
|
|
1323
|
+
return Math.min(value, WORKER_GROUP.TIMEOUT, module_1.MAX_TIMEOUT);
|
|
1324
|
+
}
|
|
1325
|
+
#max = WORKER_GROUP.MAX;
|
|
1326
|
+
#map = new Map();
|
|
1327
|
+
#workers = [];
|
|
1328
|
+
#locked = WORKER_GROUP.LOCKED;
|
|
1329
|
+
constructor(max = 0, locked) {
|
|
1330
|
+
this.#max = max;
|
|
1331
|
+
if (typeof locked === 'boolean') {
|
|
1332
|
+
this.#locked = locked;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
*[Symbol.iterator]() {
|
|
1336
|
+
for (const worker of this.workers) {
|
|
1337
|
+
yield worker;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
add(name, item, priority = 0) {
|
|
1341
|
+
this.#workers.push([item, Math.max(0, Math.min(100, priority))]);
|
|
1342
|
+
this.#map.set(name, item);
|
|
1343
|
+
if (this.#locked) {
|
|
1344
|
+
item.lock();
|
|
1345
|
+
}
|
|
1346
|
+
item.join(this, name);
|
|
1347
|
+
return this;
|
|
1348
|
+
}
|
|
1349
|
+
delete(name) {
|
|
1350
|
+
let target;
|
|
1351
|
+
if (typeof name === 'string') {
|
|
1352
|
+
target = this.#map.get(name);
|
|
1353
|
+
}
|
|
1354
|
+
else {
|
|
1355
|
+
target = name;
|
|
1356
|
+
name = '';
|
|
1357
|
+
for (const [key, item] of this.#map) {
|
|
1358
|
+
if (item === target) {
|
|
1359
|
+
name = key;
|
|
1360
|
+
break;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
if (name && target) {
|
|
1365
|
+
const index = this.#workers.findIndex(item => item[0] === target);
|
|
1366
|
+
if (index !== -1) {
|
|
1367
|
+
this.#workers.splice(index, 1);
|
|
1368
|
+
this.#map.delete(name);
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return false;
|
|
1373
|
+
}
|
|
1374
|
+
get(name, force = true) {
|
|
1375
|
+
const result = this.#map.get(name);
|
|
1376
|
+
if (result && (this.free(typeof force === 'number' ? force : 1) !== 0 || force === true || result.detached)) {
|
|
1377
|
+
return result;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
free(count = 1) {
|
|
1381
|
+
if (count > 0 && this.sizeOf + count > this.max) {
|
|
1382
|
+
const items = this.#workers.filter(([item]) => !item.detached && item.available > 0);
|
|
1383
|
+
let result = 0;
|
|
1384
|
+
if (items.length > 0) {
|
|
1385
|
+
items.sort((a, b) => {
|
|
1386
|
+
const p = a[1] - b[1];
|
|
1387
|
+
if (p === 0) {
|
|
1388
|
+
const t = Math.trunc(a[0].lastAccessed.getTime() / 1000000) - Math.trunc(b[0].lastAccessed.getTime() / 1000000);
|
|
1389
|
+
if (t === 0) {
|
|
1390
|
+
return a[0].frequencyAccessed - b[0].frequencyAccessed;
|
|
1391
|
+
}
|
|
1392
|
+
return t;
|
|
1393
|
+
}
|
|
1394
|
+
return p;
|
|
1395
|
+
});
|
|
1396
|
+
let j = 1;
|
|
1397
|
+
do {
|
|
1398
|
+
for (let i = 0; i < items.length; ++i) {
|
|
1399
|
+
const worker = items[i][0];
|
|
1400
|
+
const k = worker.drop(1);
|
|
1401
|
+
result += k;
|
|
1402
|
+
count -= k;
|
|
1403
|
+
if (count === 0) {
|
|
1404
|
+
break;
|
|
1405
|
+
}
|
|
1406
|
+
if (j >= worker.available) {
|
|
1407
|
+
items.splice(i--, 1);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
} while (items.length > 0 && ++j);
|
|
1411
|
+
}
|
|
1412
|
+
return result;
|
|
1413
|
+
}
|
|
1414
|
+
return -1;
|
|
1415
|
+
}
|
|
1416
|
+
print(format) {
|
|
1417
|
+
let rows;
|
|
1418
|
+
switch (format) {
|
|
1419
|
+
case 'stats':
|
|
1420
|
+
rows = this.#workers.map(([item, priority]) => ({ Last_Accessed: item.lastAccessed.toISOString().replace('T', ' ').replace(/\.\d+Z$/, ''), Times: item.timesAccessed, Frequency: item.frequencyAccessed, Pending: item.pending, Available: item.available, Errors: item.errors.length, Priority: priority }));
|
|
1421
|
+
break;
|
|
1422
|
+
case 'errors':
|
|
1423
|
+
rows = this.errors;
|
|
1424
|
+
break;
|
|
1425
|
+
default:
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
if (rows.length > 0) {
|
|
1429
|
+
console.table(rows);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
clear() {
|
|
1433
|
+
this.#map.clear();
|
|
1434
|
+
this.#workers.length = 0;
|
|
1435
|
+
}
|
|
1436
|
+
#collectTotal(key) {
|
|
1437
|
+
return this.#workers.reduce((a, b) => a + b[0][key], 0);
|
|
1438
|
+
}
|
|
1439
|
+
set max(value) {
|
|
1440
|
+
if (value > 1) {
|
|
1441
|
+
this.#max = value;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
get max() {
|
|
1445
|
+
return this.#max;
|
|
1446
|
+
}
|
|
1447
|
+
get workers() {
|
|
1448
|
+
return this.#workers.map(item => item[0]);
|
|
1449
|
+
}
|
|
1450
|
+
get pending() {
|
|
1451
|
+
return this.#collectTotal('pending');
|
|
1452
|
+
}
|
|
1453
|
+
get available() {
|
|
1454
|
+
return this.#collectTotal('available');
|
|
1455
|
+
}
|
|
1456
|
+
get errors() {
|
|
1457
|
+
return this.#workers.map(item => item[0].errors).flat().sort((a, b) => a.timeStamp <= b.timeStamp ? -1 : 1);
|
|
1458
|
+
}
|
|
1459
|
+
get size() {
|
|
1460
|
+
return this.#collectTotal('size');
|
|
1461
|
+
}
|
|
1462
|
+
get sizeOf() {
|
|
1463
|
+
return this.#workers.length;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
exports.WorkerGroup = WorkerGroup;
|
|
1467
|
+
class WorkerChannel extends EventEmitter {
|
|
1468
|
+
static create(filename, options, name) {
|
|
1469
|
+
if (typeof options === 'string') {
|
|
1470
|
+
name = options;
|
|
1471
|
+
options = undefined;
|
|
1472
|
+
}
|
|
1473
|
+
let min, max, timeout;
|
|
1474
|
+
if (name) {
|
|
1475
|
+
name = name.replace(/\W+/, '_').toUpperCase() + '_WORKER_';
|
|
1476
|
+
min = process.env[name + 'MIN'];
|
|
1477
|
+
max = process.env[name + 'MAX'];
|
|
1478
|
+
timeout = process.env[name + 'TIMEOUT'];
|
|
1479
|
+
}
|
|
1480
|
+
const result = new WorkerChannel(filename, options, { max: max ? parseInt(max) : undefined, idleTimeout: timeout ? parseInt(timeout) * 1000 : undefined });
|
|
1481
|
+
if (min) {
|
|
1482
|
+
result.min = parseInt(min);
|
|
1483
|
+
}
|
|
1484
|
+
return result;
|
|
1299
1485
|
}
|
|
1486
|
+
static hasPermission(options) {
|
|
1487
|
+
if ((!options || options.worker) && (!process.permission || process.permission.has('worker'))) {
|
|
1488
|
+
return true;
|
|
1489
|
+
}
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1492
|
+
#min = WORKER_CHANNEL.MIN;
|
|
1493
|
+
#max = WORKER_CHANNEL.MAX;
|
|
1494
|
+
#idleTimeout = WORKER_CHANNEL.TIMEOUT;
|
|
1495
|
+
#locked = false;
|
|
1496
|
+
#host = null;
|
|
1497
|
+
#label = undefined;
|
|
1498
|
+
#verbose = WORKER_CHANNEL.VERBOSE;
|
|
1499
|
+
#startTime = process.hrtime.bigint();
|
|
1500
|
+
#accessed = [new Date(), 0];
|
|
1501
|
+
#errors = [];
|
|
1502
|
+
#workerData = null;
|
|
1503
|
+
#filename;
|
|
1504
|
+
#options;
|
|
1505
|
+
#workers = [];
|
|
1506
|
+
#pending = new Set();
|
|
1507
|
+
#timeout = new WeakMap();
|
|
1508
|
+
constructor(filename, options = {}, { max = -1, idleTimeout = 0, verbose } = {}) {
|
|
1509
|
+
super();
|
|
1510
|
+
this.#filename = filename instanceof URL ? (0, node_url_1.fileURLToPath)(filename) : options.eval ? filename : path.resolve(filename);
|
|
1511
|
+
if ('workerData' in options) {
|
|
1512
|
+
this.#workerData = options.workerData;
|
|
1513
|
+
options = { ...options };
|
|
1514
|
+
delete options.workerData;
|
|
1515
|
+
}
|
|
1516
|
+
this.#options = Object.freeze(options);
|
|
1517
|
+
this.max = max;
|
|
1518
|
+
this.idleTimeout = idleTimeout;
|
|
1519
|
+
if (typeof verbose === 'boolean') {
|
|
1520
|
+
this.#verbose = verbose;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
*[Symbol.iterator]() {
|
|
1524
|
+
for (const worker of this.workers) {
|
|
1525
|
+
yield worker;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
sendObject(data, transferList, callback, ...returnArgs) {
|
|
1529
|
+
if (!this.detached && this.pending >= this.max) {
|
|
1530
|
+
this.emit('pass', data, transferList);
|
|
1531
|
+
throw Error("Worker queue is full");
|
|
1532
|
+
}
|
|
1533
|
+
const available = this.#workers.find(item => !this.#pending.has(item[0]));
|
|
1534
|
+
let worker, channel;
|
|
1535
|
+
if (available) {
|
|
1536
|
+
[worker, channel] = available;
|
|
1537
|
+
this.#clearTimeout(worker);
|
|
1538
|
+
}
|
|
1539
|
+
else {
|
|
1540
|
+
channel = new node_worker_threads_1.MessageChannel();
|
|
1541
|
+
const options = { ...this.#options, transferList: [channel.port1] };
|
|
1542
|
+
options.workerData = [channel.port1, this.#workerData];
|
|
1543
|
+
worker = new node_worker_threads_1.Worker(this.filename, options);
|
|
1544
|
+
worker
|
|
1545
|
+
.on('exit', exitCode => {
|
|
1546
|
+
const index = this.#findIndex(worker);
|
|
1547
|
+
if (index !== -1) {
|
|
1548
|
+
this.#workers.splice(index, 1);
|
|
1549
|
+
}
|
|
1550
|
+
this.#clear(worker);
|
|
1551
|
+
this.emit('exit', exitCode);
|
|
1552
|
+
})
|
|
1553
|
+
.on('online', () => {
|
|
1554
|
+
this.emit('online');
|
|
1555
|
+
})
|
|
1556
|
+
.on('message', value => {
|
|
1557
|
+
this.emit('message', value);
|
|
1558
|
+
})
|
|
1559
|
+
.on('messageerror', err => {
|
|
1560
|
+
this.addLog(err);
|
|
1561
|
+
this.emit('messageerror', err);
|
|
1562
|
+
})
|
|
1563
|
+
.on('error', err => {
|
|
1564
|
+
this.addLog(err);
|
|
1565
|
+
this.emit('error', err);
|
|
1566
|
+
});
|
|
1567
|
+
channel.port2.on('close', () => {
|
|
1568
|
+
void worker.terminate();
|
|
1569
|
+
});
|
|
1570
|
+
this.#workers.push([worker, channel]);
|
|
1571
|
+
}
|
|
1572
|
+
this.#pending.add(worker);
|
|
1573
|
+
channel.port2.once('message', (value) => {
|
|
1574
|
+
if (this.detached || this.max > this.size) {
|
|
1575
|
+
void worker.terminate();
|
|
1576
|
+
}
|
|
1577
|
+
else if (this.#clear(worker) && this.size > this.min && this.idleTimeout < Infinity) {
|
|
1578
|
+
this.#timeout.set(worker, setTimeout(() => {
|
|
1579
|
+
void worker.terminate();
|
|
1580
|
+
}, this.idleTimeout));
|
|
1581
|
+
}
|
|
1582
|
+
if (value != null) {
|
|
1583
|
+
this.emit('data', value);
|
|
1584
|
+
}
|
|
1585
|
+
if (typeof callback === 'function') {
|
|
1586
|
+
callback(value, ...returnArgs);
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
this.#accessed[0] = new Date();
|
|
1590
|
+
this.#accessed[1]++;
|
|
1591
|
+
try {
|
|
1592
|
+
worker.postMessage(data, transferList);
|
|
1593
|
+
return worker;
|
|
1594
|
+
}
|
|
1595
|
+
catch (err) {
|
|
1596
|
+
this.#clear(worker);
|
|
1597
|
+
this.addLog(err);
|
|
1598
|
+
this.emit('abort', err);
|
|
1599
|
+
throw err;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
sendBuffer(data, shared = true, callback, ...returnArgs) {
|
|
1603
|
+
try {
|
|
1604
|
+
return this.sendObject(data, shared ? [] : [data.buffer], callback, ...returnArgs);
|
|
1605
|
+
}
|
|
1606
|
+
catch (err) {
|
|
1607
|
+
this.addLog(err);
|
|
1608
|
+
return null;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
async send(data, transferList) {
|
|
1612
|
+
return new Promise((resolve, reject) => {
|
|
1613
|
+
try {
|
|
1614
|
+
this.sendObject(data, transferList, resolve);
|
|
1615
|
+
}
|
|
1616
|
+
catch (err) {
|
|
1617
|
+
this.addLog(err);
|
|
1618
|
+
reject(err);
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
drop(count = 1) {
|
|
1623
|
+
if (!(count > 0) || this.available === 0) {
|
|
1624
|
+
return 0;
|
|
1625
|
+
}
|
|
1626
|
+
const found = [];
|
|
1627
|
+
for (const worker of this.workers) {
|
|
1628
|
+
if (!this.#pending.has(worker)) {
|
|
1629
|
+
found.push(worker);
|
|
1630
|
+
if (--count === 0) {
|
|
1631
|
+
break;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
process.nextTick(() => {
|
|
1636
|
+
for (const worker of found) {
|
|
1637
|
+
try {
|
|
1638
|
+
void worker.terminate();
|
|
1639
|
+
}
|
|
1640
|
+
catch (err) {
|
|
1641
|
+
this.addLog(err);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
});
|
|
1645
|
+
return found.length;
|
|
1646
|
+
}
|
|
1647
|
+
join(group, label) {
|
|
1648
|
+
this.#host?.delete(this);
|
|
1649
|
+
this.#host = group;
|
|
1650
|
+
this.#label = label;
|
|
1651
|
+
}
|
|
1652
|
+
quit() {
|
|
1653
|
+
this.#host = null;
|
|
1654
|
+
this.#label = undefined;
|
|
1655
|
+
}
|
|
1656
|
+
async kill(count = 1) {
|
|
1657
|
+
if (!(count > 0) || this.available === 0) {
|
|
1658
|
+
return 0;
|
|
1659
|
+
}
|
|
1660
|
+
let result = 0;
|
|
1661
|
+
for (const worker of Array.from(this.#pending)) {
|
|
1662
|
+
try {
|
|
1663
|
+
await worker.terminate();
|
|
1664
|
+
++result;
|
|
1665
|
+
if (--count === 0) {
|
|
1666
|
+
break;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
catch (err) {
|
|
1670
|
+
this.addLog(err);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
return result;
|
|
1674
|
+
}
|
|
1675
|
+
lock() {
|
|
1676
|
+
this.#locked = true;
|
|
1677
|
+
}
|
|
1678
|
+
addLog(err, type = types_1.STATUS_TYPE.ERROR) {
|
|
1679
|
+
if (this.#errors.find(item => item.value === err)) {
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
if (this.#verbose) {
|
|
1683
|
+
console.error(err);
|
|
1684
|
+
}
|
|
1685
|
+
this.#errors.push({ timeStamp: new Date(), type, label: this.#label, value: err });
|
|
1686
|
+
}
|
|
1687
|
+
isEmpty() {
|
|
1688
|
+
return this.size === 0;
|
|
1689
|
+
}
|
|
1690
|
+
#clear(worker) {
|
|
1691
|
+
this.#clearTimeout(worker);
|
|
1692
|
+
this.#findChannel(worker)?.port2.removeAllListeners('message');
|
|
1693
|
+
return this.#pending.delete(worker);
|
|
1694
|
+
}
|
|
1695
|
+
#clearTimeout(worker) {
|
|
1696
|
+
const timeout = this.#timeout.get(worker);
|
|
1697
|
+
if (timeout) {
|
|
1698
|
+
clearTimeout(timeout);
|
|
1699
|
+
this.#timeout.delete(worker);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
#findIndex(worker) {
|
|
1703
|
+
return this.#workers.findIndex(item => item[0] === worker);
|
|
1704
|
+
}
|
|
1705
|
+
#findChannel(worker) {
|
|
1706
|
+
const index = this.#findIndex(worker);
|
|
1707
|
+
if (index !== -1) {
|
|
1708
|
+
return this.#workers[index][1];
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
set min(value) {
|
|
1712
|
+
if (this.#locked) {
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
if (value >= 0 && value <= this.max) {
|
|
1716
|
+
this.#min = value;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
get min() {
|
|
1720
|
+
return this.#min;
|
|
1721
|
+
}
|
|
1722
|
+
set max(value) {
|
|
1723
|
+
if (this.#locked) {
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
if (value >= this.min) {
|
|
1727
|
+
this.#max = value;
|
|
1728
|
+
const count = this.size - value;
|
|
1729
|
+
if (count > 0) {
|
|
1730
|
+
void this.drop(count);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
else if (value === 0) {
|
|
1734
|
+
this.#min = 0;
|
|
1735
|
+
this.#max = 0;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
get max() {
|
|
1739
|
+
return this.#max;
|
|
1740
|
+
}
|
|
1741
|
+
set idleTimeout(value) {
|
|
1742
|
+
if (this.#locked) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
if (value > 0) {
|
|
1746
|
+
this.#idleTimeout = WorkerGroup.checkTimeout(value, false);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
get idleTimeout() {
|
|
1750
|
+
return this.#idleTimeout;
|
|
1751
|
+
}
|
|
1752
|
+
get filename() {
|
|
1753
|
+
return this.#filename;
|
|
1754
|
+
}
|
|
1755
|
+
get workers() {
|
|
1756
|
+
return this.#workers.map(item => item[0]);
|
|
1757
|
+
}
|
|
1758
|
+
get detached() {
|
|
1759
|
+
return this.max === 0;
|
|
1760
|
+
}
|
|
1761
|
+
get lastAccessed() {
|
|
1762
|
+
return this.#accessed[0];
|
|
1763
|
+
}
|
|
1764
|
+
get timesAccessed() {
|
|
1765
|
+
return this.#accessed[1];
|
|
1766
|
+
}
|
|
1767
|
+
get frequencyAccessed() {
|
|
1768
|
+
return this.timesAccessed === 0 ? 0 : Number(process.hrtime.bigint() - this.#startTime) / this.timesAccessed;
|
|
1769
|
+
}
|
|
1770
|
+
get pending() {
|
|
1771
|
+
return this.#pending.size;
|
|
1772
|
+
}
|
|
1773
|
+
get available() {
|
|
1774
|
+
return this.size - this.pending;
|
|
1775
|
+
}
|
|
1776
|
+
get errors() {
|
|
1777
|
+
return this.#errors;
|
|
1778
|
+
}
|
|
1779
|
+
get size() {
|
|
1780
|
+
return this.#workers.length;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
exports.WorkerChannel = WorkerChannel;
|
|
1784
|
+
class AbortComponent {
|
|
1300
1785
|
static attach(instance, signal, options) {
|
|
1301
1786
|
let map = ABORT_LISTENER.get(instance);
|
|
1302
1787
|
if (!map) {
|
|
@@ -1319,25 +1804,25 @@ class AbortComponent {
|
|
|
1319
1804
|
map.splice(index, 1);
|
|
1320
1805
|
}
|
|
1321
1806
|
}
|
|
1807
|
+
#controller = new AbortController();
|
|
1322
1808
|
abort(reason) {
|
|
1323
1809
|
if (!this.aborted) {
|
|
1324
|
-
this
|
|
1810
|
+
this.#controller.abort(reason);
|
|
1325
1811
|
}
|
|
1326
1812
|
}
|
|
1327
1813
|
reset() {
|
|
1328
1814
|
if (this.aborted) {
|
|
1329
|
-
this
|
|
1815
|
+
this.#controller = new AbortController();
|
|
1330
1816
|
}
|
|
1331
1817
|
}
|
|
1332
1818
|
get signal() {
|
|
1333
|
-
return this
|
|
1819
|
+
return this.#controller.signal;
|
|
1334
1820
|
}
|
|
1335
1821
|
get aborted() {
|
|
1336
1822
|
return this.signal.aborted;
|
|
1337
1823
|
}
|
|
1338
1824
|
}
|
|
1339
1825
|
exports.AbortComponent = AbortComponent;
|
|
1340
|
-
_e = kAbortHandler;
|
|
1341
1826
|
class Permission {
|
|
1342
1827
|
static create(settings, parent, freeze) {
|
|
1343
1828
|
if (this.validate(settings)) {
|
|
@@ -1346,7 +1831,7 @@ class Permission {
|
|
|
1346
1831
|
parent = null;
|
|
1347
1832
|
}
|
|
1348
1833
|
const { inherit, disk_read, disk_write, unc_read, unc_write } = settings;
|
|
1349
|
-
const result = new
|
|
1834
|
+
const result = new _a(freeze);
|
|
1350
1835
|
if (inherit === false) {
|
|
1351
1836
|
parent = null;
|
|
1352
1837
|
}
|
|
@@ -1389,7 +1874,7 @@ class Permission {
|
|
|
1389
1874
|
return (0, types_1.isPlainObject)(settings) && (readable(settings.disk_read) || readable(settings.disk_write) || readable(settings.unc_read) || readable(settings.unc_write));
|
|
1390
1875
|
}
|
|
1391
1876
|
static clone(permission, freeze) {
|
|
1392
|
-
const result = new
|
|
1877
|
+
const result = new _a(freeze);
|
|
1393
1878
|
if (permission.diskRead) {
|
|
1394
1879
|
result.setDiskRead(permission.getDiskRead());
|
|
1395
1880
|
}
|
|
@@ -1425,62 +1910,102 @@ class Permission {
|
|
|
1425
1910
|
}
|
|
1426
1911
|
return '';
|
|
1427
1912
|
}
|
|
1913
|
+
#diskRead = { enabled: null, value: '' };
|
|
1914
|
+
#diskWrite = { enabled: null, value: '' };
|
|
1915
|
+
#uncRead = { enabled: null, value: '' };
|
|
1916
|
+
#uncWrite = { enabled: null, value: '' };
|
|
1917
|
+
#freeze;
|
|
1428
1918
|
constructor(freeze = false) {
|
|
1429
|
-
this
|
|
1430
|
-
this[_g] = { enabled: null, value: '' };
|
|
1431
|
-
this[_h] = { enabled: null, value: '' };
|
|
1432
|
-
this[_j] = { enabled: null, value: '' };
|
|
1433
|
-
this[kFreeze] = freeze;
|
|
1919
|
+
this.#freeze = freeze;
|
|
1434
1920
|
}
|
|
1435
1921
|
setDiskRead(pathname = '', enabled = true) {
|
|
1436
|
-
|
|
1922
|
+
const r = this.#validate(pathname, enabled, this.#diskRead.enabled);
|
|
1923
|
+
if (r) {
|
|
1924
|
+
this.#diskRead = r;
|
|
1925
|
+
}
|
|
1437
1926
|
}
|
|
1438
1927
|
setDiskWrite(pathname = '', enabled = true) {
|
|
1439
|
-
|
|
1928
|
+
const w = this.#validate(pathname, enabled, this.#diskWrite.enabled);
|
|
1929
|
+
if (w) {
|
|
1930
|
+
this.#diskWrite = w;
|
|
1931
|
+
}
|
|
1440
1932
|
}
|
|
1441
1933
|
setUNCRead(pathname = '', enabled = true) {
|
|
1442
|
-
|
|
1934
|
+
const r = this.#validate(pathname, enabled, this.#uncRead.enabled);
|
|
1935
|
+
if (r) {
|
|
1936
|
+
this.#uncRead = r;
|
|
1937
|
+
}
|
|
1443
1938
|
}
|
|
1444
1939
|
setUNCWrite(pathname = '', enabled = true) {
|
|
1445
|
-
|
|
1940
|
+
const w = this.#validate(pathname, enabled, this.#uncWrite.enabled);
|
|
1941
|
+
if (w) {
|
|
1942
|
+
this.#uncWrite = w;
|
|
1943
|
+
}
|
|
1446
1944
|
}
|
|
1447
1945
|
getDiskRead() {
|
|
1448
|
-
return this
|
|
1946
|
+
return this.#diskRead.value;
|
|
1449
1947
|
}
|
|
1450
1948
|
getDiskWrite() {
|
|
1451
|
-
return this
|
|
1949
|
+
return this.#diskWrite.value;
|
|
1452
1950
|
}
|
|
1453
1951
|
getUNCRead() {
|
|
1454
|
-
return this
|
|
1952
|
+
return this.#uncRead.value;
|
|
1455
1953
|
}
|
|
1456
1954
|
getUNCWrite() {
|
|
1457
|
-
return this
|
|
1955
|
+
return this.#uncWrite.value;
|
|
1458
1956
|
}
|
|
1459
1957
|
hasDiskRead(pathname) {
|
|
1460
|
-
return
|
|
1958
|
+
return this.#permitted(this.#diskRead, pathname);
|
|
1461
1959
|
}
|
|
1462
1960
|
hasDiskWrite(pathname) {
|
|
1463
|
-
return
|
|
1961
|
+
return this.#permitted(this.#diskWrite, pathname);
|
|
1464
1962
|
}
|
|
1465
1963
|
hasUNCRead(pathname) {
|
|
1466
|
-
return
|
|
1964
|
+
return this.#permitted(this.#uncRead, pathname);
|
|
1467
1965
|
}
|
|
1468
1966
|
hasUNCWrite(pathname) {
|
|
1469
|
-
return
|
|
1967
|
+
return this.#permitted(this.#uncWrite, pathname);
|
|
1968
|
+
}
|
|
1969
|
+
#validate(pathname, enabled, current) {
|
|
1970
|
+
if (pathname === true) {
|
|
1971
|
+
pathname = '**/*';
|
|
1972
|
+
enabled = true;
|
|
1973
|
+
}
|
|
1974
|
+
else if (pathname === false) {
|
|
1975
|
+
pathname = '';
|
|
1976
|
+
enabled = false;
|
|
1977
|
+
}
|
|
1978
|
+
if ((current === null || !this.#freeze) && (!enabled || (pathname = _a.toPosix(pathname)))) {
|
|
1979
|
+
if (enabled && Array.isArray(pathname)) {
|
|
1980
|
+
switch (pathname.length) {
|
|
1981
|
+
case 1:
|
|
1982
|
+
pathname = pathname[0];
|
|
1983
|
+
break;
|
|
1984
|
+
case 0:
|
|
1985
|
+
enabled = false;
|
|
1986
|
+
break;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
return Object.freeze({ enabled, value: enabled ? Object.freeze(pathname) : '' });
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
#permitted(permission, pathname) {
|
|
1993
|
+
const { enabled, value } = permission;
|
|
1994
|
+
return enabled === true && (0, types_1.isString)(pathname) && (value === '**/*' || value === '**' || _a.match(pathname, value));
|
|
1470
1995
|
}
|
|
1471
1996
|
get diskRead() {
|
|
1472
|
-
return this
|
|
1997
|
+
return this.#diskRead.enabled === true;
|
|
1473
1998
|
}
|
|
1474
1999
|
get diskWrite() {
|
|
1475
|
-
return this
|
|
2000
|
+
return this.#diskWrite.enabled === true;
|
|
1476
2001
|
}
|
|
1477
2002
|
get uncRead() {
|
|
1478
|
-
return this
|
|
2003
|
+
return this.#uncRead.enabled === true;
|
|
1479
2004
|
}
|
|
1480
2005
|
get uncWrite() {
|
|
1481
|
-
return this
|
|
2006
|
+
return this.#uncWrite.enabled === true;
|
|
1482
2007
|
}
|
|
1483
2008
|
}
|
|
1484
2009
|
exports.Permission = Permission;
|
|
1485
|
-
|
|
2010
|
+
_a = Permission;
|
|
1486
2011
|
PERMISSION = Host.createPermission(true, true);
|