dcp-worker 3.2.30-9 → 3.2.31
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 +27 -0
- package/bin/dcp-worker +160 -95
- package/bin/publish-docs.sh +74 -0
- package/catalog-info.yaml +21 -0
- package/docs/CODEOWNERS +2 -0
- package/docs/mkdocs.yml +16 -0
- package/etc/dcp-worker-config.js +1 -1
- package/etc/dcp-worker-config.js.md5 +1 -1
- package/lib/blessed-components/index.js +1 -0
- package/lib/blessed-components/log.js +1 -0
- package/lib/blessed-components/sandboxes.js +10 -6
- package/lib/check-scheduler-version.js +1 -0
- package/lib/dashboard-tui.js +231 -0
- package/lib/default-ui-events.js +171 -0
- package/lib/pidfile.js +1 -1
- package/lib/remote-console.js +10 -2
- package/lib/startWorkerLogger.js +98 -62
- package/lib/utils.js +28 -0
- package/lib/worker-loggers/console.js +24 -108
- package/lib/worker-loggers/dashboard.js +32 -172
- package/lib/worker-loggers/event-log.js +28 -60
- package/lib/worker-loggers/logfile.js +57 -83
- package/lib/worker-loggers/syslog.js +41 -63
- package/package.json +16 -6
- package/lib/worker-loggers/common-types.js +0 -24
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @file catalog-info.yml
|
|
2
|
+
# @author Brandon Christie <brandon@distributive.network>
|
|
3
|
+
# @date Mar 2023
|
|
4
|
+
#
|
|
5
|
+
# @description Lists all of the components and the paths to all
|
|
6
|
+
# the documentation that will be published to backstage.
|
|
7
|
+
|
|
8
|
+
apiVersion: backstage.io/v1alpha1
|
|
9
|
+
kind: Component
|
|
10
|
+
metadata:
|
|
11
|
+
name: dcp-worker
|
|
12
|
+
description: Documentation for the dcp-worker.
|
|
13
|
+
tags:
|
|
14
|
+
- documentation
|
|
15
|
+
annotations:
|
|
16
|
+
gitlab.com/project-id: '18110002'
|
|
17
|
+
backstage.io/techdocs-ref: dir:./docs
|
|
18
|
+
spec:
|
|
19
|
+
type: website
|
|
20
|
+
lifecycle: production
|
|
21
|
+
owner: core
|
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
|
package/docs/mkdocs.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @file mkdocs.yml
|
|
2
|
+
# @author Brandon Christie <brandon@distributive.network>
|
|
3
|
+
# @date Aug 2023
|
|
4
|
+
#
|
|
5
|
+
# @description Determines how the component of name: 'dcp-worker'
|
|
6
|
+
# is formatted on backstage.
|
|
7
|
+
|
|
8
|
+
site_name: dcp-worker
|
|
9
|
+
repo_url: https://gitlab.com/Distributed-Compute-Protocol/dcp-worker
|
|
10
|
+
edit_uri: edit/develop/docs
|
|
11
|
+
docs_dir: .
|
|
12
|
+
nav:
|
|
13
|
+
- README.md
|
|
14
|
+
plugins:
|
|
15
|
+
- techdocs-core
|
|
16
|
+
- same-dir
|
package/etc/dcp-worker-config.js
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
// keystore('~/.dcp/scott'),
|
|
50
50
|
],
|
|
51
51
|
|
|
52
|
-
jobAddresses:
|
|
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
|
-
|
|
1
|
+
4d49057dd014344e4be5a266e9754824
|
|
2
2
|
### DO NOT MODIFY THIS FILE!!! ###
|
|
@@ -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
|
-
|
|
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.
|
|
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
|
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file worker-loggers/dashboard.js
|
|
3
|
+
* @author Ryan Rossiter, ryan@kingsds.network
|
|
4
|
+
* @date April 2020
|
|
5
|
+
* @author Wes Garland, wes@distributive.network
|
|
6
|
+
* @date June 2023
|
|
7
|
+
*
|
|
8
|
+
* This module uses the blessed library to create a monitoring dashboard for the worker.
|
|
9
|
+
* A corresponding worker-logger, dashboard.js, knows how to log to this dashboard.
|
|
10
|
+
*/
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const dcpConfig = require('dcp/dcp-config');
|
|
14
|
+
const chalk = require('chalk');
|
|
15
|
+
const blessed = require('blessed');
|
|
16
|
+
const contrib = require('blessed-contrib');
|
|
17
|
+
const components = require('./blessed-components');
|
|
18
|
+
const utils = require('../lib/utils');
|
|
19
|
+
|
|
20
|
+
const { replaceWorkerEvent, replaceSandboxEvent } = require('./default-ui-events');
|
|
21
|
+
|
|
22
|
+
const SLICE_FETCH_STATUS = {
|
|
23
|
+
IDLE: chalk.yellow('Idle'),
|
|
24
|
+
FETCHING: chalk.blue('Fetching Work...'),
|
|
25
|
+
WORKING: chalk.green('Working'),
|
|
26
|
+
NO_WORK: chalk.red('No Work Available'),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const usingDebugger = require('module')._cache.niim instanceof require('module').Module;
|
|
30
|
+
const screenConf = {
|
|
31
|
+
input: usingDebugger ? new (require('events').EventEmitter) : undefined,
|
|
32
|
+
output: usingDebugger ? new (require('events').EventEmitter) : undefined,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
*/
|
|
36
|
+
exports.init = function dashboard$$init(worker, options)
|
|
37
|
+
{
|
|
38
|
+
var sliceFetchStatus = SLICE_FETCH_STATUS.IDLE;
|
|
39
|
+
var totalDCCs = 0;
|
|
40
|
+
const screen = blessed.screen(screenConf);
|
|
41
|
+
const grid = new contrib.grid({rows: 3, cols: 5, screen});
|
|
42
|
+
const workerInfoPane = grid.set(2, 0, 1, 5, blessed.text);
|
|
43
|
+
|
|
44
|
+
const logPane = grid.set(0, 2, 2, 3, components.log, {
|
|
45
|
+
label: 'Worker Log',
|
|
46
|
+
scrollable: true,
|
|
47
|
+
alwaysScroll: true,
|
|
48
|
+
mouse: true,
|
|
49
|
+
scrollbar: {
|
|
50
|
+
bg: 'blue',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const sandboxPane = grid.set(0, 0, 2, 2, components.sandboxes, {
|
|
55
|
+
label: 'Sandboxes',
|
|
56
|
+
defaultProgressBars: 0,
|
|
57
|
+
scrollable: true,
|
|
58
|
+
alwaysScroll: true,
|
|
59
|
+
mouse: true,
|
|
60
|
+
scrollbar: {
|
|
61
|
+
bg: 'blue',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const passwordBox = blessed.textbox({
|
|
66
|
+
parent: screen,
|
|
67
|
+
border: 'line',
|
|
68
|
+
top: 'center',
|
|
69
|
+
left: 'center',
|
|
70
|
+
width: '50%',
|
|
71
|
+
height: 'shrink',
|
|
72
|
+
padding: {
|
|
73
|
+
top: 1
|
|
74
|
+
},
|
|
75
|
+
censor: true,
|
|
76
|
+
inputOnFocus: true,
|
|
77
|
+
label: 'Password Prompt:',
|
|
78
|
+
hidden: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
function askPassword(promptMessage)
|
|
82
|
+
{
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
passwordBox.focus();
|
|
85
|
+
passwordBox.show();
|
|
86
|
+
passwordBox.setLabel(promptMessage);
|
|
87
|
+
|
|
88
|
+
function passwordSubmitFn(value)
|
|
89
|
+
{
|
|
90
|
+
passwordBox.hide();
|
|
91
|
+
passwordBox.removeListener('submit', passwordSubmitFn);
|
|
92
|
+
passwordBox.setValue('');
|
|
93
|
+
resolve(value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
passwordBox.on('submit', passwordSubmitFn);
|
|
97
|
+
screen.render();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// override wallet.passphrasePrompt with password box
|
|
102
|
+
require('dcp/wallet').passphrasePrompt = (promptMessage) => {
|
|
103
|
+
return askPassword(promptMessage);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
delete exports.init; /* singleton */
|
|
107
|
+
|
|
108
|
+
if (!usingDebugger)
|
|
109
|
+
exports.logPane = logPane; /* now dashboard log can find the pane */
|
|
110
|
+
setInterval(() => screen.render(), 50).unref(); /* 50ms = 20 fps */
|
|
111
|
+
updateWorkerInfo();
|
|
112
|
+
screen.render();
|
|
113
|
+
|
|
114
|
+
/* Apply key bindings which mimic canonical input mode */
|
|
115
|
+
screen.key(['C-c'], () => raise('SIGINT'));
|
|
116
|
+
screen.key(['C-z'], () => raise('SIGTSTP'));
|
|
117
|
+
screen.key(['\u001c'], () => raise('SIGQUIT')); /* C-\ */
|
|
118
|
+
|
|
119
|
+
screen.key(['escape'], () => {
|
|
120
|
+
console.log('Stopping worker...');
|
|
121
|
+
worker.stop();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
function updateWorkerInfo()
|
|
125
|
+
{
|
|
126
|
+
const workerOptions = worker.workerOptions;
|
|
127
|
+
|
|
128
|
+
workerInfoPane.setLabel(`Worker Status [${sliceFetchStatus}]`);
|
|
129
|
+
workerInfoPane.setContent([
|
|
130
|
+
chalk.green(` DCCs Earned: ${chalk.bold(totalDCCs.toFixed(3))}`),
|
|
131
|
+
'',
|
|
132
|
+
` Scheduler: ${chalk.yellow(dcpConfig.scheduler.location.href)}`,
|
|
133
|
+
` Bank: ${chalk.yellow(dcpConfig.bank.location.href)}`,
|
|
134
|
+
`Bank Account: ${chalk.yellow(worker.paymentAddress || 'Starting...')}`,
|
|
135
|
+
` Identity: ${chalk.yellow(worker.identityKeystore? worker.identityKeystore.address : 'Starting...')}`,
|
|
136
|
+
` Jobs: ${workerOptions.jobAddresses?.length ? workerOptions.jobAddresses.join(', ') : '<any>'}`,
|
|
137
|
+
` Priv Groups: ${Object.keys(workerOptions.computeGroups).length}`,
|
|
138
|
+
` Pub Group: ${workerOptions.leavePublicGroup ? 'no' : 'yes'}`,
|
|
139
|
+
].join('\n'));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* Override default event behaviour to work better with the Dashboard. */
|
|
143
|
+
|
|
144
|
+
/** XXXpfr @todo Is this correct? Or should we init progressData inside 'slice' like we used to. */
|
|
145
|
+
replaceSandboxEvent('ready', function dashboard$$job(sandbox, sandboxData, ev) {
|
|
146
|
+
sandboxData.progressData = {
|
|
147
|
+
indeterminate: true,
|
|
148
|
+
progress: 0,
|
|
149
|
+
label: sandbox?.public ? sandbox.public.name: '<no-label>',
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
replaceSandboxEvent('slice', function dashboard$$slice(sandbox, sandboxData, ev) {
|
|
154
|
+
sandboxPane.data.push(sandboxData.progressData);
|
|
155
|
+
sandboxPane.update();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
replaceSandboxEvent('progress', function dashboard$$progress(sandbox, sandboxData, ev) {
|
|
159
|
+
if (!ev)
|
|
160
|
+
{
|
|
161
|
+
sandboxData.progressData.progress = 100;
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
if (sandboxData.progressData.indeterminate)
|
|
164
|
+
{
|
|
165
|
+
sandboxData.progressData.progress = 0;
|
|
166
|
+
sandboxPane.update();
|
|
167
|
+
}
|
|
168
|
+
}, 500).unref();
|
|
169
|
+
}
|
|
170
|
+
else
|
|
171
|
+
{
|
|
172
|
+
sandboxData.progressData.progress = ev;
|
|
173
|
+
sandboxData.progressData.indeterminate = false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
sandboxPane.update();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
replaceSandboxEvent('sliceEnd', function dashboard$$sliceEnd(sandbox, sandboxData, ev) {
|
|
180
|
+
sandboxPane.data = sandboxPane.data.filter(d => d != sandboxData.progressData);
|
|
181
|
+
sandboxData.progressData.progress = 0;
|
|
182
|
+
sandboxPane.update();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
replaceSandboxEvent('end', function dashboard$$end(sandbox, sandboxData, ev) {
|
|
186
|
+
sandboxPane.data = sandboxPane.data.filter(d => d != sandboxData.progressData);
|
|
187
|
+
sandboxPane.deleteProgressBar();
|
|
188
|
+
sandboxData.progressData.progress = 0;
|
|
189
|
+
sandboxPane.update();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
replaceWorkerEvent('beforeFetch', function dashboard$$beforeFetch(ev) {
|
|
193
|
+
sliceFetchStatus = SLICE_FETCH_STATUS.FETCHING;
|
|
194
|
+
updateWorkerInfo();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
replaceWorkerEvent('fetch', function dashboard$$fetch(ev) {
|
|
198
|
+
sliceFetchStatus = SLICE_FETCH_STATUS.NO_WORK;
|
|
199
|
+
if (ev instanceof Error)
|
|
200
|
+
console.error('Error fetching slices:', ev);
|
|
201
|
+
else if ( !(utils.slicesFetched(ev) === 0 && sandboxPane.data.length === 0))
|
|
202
|
+
sliceFetchStatus = SLICE_FETCH_STATUS.WORKING;
|
|
203
|
+
updateWorkerInfo();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
worker.on('end', () => { screen.destroy(); });
|
|
207
|
+
|
|
208
|
+
worker.on('sandbox', function dashboard$$sandbox(ev) {
|
|
209
|
+
sandboxPane.createProgressBar();
|
|
210
|
+
sandboxPane.update();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
worker.on('payment', function dashboard$$payment(ev) {
|
|
214
|
+
const payment = parseFloat(ev);
|
|
215
|
+
|
|
216
|
+
if (!isNaN(payment))
|
|
217
|
+
totalDCCs += payment;
|
|
218
|
+
|
|
219
|
+
sandboxPane.update();
|
|
220
|
+
updateWorkerInfo();
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Send a signal to the caller
|
|
226
|
+
* @param {number|string} sig the signal to raise
|
|
227
|
+
*/
|
|
228
|
+
function raise(sig)
|
|
229
|
+
{
|
|
230
|
+
process.kill(process.pid, sig);
|
|
231
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file default-event.js
|
|
3
|
+
* Default worker/sandbox events, providing default logging behaviours (event handlers)
|
|
4
|
+
* for the dcp-worker.
|
|
5
|
+
*
|
|
6
|
+
* - All event handlers use the *current* global console object to emit messages;
|
|
7
|
+
* enhanced logging subsystems should intercept this object to achieve their desired
|
|
8
|
+
* behaviours.
|
|
9
|
+
*
|
|
10
|
+
* - All event handlers invoke functions which are properties of the eventHandlers return
|
|
11
|
+
* value from the hook function. This means that alternate user interfaces can either
|
|
12
|
+
* hook or intercept the properties of that object to modify the event handlers'
|
|
13
|
+
* behaviour without actually removing/replacing the event handler on the instance of
|
|
14
|
+
* Worker.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: This is just a convenience module. There is no requirement to use this module to
|
|
17
|
+
* hook worker events, this module mainly exists to make it easy for the
|
|
18
|
+
* dashboard-tui to replace event handlers with better ones, but it also makes it
|
|
19
|
+
* easier to sandbox events since we only need to register one event handler here
|
|
20
|
+
* to handle every sandbox.
|
|
21
|
+
*
|
|
22
|
+
* @author Ryan Rossiter, ryan@kingsds.network
|
|
23
|
+
* @date April 2020
|
|
24
|
+
* @author Wes Garland, wes@distributive.network
|
|
25
|
+
* @date June 2023
|
|
26
|
+
*/
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const utils = require('../lib/utils');
|
|
30
|
+
|
|
31
|
+
const sandboxEventHandlers = {};
|
|
32
|
+
const workerEventHandlers = {};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sandbox 1: Slice Started: slice 1, 0x5b5214D48F0428669c4E: Simple Job
|
|
36
|
+
* Sandbox 1: Slice Completed: slice 1, 0x5b5214D48F0428669c4E: Simple Job: dt 114ms
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param worker The instance of Worker to hook
|
|
41
|
+
* @param options cliArgs from worker
|
|
42
|
+
*/
|
|
43
|
+
exports.hook = function hookWorkerEvents$$hook(worker, options)
|
|
44
|
+
{
|
|
45
|
+
const sliceMap = {}; // jobAddress --> ( sliceNumber, t0 )
|
|
46
|
+
const truncationLength = 22; // Extra 2 for '0x'
|
|
47
|
+
|
|
48
|
+
delete exports.hook;
|
|
49
|
+
|
|
50
|
+
function makeSliceId (sandbox, sliceNumber)
|
|
51
|
+
{
|
|
52
|
+
if (!sandbox.jobAddress)
|
|
53
|
+
return '<no job>';
|
|
54
|
+
|
|
55
|
+
const address = sandbox.jobAddress.slice(0, truncationLength);
|
|
56
|
+
const baseInfo = sandbox?.public ? `${address}: ${sandbox.public.name}` : address;
|
|
57
|
+
|
|
58
|
+
if (!sliceNumber)
|
|
59
|
+
sliceNumber = sandbox.sliceNumber;
|
|
60
|
+
return sliceNumber > 0 ? `slice ${sliceNumber}, ${baseInfo}` : baseInfo;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
sandboxEventHandlers.ready = function sandboxReadyHandler(sandbox, sandboxData, ev) {
|
|
64
|
+
console.log(` . Sandbox ${sandboxData.shortId}: Initialized`);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
sandboxEventHandlers.slice = function sliceHandler(sandbox, sandboxData, ev) {
|
|
68
|
+
sliceMap[sandbox.id] = { slice: sandbox.sliceNumber, t0: Date.now() };
|
|
69
|
+
console.log(` . Sandbox ${sandboxData.shortId}: Slice Started: ${makeSliceId(sandbox)}`);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
sandboxEventHandlers.progress = function progressHandler(sandbox, sandboxdData, ev) {
|
|
73
|
+
// Overridden in dashboard-tui.js
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
sandboxEventHandlers.sliceEnd = function sliceEndHandler(sandbox, sandboxData, ev) {
|
|
77
|
+
const sliceInfo = sliceMap[sandbox.id];
|
|
78
|
+
if (sliceInfo)
|
|
79
|
+
console.log(` * Sandbox ${sandboxData.shortId}: Slice Completed: ${makeSliceId(sandbox, sliceInfo.slice)}: dt ${Date.now() - sliceInfo.t0}ms`);
|
|
80
|
+
else
|
|
81
|
+
console.log(` * Sandbox ${sandboxData.shortId}: Slice Completed: ${makeSliceId(sandbox)}`);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
sandboxEventHandlers.end = function endHandler(sandbox,sandboxData, ev) {
|
|
85
|
+
const sliceInfo = sliceMap[sandbox.id];
|
|
86
|
+
console.log(` * Sandbox ${sandboxData.shortId}: Terminated: ${makeSliceId(sandbox, sliceInfo?.slice)}`);
|
|
87
|
+
delete sliceMap[sandbox.id];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
workerEventHandlers.payment = function paymentHandler(ev) {
|
|
91
|
+
const payment = parseFloat(ev);
|
|
92
|
+
|
|
93
|
+
if (isNaN(payment))
|
|
94
|
+
console.error(' ! Failed to parse payment:', payment);
|
|
95
|
+
else
|
|
96
|
+
console.log(` . Payment: ${payment.toFixed(3)} ⊇`);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
workerEventHandlers.beforeFetch = function beforeFetchHandler() {
|
|
100
|
+
options.verbose && console.log(' * Fetching slices...');
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
workerEventHandlers.fetch = function fetchHandler(ev) {
|
|
104
|
+
if (ev instanceof Error)
|
|
105
|
+
console.error(' ! Failed to fetch slices:', ev);
|
|
106
|
+
else
|
|
107
|
+
options.verbose && console.log(' . Fetched', utils.slicesFetched(ev), 'slices');
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
workerEventHandlers.beforeResult = function beforeResultHandler() {
|
|
112
|
+
options.verbose >= 2 && console.log(' * Submitting results...');
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
workerEventHandlers.result = function resultHandler(ev) {
|
|
116
|
+
if (ev instanceof Error)
|
|
117
|
+
console.error(" ! Failed to submit results:", ev);
|
|
118
|
+
else
|
|
119
|
+
options.verbose >= 2 && console.log(' . Submitted');
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/* Register the appropriate event handlers on the worker and on each sandbox. The handlers are
|
|
123
|
+
* registered in such a way that mutating the exports object to supply different handlers after
|
|
124
|
+
* registration will work.
|
|
125
|
+
*
|
|
126
|
+
* The handlers registered on each sandbox receive two extra arguments before the usual event
|
|
127
|
+
* arguments; these are the sandbox handle emitted by the Worker<sandbox> event and an object
|
|
128
|
+
* called `sandboxData` which is just arbitrary storage for the eventHandlers' use, eg for memos.
|
|
129
|
+
*/
|
|
130
|
+
for (let eventName in workerEventHandlers)
|
|
131
|
+
worker.on(eventName, (...args) => workerEventHandlers[eventName](...args));
|
|
132
|
+
|
|
133
|
+
worker.on('sandbox', function newSandboxHandler(sandbox) {
|
|
134
|
+
const sandboxData = {
|
|
135
|
+
shortId: sandbox.id.toString(10).padStart(3)
|
|
136
|
+
};
|
|
137
|
+
for (let eventName in sandboxEventHandlers)
|
|
138
|
+
sandbox.on(eventName, (...args) => sandboxEventHandlers[eventName](sandbox, sandboxData, ...args));
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
exports.sandboxEventHandlers = sandboxEventHandlers;
|
|
142
|
+
exports. workerEventHandlers = workerEventHandlers;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Function to replace a worker event handler.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} eventName name of the event to replace
|
|
149
|
+
* @param {function} eventHandler new event handler
|
|
150
|
+
*/
|
|
151
|
+
exports.replaceWorkerEvent = function hookWorkerEvents$$replace(eventName, eventHandler)
|
|
152
|
+
{
|
|
153
|
+
if (!workerEventHandlers.hasOwnProperty(eventName))
|
|
154
|
+
throw new Error('unknown worker event: ' + eventName + `(${Object.keys(workerEventHandlers).join(', ')})`);
|
|
155
|
+
|
|
156
|
+
workerEventHandlers[eventName] = eventHandler;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Function to replace a sandbox event handler.
|
|
161
|
+
*
|
|
162
|
+
* @param {string} eventName name of the event to replace
|
|
163
|
+
* @param {function} eventHandler new event handler
|
|
164
|
+
*/
|
|
165
|
+
exports.replaceSandboxEvent = function hookSandboxEvents$$replace(eventName, eventHandler)
|
|
166
|
+
{
|
|
167
|
+
if (!sandboxEventHandlers.hasOwnProperty(eventName))
|
|
168
|
+
throw new Error('unknown sandbox event: ' + eventName + `(${Object.keys(sandboxEventHandlers).join(', ')})`);
|
|
169
|
+
|
|
170
|
+
sandboxEventHandlers[eventName] = eventHandler;
|
|
171
|
+
}
|
package/lib/pidfile.js
CHANGED
package/lib/remote-console.js
CHANGED
|
@@ -47,7 +47,7 @@ function daemonEval()
|
|
|
47
47
|
|
|
48
48
|
function callbackTelnet(port, client, registry) {
|
|
49
49
|
client.unref();
|
|
50
|
-
debugging() && console.
|
|
50
|
+
debugging() && console.notice(' ! telnetd - listening on port', port);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -76,8 +76,16 @@ exports.init = function remoteConsole$$init(...commands)
|
|
|
76
76
|
|
|
77
77
|
console.warn('*** Enabling telnet daemon on port', port, '(security risk) ***');
|
|
78
78
|
|
|
79
|
+
if (port !== 0)
|
|
80
|
+
exports.port = port;
|
|
81
|
+
else
|
|
82
|
+
{
|
|
83
|
+
/* telnet-console library does not properly support port 0 so we mostly work-around here */
|
|
84
|
+
exports.port = Math.floor(1023 + (Math.random() * (63 * 1024)));
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
ci = require('telnet-console').start({
|
|
80
|
-
port,
|
|
88
|
+
port: exports.port,
|
|
81
89
|
callbackTelnet,
|
|
82
90
|
eval: daemonEval,
|
|
83
91
|
histfile: edcFilename + '.history',
|