dcp-worker 3.2.30-9 → 3.2.30

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/.gitlab-ci.yml CHANGED
@@ -28,4 +28,5 @@ tidelift:
28
28
  script:
29
29
  - echo "Running alignment and saving to Tidelift"
30
30
  - ./tidelift alignment save --wait
31
+ allow_failure: true
31
32
  cache: []
package/bin/dcp-worker CHANGED
@@ -4,25 +4,26 @@
4
4
  * Standalone NodeJS DCP Worker
5
5
  *
6
6
  * @author Ryan Rossiter, ryan@kingsds.network
7
+ * Paul, paul@distributive.network
8
+ * Wes Garland, wes@distributive.network
9
+ *
7
10
  * @date April 2020
11
+ * April-May 2023
12
+ * May-June 2023
8
13
  */
9
14
  'use strict';
10
15
 
16
+ var worker;
17
+
11
18
  const process = require('process');
12
19
  const fs = require('fs');
20
+ const path = require('path');
13
21
  const crypto = require('crypto');
14
22
  const chalk = require('chalk');
23
+ const telnetd = require('../lib/remote-console');
24
+ const utils = require('../lib/utils');
15
25
 
16
26
  const configName = process.env.DCP_CONFIG || '../etc/dcp-worker-config';
17
- var worker, dcpConfig, debugging;
18
-
19
- const debug = (...args) => {
20
- if (!debugging)
21
- debugging = require('dcp/internal/debugging').scope('dcp-worker');
22
- if (debugging())
23
- console.debug('dcp-worker:', ...args);
24
- };
25
-
26
27
  const EXIT_UNHANDLED = 5;
27
28
 
28
29
  /* Setup the telnet REPL up early to ensure early-failure log messages are captured */
@@ -34,13 +35,15 @@ const replHelpers = {
34
35
  },
35
36
  commands: {
36
37
  report: printReport,
37
- kill: process.exit,
38
+ kill: processExit,
38
39
  die: () => worker && worker.stop()
39
40
  },
40
41
  };
41
- require('../lib/remote-console').init(replHelpers);
42
+ telnetd.init(replHelpers);
42
43
 
43
- /* Initialize dcp-client with local config defaults and run the main function. DCP_CONFIG_COOKIE becomes dcpConfig.cookie. */
44
+ /* Initialize dcp-client with local config defaults and run the main function. DCP_CONFIG_COOKIE becomes dcpConfig.cookie.
45
+ * And dcpConfig is defined as a side effect of initializing dcp-client.
46
+ */
44
47
  process.env.DCP_CONFIG_COOKIE = (Math.random().toString(16)).slice(2) + '-' + process.pid + '-' + Date.now();
45
48
  require('dcp-client').init({ configName }).then(main).catch(handleUnhandled);
46
49
 
@@ -48,7 +51,6 @@ function parseCliArgs()
48
51
  {
49
52
  var defaultPidFileName;
50
53
 
51
- dcpConfig = require('dcp/dcp-config');
52
54
  defaultPidFileName = require('../lib/pidfile').getDefaultPidFileName(dcpConfig.worker.pidfile);
53
55
 
54
56
  const cliArgs = require('dcp/cli')
@@ -67,7 +69,6 @@ function parseCliArgs()
67
69
  alias: 'd',
68
70
  describe: 'default proportion of CPU,GPU to use when cores not specified',
69
71
  type: 'string',
70
- default: JSON.stringify(dcpConfig.worker.defaultCoreDensity),
71
72
  },
72
73
  verbose: {
73
74
  alias: 'v',
@@ -98,18 +99,21 @@ function parseCliArgs()
98
99
  },
99
100
  priorityOnly: {
100
101
  alias: 'P',
102
+ hidden: true,
101
103
  describe: 'Set the priority mode [deprecated]',
102
104
  type: 'boolean',
103
105
  default: false
104
106
  },
105
107
  'job-id': {
106
108
  alias: 'j',
109
+ hidden: true,
107
110
  describe: 'Restrict worker to a specific job (use N times for N jobs)',
108
111
  type: 'array',
109
112
  },
110
113
 
111
114
  join: {
112
115
  alias: 'g',
116
+ hidden: true,
113
117
  describe: 'Join compute group; the format is "joinKey,joinSecret" or "joinKey,eh1-joinHash"',
114
118
  type: 'array'
115
119
  },
@@ -120,22 +124,27 @@ function parseCliArgs()
120
124
 
121
125
  leavePublicGroup: {
122
126
  type: 'boolean',
123
- describe: 'Do not fetch slices from public compute group. Ignored if --publicGroupFallback is set',
124
- default: false,
127
+ hidden: true,
128
+ describe: 'Do not fetch slices from public compute group.',
129
+ default: undefined,
125
130
  },
131
+
126
132
  publicGroupFallback: {
133
+ hidden: true,
127
134
  describe: 'If set, worker will prefer private groups but fall back on the public group if no preferred work is available',
128
135
  type: 'boolean',
129
- default: 'false',
130
- defaultDescription: false,
136
+ default: 'undefined',
137
+ defaultDescription: undefined,
131
138
  },
132
139
 
133
140
  identityKey: {
141
+ hidden: true,
134
142
  describe: 'Identity key, in hex format',
135
143
  type: 'string',
136
144
  group: 'Identity options',
137
145
  },
138
146
  identityKeystore: {
147
+ hidden: true,
139
148
  describe: 'Identity keystore, in json format',
140
149
  type: 'string',
141
150
  group: 'Identity options',
@@ -147,30 +156,40 @@ function parseCliArgs()
147
156
  group: 'Output options',
148
157
  },
149
158
  eventDebug: {
150
- hide: true,
159
+ hidden: true,
151
160
  describe: 'If set, dump all sandbox and worker events',
152
161
  },
153
162
 
154
163
  logfile: {
155
- describe: 'Path to log file (if --output=file)',
164
+ describe: 'Path to log file',
156
165
  type: 'string',
157
166
  group: 'Log File output options',
167
+ default: path.resolve('../log/dcp-worker.log'),
158
168
  },
159
169
  syslogAddress: {
160
- describe: 'Address of rsyslog server (if --output=syslog)',
170
+ describe: 'Address of syslog server',
161
171
  type: 'string',
162
172
  group: 'Syslog output options',
173
+ default: 'loghost',
174
+ },
175
+ syslogFacility: {
176
+ describe: 'Name of syslog facility',
177
+ type: 'string',
178
+ group: 'Syslog output options',
179
+ default: 'local7',
163
180
  },
164
181
  syslogTransport: {
165
- describe: 'Transport to connect to rsyslog daemon (if --output=syslog)',
182
+ describe: 'Transport to connect to use for syslog',
166
183
  type: 'string',
167
- choices: ['udp','tcp'],
184
+ choices: ['udp','tcp','unix','tls'],
168
185
  group: 'Syslog output options',
186
+ default: 'udp',
169
187
  },
170
188
  syslogPort: {
171
- describe: 'UDP/TCP port of rsyslog server',
189
+ describe: 'UDP/TCP port to use for syslog',
172
190
  type: 'number',
173
191
  group: 'Syslog output options',
192
+ default: 514,
174
193
  },
175
194
 
176
195
  allowedOrigins: {
@@ -202,8 +221,8 @@ function parseCliArgs()
202
221
 
203
222
  if (cliArgs.dumpConfig)
204
223
  {
205
- console.debug(JSON.stringify(require('dcp/dcp-config'), null, 2));
206
- process.exit(0);
224
+ console.log(JSON.stringify(require('dcp/dcp-config'), null, 2));
225
+ processExit(0);
207
226
  }
208
227
 
209
228
  return cliArgs;
@@ -228,6 +247,20 @@ function addConfig(target, ...objs)
228
247
  Object.assign(target, tmp);
229
248
  }
230
249
 
250
+ /**
251
+ * Replacement for process.exit() that tries to increase the probability
252
+ * that remote log messages will make it out over the network.
253
+ */
254
+ function processExit()
255
+ {
256
+ logClosing('debug', 'Exit Code:', process.exitCode || 0);
257
+ if (console.close)
258
+ console.close();
259
+ setImmediate(() => {
260
+ process.exit.apply(null, arguments);
261
+ });
262
+ }
263
+
231
264
  /**
232
265
  * Main program entry point. Assumes DCP client is already initialized and console logging is ready.
233
266
  */
@@ -235,21 +268,22 @@ async function main()
235
268
  {
236
269
  const wallet = require('dcp/wallet');
237
270
  const DCPWorker = require('dcp/worker').Worker;
238
- const { startWorkerLogger } = require('../lib/startWorkerLogger');
239
271
  const cliArgs = parseCliArgs();
240
272
  const sawOptions = {
241
273
  hostname: cliArgs.hostname,
242
274
  port: cliArgs.port
243
275
  };
244
276
 
245
- verifyDefaultConfigIntegrity();
277
+ telnetd.setMainEval(function mainEval() { return eval(arguments[0]) }); // eslint-disable-line no-eval
278
+ require('../lib/startWorkerLogger').init(cliArgs); /* Start remote logger as early as possible */
279
+ verifyDefaultConfigIntegrity(); /* Bail before TUI & as early as possible if bad conf */
246
280
 
247
281
  process.on('SIGINT', handleSigDeath);
248
282
  process.on('SIGTERM', handleSigDeath);
249
283
  process.on('SIGQUIT', handleSigDeath);
250
284
  process.on('unhandledRejection', handleUnhandled);
251
285
  process.on('uncaughtException', handleUnhandled);
252
-
286
+
253
287
  let paymentAddress = false
254
288
  || cliArgs.paymentAddress
255
289
  || dcpConfig.worker.paymentAddress
@@ -260,7 +294,7 @@ async function main()
260
294
  if (cliArgs.pidFile)
261
295
  require('../lib/pidfile').write(cliArgs.pidFile);
262
296
 
263
- /* Figure out of the worker's identity and put that keystore in the wallet */
297
+ /* Figure out the worker's identity and put that keystore in the wallet */
264
298
  let identityKeystore = false;
265
299
  if (cliArgs.identityKey)
266
300
  identityKeystore = await new wallet.IdKeystore(cliArgs.identityKey, '');
@@ -278,11 +312,14 @@ async function main()
278
312
  * which were derived from dcpConfig in the first place. defaultOptions are overrideable by the usual
279
313
  * dcpConfig mechanisms, but since they are dynamic (or non-user-facing) they don't come from the
280
314
  * etc/dcp-worker-config.js file that ships with the work.
315
+ *
316
+ * It is important to never disable leavePublicGroup as a side effect of any other operation, or
317
+ * slight configuration errors could have large security impacts.
281
318
  */
282
319
  const dcpWorkerOptions = dcpConfig.worker;
283
320
  const forceOptions = {
284
321
  paymentAddress,
285
- leavePublicGroup: cliArgs.leavePublicGroup || dcpConfig.worker.leavePublicGroup || cliArgs.publicGroupFallback || false,
322
+ maxWorkingSandboxes: cliArgs.cores,
286
323
  };
287
324
  const defaultOptions = {
288
325
  sandboxOptions: {
@@ -290,9 +327,21 @@ async function main()
290
327
  },
291
328
  };
292
329
 
330
+ if (cliArgs.leavePublicGroup !== undefined)
331
+ forceOptions.leavePublicGroup = mkBool(cliArgs.leavePublicGroup);
332
+ if (cliArgs.publicGroupFallback !== undefined)
333
+ forceOptions.publicGroupFallback = mkBool(cliArgs.publicGroupFallback);
334
+
293
335
  addConfig(dcpWorkerOptions, defaultOptions, dcpConfig.worker, forceOptions);
294
336
  processCoresAndDensity(dcpWorkerOptions, cliArgs);
295
337
 
338
+ /* Support magic value used by Windows screensaver configuration /wg June 2023 */
339
+ if (dcpWorkerOptions.leavePublicGroup === 'fallback')
340
+ {
341
+ dcpWorkerOptions.publicGroupFallback = true;
342
+ dcpWorkerOptions.leavePublicGroup = undefined;
343
+ }
344
+
296
345
  /* cliArgs.join is the list of compute groups to join */
297
346
  if (cliArgs.join && cliArgs.join.length)
298
347
  {
@@ -325,47 +374,44 @@ async function main()
325
374
  dcpWorkerOptions.watchdogInterval = cliArgs.watchdogInterval;
326
375
 
327
376
  worker = new DCPWorker(identityKeystore, dcpWorkerOptions);
328
- worker.on('error', (...payload) => console.error(...payload));
329
- worker.on('warning', (...payload) => console.warn(...payload));
377
+ worker.on('error', (...payload) => console.error(...payload));
378
+ worker.on('warning', (...payload) => console.warn (...payload));
379
+ worker.on('stop', () => { console.log('Worker is stopping') });
380
+ worker.on('end', () => { logClosing('log', 'Worker has stopped') });
381
+ require('../lib/default-ui-events').hook(worker, cliArgs);
330
382
 
383
+ if (cliArgs.outputMode === 'dashboard')
384
+ require('../lib/dashboard-tui').init(worker, cliArgs);
385
+
331
386
  /* Let incorrect event-loop references keep us alive when linked with a debug library, but
332
387
  * exit quickly/accurately for production code even when the library isn't perfect.
333
388
  */
334
389
  if (require('dcp/build').config.build !== 'debug')
335
- worker.on('end', process.exit);
390
+ worker.on('end', processExit);
336
391
  else
337
- worker.on('end', () => setTimeout(process.exit, getCleanupTimeoutMs()).unref());
392
+ worker.on('end', () => setTimeout(processExit, getCleanupTimeoutMs()).unref());
338
393
 
339
394
  if (cliArgs.eventDebug)
340
395
  worker.enableDebugEvents = true;
341
396
 
342
- worker.on('stop', () => { console.log('Worker is stopping') });
343
- worker.on('end', () => { logClosing('log', 'Worker has stopped') });
344
- startWorkerLogger(worker, cliArgs);
345
-
346
- require('../lib/remote-console').setMainEval(function mainEval() { return eval(arguments[0]) });
347
-
348
- // Activate public group fallback
349
- // If requested by CLI
350
- // OR if requested by dcpConfig and not forbidden by the cli
351
- if (cliArgs.publicGroupFallback
352
- || (dcpConfig.worker?.leavePublicGroup === 'fallback'
353
- && typeof cliArgs.publicGroupFallback !== false))
397
+ if (dcpWorkerOptions.publicGroupFallback)
354
398
  {
355
- dcpWorkerOptions.publicGroupFallback = true;
356
-
357
- // If local config blocks the public group, then complain instead of activating fallback
358
- if (dcpConfig.worker?.leavePublicGroup === true)
359
- {
360
- console.warn('* Public Group fallback has been requested, but the public group is blocked by local configuration');
361
- }
399
+ if (dcpWorkerOptions.leavePublicGroup)
400
+ console.warn(' ! Public Group fallback has been requested, but the public group is blocked by local configuration');
362
401
  else
363
402
  {
364
- worker.on('fetchend', slicesFetched => {
365
- // Iff we got work in this fetch, then leave the public group for the
366
- // next fetch
367
- dcpConfig.worker.leavePublicGroup = Boolean(slicesFetched > 0);
368
- });
403
+ /* Enable public group fallback - this currently works by enabling or disabling the public group
404
+ * on the next fetch based on whether or not the most recent fetch was an empty task or not.
405
+ */
406
+ worker.on('fetch', fetchEventHandler);
407
+
408
+ function fetchEventHandler(ev)
409
+ {
410
+ if (ev instanceof Error)
411
+ console.error('Error fetching task:', ev);
412
+ else
413
+ dcpWorkerOptions.leavePublicGroup = Boolean(utils.slicesFetched(ev) > 0);
414
+ }
369
415
  }
370
416
  }
371
417
 
@@ -391,21 +437,23 @@ async function main()
391
437
 
392
438
  if (dcpWorkerOptions.jobAddresses?.length > 0)
393
439
  introBanner += ` * Processing only ${qty(dcpWorkerOptions.jobAddresses, 'job')} ` + dcpWorkerOptions.jobAddresses.join(', ') + '\n';
394
- if (dcpWorkerOptions.computeGroups?.length > 0)
440
+ if (dcpWorkerOptions.computeGroups && Object.keys(dcpWorkerOptions.computeGroups).length > 0)
395
441
  introBanner += ` . Joining compute ${qty(dcpWorkerOptions.computeGroups, 'group')} ` + dcpWorkerOptions.computeGroups.map(el => el.joinKey).join(', ') + '\n';
396
442
  if (dcpWorkerOptions.publicGroupFallback)
397
443
  introBanner += ' . Falling back on public group when preferred groups have no work' + '\n';
398
- else if (dcpWorkerOptions.leavePublicGroup)
444
+ if (dcpWorkerOptions.leavePublicGroup)
399
445
  introBanner += ' . Leaving the public compute group' + '\n';
400
446
  if (dcpWorkerOptions.cores)
401
- introBanner += ` . Target cores: ${JSON.stringify(dcpWorkerOptions.cores)}\n`;
447
+ introBanner += ` . Configured Cores: ${dcpWorkerOptions.cores.cpu},${dcpWorkerOptions.cores.gpu}\n`
402
448
  else
403
449
  introBanner += ` . Target core density: ${JSON.stringify(dcpWorkerOptions.defaultCoreDensity)}\n`;
404
450
  if (cliArgs.verbose)
405
451
  introBanner += ` + Verbosity level: ${cliArgs.verbose}` + '\n';
406
452
  if (cliArgs.eventDebug)
407
453
  introBanner += ' + Event debug on' + '\n';
408
-
454
+ if (telnetd.hasOwnProperty('port'))
455
+ introBanner += ` ! telnetd listening on port ${telnetd.port}\n`;
456
+
409
457
  introBanner += ' . Supervisor version: ' + worker.supervisorVersion;
410
458
  introBanner += ' . Output mode: ' + cliArgs.outputMode + '\n';
411
459
  introBanner += ' * Ready' + '\n';
@@ -418,7 +466,7 @@ async function main()
418
466
  if (cliArgs.outputMode !== 'dashboard')
419
467
  setInterval(printReport, parseFloat(cliArgs.reportInterval) * 1000).unref();
420
468
  else
421
- console.log('Ignoring --reportInterval in dashboard output mode');
469
+ console.warn('Ignoring --reportInterval in dashboard output mode');
422
470
  }
423
471
 
424
472
  /* Start the worker. Normal process exit happens by virtue of the worker<end> event */
@@ -445,21 +493,22 @@ function processCoresAndDensity (dcpWorkerOptions, cliArgs)
445
493
 
446
494
  const parseArg = (which) => {
447
495
  if (!cliArgs[which])
448
- return false;
449
-
450
- const [cpu, gpu] = cliArgs[which].split(',');
451
- dcpWorkerOptions[which] = { cpu: Number(cpu || defaultTargets[which].cpu),
452
- gpu: Number(gpu || defaultTargets[which].gpu) };
453
- return true;
496
+ dcpWorkerOptions[which] = defaultTargets[which];
497
+ else
498
+ {
499
+ const [cpu, gpu] = cliArgs[which].split(',');
500
+ dcpWorkerOptions[which] = { cpu: Number(cpu || defaultTargets[which].cpu),
501
+ gpu: Number(gpu || defaultTargets[which].gpu) };
502
+ }
454
503
  };
455
504
 
456
505
  parseArg('density');
457
506
  parseArg('cores');
458
507
 
459
508
  if (dcpWorkerOptions.cores)
460
- debug('cores = ', dcpWorkerOptions.cores);
461
- else
462
- debug('core density = ', dcpWorkerOptions.defaultCoreDensity);
509
+ debugging() && console.debug('dcp-worker: cores =', dcpWorkerOptions.cores);
510
+ if (dcpWorkerOptions.density)
511
+ debugging() && console.debug('dcp-worker: core density =', dcpWorkerOptions.density);
463
512
  }
464
513
 
465
514
  /**
@@ -470,9 +519,7 @@ function logClosing(facility, ...message)
470
519
  {
471
520
  var screen = require('../lib/worker-loggers/dashboard').screen;
472
521
 
473
- if (!screen)
474
- console[facility](message);
475
- else
522
+ if (screen)
476
523
  {
477
524
  /* Turn off fullscreen TUI and resume "normal" console logging.
478
525
  * FUTURE: dashboard API should know how to unregister its hook so that we don't have to clobber
@@ -481,10 +528,11 @@ function logClosing(facility, ...message)
481
528
  screen.log(...message);
482
529
  screen.destroy();
483
530
  screen = false;
484
- console = new (require('console').Console)(process);
485
- require('../lib/remote-console').reintercept();
486
- console[facility].call(null, ...message);
531
+ console = new (require('console').Console)(process); // eslint-disable-line no-global-assign
532
+ telnetd.reintercept();
487
533
  }
534
+
535
+ console[facility](...message);
488
536
  }
489
537
 
490
538
  /**
@@ -493,7 +541,7 @@ function logClosing(facility, ...message)
493
541
  * the worker must be restarted. This handler does its best to report the rejection and give the worker a few
494
542
  * seconds in which to attempt to return slices to the scheduler before it gives up completely.
495
543
  */
496
- async function handleUnhandled(error)
544
+ function handleUnhandled(error)
497
545
  {
498
546
  var _worker = worker;
499
547
  worker = false;
@@ -502,21 +550,21 @@ async function handleUnhandled(error)
502
550
 
503
551
  try
504
552
  {
505
- logClosing(error);
506
- } catch(e) {};
553
+ logClosing('error', error);
554
+ } catch(e) {} // eslint-disable-line no-empty
507
555
 
508
556
  if (!_worker)
509
557
  console.error('trapped unhandled error:', error)
510
558
  else
511
559
  {
512
560
  console.error('trapped unhandled error -- stopping worker:', error);
513
- _worker.on('end', process.exit);
561
+ _worker.on('end', processExit);
514
562
  _worker.stop();
515
563
  }
516
564
 
517
565
  setTimeout(() => {
518
566
  logClosing('error', 'handleFatalError timeout - exiting now');
519
- process.exit();
567
+ processExit();
520
568
  }, getCleanupTimeoutMs()).unref();
521
569
 
522
570
  try {
@@ -526,7 +574,7 @@ async function handleUnhandled(error)
526
574
  fs.appendFileSync(process.env.DCP_WORKER_UNHANDLED_REJECTION_LOG,
527
575
  `${Date.now()}: ${error.message}\n${error.stack}\n\n`);
528
576
  }
529
- } catch(e) {};
577
+ } catch(e) {} // eslint-disable-line no-empty
530
578
  }
531
579
 
532
580
  /** print the slice report via console.log */
@@ -584,14 +632,14 @@ function sliceReport()
584
632
 
585
633
  report += ('Progress:') + '\n';
586
634
  worker.workingSandboxes.forEach(sb => {
587
- const jobName = sb.job && sb.job.public && sb.job.public.name || `idek (${sb.jobAddress})`;
635
+ const jobName = sb.job?.public?.name || `idek (${sb.jobAddress})`;
588
636
  let el = Date.now() - sb.sliceStartTime;
589
637
  const t = el < 1000000
590
638
  ? toInterval(el)
591
639
  : 'new';
592
640
 
593
641
  el = sb.progressReports && sb.progressReports.last
594
- ? Date.now() - (sb.sliceStartTime + sb.progressReports.last.timestamp)
642
+ ? Date.now() - (sb.sliceStartTime + (sb.progressReports.last?.timestamp ?? 0))
595
643
  : 0;
596
644
  const pct = (typeof sb.progress) === 'number'
597
645
  ? `${Number(sb.progress).toFixed(0).padStart(2)}%`
@@ -623,14 +671,14 @@ function handleSigDeath(signalName, signal)
623
671
  process.off(signalName, handleSigDeath);
624
672
 
625
673
  if (!worker)
626
- console.error(`trapped ${signalName}, signal ${signal}`);
674
+ console.warn(`trapped ${signalName}, signal ${signal}`);
627
675
  else
628
676
  {
629
- console.error(`trapped ${signalName}, signal ${signal} -- stopping worker`);
677
+ console.warn(`trapped ${signalName}, signal ${signal} -- stopping worker`);
630
678
  worker.stop(signalName === 'SIGQUIT');
631
679
  }
632
680
 
633
- setTimeout(() => process.exit(signal - 128), getCleanupTimeoutMs()).unref();
681
+ setTimeout(() => processExit(signal - 128), getCleanupTimeoutMs()).unref();
634
682
  }
635
683
 
636
684
  /**
@@ -650,7 +698,7 @@ function getCleanupTimeoutMs()
650
698
  cleanupTimeout = defaultCT;
651
699
  if (!getCleanupTimeoutMs.warned)
652
700
  {
653
- console.warn(`warning: dcpConfig.worker.cleanupTimeout is not a number (${dcpConfig.worker.cleanupTimeout})`);
701
+ console.error(`warning: dcpConfig.worker.cleanupTimeout is not a number (${dcpConfig.worker.cleanupTimeout})`);
654
702
  getCleanupTimeoutMs.warned = true;
655
703
  }
656
704
  }
@@ -672,14 +720,14 @@ function verifyDefaultConfigIntegrity()
672
720
 
673
721
  if (!fs.existsSync(md5sumPath))
674
722
  {
675
- console.log(chalk.bold.red(` ! warning: ${md5sumPath} not found; cannot verify configuration integrity`));
723
+ console.error(chalk.bold.red(` ! warning: ${md5sumPath} not found; cannot verify configuration integrity`));
676
724
  require('dcp/utils').sleep(2);
677
725
  }
678
726
  else
679
727
  {
680
728
  const originalMd5sum = fs.readFileSync(md5sumPath, 'ascii');
681
729
  const actualMd5sum = crypto.createHash('md5')
682
- .update(fs.readFileSync(workerConfPath, 'ascii'))
730
+ .update(fs.readFileSync(workerConfPath))
683
731
  .digest('hex');
684
732
 
685
733
  if (!originalMd5sum.startsWith(actualMd5sum))
@@ -694,7 +742,7 @@ function verifyDefaultConfigIntegrity()
694
742
  console.warn(' - the Windows Registry');
695
743
 
696
744
  if (require('dcp/build').config.build !== 'debug')
697
- process.exit(1);
745
+ processExit(1);
698
746
 
699
747
  console.log(chalk.bold.red.inverse("If this wasn't a debug build, the worker would exit now."));
700
748
  require('dcp/utils').sleep(2);
@@ -704,6 +752,23 @@ function verifyDefaultConfigIntegrity()
704
752
  if (dcpConfig.cookie !== process.env.DCP_CONFIG_COOKIE || !dcpConfig.cookie)
705
753
  {
706
754
  console.error(' ! DCP Worker default configuration was not loaded; exiting.');
707
- process.exit(1);
755
+ processExit(1);
708
756
  }
709
757
  }
758
+
759
+ /* thunk - ensures global debugging() symbol always available even if called before dcp-client init */
760
+ function debugging()
761
+ {
762
+ require('dcp-client');
763
+ debugging = require('dcp/internal/debugging').scope('dcp-worker');
764
+ return debugging.apply(this, arguments);
765
+ }
766
+
767
+ /**
768
+ * Cast b to boolean such that 'false' becomes false, falsey things become false, and everything else
769
+ * becomes true.
770
+ */
771
+ function mkBool(b)
772
+ {
773
+ return Boolean(b) && (b !== 'false');
774
+ }
package/docs/CODEOWNERS CHANGED
@@ -18,9 +18,11 @@
18
18
  /package-lock.json @eroosenmaallen
19
19
 
20
20
  [Wes]
21
+ /npm-hooks/ @wesgarland
21
22
  /README.md @wesgarland
22
23
  /docs/ @wesgarland
23
24
  /.eslintrc.json @wesgarland
25
+ /.npmrc @wesgarland
24
26
  /.tidelift @wesgarland
25
27
  /lib/ @wesgarland
26
28
  /LICENSE.md @wesgarland
@@ -49,7 +49,7 @@
49
49
  // keystore('~/.dcp/scott'),
50
50
  ],
51
51
 
52
- jobAddresses: [], /* If specified, restrict the worker to only these jobs */
52
+ jobAddresses: false, /* If specified, restrict the worker to only these jobs */
53
53
  paymentAddress: undefined, /* Bank account where earned funds are transfered if not specified on command-line */
54
54
  },
55
55
 
@@ -1,2 +1,2 @@
1
- 8edf1c57bee521ed7f151a21b8f3f34d
1
+ 4d49057dd014344e4be5a266e9754824
2
2
  ### DO NOT MODIFY THIS FILE!!! ###
@@ -1,3 +1,4 @@
1
+ 'use strict';
1
2
 
2
3
  Object.assign(exports, require('./log'));
3
4
  Object.assign(exports, require('./sandboxes'));
@@ -7,6 +7,7 @@
7
7
  * log component, but features text wrapping and behaves
8
8
  * closer to the built-in console log methods.
9
9
  */
10
+ 'use strict';
10
11
 
11
12
  const { Box } = require('blessed');
12
13
 
@@ -67,11 +67,7 @@ class Sandboxes extends Box {
67
67
  update(data=this.data) {
68
68
  this.data = data;
69
69
  for (let i = 0; i < this.data.length; i++) {
70
- if (i < this.progressBars.length) {
71
- this.updateProgressBar(i, this.data[i]);
72
- } else {
73
- this.createProgressBar();
74
- }
70
+ this.updateProgressBar(i, this.data[i]);
75
71
  }
76
72
 
77
73
  if (this.data.length < this.progressBars.length) {
@@ -80,7 +76,15 @@ class Sandboxes extends Box {
80
76
  }
81
77
  }
82
78
 
83
- this.setLabel(`${this.options.label} (${this.data.length})`);
79
+ this.setLabel(`${this.options.label} (${this.progressBars.length})`);
80
+ }
81
+
82
+ // Deletes last progress bar
83
+ deleteProgressBar() {
84
+ let i = this.progressBars.length - 1;
85
+ this.progressBars[i].label.destroy()
86
+ this.progressBars[i].progressBar.destroy()
87
+ this.progressBars.pop(i)
84
88
  }
85
89
  }
86
90
 
@@ -6,6 +6,7 @@
6
6
  * @author Sam Cantor
7
7
  * @date Nov 2020
8
8
  */
9
+ 'use strict';
9
10
 
10
11
  exports.check = function checkSchedulerVersion$$check(quiet)
11
12
  {