dcp-client 4.4.7 → 4.4.9-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.
@@ -0,0 +1,61 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <!--
4
+ -- @file simple-job.html - Sample web page showing how to deploy a simple DCP job.
5
+ --
6
+ -- @author Wes Garland <wes@distributive.network>
7
+ -- @author Kevin Yu <kevin@distributive.network>
8
+ -- @date Aug 2019, April 2020, July 2024
9
+ --
10
+ -->
11
+ <head>
12
+ <meta charset="utf-8"/>
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
+
15
+ <!-- Load dcp-client into `window.dcp`. -->
16
+ <script src="https://scheduler.distributed.computer/dcp-client/dcp-client.js"></script>
17
+
18
+ <script>
19
+ 'use strict';
20
+
21
+ function addJobEventListeners(job)
22
+ {
23
+ // Log the job's assigned id.
24
+ job.on('accepted', ({ id }) => console.log(`Job accepted with id ${id}`));
25
+
26
+ // Log returned slice results
27
+ job.on('result', (result) => console.log('Received result:', result));
28
+ }
29
+
30
+ async function start()
31
+ {
32
+ const { compute } = window.dcp;
33
+
34
+ // Creates a Job for the distributed computer.
35
+ // https://docs.dcp.dev/specs/compute-api.html#compute-for
36
+ const job = compute.for(
37
+ [1, 2, 3, 4, 5],
38
+ (datum) => {
39
+ // If a progress event is not emitted within 30 seconds,
40
+ // the scheduler will throw an ENOPROGRESS error.
41
+ progress();
42
+ return datum * 2;
43
+ },
44
+ );
45
+
46
+ // Listen for job emitted events
47
+ addJobEventListeners(job);
48
+
49
+ // Deploy job
50
+ const results = await job.exec(compute.marketRate);
51
+ console.log('Job completed, here are the results: ', Array.from(results));
52
+ }
53
+ </script>
54
+ </head>
55
+ <body onload="start()">
56
+ <p
57
+ style="text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24px;">
58
+ This is a simple vanilla web job deployment example. <br />Look in your browser's console for output.
59
+ </p>
60
+ </body>
61
+ </html>
@@ -1,81 +1,108 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <!--
4
- -- @file dcp-worker.html - Sample web page showing how to implement a
5
- -- trivial DCP worker.
6
- --
7
- -- @author Wes Garland <wes@distributive.network>
8
- -- @author Bryan Hoang <bryan@distributive.network>
9
- -- @date Aug. 2019, Sept. 2022
10
- -->
4
+ -- @file simple-worker.html - Sample web page showing how to implement a trivial DCP worker.
5
+ --
6
+ -- @author Wes Garland <wes@distributive.network>
7
+ -- @author Bryan Hoang <bryan@distributive.network>
8
+ -- @author Kevin Yu <kevin@distributive.network>
9
+ -- @date Aug. 2019, Sept. 2022, July 2024
10
+ -->
11
11
  <head>
12
12
  <meta charset="utf-8" />
13
13
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
14
 
15
+ <!-- Load dcp-client into `window.dcp`. -->
15
16
  <script src="https://scheduler.distributed.computer/dcp-client/dcp-client.js"></script>
16
- <script type="module">
17
- const {
18
- wallet,
19
- worker: { Worker: DCPWorker },
20
- } = window.dcp;
21
17
 
22
- // The maximum number of sanxboxes to have working in parallel.
23
- const defaultMaxSliceCount = 1;
24
-
25
- // What bank account the worker will send its earned funds to.
26
- const paymentAddress = (await wallet.get()).address;
27
-
28
- // What identity the worker will use to communicate to the scheduler.
29
- const identity = await wallet.getId();
18
+ <script>
19
+ 'use strict';
20
+
21
+ function addWorkerEventListeners(worker)
22
+ {
23
+ // The start event fires after the worker is ready to fetch tasks, but
24
+ // before the first task has been fetched.
25
+ worker.on('start', () => {
26
+ console.log('Worker ready to fetch tasks');
27
+ });
30
28
 
31
- const worker = new DCPWorker({
32
- defaultMaxSliceCount,
33
- paymentAddress,
34
- // TODO: Change to `identityAddress` once the API is updated.
35
- identity,
36
- });
29
+ // The fetch event is fired when the worker has fetched a task from the
30
+ // task distributor.
31
+ worker.on('fetch', (task) => {
32
+ if (task.slices)
33
+ console.log(`Worker has fetched ${Object.keys(task.slices).length} slices`);
34
+ });
37
35
 
38
- // Attaching event listeners to see what's going on.
39
- worker.on('start', () => {
40
- console.log('Worker started working!');
41
- });
36
+ // The sandbox event is emitted when a new sandbox is created. The event
37
+ // handler receives as its sole argument an EventEmitter which is used
38
+ // to emit sandbox events
39
+ worker.on('sandbox', (sandbox) => {
40
+ // The progress event is fired to indicate progress throughout a job
41
+ // this is triggered by the progress() call in the work function,
42
+ // however, quickly-repeating calls to progress() may be composited
43
+ // into a single event.
44
+ sandbox.on('progress', (event) => {
45
+ console.log('Sandbox progress', event);
46
+ });
47
+ });
42
48
 
43
- worker.on('sandbox', (sandbox) => {
44
- sandbox.on('ready', (event) => {
45
- console.log('sandbox ready', event);
49
+ // After a result is sent to the result-submitter for consideration
50
+ worker.on('payment', (event) => {
51
+ console.log('Work payment', event);
46
52
  });
47
53
 
48
- sandbox.on('start', ({ sandbox, job }) => {
49
- const { name = '', description = '', link = '' } = job;
50
- console.log(
51
- `Sandbox ${sandbox.id} started slice for job with`,
52
- `Name: "${name}",`,
53
- `Description: "${description}", and`,
54
- `Link: "${link}"`,
55
- );
54
+ // Result event is fired immediately after the worker sends a result to
55
+ // the the result data sink
56
+ worker.on('result', (event) => {
57
+ console.log('Worker has sent a result back to the scheduler');
56
58
  });
57
59
 
58
- sandbox.on('progress', (event) => {
59
- console.log(`Sandbox ${sandbox.id} progress`, event);
60
+ // Worker has stopped working and no new results will be sent to the
61
+ // result submitter or the result data sink and no more slices will be
62
+ // returned to the scheduler
63
+ worker.on('end', () => {
64
+ console.log('Worker has stopped working');
60
65
  });
61
66
 
62
- const sandboxEmit = sandbox.emit.bind(sandbox);
63
- });
67
+ // Log errors
68
+ worker.on('error', console.error);
69
+ }
70
+
71
+ async function start()
72
+ {
73
+ const {
74
+ wallet,
75
+ worker: { Worker: DCPWorker },
76
+ } = window.dcp;
77
+
78
+ // Bank account funds will deposit into
79
+ const paymentAddress = (await wallet.get()).address;
80
+
81
+ // Retrieve auth keystore object
82
+ const identity = await wallet.getId();
83
+
84
+ // Instantiate DCP worker
85
+ const worker = new DCPWorker(
86
+ identity,
87
+ {
88
+ cores: { cpu: 1 },
89
+ paymentAddress,
90
+ }
91
+ );
64
92
 
65
- worker.on('payment', ({ accepted, payment }) => {
66
- if (accepted) {
67
- console.log(`You earned ${payment} DCC!`);
68
- } else {
69
- console.log('the result you computed was not accepted.');
70
- }
71
- });
93
+ // Listen for work emitted events
94
+ addWorkerEventListeners(worker);
72
95
 
73
- // Starting the worker.
74
- await worker.start();
96
+ // Start the worker
97
+ await worker.start();
98
+ }
75
99
  </script>
76
100
  </head>
77
- <body>
78
- This is a minimal vanilla web DCP Worker example. Look in your browser's
79
- console for output.
101
+ <body onload="start()">
102
+ <p
103
+ style="text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24px;">
104
+ This is a simple vanilla web DCP Worker example. <br />Look in your browser's
105
+ console for output.
106
+ </p>
80
107
  </body>
81
108
  </html>
package/index.js CHANGED
@@ -908,6 +908,9 @@ function handleInitArgs(initArgv)
908
908
  * - parseArgv; false => not parse cli for scheduler/wallet
909
909
  * - bundleLocation (URL or string)
910
910
  * - reportErrors; false => throw, else=>console.log, exit(1)
911
+ * - configName: filename to load as part of default dcpConfig
912
+ * - dcpConfig: object to include as part of default dcpConfig
913
+ * - enableSourceMaps: boolean to activate legible error stack traces
911
914
  */
912
915
  /**
913
916
  * Form 4
@@ -922,6 +925,7 @@ function handleInitArgs(initArgv)
922
925
  * - reportErrors; false => throw, else=>console.log, exit(1)
923
926
  * - configName: filename to load as part of default dcpConfig
924
927
  * - dcpConfig: object to include as part of default dcpConfig
928
+ * - enableSourceMaps: boolean to activate legible error stack traces
925
929
  */
926
930
  exports.init = async function dcpClient$$init() {
927
931
  var { initConfig, options } = handleInitArgs(arguments);
@@ -950,6 +954,9 @@ exports.init = async function dcpClient$$init() {
950
954
  }
951
955
  }
952
956
 
957
+ if (process.env.DCP_CLIENT_ENABLE_SOURCEMAPS || options.enableSourceMaps)
958
+ require('source-map-support').install();
959
+
953
960
  return initTail(configFrags, options, finalBundleCode, finalBundleURL);
954
961
  }
955
962
 
@@ -100,10 +100,20 @@ function StandaloneWorker(options = {}) {
100
100
  socket.setNoDelay(dcpConfig.worker ? dcpConfig.worker.nagle : true);
101
101
  socket.connect(port, hostname);
102
102
  socket.on('connect', beginSession.bind(this));
103
- socket.on('end', () => {
103
+
104
+ let alreadySignaled = false;
105
+ const sandboxDeath = () => {
104
106
  connected = false;
105
- ee.emit('end')
106
- })
107
+ if (!alreadySignaled) {
108
+ ee.emit('end');
109
+ alreadySignaled = true;
110
+ }
111
+ };
112
+ // common culprits include ECONNRESET, ECONNREFUSED, ECONNABORTED, ETIMEDOUT
113
+ socket.on('error', sandboxDeath);
114
+ // when the evaluator half closes the connection, the sandbox can't be useful anymore
115
+ socket.on('end', sandboxDeath);
116
+
107
117
  socket.on('error', function saWorker$$socket$errorHandler(e) {
108
118
  connecting = false;
109
119
  if (!dcpConfig.standaloneWorker.quiet)
@@ -173,7 +173,17 @@ def prepPyodide(args):
173
173
  image = bytes(image)
174
174
  imageFile = io.BytesIO(image)
175
175
  tar = tarfile.open(mode='r', fileobj=imageFile)
176
- tar.extractall()
176
+
177
+ # Don't overwrite directories which corrupts Pyodide's in memory filesystem
178
+ def safe_extract(tar, path="/"):
179
+ for member in tar.getmembers():
180
+ if member.isdir():
181
+ dir_path = os.path.join(path, member.name)
182
+ if not os.path.exists(dir_path):
183
+ os.makedirs(dir_path)
184
+ else:
185
+ tar.extract(member, path)
186
+ safe_extract(tar)
177
187
 
178
188
  for item, value in args['environmentVariables'].items():
179
189
  os.environ[item] = value
@@ -236,7 +246,7 @@ prepPyodide`);
236
246
  const sliceHandlerResult = await pythonSliceHandler(pyodide.toPy(datum));
237
247
 
238
248
  // if it is a PyProxy, convert its value to JavaScript
239
- if (sliceHandlerResult.toJs)
249
+ if (sliceHandlerResult?.toJs)
240
250
  return sliceHandlerResult.toJs();
241
251
 
242
252
  return sliceHandlerResult;
@@ -176,7 +176,7 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, function eve
176
176
  const event = events.shift();
177
177
  if (event.eventType === 'timer')
178
178
  {
179
- serviceEvents.executingTimeout = realSetTimeout(event.fn, 0, event.args);
179
+ serviceEvents.executingTimeout = realSetTimeout(event.fn, 0);
180
180
  if (event.recur)
181
181
  {
182
182
  event.when = Date.now() + event.recur;
@@ -224,14 +224,10 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, function eve
224
224
  }
225
225
  }
226
226
 
227
- // if user supplies arguments, apply them to the callback function
228
- if (arg)
229
- {
230
- args = Array.prototype.slice.call(arguments); // get a plain array from function arguments
231
- args = args.slice(2); // slice the first two elements (callback & timeout), leaving an array of user arguments
232
- let fn = callback;
233
- callback = () => fn.apply(fn, args); // apply the arguments to the callback function
234
- }
227
+ args = Array.prototype.slice.call(arguments); // get a plain array from function arguments
228
+ args = args.slice(2); // slice the first two elements (callback & timeout), leaving an array of user arguments
229
+ let fn = callback;
230
+ callback = () => fn.apply(fn, args); // apply the arguments to the callback function
235
231
 
236
232
  events.serial = +events.serial + 1;
237
233
  timer = {
@@ -93,13 +93,10 @@ self.wrapScriptLoading({ scriptName: 'native-event-loop' }, function nativeEvent
93
93
  }
94
94
  }
95
95
 
96
- // if user supplies arguments, apply them to the callback function
97
- if (arg) {
98
- args = Array.prototype.slice.call(arguments); // get a plain array from function arguments
99
- args = args.slice(2); // slice the first two elements (callback & timeout), leaving an array of user arguments
100
- let fn = callback;
101
- callback = () => fn.apply(fn, args); // apply the arguments to the callback function
102
- }
96
+ args = Array.prototype.slice.call(arguments); // get a plain array from function arguments
97
+ args = args.slice(2); // slice the first two elements (callback & timeout), leaving an array of user arguments
98
+ let fn = callback;
99
+ callback = () => fn.apply(fn, args); // apply the arguments to the callback function
103
100
 
104
101
  timers.serial = +timers.serial + 1;
105
102
  timer = {
@@ -18,7 +18,7 @@ function worktimes$$fn(protectedStorage, _ring2PostMessage)
18
18
 
19
19
  const worktimes = [
20
20
  { name: 'map-basic', versions: ['1.0.0'] },
21
- { name: 'pyodide', versions: ['0.24.0'] },
21
+ { name: 'pyodide', versions: ['0.24.1'] },
22
22
  ];
23
23
 
24
24
  function registerWorktime(name, version)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcp-client",
3
- "version": "4.4.7",
3
+ "version": "4.4.9-0",
4
4
  "description": "Core libraries for accessing DCP network",
5
5
  "keywords": [
6
6
  "dcp"
@@ -44,6 +44,7 @@
44
44
  "regedit": "^3.0.3",
45
45
  "semver": "^7.3.5",
46
46
  "webpack": "5.92.0",
47
+ "source-map-support": "0.5.21",
47
48
  "webpack-cli": "^4.7.2",
48
49
  "yargs": "16.2.0"
49
50
  },
@@ -0,0 +1,29 @@
1
+ #! /usr/bin/env node
2
+ /**
3
+ * @file attempt-to-fetch.js
4
+ *
5
+ * Attempt to fetch using nodejs' global fetch. This
6
+ * should have been blocked after access-lists was
7
+ * applied.
8
+ *
9
+ * This test must be called from a bash test so Peter is
10
+ * able to run it properly despite changes to globalThis.
11
+ *
12
+ * @author Will Pringle <will@distributive.network>
13
+ * @date December 2023
14
+ */
15
+ const sandboxScripts = '../../libexec/sandbox/';
16
+
17
+ const files = [
18
+ require.resolve(sandboxScripts + 'script-load-wrapper.js'),
19
+ require.resolve(sandboxScripts + 'access-lists.js'),
20
+ ];
21
+
22
+ require('../../test-helpers/globalPolyfillHelper').init(files, ()=>{});
23
+ emitEvent('message', {request: 'applyRequirements', requirements: {environment: {}}});
24
+
25
+ setTimeout(() => {
26
+ // let's attempt to use nodejs' fetch to make a request to example.com
27
+ fetch('https://example.com').then(console.log);
28
+ })
29
+
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @file autoupdate-check.js
3
+ * post-init details for auto update tests
4
+ *
5
+ * @author Wes Garland, wes@distributive.network
6
+ * @date March 2023
7
+ */
8
+ const assert = require('assert').strict;
9
+
10
+ const runningBundle = require('dcp/build');
11
+ const bootstrapBundle = require('dcp/bootstrap-build');
12
+
13
+ console.log(' running bundle', runningBundle.version, runningBundle.branch);
14
+ console.log('bootstrap bundle', bootstrapBundle.version, bootstrapBundle.branch);
15
+
16
+ assert(runningBundle !== bootstrapBundle);
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @file config.js
3
+ * This is the actual test called for config-sync.tap and config-async.tap
4
+ *
5
+ * @author KC Erb
6
+ * @date Jul 2020
7
+ */
8
+ 'use strict';
9
+ const { test } = require('zora');
10
+ const os = require('os');
11
+ const dcpConfig = require('dcp/dcp-config');
12
+
13
+ test('config order', function (t) {
14
+ t.equal(dcpConfig.etcOnly, "in-etc");
15
+ t.equal(dcpConfig.etcProgramName, "in-etc-config-tap");
16
+ t.equal(dcpConfig.homeDir, "in-homedir");
17
+ t.equal(dcpConfig.homeDirProgramName, "in-homedir-config-tap");
18
+ t.equal(dcpConfig.etcOverriden, "in-override");
19
+ t.equal(dcpConfig.etcProgramNameOverridden, "in-override");
20
+ t.equal(dcpConfig.homeDirOverridden, "in-override");
21
+ t.equal(dcpConfig.homeDirProgramNameOverriden, "in-override");
22
+ });
23
+
24
+ test('config language - can call `scheduler` global', function (t) {
25
+ t.ok(dcpConfig.scheduler.canSetProgrammatically);
26
+ })
27
+
28
+ if (os.platform === 'win32') {
29
+ test('check some of that registry stuff', function (t) {
30
+ t.ok(false) // untested on windows!
31
+ })
32
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @file etc/dcp-config.js
3
+ * DCP Config file fragment for the custom-config-2.simple test
4
+ * @author Wes Garland, wes@distributive.network
5
+ * @date Sep 2022
6
+ */
7
+ return {
8
+ stack: {
9
+ './etc/dcp-config-2.js': 'yes',
10
+ }
11
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file etc/dcp-config.js
3
+ * DCP Config file fragment for the simple config test
4
+ * @author Wes Garland, wes@distributive.network
5
+ * @date Sep 2022
6
+ */
7
+ {
8
+ stack: {
9
+ '/etc/dcp/dcp-config': 'should be overridden',
10
+ './etc/dcp-config.js': 'yes',
11
+ '/home/username/.dcp/dcp-config.js': undefined,
12
+ '/home/username/.dcp/config.simple': undefined,
13
+ '/home/username/.dcp/config-simple-scope': undefined,
14
+ 'initConfig': undefined,
15
+ '/etc/dcp/override-dcp-config': undefined,
16
+ '/etc/dcp/config-simple-scope': undefined,
17
+ }
18
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @file globalPolyfillHelper.js
3
+ *
4
+ * Helper file for tests of scripts in libexec/sandbox. Most of the scripts assume
5
+ * some specific global symbols exist, so this script polyfills most of them. Depending on
6
+ * the scripts being tested, more polyfills may be required, which should be implemented
7
+ * in the individual test files. This file also executes the scripts provided in the global scope.
8
+ *
9
+ * @author Ryan Saweczko, ryansaweczko@kingsds.network
10
+ * @date January 2022
11
+ */
12
+
13
+
14
+ const fs = require('fs');
15
+ /**
16
+ * Initializes the global scope by evaluating a list of files. Typically,
17
+ * sandbox initialization files to setup necessary symbols to run test.
18
+ *
19
+ * Accepts a callback to make spying on post messages easier for test
20
+ * assertions.
21
+ *
22
+ * @param {string[]} files - A list of files to execute in the global scope.
23
+ * @param {(message: object) => void} [outputTesting] - Callback that receives post messages.
24
+ */
25
+ exports.init = function init(files, outputTesting)
26
+ {
27
+ let code = ''
28
+ for (const file of files)
29
+ {
30
+ const fd = fs.openSync(file, 'r');
31
+ code += fs.readFileSync(fd, 'utf-8') + '\n';
32
+ fs.closeSync(fd);
33
+ }
34
+
35
+ // The node worker injects several symbols into the context of the evaluator when it
36
+ // is started. These symbols are expected to exist on the global object within the evaluator.
37
+ // Emulate the expected global symbols that are most commonly used.
38
+ self = global;
39
+ global.KVIN = require('kvin');
40
+ global.performance = { now: Date.now };
41
+ const unmarshal = KVIN.unmarshal;
42
+
43
+ // postMessage is:
44
+ // a) expected to be a symbol in the evaluator
45
+ // b) the method almost always used to get information out of the evaluator.
46
+ // for this purpose, a callback function should be defined in each test to check
47
+ // whatever desired functionality works.
48
+ // eslint-disable-next-line vars-on-top
49
+ global.postMessage = (line) =>
50
+ {
51
+ line = unmarshal(line)
52
+ if (typeof outputTesting === 'function')
53
+ outputTesting(line);
54
+ }
55
+
56
+ // Simulate die with process.exit
57
+ global.die = process.exit
58
+
59
+ // Very, very, very badly created event listener implementation - but suits the needs
60
+ const eventsListening = {}
61
+ global.addEventListener = (event,callback) =>
62
+ {
63
+ if (!eventsListening[event])
64
+ eventsListening[event] = [];
65
+ eventsListening[event].push(callback)
66
+ }
67
+ global.emitEvent = (event, data) =>
68
+ {
69
+ if (eventsListening[event])
70
+ for (let cb of eventsListening[event])
71
+ cb.call(null, data);
72
+ }
73
+ global.removeEventListener = (event, listener) =>
74
+ {
75
+ const listenerIdx = eventsListening[event].indexOf(listener);
76
+ eventsListening[event].splice(listenerIdx, 1);
77
+ }
78
+
79
+ const indirect = eval;
80
+ indirect(code);
81
+ // At this point a very primitive version of the evaluator exists - all global symbols defined in
82
+ // by the supplied evaluator scripts 'files' exist/are overwritten in the global scope.
83
+ // Tests can now use such symbols, or event listeners that would be set up by the files to run tests over them.
84
+ }
85
+
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file setup-testenv.js
3
+ * Library code to set up the test environment for Peter .simple tests, so that the tests
4
+ * do not require a running scheduler, and are not influenced by the testing user's personal
5
+ * nor machine-wide configs, nor the scheduler's configs.
6
+ * @author Wes Garland, wes@kingsds.network
7
+ * @date Sep 2020
8
+ */
9
+ 'use strict';
10
+
11
+ const path = require('path');
12
+
13
+ process.env.DCP_HOMEDIR = path.resolve(path.dirname(module.filename), '../test-pseudo-root/home/username');
14
+ process.env.DCP_ETCDIR = path.resolve(path.dirname(module.filename), '../test-pseudo-root/etc');
15
+ if (!process.env.DCP_CONFIG_LOCATION)
16
+ process.env.DCP_CONFIG_LOCATION = '';
17
+ if (process.env.DCP_SCHEDULER_LOCATION)
18
+ process.env.DCP_SCHEDULER_LOCATION = '';
19
+ if (!process.env.DCP_BUNDLE_LOCATION)
20
+ process.env.DCP_BUNDLE_LOCATION = 'https://scheduler.distributed.computer/dcp-client/dist/dcp-client-bundle.js';
21
+ process.env.DCP_REGISTRY_BASEKEY = `Software\\Distributive\\DCP-Client-Tests\\Peter`;
22
+
23
+ if (require('os').platform() === 'win32')
24
+ {
25
+ require('child_process').spawnSync('reg.exe', [ 'delete', 'HKLM\\' + process.env_DCP_REGISTRY_BASEKEY, '-f' ]);
26
+ require('child_process').spawnSync('reg.exe', [ 'delete', 'HKCU\\' + process.env_DCP_REGISTRY_BASEKEY, '-f' ]);
27
+ }
28
+
29
+ /* Some tests don't load dcp-client */
30
+ var dcpDcp;
31
+ try
32
+ {
33
+ dotDcp = require('dcp/dcp-dot-dir');
34
+ }
35
+ catch(e) {};
36
+ if (dcpDcp)
37
+ dotDcp.setHomeDir(process.env.DCP_HOMEDIR);
@@ -1,35 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <!-- @file minimal.html
4
- --
5
- -- Sample web page showing how to deploy a minimal DCP job with a client written
6
- -- using BravoJS
7
- --
8
- -- @author Wes Garland, wes@kingsds.network
9
- -- @date Oct 2019
10
- --
11
- -->
12
- <head><meta charset="utf-8">
13
- <script src="../../../bravojs/bravo.js"></script>
14
- <script src="https://scheduler.distributed.computer/etc/dcp-config.js"></script>
15
- </head>
16
- <body onload="module.main.start()">
17
- This is a minimal vanilla web dcp-client/BravoJS example. Look in your browser&apos;s console for output.
18
- <script>
19
- module.declare(['../../dcp-client'], function(require, exports, module) {
20
- exports.start = async function() {
21
- await require('../../dcp-client').init()
22
- const compute = require('dcp/compute')
23
- let results = await compute.for(1, 10,
24
- function(i) {
25
- let result = i*3
26
- console.log(`Calculated result for slice #${i}`)
27
- progress(i/10)
28
- return result
29
- }).exec(compute.marketValue)
30
- console.log(results)
31
- }
32
- })
33
- </script>
34
- </body>
35
- </html>