dcp-worker 4.5.3 → 4.6.1
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 +13 -0
- package/README.md +3 -3
- package/bin/dcp-worker +5 -5
- package/lib/p2p-shared.js +98 -11
- package/lib/show.js +1 -1
- package/lib/worker-info.js +22 -14
- package/package.json +2 -2
- package/www/hud/small-dark.html +3 -0
package/.gitlab-ci.yml
CHANGED
|
@@ -8,6 +8,11 @@ variables:
|
|
|
8
8
|
npm_config_cache: '.cache/npm/'
|
|
9
9
|
npm_config_prefer_offline: 'true'
|
|
10
10
|
npm_config_fund: 'false'
|
|
11
|
+
# DCP_BUILD variables only apply when using a gitlab-hosted dcp-client
|
|
12
|
+
DCP_BUILD: debug
|
|
13
|
+
DCP_BUILD_BRANCH: develop
|
|
14
|
+
DCP_BUILD_HOST: 'http://dcp-client-srv.office.distributive.network'
|
|
15
|
+
DCP_CLIENT_GITLAB: 'gitlab:Distributed-Compute-Protocol/dcp-client#'
|
|
11
16
|
|
|
12
17
|
default:
|
|
13
18
|
# Use in-house GitLab runners.
|
|
@@ -28,6 +33,8 @@ workflow:
|
|
|
28
33
|
# Only run branch pipelines for `develop`, or merge request pipelines.
|
|
29
34
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
30
35
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
36
|
+
# Allow manually running a branch pipeline without opening an MR first.
|
|
37
|
+
- if: $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api"
|
|
31
38
|
|
|
32
39
|
stages:
|
|
33
40
|
- build
|
|
@@ -40,6 +47,12 @@ build:
|
|
|
40
47
|
stage: build
|
|
41
48
|
script:
|
|
42
49
|
- npm clean-install
|
|
50
|
+
- DCP_CLIENT_VERSION=`node -p "require('./package.json').dependencies['dcp-client']"`
|
|
51
|
+
- DCP_CLIENT_ORIGIN=`printf "${DCP_CLIENT_GITLAB}"`
|
|
52
|
+
- |
|
|
53
|
+
[[ "${DCP_CLIENT_VERSION}" == "gitlab:"* ]] &&
|
|
54
|
+
wget "${DCP_BUILD_HOST}/?dcpClient=${DCP_CLIENT_VERSION//$DCP_CLIENT_ORIGIN/}&build=${DCP_BUILD}" -O node_modules/dcp-client/dist/dcp-client-bundle.js
|
|
55
|
+
- echo "Done" # Because CI will error if the last command returns with a non-zero exit code... and the above will be unless a specific dcp-client version is required
|
|
43
56
|
cache:
|
|
44
57
|
- key:
|
|
45
58
|
prefix: $CI_JOB_NAME_SLUG
|
package/README.md
CHANGED
|
@@ -156,7 +156,7 @@ A Node.js daemon which
|
|
|
156
156
|
A Node.js daemon which
|
|
157
157
|
* manages a ledger for DCC. This is not a blockchain currency.
|
|
158
158
|
* enables the movement of DCC between entities requesting work and entities performing work
|
|
159
|
-
* enables the movement of DCC between the ledger and
|
|
159
|
+
* enables the movement of DCC between the ledger and Paypal
|
|
160
160
|
* enables the placement of DCC in escrow on behalf of the Scheduler for work which is anticipated to be done
|
|
161
161
|
|
|
162
162
|
#### Compute Group
|
|
@@ -167,7 +167,7 @@ A user-facing web application which allows or enables
|
|
|
167
167
|
* creation and management of user accounts
|
|
168
168
|
* management of bank accounts (ledgers)
|
|
169
169
|
* transfer of DCC between bank accounts
|
|
170
|
-
* transfer of DCC to and from
|
|
170
|
+
* transfer of DCC to and from USD
|
|
171
171
|
* execution of the browser-based Worker
|
|
172
172
|
|
|
173
173
|
#### Worker
|
|
@@ -209,7 +209,7 @@ A group of related modules
|
|
|
209
209
|
A parallel supercomputer consisting of one or more schedulers and workers. When used as a proper noun, the distributed computer being discussed is the one hosted at https://portal.distributed.computer/
|
|
210
210
|
|
|
211
211
|
#### Bank Account
|
|
212
|
-
A ledger which acts a repository for DCC which is not on the block chain.
|
|
212
|
+
A ledger which acts a repository for DCC which is not on the block chain. Meta data attached to bank accounts can restrict certain operations, such as ear-marking funds for use only by job deployment.
|
|
213
213
|
|
|
214
214
|
#### Address
|
|
215
215
|
A unique identifier in DCP which can be used to identity a bank account, user, compute group, etc.
|
package/bin/dcp-worker
CHANGED
|
@@ -644,6 +644,9 @@ async function main()
|
|
|
644
644
|
if (loggingOptions.verbose)
|
|
645
645
|
console.info(` + Verbosity level: ${loggingOptions.verbose}`);
|
|
646
646
|
|
|
647
|
+
if (worker.config.pidfile && require('../lib/pidfile').write(worker.config.pidfile) !== true)
|
|
648
|
+
await cleanupThenExit(exitCodes.pidConflict);
|
|
649
|
+
|
|
647
650
|
/* Poll the evaluator forever until it accepts a connection */
|
|
648
651
|
let evaluatorInfo = false;
|
|
649
652
|
let p$throbSleep;
|
|
@@ -665,7 +668,7 @@ async function main()
|
|
|
665
668
|
utils.noteWorkerStart(worker);
|
|
666
669
|
if (performance.now() - ts > 100)
|
|
667
670
|
console.throb();
|
|
668
|
-
p$throbSleep = a$sleep(Math.
|
|
671
|
+
p$throbSleep = a$sleep(Math.min(i + 1, 30) / 4);
|
|
669
672
|
await p$throbSleep;
|
|
670
673
|
console.throb();
|
|
671
674
|
}
|
|
@@ -807,9 +810,6 @@ async function main()
|
|
|
807
810
|
}
|
|
808
811
|
});
|
|
809
812
|
|
|
810
|
-
if (worker.config.pidfile && require('../lib/pidfile').write(worker.config.pidfile) !== true)
|
|
811
|
-
await cleanupThenExit(exitCodes.pidConflict);
|
|
812
|
-
|
|
813
813
|
if (worker.config.claimEarnings === false && !worker.config.unmanaged)
|
|
814
814
|
{
|
|
815
815
|
const amount = await DistributiveWorker.checkUnclaimedEarnings();
|
|
@@ -934,7 +934,7 @@ async function cleanupThenExit(exitCode)
|
|
|
934
934
|
worker.stop(true); /* toggle internal worker state so it won't surprise us by starting sandboxes */
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
-
console.warn(' !
|
|
937
|
+
console.warn(' ! shutdown, exit code =', exitCode);
|
|
938
938
|
const p$workerShutdownTasks = Promise.all([
|
|
939
939
|
require('../lib/p2p-shared').shutdown(),
|
|
940
940
|
utils.noteWorkerShutdown(worker),
|
package/lib/p2p-shared.js
CHANGED
|
@@ -16,8 +16,9 @@ const debug = require('debug');
|
|
|
16
16
|
const assert = require('assert');
|
|
17
17
|
const wallet = require('dcp/wallet');
|
|
18
18
|
|
|
19
|
-
const {
|
|
20
|
-
const {
|
|
19
|
+
const { DistributiveWorker } = require('dcp/worker');
|
|
20
|
+
const { a$sleep } = require('dcp/utils');
|
|
21
|
+
const { DcpURL } = require('dcp/dcp-url');
|
|
21
22
|
|
|
22
23
|
const version = '1.0.0';
|
|
23
24
|
var worker; /* singleton instance of DistributiveWorker - held even after stop */
|
|
@@ -80,6 +81,11 @@ exports.shutdown = async function shutdown()
|
|
|
80
81
|
await p2p.cleanupForExit();
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Send an announcement to the worker. This carries ad-hoc information about changes in the internal
|
|
86
|
+
* worker state. Many elements in the UI are affected by the announcement via worker-announce-*
|
|
87
|
+
* attributes.
|
|
88
|
+
*/
|
|
83
89
|
function announce(announcement, details)
|
|
84
90
|
{
|
|
85
91
|
debug('dcp-worker:p2p')('sending anouncement', announcement);
|
|
@@ -94,7 +100,7 @@ function announce(announcement, details)
|
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
if (!exports.disabled)
|
|
97
|
-
p2p.sendMessage(`worker-${workerId}-announce`, { announce: announcement, version }, owner);
|
|
103
|
+
p2p.sendMessage(`worker-${workerId}-announce`, { announce: announcement, version, details }, owner);
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
function enqRespond(message, details)
|
|
@@ -182,6 +188,72 @@ function pauseWorker()
|
|
|
182
188
|
return p$pause;
|
|
183
189
|
}
|
|
184
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Replace an existing configuration value, coercing value as necessary.
|
|
193
|
+
* @param {string} path path within worker.config to the current value, eg utilization.cpu
|
|
194
|
+
* @param {string} value the new value
|
|
195
|
+
*/
|
|
196
|
+
function replaceConfigValue(path, value)
|
|
197
|
+
{
|
|
198
|
+
var node = worker.config;
|
|
199
|
+
var components = path.split('.');
|
|
200
|
+
var component;
|
|
201
|
+
|
|
202
|
+
if (!/^([a-z][A-Za-z0-9_.]+)+$/.test(path))
|
|
203
|
+
throw new Error(`invalid config path: ${path}`);
|
|
204
|
+
|
|
205
|
+
while((component = components.shift()))
|
|
206
|
+
{
|
|
207
|
+
if (components.length === 0)
|
|
208
|
+
break;
|
|
209
|
+
if (!node[component])
|
|
210
|
+
{
|
|
211
|
+
console.error(`Invalid property ${component} in ${path}`);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
node = node[component];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
switch(typeof node[component])
|
|
218
|
+
{
|
|
219
|
+
case 'object':
|
|
220
|
+
if (node[component] === null)
|
|
221
|
+
{
|
|
222
|
+
console.error(`cannot replace null value at ${path}`);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
/* fallthrough */
|
|
226
|
+
default:
|
|
227
|
+
console.error(`cannot replace ${typeof node[component]} at ${path}`);
|
|
228
|
+
break;
|
|
229
|
+
case 'number':
|
|
230
|
+
value = value.trim();
|
|
231
|
+
if (value.endsWith('%'))
|
|
232
|
+
value = parseInt(value, 10) / 100;
|
|
233
|
+
replaceWith(Number(value));
|
|
234
|
+
break;
|
|
235
|
+
case 'boolean':
|
|
236
|
+
switch(value)
|
|
237
|
+
{
|
|
238
|
+
case 'true': replaceWith(true); break;
|
|
239
|
+
case 'false': replaceWith(false); break;
|
|
240
|
+
default:
|
|
241
|
+
console.error(`cannot replace boolean component at ${path} with ${value}`);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
case 'string':
|
|
246
|
+
replaceWith(value)
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function replaceWith(newValue)
|
|
251
|
+
{
|
|
252
|
+
console.info(`worker.config.${path}: ${node[component]} => ${newValue}`);
|
|
253
|
+
node[component] = newValue;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
185
257
|
/**
|
|
186
258
|
* Handle a control message, eg from the portal. Control messages are sent on channel worker-ID and
|
|
187
259
|
* tell the worker what to do, eg enable logs, reboot, change configuration, etc. These are always
|
|
@@ -222,18 +294,13 @@ function handleControlMessage(message, channel, sender, originator)
|
|
|
222
294
|
console.info(' . Unpausing worker');
|
|
223
295
|
break;
|
|
224
296
|
case 'stop':
|
|
297
|
+
console.info(' . Remote peer requested worker stop');
|
|
225
298
|
worker.stop(message.arguments?.[0]); /* announcement comes from worker<stop> */
|
|
226
299
|
break;
|
|
227
300
|
case 'halt':
|
|
228
301
|
throw new Error(`halt (p2p ${message.sender})`);
|
|
229
|
-
case '
|
|
230
|
-
|
|
231
|
-
worker.dropSandboxes();
|
|
232
|
-
console.info(' . Set cores:', worker.config.cores);
|
|
233
|
-
break;
|
|
234
|
-
case 'set-max-sandboxes':
|
|
235
|
-
worker.config.maxSandboxes = Number(message.arguments[0]);
|
|
236
|
-
console.info(' . Set max sandboxes:', worker.config.maxSandboxes);
|
|
302
|
+
case 'replace-config-value':
|
|
303
|
+
replaceConfigValue.apply(null, message.arguments);
|
|
237
304
|
break;
|
|
238
305
|
case 'update-runinfo':
|
|
239
306
|
worker.updateRunInfo();
|
|
@@ -264,6 +331,26 @@ function handleControlMessage(message, channel, sender, originator)
|
|
|
264
331
|
}).finally(() => worker.stop(true));
|
|
265
332
|
break;
|
|
266
333
|
}
|
|
334
|
+
case 'claim':
|
|
335
|
+
{
|
|
336
|
+
const earningsAccount = new wallet.Address(message.arguments[0]);
|
|
337
|
+
DistributiveWorker.transferUnclaimedEarnings(earningsAccount).then(res => {
|
|
338
|
+
if (res.payload)
|
|
339
|
+
{
|
|
340
|
+
console.log(` ! Claimed ${res.payload} ⊇ for ${earningsAccount}`);
|
|
341
|
+
announce('alert', `Moved ${res.payload} ⊇ into account ${earningsAccount.toShortString()}`);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/* fallthrough */
|
|
346
|
+
case 'set-earnings-account':
|
|
347
|
+
{
|
|
348
|
+
const newAccount = new wallet.Address(message.arguments[0]);
|
|
349
|
+
worker.config.paymentAddress = newAccount;
|
|
350
|
+
console.info(` . Set earnings account: ${worker.config.paymentAddress}`);
|
|
351
|
+
announce('earnings-account', String(worker.config.paymentAddress));
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
267
354
|
case 'enq':
|
|
268
355
|
handleEnquireMessage(message, channel, sender, originator);
|
|
269
356
|
break;
|
package/lib/show.js
CHANGED
|
@@ -36,7 +36,7 @@ async function show(worker, mode)
|
|
|
36
36
|
case 'identity':
|
|
37
37
|
return identity.get().address;
|
|
38
38
|
case 'owner':
|
|
39
|
-
return await require('./utils').getOwner(worker) || 'worker is not registered';
|
|
39
|
+
return String(await require('./utils').getOwner(worker)) || 'worker is not registered';
|
|
40
40
|
case 'earnings-account':
|
|
41
41
|
return false
|
|
42
42
|
|| (worker.config.paymentAddress && String(worker.config.paymentAddress))
|
package/lib/worker-info.js
CHANGED
|
@@ -72,18 +72,15 @@ async function eval$$getInfo()
|
|
|
72
72
|
*/
|
|
73
73
|
function getEvaluatorInformation(evaluatorConfig)
|
|
74
74
|
{
|
|
75
|
+
if (!getEvaluatorInformation.seq)
|
|
76
|
+
getEvaluatorInformation.seq = 0;
|
|
77
|
+
const seq = ++getEvaluatorInformation.seq;
|
|
75
78
|
const StandaloneWorker = require('dcp-client/lib/standaloneWorker').workerFactory(evaluatorConfig);
|
|
76
|
-
const evaluatorHandle = new StandaloneWorker({ name:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}).finally(() => {
|
|
82
|
-
evaluatorHandle.terminate();
|
|
83
|
-
evaluatorHandle.removeAllListeners();
|
|
84
|
-
});
|
|
85
|
-
evaluatorHandle.addEventListener('end', () => resolve(false));
|
|
86
|
-
evaluatorHandle.addEventListener('error', reject);
|
|
79
|
+
const evaluatorHandle = new StandaloneWorker({ name: `DCP Probe Sandbox #${seq}` });
|
|
80
|
+
const pr$workerInfo = Promise.withResolvers();
|
|
81
|
+
|
|
82
|
+
evaluatorHandle.addEventListener('end', () => pr$workerInfo.resolve(false));
|
|
83
|
+
evaluatorHandle.addEventListener('error', pr$workerInfo.reject);
|
|
87
84
|
evaluatorHandle.ref();
|
|
88
85
|
|
|
89
86
|
evaluatorHandle.onmessage = function onmessage(__event)
|
|
@@ -94,18 +91,29 @@ function getEvaluatorInformation(evaluatorConfig)
|
|
|
94
91
|
{
|
|
95
92
|
const workerInfo = reply.data;
|
|
96
93
|
if (typeof workerInfo !== 'object' || !workerInfo.worktimes || !workerInfo.webgpu)
|
|
97
|
-
throw new Error(
|
|
98
|
-
resolve(workerInfo);
|
|
94
|
+
throw new Error('malformed response from evaluator');
|
|
95
|
+
pr$workerInfo.resolve(workerInfo);
|
|
99
96
|
}
|
|
100
97
|
}
|
|
101
98
|
|
|
99
|
+
const timerId = setTimeout(() => {
|
|
100
|
+
pr$workerInfo.resolve(false);
|
|
101
|
+
}, 5000); /* 5000ms is about 4800ms more than this should take even on a busy machine. */
|
|
102
|
+
|
|
102
103
|
const message = {
|
|
103
104
|
request: 'eval',
|
|
104
105
|
data: '(' + eval$$getInfo.toString() + ')()',
|
|
105
106
|
msgId: evaluatorId,
|
|
106
107
|
}
|
|
108
|
+
|
|
109
|
+
pr$workerInfo.promise.finally(() => {
|
|
110
|
+
evaluatorHandle.terminate();
|
|
111
|
+
evaluatorHandle.removeAllListeners();
|
|
112
|
+
clearTimeout(timerId);
|
|
113
|
+
});
|
|
114
|
+
|
|
107
115
|
evaluatorHandle.postMessage(StandaloneWorker.encodeMessage(message));
|
|
108
|
-
return
|
|
116
|
+
return pr$workerInfo.promise;
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
exports.getEvaluatorInformation = getEvaluatorInformation;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dcp-worker",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.1",
|
|
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.2",
|
|
42
|
-
"dcp-client": "^5.
|
|
42
|
+
"dcp-client": "^5.8.1",
|
|
43
43
|
"kvin": "9.1.0",
|
|
44
44
|
"mux-net": "github:wesgarland/mux-net#e7f81800db4a84ec880026596f7ee68549a6d0f5",
|
|
45
45
|
"posix-getopt": "1.2.1",
|
package/www/hud/small-dark.html
CHANGED