dcp-worker 4.0.0 → 4.1.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/bin/dcp-task-probe +21 -37
- package/bin/dcp-worker +13 -12
- package/lib/dashboard-tui.js +2 -2
- package/lib/default-ui-events.js +5 -7
- package/package.json +2 -2
- package/tests/worker-with-no-options.simple +6 -10
- package/tests/worker-with-options.simple +9 -9
package/bin/dcp-task-probe
CHANGED
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
* - signature: ethereum signature object
|
|
10
10
|
* - auth:
|
|
11
11
|
* - workerId: our worker id
|
|
12
|
-
* - authSlices: job
|
|
12
|
+
* - authSlices: job id props -> array of number
|
|
13
13
|
* - schedulerId: { address: scheduler's address }
|
|
14
|
-
* - jobCommissions: job
|
|
14
|
+
* - jobCommissions: job id props
|
|
15
15
|
* - rate: number
|
|
16
16
|
* - bank account
|
|
17
17
|
* - body:
|
|
18
|
-
* - newJobs: job
|
|
19
|
-
* - address: job
|
|
18
|
+
* - newJobs: job id props
|
|
19
|
+
* - address: job id
|
|
20
20
|
* - metrics:
|
|
21
21
|
* - sliceCPUTime
|
|
22
22
|
* - sliceGPUTime
|
|
@@ -40,15 +40,14 @@
|
|
|
40
40
|
* - modulePath: array
|
|
41
41
|
* - dependencies: array of module identifiers
|
|
42
42
|
* - urlParameters:
|
|
43
|
-
* - job: job
|
|
43
|
+
* - job: job id
|
|
44
44
|
* - jobId: uuid
|
|
45
45
|
* - workerConsole: 0
|
|
46
46
|
* - worktime:
|
|
47
47
|
* - name
|
|
48
48
|
* - version
|
|
49
|
-
* - task: job
|
|
50
|
-
* -
|
|
51
|
-
* - uuid: uuid
|
|
49
|
+
* - task: job id props -> array
|
|
50
|
+
* - jobId: opaqueId
|
|
52
51
|
* - worker: worker opaque id
|
|
53
52
|
* - sliceNumber
|
|
54
53
|
* - cotaskCount
|
|
@@ -281,7 +280,7 @@ async function processOptions(workerConfig)
|
|
|
281
280
|
const opts = { verbose: 0 };
|
|
282
281
|
const parser = new getopt.BasicParser('h(help)C(dumpConfig)S:(set)M:(merge)a:(allowedOrigins)'
|
|
283
282
|
+ 'c:(cores)u:(utilization)m:(maxSandboxes)w:(workerId)'
|
|
284
|
-
+ '
|
|
283
|
+
+ 'j:(job)g:(computeGroup)G(leaveGlobalGroup)'
|
|
285
284
|
+ 'H:(hostname)p:(port)r(replay)l(load)i(input)o(output)'
|
|
286
285
|
+ 'v(verbose)',
|
|
287
286
|
process.argv);
|
|
@@ -334,12 +333,8 @@ async function processOptions(workerConfig)
|
|
|
334
333
|
workerConfig.maxSandboxes = Number(opthnd.optarg);
|
|
335
334
|
break;
|
|
336
335
|
|
|
337
|
-
case '
|
|
338
|
-
workerConfig.
|
|
339
|
-
break;
|
|
340
|
-
|
|
341
|
-
case 'j': /** @todo integrate with upcoming scheduler changes to opaqueId /wg dec 2024 */
|
|
342
|
-
workerConfig.jobs = (workerConfig.jobs || []).concat(opthnd.optarg);
|
|
336
|
+
case 'j':
|
|
337
|
+
workerConfig.jobIds = (workerConfig.jobIds || []).concat(opthnd.optarg);
|
|
343
338
|
break;
|
|
344
339
|
|
|
345
340
|
case 'G':
|
|
@@ -474,24 +469,6 @@ function readWorkerSnapshot()
|
|
|
474
469
|
return readWorkerSnapshot.cache;
|
|
475
470
|
}
|
|
476
471
|
|
|
477
|
-
/**
|
|
478
|
-
* Generate non-global compute group secrets, hashed with the current task distributor connection's
|
|
479
|
-
* dcpsid. Add in the public group if necessary.
|
|
480
|
-
*
|
|
481
|
-
* @todo unify with supervisor /wg dec2024
|
|
482
|
-
*/
|
|
483
|
-
function makeComputeGroupsRequest(tdConn, dummyWorker)
|
|
484
|
-
{
|
|
485
|
-
const options = Object.assign({}, dummyWorker.config);
|
|
486
|
-
const taskDistributor = { connection: tdConn };
|
|
487
|
-
|
|
488
|
-
dummyWorker.badSupervisorBackdoor.dcp4.generateWorkerComputeGroups.apply({ taskDistributor, options });
|
|
489
|
-
if (!dummyWorker.config.leavePublicGroup && !dummyWorker.config.leaveGlobalGroup)
|
|
490
|
-
options.computeGroups.unshift({ joinKey: 'public' });
|
|
491
|
-
return options.computeGroups;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
|
|
495
472
|
/**
|
|
496
473
|
* Request a task from the task distributor
|
|
497
474
|
*
|
|
@@ -525,8 +502,7 @@ async function requestTask(dummyWorker, opts)
|
|
|
525
502
|
jobQuanta: [ 1 ]/* this.quanta.calculateJobQuanta() */,
|
|
526
503
|
capabilities: dummyWorker.config.capabilities,
|
|
527
504
|
paymentAddress: dummyWorker.config.paymentAddress,
|
|
528
|
-
|
|
529
|
-
workerComputeGroups: makeComputeGroupsRequest(tdConn, dummyWorker),
|
|
505
|
+
jobIds: dummyWorker.config.jobIds || [],
|
|
530
506
|
minimumWage: dummyWorker.config.minimumWage,
|
|
531
507
|
soteriaJobs: [],
|
|
532
508
|
overdueSlices: [],
|
|
@@ -542,7 +518,16 @@ async function requestTask(dummyWorker, opts)
|
|
|
542
518
|
debug('dcp-task-probe:request')('Task Request:', request);
|
|
543
519
|
|
|
544
520
|
const rtStart = Date.now();
|
|
545
|
-
const
|
|
521
|
+
const tdRequest = new tdConn.Request({operation: 'requestTask', data: request});
|
|
522
|
+
tdRequest.connection.on('beforeSend', function beforeSendHandler (request) {
|
|
523
|
+
/* need to delay hashing because connection might not be established yet, but we need the dcpsid */
|
|
524
|
+
if (request !== tdRequest)
|
|
525
|
+
return;
|
|
526
|
+
const hashedComputeGroups = require('dcp/compute-groups').generateTaskRequestWorkerComputeGroups(dummyWorker.config, request);
|
|
527
|
+
request.payload.data.workerComputeGroups = hashedComputeGroups;
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
const response = await tdRequest.send();
|
|
546
531
|
const rtElapsed = Date.now() - rtStart;
|
|
547
532
|
console.log('Task Request Time: ', fmtMs(rtElapsed));
|
|
548
533
|
|
|
@@ -550,7 +535,6 @@ async function requestTask(dummyWorker, opts)
|
|
|
550
535
|
if (!response.success)
|
|
551
536
|
panic('request failed:', response.payload);
|
|
552
537
|
|
|
553
|
-
debugger;
|
|
554
538
|
return { response, workerId: request.coreStats?.worker, workerConfig: dummyWorker.config };
|
|
555
539
|
}
|
|
556
540
|
|
package/bin/dcp-worker
CHANGED
|
@@ -166,7 +166,7 @@ function parseCliArgs()
|
|
|
166
166
|
showConfig: {
|
|
167
167
|
hide: false,
|
|
168
168
|
describe: 'Show worker config',
|
|
169
|
-
type: '
|
|
169
|
+
type: 'boolean',
|
|
170
170
|
},
|
|
171
171
|
|
|
172
172
|
logfile: {
|
|
@@ -316,19 +316,20 @@ async function main()
|
|
|
316
316
|
return isHash(b) ? { joinKey: a, joinHash: b } : { joinKey: a, joinSecret: b };
|
|
317
317
|
})
|
|
318
318
|
.filter((el) => el.joinKey); /* Filter out entries with no joinKey */
|
|
319
|
-
|
|
320
|
-
leafMergeInto(workerConfig.computeGroups, cliComputeGroups);
|
|
319
|
+
workerConfig.computeGroups = cliComputeGroups;
|
|
321
320
|
}
|
|
322
321
|
|
|
323
322
|
if (cliArgs.jobId)
|
|
324
323
|
{
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
workerConfig.jobAddresses.push(...cliArgs.jobId);
|
|
324
|
+
workerConfig.jobIds = [];
|
|
325
|
+
workerConfig.jobIds.push(...cliArgs.jobId);
|
|
328
326
|
}
|
|
329
327
|
|
|
330
328
|
if (cliArgs.allowedOrigins)
|
|
329
|
+
{
|
|
330
|
+
workerConfig.allowOrigins = { any: [] };
|
|
331
331
|
workerConfig.allowOrigins.any.push(...cliArgs.allowedOrigins);
|
|
332
|
+
}
|
|
332
333
|
|
|
333
334
|
if (cliArgs.watchdogInterval)
|
|
334
335
|
workerConfig.watchdogInterval = cliArgs.watchdogInterval;
|
|
@@ -345,7 +346,7 @@ async function main()
|
|
|
345
346
|
|
|
346
347
|
if (cliArgs.showConfig)
|
|
347
348
|
{
|
|
348
|
-
console.log(
|
|
349
|
+
console.log(JSON.stringify(worker.config, null, 2));
|
|
349
350
|
process.exit();
|
|
350
351
|
}
|
|
351
352
|
|
|
@@ -359,7 +360,7 @@ async function main()
|
|
|
359
360
|
worker.on('warning', (...payload) => console.warn (...payload));
|
|
360
361
|
worker.on('stop', () => { console.log('Worker is stopping') });
|
|
361
362
|
worker.on('end', () => { logClosing('log', 'Worker has stopped') });
|
|
362
|
-
worker.on('job', job => console.log(` . Job: ${job.name} ${job.
|
|
363
|
+
worker.on('job', job => console.log(` . Job: ${job.name} ${job.id.slice(0,8)} ${job.description || ''} ${job.link || ''}`));
|
|
363
364
|
|
|
364
365
|
// Display clean diagnostic when not debugging and env var
|
|
365
366
|
// DCP_SUPERVISOR_DEBUG_DISPLAY_MAX_INFO isn't set.
|
|
@@ -425,8 +426,8 @@ async function main()
|
|
|
425
426
|
return plural;
|
|
426
427
|
}
|
|
427
428
|
|
|
428
|
-
if (worker.config.
|
|
429
|
-
bannerLog(` * Processing only ${qty(worker.config.
|
|
429
|
+
if (worker.config.jobIds?.length > 0)
|
|
430
|
+
bannerLog(` * Processing only ${qty(worker.config.jobIds, 'job')} ` + worker.config.jobIds.join(', '));
|
|
430
431
|
if (worker.config.computeGroups && Object.keys(worker.config.computeGroups).length > 0)
|
|
431
432
|
bannerLog(` . Joining compute ${qty(worker.config.computeGroups, 'group')} ` + worker.config.computeGroups.map(el => el.joinKey).join(', '));
|
|
432
433
|
if (worker.config.publicGroupFallback)
|
|
@@ -663,7 +664,7 @@ function sliceReport()
|
|
|
663
664
|
|
|
664
665
|
report += ('Progress:') + '\n';
|
|
665
666
|
worker.workingSandboxes.forEach(sb => {
|
|
666
|
-
const jobName = sb.job?.public?.name || `idek (${sb.
|
|
667
|
+
const jobName = sb.job?.public?.name || `idek (${sb.jobId})`;
|
|
667
668
|
let el = Date.now() - sb.sliceStartTime;
|
|
668
669
|
const t = el < 1000000
|
|
669
670
|
? toInterval(el)
|
|
@@ -677,7 +678,7 @@ function sliceReport()
|
|
|
677
678
|
: 'ind';
|
|
678
679
|
const stale = (el < 2000) ? '' : `(stale: ${toInterval(el)})`;
|
|
679
680
|
|
|
680
|
-
report += (` ${String(sb.id).padStart(4)}: ${sb.
|
|
681
|
+
report += (` ${String(sb.id).padStart(4)}: ${sb.jobId} ${jobName.padEnd(34)} `+ `${t} ${pct} ${stale}`.padStart(13)) + '\n';
|
|
681
682
|
});
|
|
682
683
|
|
|
683
684
|
report += ('Slices:') + '\n';
|
package/lib/dashboard-tui.js
CHANGED
|
@@ -162,7 +162,7 @@ exports.init = function dashboard$$init(worker, options, bannerLogCumulative)
|
|
|
162
162
|
` Bank Account: ${chalk.yellow(worker.paymentAddress || 'Starting...')}`,
|
|
163
163
|
` Identity: ${chalk.yellow(worker.identityKeystore? worker.identityKeystore.address : 'Starting...')}`,
|
|
164
164
|
` GPU: ${gpuInfo}`,
|
|
165
|
-
` Jobs: ${worker.config.
|
|
165
|
+
` Jobs: ${worker.config.jobIds?.length ? worker.config.jobIds.join(', ') : '<any>'}`,
|
|
166
166
|
` Compute Groups: ${Object.keys(worker.config.computeGroups).length + (worker.config.leavePublicGroup ? 0 : 1)}`,
|
|
167
167
|
`Global Compute Group: ${worker.config.leavePublicGroup ? 'no' : 'yes'}`,
|
|
168
168
|
` Worker Id: ${worker.id}`,
|
|
@@ -184,7 +184,7 @@ exports.init = function dashboard$$init(worker, options, bannerLogCumulative)
|
|
|
184
184
|
|
|
185
185
|
replaceSandboxEventHandler('job', function dashboard$$sandboxJob(sandbox, sandboxData, job) {
|
|
186
186
|
sandboxData.job = job;
|
|
187
|
-
sandboxData.label = job.name ? `${job.name} ${job.
|
|
187
|
+
sandboxData.label = job.name ? `${job.name} ${job.opaqueId.slice(0,8)}` : `<job ${job.opaqueId}>`;
|
|
188
188
|
if (job.description)
|
|
189
189
|
sandboxData.label += ': ' + job.description;
|
|
190
190
|
sandboxPane.update();
|
package/lib/default-ui-events.js
CHANGED
|
@@ -44,18 +44,16 @@ function placeholder()
|
|
|
44
44
|
*/
|
|
45
45
|
exports.hook = function defaultUiEvents$$hook(worker, options)
|
|
46
46
|
{
|
|
47
|
-
const sliceMap = {}; //
|
|
48
|
-
const truncationLength = 22; // Extra 2 for '0x'
|
|
47
|
+
const sliceMap = {}; // jobId --> ( sliceNumber, t0 )
|
|
49
48
|
|
|
50
49
|
delete exports.hook;
|
|
51
50
|
|
|
52
51
|
function makeSliceId (sandbox, sliceNumber)
|
|
53
52
|
{
|
|
54
|
-
if (!sandbox.
|
|
53
|
+
if (!sandbox.jobId)
|
|
55
54
|
return '<no job>';
|
|
56
55
|
|
|
57
|
-
const
|
|
58
|
-
const baseInfo = sandbox?.public ? `${address}: ${sandbox.public.name}` : address;
|
|
56
|
+
const baseInfo = sandbox?.public ? `${sandbox.jobId}: ${sandbox.public.name}` : sandbox.jobId;
|
|
59
57
|
|
|
60
58
|
if (!sliceNumber)
|
|
61
59
|
sliceNumber = sandbox.sliceNumber;
|
|
@@ -88,13 +86,13 @@ exports.hook = function defaultUiEvents$$hook(worker, options)
|
|
|
88
86
|
delete sliceMap[sandbox.id];
|
|
89
87
|
};
|
|
90
88
|
|
|
91
|
-
workerEventHandlers.payment = function paymentHandler(dcc, account,
|
|
89
|
+
workerEventHandlers.payment = function paymentHandler(dcc, account, jobId) {
|
|
92
90
|
const payment = parseFloat(dcc);
|
|
93
91
|
|
|
94
92
|
if (isNaN(payment))
|
|
95
93
|
console.error(' ! Failed to parse payment:', payment);
|
|
96
94
|
else
|
|
97
|
-
console.log(` . Payment: ${payment.toFixed(3)} ⊇ ${
|
|
95
|
+
console.log(` . Payment: ${payment.toFixed(3)} ⊇ ${jobId.slice(0, 8)}`);
|
|
98
96
|
};
|
|
99
97
|
|
|
100
98
|
workerEventHandlers.beforeFetch = function beforeFetchHandler() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dcp-worker",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Node.js Worker for Distributive Compute Platform",
|
|
5
5
|
"main": "bin/dcp-worker",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"blessed": "^0.1.81",
|
|
40
40
|
"blessed-contrib": "4.11.0",
|
|
41
41
|
"chalk": "^4.1.0",
|
|
42
|
-
"dcp-client": "^
|
|
42
|
+
"dcp-client": "^5.0.0",
|
|
43
43
|
"kvin": "^1.2.7",
|
|
44
44
|
"posix-getopt": "^1.2.1",
|
|
45
45
|
"semver": "^7.3.8",
|
|
@@ -31,7 +31,7 @@ async function main()
|
|
|
31
31
|
writeFileSync(`${tempd}/default.keystore`, JSON.stringify(ks.toJSON()), { encoding: 'utf-8' });
|
|
32
32
|
writeFileSync(`${tempd}/id.keystore`, JSON.stringify(id.toJSON()), { encoding: 'utf-8' });
|
|
33
33
|
const res = spawnSync(
|
|
34
|
-
'../bin/dcp-worker', ['--
|
|
34
|
+
'../bin/dcp-worker', ['--showConfig'],
|
|
35
35
|
{
|
|
36
36
|
encoding: 'utf-8',
|
|
37
37
|
env: {
|
|
@@ -42,15 +42,11 @@ async function main()
|
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
const confObj = JSON.parse(res.stdout);
|
|
45
|
-
strictEqual(confObj.
|
|
46
|
-
strictEqual(confObj.
|
|
47
|
-
deepEqual(confObj.
|
|
48
|
-
deepEqual(confObj.
|
|
49
|
-
deepEqual(confObj.
|
|
50
|
-
deepEqual(confObj.worker.utilization, { cpu: 1, gpu: 0.75 }, `Mismatch in utilization! cpu: ${confObj.worker.utilization.cpu}, gpu: ${confObj.worker.utilization.gpu}`);
|
|
51
|
-
deepEqual(confObj.worker.computeGroups, [], `computeGroups should be an empty array it includes ${confObj.worker.computeGroups}`);
|
|
52
|
-
deepEqual(confObj.worker.maxSandboxes, undefined, `Mismatch! maxSandboxes:${confObj.worker.maxSandboxes}`);
|
|
53
|
-
deepEqual(confObj.worker.jobAddresses, undefined, `jobAddresses should be false but it is ${confObj.worker.jobAddresses}`);
|
|
45
|
+
strictEqual(confObj.paymentAddress, ks.address.valueOf(), `${confObj.paymentAddress} payment address is not correct`);
|
|
46
|
+
strictEqual(confObj.leavePublicGroup, undefined, `leaveComputeGroup is ${confObj.leavePublicGroup}`);
|
|
47
|
+
deepEqual(confObj.allowOrigins.any, [], `allowOrigins should be empty. It includes ${confObj.allowOrigins.any}`);
|
|
48
|
+
deepEqual(confObj.utilization, { cpu: 1, gpu: 0.75 }, `Mismatch in utilization! cpu: ${confObj.utilization.cpu}, gpu: ${confObj.utilization.gpu}`);
|
|
49
|
+
deepEqual(confObj.jobIds, undefined, `jobIds should be false but it is ${confObj.jobIds}`);
|
|
54
50
|
|
|
55
51
|
console.log('Done.');
|
|
56
52
|
}
|
|
@@ -40,7 +40,7 @@ async function main()
|
|
|
40
40
|
'--maxSandboxes', '5',
|
|
41
41
|
'--job-id', '09fd0909Bd93f7bad915726C3AB4',
|
|
42
42
|
'--join', `joinKey1,joinHash1`, '-g', 'joinKey2,joinHash2',
|
|
43
|
-
'--
|
|
43
|
+
'--showConfig' ],
|
|
44
44
|
{
|
|
45
45
|
encoding: 'utf-8',
|
|
46
46
|
env: {
|
|
@@ -51,14 +51,14 @@ async function main()
|
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
const confObj = JSON.parse(res.stdout);
|
|
54
|
-
strictEqual(confObj.
|
|
55
|
-
strictEqual(confObj.
|
|
56
|
-
deepEqual(confObj.
|
|
57
|
-
deepEqual(confObj.
|
|
58
|
-
deepEqual(confObj.
|
|
59
|
-
deepEqual(confObj.
|
|
60
|
-
deepEqual(confObj.
|
|
61
|
-
deepEqual(confObj.
|
|
54
|
+
strictEqual(confObj.paymentAddress, '0x9fd0909Bd93f7bad915726C3AB499391384b8b4b', `${confObj.paymentAddress} payment address is not corrrect`);
|
|
55
|
+
strictEqual(confObj.leavePublicGroup, true, `leaveComputeGroup is ${confObj.leavePublicGroup}`);
|
|
56
|
+
deepEqual(confObj.allowOrigins.any.includes('test-url'), true, `allowOrigins only includes ${confObj.allowOrigins.any}!`);
|
|
57
|
+
deepEqual(confObj.cores, { cpu: 3, gpu: 1 }, `Mismatch in cores! cpu: ${confObj.cores.cpu}, gpu: ${confObj.cores.gpu}`);
|
|
58
|
+
deepEqual(confObj.utilization, { cpu: 0.1, gpu: 0.5 }, `Mismatch in utilization! cpu: ${confObj.utilization.cpu}, gpu: ${confObj.utilization.gpu}`);
|
|
59
|
+
deepEqual(confObj.computeGroups, [{ joinKey: 'joinKey1', joinSecret: 'joinHash1' }, { joinKey: 'joinKey2', joinSecret: 'joinHash2' }], 'Mismatch in computeGroups')
|
|
60
|
+
deepEqual(confObj.maxSandboxes, 5, `Mismatch! maxSandboxes:${confObj.maxSandboxes}`);
|
|
61
|
+
deepEqual(confObj.jobIds, ['09fd0909Bd93f7bad915726C3AB4'], `Mismatch in job ids! jobIds:${confObj.jobIds}`);
|
|
62
62
|
|
|
63
63
|
console.log('Done.');
|
|
64
64
|
}
|