dcp-worker 3.2.32 → 3.2.34

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/.eslintrc.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @file .eslintrc.js - ESLint configuration file, following the Core Team's JS Style Guide.
3
+ *
4
+ * @author Wes Garland <wes@distributive.network>
5
+ * @author Bryan Hoang <bryan@distributive.network>
6
+ * @date Mar. 2022, Sep. 2023
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * @see {@link https://eslint.org/docs/latest/use/configure/}
13
+ * @type {import('eslint').Linter.Config}
14
+ */
15
+ module.exports = {
16
+ root: true,
17
+ reportUnusedDisableDirectives: true,
18
+ extends: ['eslint:recommended', '@distributive'],
19
+ env: {
20
+ node: true,
21
+ es2022: true,
22
+ },
23
+ globals: {
24
+ dcpConfig: true,
25
+ },
26
+ parserOptions: {
27
+ ecmaVersion: 'latest',
28
+ sourceType: 'script',
29
+ },
30
+ rules: {},
31
+ };
package/.gitlab-ci.yml CHANGED
@@ -1,23 +1,70 @@
1
1
  # @file .gitlab-ci.yml - GitLab CI configuration file.
2
2
  # @author Eddie Roosenmallen <eddie@distributive.network>
3
+ # @author Bryan Hoang <bryan@distributive.network>
3
4
  # @date September 2022
4
5
 
6
+ variables:
7
+ # Can't cache `~/.npm/`.
8
+ npm_config_cache: '.cache/npm/'
9
+ npm_config_prefer_offline: 'true'
10
+ npm_config_fund: 'false'
11
+
5
12
  default:
6
13
  # Use in-house GitLab runners.
7
14
  tags:
8
- - dcp
15
+ - dcp-core
9
16
  - linux
17
+ image: node:lts
18
+ before_script:
19
+ - npm add --global npm@latest
20
+ # Access private deps. e.g., `dcp-client` from GitLab.
21
+ - git config --global
22
+ url."${CI_SERVER_PROTOCOL}://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}".insteadOf
23
+ "${CI_SERVER_URL}"
24
+
25
+ workflow:
26
+ rules:
27
+ # Only run branch pipelines for `develop`, or merge request pipelines.
28
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
29
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
10
30
 
11
31
  stages:
12
32
  - build
33
+ - test
13
34
  - deploy
14
35
 
36
+ # Installs npm dependencies to be cached for subsequent jobs. Also checks that
37
+ # the lock file is synced with the manifest file.
38
+ build:
39
+ stage: build
40
+ script:
41
+ - npm clean-install
42
+ cache:
43
+ - key:
44
+ prefix: $CI_JOB_NAME_SLUG
45
+ files:
46
+ - package-lock.json
47
+ paths:
48
+ - $npm_config_cache
49
+ - key:
50
+ prefix: node-modules
51
+ files:
52
+ - package-lock.json
53
+ paths:
54
+ - node_modules/
55
+ policy: push
56
+
15
57
  tidelift:
16
58
  stage: build
59
+ rules:
60
+ - when: never
17
61
  variables:
18
62
  # This should be kept in a GitLab Variable. Read more:
19
63
  # https://docs.gitlab.com/ee/ci/variables/#create-a-custom-variable-in-the-ui
20
64
  TIDELIFT_API_KEY: $TIDELIFT_API_KEY
65
+ inherit:
66
+ default:
67
+ - tags
21
68
  # The CLI only requires `glibc`.
22
69
  image: frolvlad/alpine-glibc
23
70
  before_script:
@@ -30,9 +77,39 @@ tidelift:
30
77
  - echo "Running alignment and saving to Tidelift"
31
78
  - ./tidelift alignment save --wait
32
79
  allow_failure: true
33
- cache: []
80
+
81
+ # Run `trunk check` on the project to hightlight newly introduced lint issues
82
+ # when compared to the target branch.
83
+ check:
84
+ variables:
85
+ # Can't cache `~/.cache/trunk/`.
86
+ TRUNK_CACHE: ${CI_PROJECT_DIR}/.cache/trunk/
87
+ stage: test
88
+ script:
89
+ - UPSTREAM_BRANCH=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_DEFAULT_BRANCH}
90
+ # Fetch the branch so that `trunk` has the proper information needed to
91
+ # determine the upstream changes to compare lint results against.
92
+ - git fetch origin $UPSTREAM_BRANCH
93
+ - npm run check -- --ci --upstream origin/$UPSTREAM_BRANCH
94
+ cache:
95
+ - key:
96
+ prefix: $CI_JOB_NAME_SLUG
97
+ files:
98
+ - .trunk/trunk.yaml
99
+ paths:
100
+ - $TRUNK_CACHE
101
+ - key:
102
+ prefix: node-modules
103
+ files:
104
+ - package-lock.json
105
+ paths:
106
+ - node_modules/
107
+ policy: pull
34
108
 
35
109
  publish_docs:
110
+ stage: deploy
111
+ needs:
112
+ - build
36
113
  rules:
37
114
  - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
38
115
  changes:
@@ -51,8 +128,14 @@ publish_docs:
51
128
  ENTITY_NAMESPACE: 'default'
52
129
  stage: deploy
53
130
  needs: []
54
- image: registry.gitlab.com/distributed-compute-protocol/docker/dcp-ci:2023-09-13
131
+ image: registry.gitlab.com/distributed-compute-protocol/backstage-ci-image:latest
55
132
  script:
56
- - npm clean-install
57
- - python3 -m pip install mkdocs mkdocs-techdocs-core==1.* mkdocs-same-dir
58
133
  - bin/publish-docs.sh
134
+ cache:
135
+ - key:
136
+ prefix: node-modules
137
+ files:
138
+ - package-lock.json
139
+ paths:
140
+ - node_modules/
141
+ policy: pull
@@ -0,0 +1,29 @@
1
+ # @file trunk.yaml - This file controls the behavior of Trunk:
2
+ # https://docs.trunk.io/cli
3
+ #
4
+ # To learn more about the format of this file, see
5
+ # https://docs.trunk.io/reference/trunk-yaml
6
+ #
7
+ # Initially autogenerated by `npm exec -- trunk init --lock`
8
+ #
9
+ # @author Bryan Hoang <bryan@distributive.network>
10
+ # @date Oct. 2023
11
+
12
+ version: 0.1
13
+ cli:
14
+ version: 1.17.1
15
+ sha256:
16
+ darwin_arm64: 707359316ea1f972cbad8a77cb076449155c19d42933cecfe5b70cfefc38d085
17
+ darwin_x86_64: d5e5928a24a4eb9931eaed1d5899be12ab2556f17ce5cd89ef73fa42b2293c88
18
+ linux_x86_64: f2bbf8de19e7961390633fe23599b8890f617a6e8b2563ac6741a0514e7d16e6
19
+ plugins:
20
+ sources:
21
+ - id: trunk
22
+ ref: v1.2.6
23
+ uri: https://github.com/trunk-io/plugins
24
+ runtimes:
25
+ enabled:
26
+ - node@18.12.1
27
+ lint:
28
+ enabled:
29
+ - eslint@8.52.0
@@ -0,0 +1,512 @@
1
+ #! /usr/bin/env node
2
+ /**
3
+ * @file dcp-evaluator-manager
4
+ * Daemon to monitor the state of the system and enable/disable
5
+ * the evaluator as appropriate.
6
+ *
7
+ * The actual mechanics of communicating with the evaluator is
8
+ * similar in principle to how inetd works, and the code is, in
9
+ * fact, based on the dcp inet-daemon.
10
+ *
11
+ * The methods the system can be monitored include:
12
+ * - screensaver enabled/disabled
13
+ *
14
+ * @author Wes Garland, wes@distributive.network
15
+ * @date June 2018, Sep 2022
16
+ */
17
+ 'use strict';
18
+
19
+ const os = require('os');
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const net = require('net')
23
+ const dns = require('dns');
24
+ const debug = require('debug');
25
+ const getopt = require('posix-getopt');
26
+
27
+ var userActivity = { /* no props true => okay to launch evaluator */
28
+ screensaver: true,
29
+ session: true,
30
+ };
31
+ var children;
32
+ var seq = 0;
33
+ var ptsDir = '/dev/pts';
34
+ var lastConnectionMs = 0;
35
+
36
+ const defaultPrefix = '/usr';
37
+ const daemonConfig = {
38
+ net: new URL('tcpip://localhost:9000/'),
39
+ proc: require.resolve('./dcp-evaluator-start'),
40
+ argv: [ '-s', '--prefix', `${path.resolve(defaultPrefix)}/` ],
41
+ limits: {},
42
+ session: {
43
+ idlePoll: 3, /* s between checks*/
44
+ idleTimeout: 30, /* s to decide the session really IS idle */
45
+ }
46
+ };
47
+
48
+ function usage()
49
+ {
50
+ console.log(
51
+ `
52
+ DCP Evaluator Monitor - Copyright (c) 2022-2023 Distributive Corp.
53
+ Released under the terms of the MIT License.
54
+
55
+ Usage: ${process.argv[0]} [-h | --help] [--prefix=<dir>] [--pts=<dir>] [-a]
56
+ [--disable-monitor=<session|screensaver>] [-i <timeout>] [-p port]
57
+ [-l | --max-load=<number>] [-r | --rate=<number>] [-L]
58
+ [-- <options to dcp-evaluator-start, must be last option>]
59
+ Where:
60
+ - -i sets the idle timeout in seconds for tty sessions (${daemonConfig.session.idleTimeout}s)
61
+ - -p specifies the port to listen on for dcpsaw: worker connections (${daemonConfig.net.port})
62
+ - --prefix specifies the directory where the DCP evaluator was installed
63
+ - --pts specifies the location of the system's pseudo terminal (${ptsDir})
64
+ - --disable-monitor=session disables monitoring of ssh/telnet/etc sessions
65
+ - --disable-monitor=screensaver disables monitoring of the screensaver
66
+ - -a means always run the evaluator, even when the monitors say the machine is busy
67
+ - --max-load specifies the point at which machine load prevents connections
68
+ - --rate specifies the minimum number of seconds between connections
69
+ - -L only apply the limits when the monitors say the machine is busy
70
+ `);
71
+
72
+ process.exit(0);
73
+ }
74
+
75
+ /**
76
+ * Establish listening socket evaluator proxy
77
+ */
78
+ async function listenForConnections(config)
79
+ {
80
+ var server = net.createServer((socket) => handleConnection(socket, config));
81
+ var hostaddr;
82
+
83
+ if (config.net.hostname === 'localhost')
84
+ hostaddr = '::';
85
+ else
86
+ hostaddr = await dns.promises.lookup(config.net.hostname, { family: 4 });
87
+
88
+ server.on('error', (error) => {
89
+ delete error.stack;
90
+ console.error(error);
91
+ process.exit(2);
92
+ });
93
+
94
+ server.listen({ host: hostaddr, port: config.net.port }, function daemonReady() {
95
+ console.log('Listening for connections on', server._connectionKey);
96
+ console.log('Evaluator command is', config.proc, config.argv);
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Check the state of the userActivity object to determine if there has been user activity
102
+ * on the system. If there has been, it returns a string of activity types. If there
103
+ * hasn't, it returns false and we are clear to evaluate.
104
+ */
105
+ function checkUserActivity()
106
+ {
107
+ var active = [];
108
+
109
+ for (let prop in userActivity)
110
+ {
111
+ if (userActivity[prop])
112
+ active.push(prop);
113
+ }
114
+
115
+ if (active.length)
116
+ debug('dcp-evaluator-manager')('System is not idle; activity detected via', active.join(', '));
117
+ else
118
+ debug('dcp-evaluator-manager')('System is idle; checked', Object.entries(userActivity).filter(a => a[1] !== null).map(a => a[0]).join(', '));
119
+
120
+ return active.length ? active.join() : false;
121
+ }
122
+
123
+ /**
124
+ * Handle an incoming connection. If the screensaver is not active, the conneciton
125
+ * is immediately rejected. Otherwise, we spin up an evaluator process and proxy its
126
+ * stdio to the socket.
127
+ */
128
+ function handleConnection (socket, config)
129
+ {
130
+ var child;
131
+ var userActivityMemo = checkUserActivity();
132
+
133
+ function cleanup()
134
+ {
135
+ try
136
+ {
137
+ if (socket)
138
+ {
139
+ socket.end();
140
+ socket.destroy();
141
+ socket = null;
142
+ }
143
+ }
144
+ finally
145
+ {
146
+ if (child)
147
+ {
148
+ child.kill();
149
+ if (children.includes(child))
150
+ children.delete(child);
151
+ }
152
+ }
153
+ }
154
+
155
+ if (userActivityMemo && !daemonConfig.limits.onlyWhenBusy)
156
+ {
157
+ debug('dcp-evaluator-manager')(`New connection; closing due to activity (${userActivityMemo})`);
158
+ cleanup();
159
+ return;
160
+ }
161
+
162
+ if (!daemonConfig.limits.onlyWhenBusy || (daemonConfig.limits.onlyWhenBusy && userActivityMemo))
163
+ {
164
+ if (daemonConfig.limits.maxLoad < os.loadavg()[0])
165
+ {
166
+ debug('dcp-evaluator-manager')(`New connection; closing due to system load (${os.loadavg().join(', ')})`);
167
+ cleanup();
168
+ return;
169
+ }
170
+
171
+ if (daemonConfig.limits.rateMs > (Date.now() - lastConnectionMs))
172
+ {
173
+ debug('dcp-evaluator-manager')(`New connection; closing due to rate-limit ${daemonConfig.limits.rateMs} > ${Date.now() - lastConnectionMs}`);
174
+ cleanup();
175
+ return;
176
+ }
177
+ }
178
+
179
+ debug('dcp-evaluator-manager')('New connection; spawning ', config.proc, config.argv);
180
+ lastConnectionMs = Date.now();
181
+
182
+ child = require('child_process').spawn(config.proc, config.argv);
183
+ child.stderr.setEncoding('ascii')
184
+ child.socket = socket;
185
+ children.add(child);
186
+ child.id = ++seq;
187
+ debug('dcp-evaluator-manager')(`Spawned worker process ${child.pid} for child ${child.id}`);
188
+
189
+ socket.on('end', function socketEnd() {
190
+ debug('dcp-evaluator-manager')('Socket end; killing child', child.id);
191
+ cleanup();
192
+ });
193
+
194
+ socket.on('error', function socketError(error) {
195
+ debug('dcp-evaluator-manager')(`Socket error ${error.code}; killing child`, child.id);
196
+ debug('dcp-evaluator-manager')(error);
197
+ cleanup();
198
+ });
199
+
200
+ child.on('error', function childError(error) {
201
+ console.error('Error from worker ' + child.id + ':', error);
202
+ cleanup();
203
+ });
204
+
205
+ child.on('exit', function(code) {
206
+ debug('dcp-evaluator-manager')(`child ${child.id} exited; closing socket`, code || '');
207
+ cleanup();
208
+ });
209
+
210
+ child.stdout.on('data', function (data) {
211
+ debug('dcp-evaluator-manager:network')('<', child.id, bufToDisplayStr(data), 93);
212
+ if (socket)
213
+ socket.write(data)
214
+ });
215
+
216
+ child.stderr.on('data', function (data) {
217
+ console.log('child ' + child.id + ' stderr: ', data);
218
+ });
219
+
220
+ socket.on('data', function (data) {
221
+ debug('dcp-evaluator-manager:network')('>', child.id, bufToDisplayStr(data, 93));
222
+
223
+ try
224
+ {
225
+ child.stdin.write(data)
226
+ }
227
+ catch (error)
228
+ {
229
+ console.warn('could not write to child process (', child.pid, ', index', child.id, ') stdin')
230
+ throw error;
231
+ }
232
+ });
233
+ }
234
+
235
+ /**
236
+ * Format detailed debug output of raw socket traffic
237
+ */
238
+ function bufToDisplayStr (buf, limit)
239
+ {
240
+ const str = buf.toString('utf-8').replace(/\n/, '\u2424').toString('utf-8');
241
+
242
+ if (typeof limit === 'number' && str.length > limit)
243
+ return str.substr(0, limit) + '\u2026';
244
+ else
245
+ return str;
246
+ }
247
+
248
+ /**
249
+ * Kill all evaluators, as quickly as possible.
250
+ */
251
+ function killChildren()
252
+ {
253
+ if (!children.length)
254
+ return;
255
+
256
+ debug('dcp-evaluator-manager')(`Terminating all (${children.length}) running evaluators..`);
257
+ for (let child of children)
258
+ {
259
+ debug('dcp-evaluator-manager')(`killing child ${child.pid}`);
260
+ try
261
+ {
262
+ child.kill('SIGKILL');
263
+ }
264
+ catch(error)
265
+ {
266
+ /* Don't throw if process death race */
267
+ if (error.code !== 'ESRCH')
268
+ throw error;
269
+ }
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Monitor dbus messages for screensaver start / stop events.
275
+ */
276
+ async function dbusScreenSaverMonitor()
277
+ {
278
+ const dbus = odRequire('dbus-next');
279
+ const bus = dbus.sessionBus();
280
+ const screensaverList = [
281
+ 'org.gnome.ScreenSaver',
282
+ 'org.cinnamon.ScreenSaver',
283
+ 'org.kde.screensaver',
284
+ 'org.freedesktop.ScreenSaver'
285
+ ];
286
+ var iface;
287
+
288
+ for (let ss of screensaverList)
289
+ {
290
+ try
291
+ {
292
+ let obj = await bus.getProxyObject(ss, '/' + ss.replace(/\./g, '/'));
293
+ if (obj)
294
+ {
295
+ iface = obj.interfaces[ss];
296
+ break;
297
+ }
298
+ }
299
+ catch (error)
300
+ {
301
+ debug('dcp-evaluator-manager:dbus')('Could not acquire screensaver', ss + '; trying next', error);
302
+ }
303
+ }
304
+
305
+ if (!iface)
306
+ {
307
+ console.error('Could not open dbus session to any screensaver, tried', screensaverList);
308
+ process.exit(3);
309
+ }
310
+
311
+ const ssActive = await iface.GetActive();
312
+ debug('dcp-evaluator-manager')('Screen saver active:', ssActive);
313
+ userActivity.screensaver = ssActive ? false : 'active dbus screensaver (initial)';
314
+
315
+ /* screensaver not active => user activity */
316
+ iface.on('ActiveChanged', function screenSaverChangeHandler(active) {
317
+ userActivity.screensaver = active ? false : 'active dbus screensaver (change)';
318
+ debug('dcp-evaluator-manager')(`screen saver ${active ? 'started' : 'finished'} at`, new Date());
319
+ if (!daemonConfig.limits.onlyWhenBusy && checkUserActivity())
320
+ killChildren();
321
+ });
322
+
323
+ console.log('Monitoring dbus messages for', iface.$name);
324
+ }
325
+
326
+ /* Activate screensaver monitor. Promise resolves when the initial state has been figured out. */
327
+ function screensaverMonitor()
328
+ {
329
+ if (userActivity.screensaver === null) /* disabled */
330
+ return;
331
+
332
+ return dbusScreenSaverMonitor();
333
+ }
334
+
335
+ /**
336
+ * Activate session monitor - mechanism is similar to last/fingerd, where we check the last
337
+ * update time on all ttys to see if there is a remote user using the system or not. We poll
338
+ * this every idleTimeout (15?) seconds, when the screen saver is active.
339
+ */
340
+ function sessionMonitor()
341
+ {
342
+ const myTTY = fs.realpathSync('/dev/stdout');
343
+
344
+ if (userActivity.session === null) /* disabled */
345
+ return;
346
+
347
+ function checkSessions()
348
+ {
349
+ const recentMs = Date.now() - (daemonConfig.session.idleTimeout * 1000);
350
+
351
+ userActivity.session = false;
352
+ for (let dent of fs.readdirSync(ptsDir, { withFileTypes: true }))
353
+ {
354
+ if (!dent.isCharacterDevice())
355
+ continue;
356
+
357
+ const fullPath = path.join(ptsDir, dent.name);
358
+ debug('dcp-evaluator-manager:session')(`Checking TTY ${fullPath}`);
359
+ if (fullPath === myTTY)
360
+ continue;
361
+
362
+ const sb = fs.statSync(fullPath);
363
+ if (sb.atimeMs > recentMs)
364
+ {
365
+ /* Experiment suggests atime involves reads and mtime includes writes. Using mtime so that
366
+ * tailing logs has anticipated result.
367
+ */
368
+ userActivity.session = fullPath;
369
+ debug('dcp-evaluator-manager:session')(`TTY ${fullPath} is active`);
370
+ break;
371
+ }
372
+ }
373
+
374
+ if (!daemonConfig.limits.onlyWhenBusy && checkUserActivity())
375
+ killChildren();
376
+ }
377
+
378
+ setInterval(checkSessions, daemonConfig.session.idlePoll * 1000);
379
+ checkSessions();
380
+ }
381
+
382
+ /* Require an optional dependency, print decent error message if not found, then exit. */
383
+ function odRequire(moduleId)
384
+ {
385
+ try
386
+ {
387
+ return require(moduleId);
388
+ }
389
+ catch(error)
390
+ {
391
+ if (error.code !== 'MODULE_NOT_FOUND')
392
+ throw error;
393
+ }
394
+
395
+ console.error(`Screensaver operating mode requires optional dependency ${moduleId}.`);
396
+ console.error(`Please \`npm i ${moduleId}\` and try again.`);
397
+ process.exit(2);
398
+ }
399
+
400
+ /* Main program entry point */
401
+ async function main()
402
+ {
403
+ const parser = new getopt.BasicParser('h(help)P:(prefix)d:(disable-monitor)l:(max-load)r:(rate)Li:ap:', process.argv);
404
+ var option;
405
+
406
+ while ((option = parser.getopt()) !== undefined)
407
+ {
408
+ switch (option.option)
409
+ {
410
+ case 'h':
411
+ usage();
412
+ break;
413
+
414
+ default:
415
+ throw new Error('defined but unspecified option', option);
416
+
417
+ case '?':
418
+ process.exit(1);
419
+
420
+ case 'P':
421
+ {
422
+ const re = new RegExp(`^${defaultPrefix}/`);
423
+ for (let i=0; i < daemonConfig.argv.length; i++)
424
+ daemonConfig.argv[i] = daemonConfig.argv[i].replace(re, path.resolve(option.optarg + '/'));
425
+ break;
426
+ }
427
+
428
+ case 'd':
429
+ {
430
+ let what = option.optarg;
431
+
432
+ if (what[0] === '=')
433
+ what = what.slice(1);
434
+ userActivity[what] = null; /* null => do not check for this */
435
+ debug('dcp-evaluator-manager')('!', what, 'monitor is disabled');
436
+ break;
437
+ }
438
+
439
+ case 'i':
440
+ {
441
+ daemonConfig.session.idleTimeout = Number(option.optarg).toFixed(1);
442
+ break;
443
+ }
444
+
445
+ case 'a': /* always on => disable everything */
446
+ {
447
+ for (let prop in userActivity)
448
+ {
449
+ if (userActivity.hasOwnProperty(prop))
450
+ userActivity[prop] = null;
451
+ }
452
+ break;
453
+ }
454
+
455
+ case 'L':
456
+ {
457
+ daemonConfig.limits.onlyWhenBusy = true;
458
+ break;
459
+ }
460
+
461
+ case 'p':
462
+ {
463
+ daemonConfig.net.port = Number(option.optarg);
464
+ break;
465
+ }
466
+
467
+ case 'l':
468
+ {
469
+ daemonConfig.limits.maxLoad = Number(option.optarg);
470
+ break;
471
+ }
472
+
473
+ case 'r':
474
+ {
475
+ daemonConfig.limits.rateMs = 1000 * Number(option.optarg);
476
+ break;
477
+ }
478
+ }
479
+ }
480
+
481
+ daemonConfig.argv = daemonConfig.argv.concat(process.argv.slice(parser.optind())); /* All options after -- pass to dcp-evaluator-start */
482
+
483
+ process.on('uncaughtException', function (error) {
484
+ console.error('\n---', (new Date()).toLocaleString(), '-------------------------------------------------')
485
+ console.error('uncaught exception:', error.stack)
486
+ console.error('\n')
487
+ });
488
+
489
+ process.on('unhandledRejection', function (error) {
490
+ console.error('\n---', (new Date()).toLocaleString(), '-------------------------------------------------')
491
+ console.error('unhandled rejection:', error.stack)
492
+ console.error('\n')
493
+ })
494
+
495
+ children = new (require('dcp/utils').Inventory)();
496
+
497
+ await screensaverMonitor();
498
+ sessionMonitor();
499
+
500
+ listenForConnections(daemonConfig);
501
+ }
502
+
503
+ /* Initialize dcp-client to use only local resources before launching the main function */
504
+ require('dcp-client').init({
505
+ progName: 'dcp-worker',
506
+ parseArgv: false,
507
+ configName: process.env.DCP_CONFIG || '../etc/dcp-worker-config',
508
+ dcpConfig: {
509
+ scheduler: { configLocation: false },
510
+ bundle: { location: false },
511
+ }
512
+ }).then(main);
package/bin/dcp-worker CHANGED
@@ -155,9 +155,10 @@ function parseCliArgs()
155
155
  type: 'number',
156
156
  group: 'Output options',
157
157
  },
158
- eventDebug: {
159
- hidden: true,
160
- describe: 'If set, dump all sandbox and worker events',
158
+
159
+ showConfig: {
160
+ hide: false,
161
+ describe: 'Show merged configuration node (eg worker)',
161
162
  },
162
163
 
163
164
  logfile: {
@@ -219,6 +220,12 @@ function parseCliArgs()
219
220
  .wrap(process.stdout.columns || 80)
220
221
  .argv;
221
222
 
223
+ if (cliArgs.showConfig)
224
+ {
225
+ console.log(eval('dcpConfig.' + cliArgs.showConfig));
226
+ process.exit();
227
+ }
228
+
222
229
  if (cliArgs.dumpConfig)
223
230
  {
224
231
  console.log(JSON.stringify(require('dcp/dcp-config'), null, 2));
@@ -391,9 +398,6 @@ async function main()
391
398
  else
392
399
  worker.on('end', () => setTimeout(processExit, getCleanupTimeoutMs()).unref());
393
400
 
394
- if (cliArgs.eventDebug)
395
- worker.enableDebugEvents = true;
396
-
397
401
  if (dcpWorkerOptions.publicGroupFallback)
398
402
  {
399
403
  if (dcpWorkerOptions.leavePublicGroup)
@@ -449,8 +453,6 @@ async function main()
449
453
  introBanner += ` . Target core density: ${JSON.stringify(dcpWorkerOptions.defaultCoreDensity)}\n`;
450
454
  if (cliArgs.verbose)
451
455
  introBanner += ` + Verbosity level: ${cliArgs.verbose}` + '\n';
452
- if (cliArgs.eventDebug)
453
- introBanner += ' + Event debug on' + '\n';
454
456
  if (telnetd.hasOwnProperty('port'))
455
457
  introBanner += ` ! telnetd listening on port ${telnetd.port}\n`;
456
458
 
@@ -67,8 +67,8 @@ npx techdocs-cli publish \
67
67
  --publisher-type awsS3 \
68
68
  --storage-name "$TECHDOCS_S3_BUCKET_NAME" \
69
69
  --entity "$ENTITY_NAMESPACE"/"$ENTITY_KIND"/"$ENTITY_NAME" \
70
- --directory "$ROOT_DIR"/site
70
+ --directory "$DOCS_DIR"/site
71
71
 
72
- rm -r "$ROOT_DIR"/site
72
+ rm -r "$DOCS_DIR"/site
73
73
 
74
74
  echo "View generated component: https://backstage.overwatch.distributive.network/docs/default/component/$ENTITY_NAME"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcp-worker",
3
- "version": "3.2.32",
3
+ "version": "3.2.34",
4
4
  "description": "JavaScript portion of DCP Workers for Node.js",
5
5
  "main": "bin/dcp-worker",
6
6
  "keywords": [
@@ -17,6 +17,7 @@
17
17
  "license": "MIT",
18
18
  "author": "Kings Distributed Systems",
19
19
  "bin": {
20
+ "dcp-evaluator-manager": "bin/dcp-evaluator-manager",
20
21
  "dcp-evaluator-start": "bin/dcp-evaluator-start",
21
22
  "dcp-worker": "bin/dcp-worker"
22
23
  },
@@ -25,9 +26,11 @@
25
26
  "etc": "etc"
26
27
  },
27
28
  "scripts": {
29
+ "check": "trunk check",
28
30
  "start": "node bin/dcp-worker start",
29
31
  "start-evaluator": "node bin/dcp-evaluator-start",
30
32
  "hook": "PATH=npm-hooks:$PATH &&",
33
+ "lint": "eslint --cache --cache-strategy=content --cache-location=.cache/eslint/ --ignore-path=.gitignore --ext=js .",
31
34
  "test": "peter tests",
32
35
  "prepack": "node npm-hooks/prepack",
33
36
  "postpublish": "npm-hooks/postpublish",
@@ -37,17 +40,22 @@
37
40
  "blessed": "^0.1.81",
38
41
  "blessed-contrib": "^4.11.0",
39
42
  "chalk": "^4.1.0",
40
- "dcp-client": "4.3.2",
43
+ "dcp-client": "4.3.4",
44
+ "kvin": "^1.2.7",
45
+ "posix-getopt": "^1.2.1",
41
46
  "semver": "^7.3.8",
42
47
  "syslog-client": "1.1.1"
43
48
  },
44
49
  "optionalDependencies": {
50
+ "dbus-next": "^0.10.2",
45
51
  "telnet-console": "^1.0.4"
46
52
  },
47
53
  "devDependencies": {
54
+ "@distributive/eslint-plugin": "1.0.2",
48
55
  "@kingsds/eslint-config": "^1.0.1",
49
- "@techdocs/cli": "1.4.6",
50
- "eslint": ">=8"
56
+ "@trunkio/launcher": "1.2.7",
57
+ "eslint": ">=8",
58
+ "eslint-plugin-jsdoc": "46.8.2"
51
59
  },
52
60
  "peerDependencies": {
53
61
  "node-eventlog": "https://gitpkg.now.sh/Distributive-Network/node-eventlog/package?dcp/0.0.1"
@@ -60,5 +68,8 @@
60
68
  "engines": {
61
69
  "node": ">=18",
62
70
  "npm": ">=7"
71
+ },
72
+ "overrides": {
73
+ "@azure/msal-node": "2.2.0"
63
74
  }
64
75
  }
package/.eslintrc.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "env": {
3
- "commonjs": true,
4
- "es2021": true,
5
- "node": true
6
- },
7
- "extends": ["@kingsds"],
8
- "parserOptions": {
9
- "ecmaVersion": 12
10
- },
11
- "rules": {}
12
- }