@scrypted/server 0.123.32 → 0.123.34

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.
Files changed (47) hide show
  1. package/dist/cluster/cluster-setup.js +3 -3
  2. package/dist/cluster/cluster-setup.js.map +1 -1
  3. package/dist/plugin/plugin-host.d.ts +2 -1
  4. package/dist/plugin/plugin-host.js +17 -11
  5. package/dist/plugin/plugin-host.js.map +1 -1
  6. package/dist/plugin/plugin-remote-worker.js +10 -9
  7. package/dist/plugin/plugin-remote-worker.js.map +1 -1
  8. package/dist/plugin/runtime/child-process-worker.d.ts +1 -1
  9. package/dist/plugin/runtime/child-process-worker.js +2 -2
  10. package/dist/plugin/runtime/child-process-worker.js.map +1 -1
  11. package/dist/plugin/runtime/cluster-fork-worker.d.ts +2 -2
  12. package/dist/plugin/runtime/cluster-fork-worker.js +8 -4
  13. package/dist/plugin/runtime/cluster-fork-worker.js.map +1 -1
  14. package/dist/plugin/runtime/custom-worker.d.ts +1 -1
  15. package/dist/plugin/runtime/custom-worker.js +3 -3
  16. package/dist/plugin/runtime/custom-worker.js.map +1 -1
  17. package/dist/plugin/runtime/node-fork-worker.d.ts +1 -1
  18. package/dist/plugin/runtime/node-fork-worker.js +2 -2
  19. package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
  20. package/dist/plugin/runtime/python-worker.d.ts +1 -1
  21. package/dist/plugin/runtime/python-worker.js +3 -3
  22. package/dist/plugin/runtime/python-worker.js.map +1 -1
  23. package/dist/plugin/runtime/runtime-host.d.ts +1 -1
  24. package/dist/plugin/runtime/runtime-host.js +3 -3
  25. package/dist/plugin/runtime/runtime-host.js.map +1 -1
  26. package/dist/scrypted-cluster-main.d.ts +10 -2
  27. package/dist/scrypted-cluster-main.js +15 -14
  28. package/dist/scrypted-cluster-main.js.map +1 -1
  29. package/dist/scrypted-server-main.js +14 -2
  30. package/dist/scrypted-server-main.js.map +1 -1
  31. package/dist/services/cluster-fork.d.ts +3 -2
  32. package/dist/services/cluster-fork.js +38 -7
  33. package/dist/services/cluster-fork.js.map +1 -1
  34. package/package.json +2 -2
  35. package/python/plugin_remote.py +15 -2
  36. package/src/cluster/cluster-setup.ts +3 -3
  37. package/src/plugin/plugin-host.ts +31 -21
  38. package/src/plugin/plugin-remote-worker.ts +16 -10
  39. package/src/plugin/runtime/child-process-worker.ts +3 -1
  40. package/src/plugin/runtime/cluster-fork-worker.ts +16 -10
  41. package/src/plugin/runtime/custom-worker.ts +3 -3
  42. package/src/plugin/runtime/node-fork-worker.ts +2 -2
  43. package/src/plugin/runtime/python-worker.ts +3 -3
  44. package/src/plugin/runtime/runtime-host.ts +4 -4
  45. package/src/scrypted-cluster-main.ts +28 -22
  46. package/src/scrypted-server-main.ts +16 -3
  47. package/src/services/cluster-fork.ts +43 -9
@@ -21,7 +21,7 @@ import { createClusterForkWorker } from './runtime/cluster-fork-worker';
21
21
  import { NodeThreadWorker } from './runtime/node-thread-worker';
22
22
  import { prepareZip } from './runtime/node-worker-common';
23
23
  import { getBuiltinRuntimeHosts } from './runtime/runtime-host';
24
- import { RuntimeWorker } from './runtime/runtime-worker';
24
+ import { RuntimeWorker, RuntimeWorkerOptions } from './runtime/runtime-worker';
25
25
  import type { ClusterForkService } from '../services/cluster-fork';
26
26
  import type { PluginComponent } from '../services/plugin';
27
27
  import { ClusterManagerImpl } from '../scrypted-cluster-main';
@@ -216,10 +216,23 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
216
216
  let nativeWorker: child_process.ChildProcess | worker_threads.Worker;
217
217
  let clusterWorkerId: Promise<string>;
218
218
 
219
+ const runtimeWorkerOptions: RuntimeWorkerOptions = {
220
+ packageJson,
221
+ env: undefined,
222
+ pluginDebug: undefined,
223
+ zipFile,
224
+ unzippedPath,
225
+ zipHash,
226
+ };
227
+
219
228
  // if running in a cluster, fork to a matching cluster worker only if necessary.
220
229
  if (needsClusterForkWorker(options)) {
221
230
  ({ runtimeWorker, forkPeer, clusterWorkerId } = createClusterForkWorker(
222
- api.getComponent('cluster-fork'), zipHash, () => zipAPI.getZip(), options, packageJson, scrypted.connectRPCObject)
231
+ runtimeWorkerOptions,
232
+ options,
233
+ api.getComponent('cluster-fork'),
234
+ () => zipAPI.getZip(),
235
+ scrypted.connectRPCObject)
223
236
  );
224
237
  }
225
238
  else {
@@ -228,14 +241,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
228
241
  const runtime = builtins.get(options.runtime);
229
242
  if (!runtime)
230
243
  throw new Error('unknown runtime ' + options.runtime);
231
- runtimeWorker = runtime(mainFilename, pluginId, {
232
- packageJson,
233
- env: undefined,
234
- pluginDebug: undefined,
235
- zipFile,
236
- unzippedPath,
237
- zipHash,
238
- }, undefined);
244
+ runtimeWorker = runtime(mainFilename, runtimeWorkerOptions, undefined);
239
245
 
240
246
  if (runtimeWorker instanceof ChildProcessWorker) {
241
247
  nativeWorker = runtimeWorker.childProcess;
@@ -4,14 +4,16 @@ import { RpcMessage, RpcPeer } from "../../rpc";
4
4
  import { RuntimeWorker, RuntimeWorkerOptions } from "./runtime-worker";
5
5
 
6
6
  export abstract class ChildProcessWorker extends EventEmitter implements RuntimeWorker {
7
+ public pluginId: string;
7
8
  protected worker: child_process.ChildProcess;
8
9
 
9
10
  get childProcess() {
10
11
  return this.worker;
11
12
  }
12
13
 
13
- constructor(public pluginId: string, options: RuntimeWorkerOptions) {
14
+ constructor(options: RuntimeWorkerOptions) {
14
15
  super();
16
+ this.pluginId = options.packageJson.name;
15
17
  }
16
18
 
17
19
  setupWorker() {
@@ -5,15 +5,20 @@ import { RpcPeer } from "../../rpc";
5
5
  import { PeerLiveness } from "../../scrypted-cluster-main";
6
6
  import type { ClusterForkService } from "../../services/cluster-fork";
7
7
  import { writeWorkerGenerator } from "../plugin-console";
8
- import type { RuntimeWorker } from "./runtime-worker";
8
+ import type { RuntimeWorker, RuntimeWorkerOptions } from "./runtime-worker";
9
9
 
10
10
  export function createClusterForkWorker(
11
+ runtimeWorkerOptions: RuntimeWorkerOptions,
12
+ options: Partial<ClusterFork>,
11
13
  forkComponentPromise: Promise<ClusterForkService>,
12
- zipHash: string,
13
14
  getZip: () => Promise<Buffer>,
14
- options: Partial<ClusterFork>,
15
- packageJson: any,
16
15
  connectRPCObject: (o: any) => Promise<any>) {
16
+
17
+ // these are specific to the cluster worker host
18
+ // and will be set there.
19
+ delete runtimeWorkerOptions.zipFile;
20
+ delete runtimeWorkerOptions.unzippedPath;
21
+
17
22
  const waitKilled = new Deferred<void>();
18
23
  waitKilled.promise.finally(() => events.emit('exit'));
19
24
  const events = new EventEmitter();
@@ -38,21 +43,22 @@ export function createClusterForkWorker(
38
43
  });
39
44
 
40
45
  const peerLiveness = new PeerLiveness(waitKilled.promise);
41
- const clusterForkResultPromise = forkComponentPromise.then(forkComponent => forkComponent.fork(peerLiveness, {
46
+ const clusterForkResultPromise = forkComponentPromise.then(forkComponent => forkComponent.fork(runtimeWorkerOptions, {
42
47
  runtime: options.runtime || 'node',
43
48
  id: options.id,
44
49
  ...options,
45
- }, packageJson, zipHash, getZip));
46
- clusterForkResultPromise.catch(() => {});
50
+ }, peerLiveness,
51
+ getZip));
52
+ clusterForkResultPromise.catch(() => { });
47
53
 
48
54
  const clusterWorkerId = clusterForkResultPromise.then(clusterForkResult => clusterForkResult.clusterWorkerId);
49
- clusterWorkerId.catch(() => {});
55
+ clusterWorkerId.catch(() => { });
50
56
 
51
57
  const forkPeer = (async () => {
52
58
  const clusterForkResult = await clusterForkResultPromise;
53
59
  waitKilled.promise.finally(() => {
54
60
  runtimeWorker.pid = undefined;
55
- clusterForkResult.kill().catch(() => {});
61
+ clusterForkResult.kill().catch(() => { });
56
62
  });
57
63
  clusterForkResult.waitKilled().catch(() => { })
58
64
  .finally(() => {
@@ -79,7 +85,7 @@ export function createClusterForkWorker(
79
85
  return peer;
80
86
  }
81
87
  catch (e) {
82
- clusterForkResult.kill();
88
+ clusterForkResult.kill().catch(() => {});
83
89
  throw e;
84
90
  }
85
91
  })();
@@ -11,8 +11,8 @@ export class CustomRuntimeWorker extends ChildProcessWorker {
11
11
  serializer: ReturnType<typeof createRpcDuplexSerializer>;
12
12
  fork: boolean;
13
13
 
14
- constructor(pluginId: string, options: RuntimeWorkerOptions, runtime: ScryptedRuntime) {
15
- super(pluginId, options);
14
+ constructor(options: RuntimeWorkerOptions, runtime: ScryptedRuntime) {
15
+ super(options);
16
16
 
17
17
  const pluginDevice = runtime.findPluginDevice(this.pluginId);
18
18
  const scryptedRuntimeArguments: ScryptedRuntimeArguments = pluginDevice.state.scryptedRuntimeArguments?.value;
@@ -27,7 +27,7 @@ export class CustomRuntimeWorker extends ChildProcessWorker {
27
27
  // stdin, stdout, stderr, peer in, peer out
28
28
  stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
29
29
  env: Object.assign({}, process.env, env, {
30
- SCRYYPTED_PLUGIN_ID: pluginId,
30
+ SCRYYPTED_PLUGIN_ID: this.pluginId,
31
31
  SCRYPTED_DEBUG_PORT: pluginDebug?.inspectPort?.toString(),
32
32
  SCRYPTED_UNZIPPED_PATH: options.unzippedPath,
33
33
  SCRYPTED_ZIP_FILE: options.zipFile,
@@ -28,8 +28,8 @@ export function isNodePluginChildProcess() {
28
28
 
29
29
  export class NodeForkWorker extends ChildProcessWorker {
30
30
 
31
- constructor(mainFilename: string, pluginId: string, options: RuntimeWorkerOptions) {
32
- super(pluginId, options);
31
+ constructor(mainFilename: string, options: RuntimeWorkerOptions) {
32
+ super(options);
33
33
 
34
34
  const { env, pluginDebug } = options;
35
35
 
@@ -41,8 +41,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
41
41
  return this._stderr;
42
42
  }
43
43
 
44
- constructor(pluginId: string, options: RuntimeWorkerOptions) {
45
- super(pluginId, options);
44
+ constructor(options: RuntimeWorkerOptions) {
45
+ super(options);
46
46
 
47
47
  const { env, pluginDebug } = options;
48
48
  const args: string[] = [
@@ -148,7 +148,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
148
148
  };
149
149
 
150
150
  const pyVersion = require('py/package.json').version;
151
- const pyPath = path.join(getPluginVolume(pluginId), 'py');
151
+ const pyPath = path.join(getPluginVolume(this.pluginId), 'py');
152
152
  const portableInstallPath = path.join(pyPath, pyVersion);
153
153
 
154
154
  const py = new PortablePython(pluginPythonVersion, portableInstallPath, portablePythonOptions);
@@ -4,14 +4,14 @@ import { NodeForkWorker } from "./node-fork-worker";
4
4
  import { PythonRuntimeWorker } from "./python-worker";
5
5
  import type { RuntimeWorker, RuntimeWorkerOptions } from "./runtime-worker";
6
6
 
7
- export type RuntimeHost = (mainFilename: string, pluginId: string, options: RuntimeWorkerOptions, runtime: ScryptedRuntime) => RuntimeWorker;
7
+ export type RuntimeHost = (mainFilename: string, options: RuntimeWorkerOptions, runtime: ScryptedRuntime) => RuntimeWorker;
8
8
 
9
9
  export function getBuiltinRuntimeHosts() {
10
10
  const pluginHosts = new Map<string, RuntimeHost>();
11
11
 
12
- pluginHosts.set('custom', (_, pluginId, options, runtime) => new CustomRuntimeWorker(pluginId, options, runtime));
13
- pluginHosts.set('python', (_, pluginId, options) => new PythonRuntimeWorker(pluginId, options));
14
- pluginHosts.set('node', (mainFilename, pluginId, options) => new NodeForkWorker(mainFilename, pluginId, options));
12
+ pluginHosts.set('custom', (_, options, runtime) => new CustomRuntimeWorker(options, runtime));
13
+ pluginHosts.set('python', (_, options) => new PythonRuntimeWorker(options));
14
+ pluginHosts.set('node', (mainFilename, options) => new NodeForkWorker(mainFilename, options));
15
15
 
16
16
  return pluginHosts;
17
17
  }
@@ -15,7 +15,7 @@ import type { PluginAPI } from './plugin/plugin-api';
15
15
  import { getPluginVolume, getScryptedVolume } from './plugin/plugin-volume';
16
16
  import { prepareZip } from './plugin/runtime/node-worker-common';
17
17
  import { getBuiltinRuntimeHosts } from './plugin/runtime/runtime-host';
18
- import type { RuntimeWorker } from './plugin/runtime/runtime-worker';
18
+ import type { RuntimeWorker, RuntimeWorkerOptions } from './plugin/runtime/runtime-worker';
19
19
  import { RpcPeer } from './rpc';
20
20
  import { createRpcDuplexSerializer } from './rpc-serializer';
21
21
  import type { ScryptedRuntime } from './runtime';
@@ -76,6 +76,7 @@ export interface RunningClusterWorker extends ClusterWorkerProperties {
76
76
  id: string;
77
77
  peer: RpcPeer;
78
78
  forks: Set<ClusterForkOptions>;
79
+ address: string;
79
80
  }
80
81
 
81
82
  export class PeerLiveness {
@@ -86,7 +87,7 @@ export class PeerLiveness {
86
87
  }
87
88
  }
88
89
 
89
- export class ClusterForkResult extends PeerLiveness {
90
+ export class ClusterForkResult extends PeerLiveness implements ClusterForkResultInterface {
90
91
  [RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] = ['kill'];
91
92
  clusterWorkerId?: string;
92
93
 
@@ -103,9 +104,17 @@ export class ClusterForkResult extends PeerLiveness {
103
104
  }
104
105
  }
105
106
 
106
- export type ClusterForkParam = (peerLiveness: PeerLiveness, runtime: string, packageJson: any, zipHash: string, getZip: () => Promise<Buffer>) => Promise<ClusterForkResult>;
107
+ export interface ClusterForkResultInterface {
108
+ clusterWorkerId?: string;
109
+ getResult(): Promise<any>;
110
+ kill(): Promise<void>;
111
+ waitKilled(): Promise<void>;
112
+ }
113
+
114
+ export type ClusterForkParam = (runtime: string, options: RuntimeWorkerOptions, peerLiveness: PeerLiveness, getZip: () => Promise<Buffer>) => Promise<ClusterForkResultInterface>;
107
115
 
108
116
  export function startClusterClient(mainFilename: string) {
117
+ console.log('Cluster client starting.');
109
118
  const originalClusterAddress = process.env.SCRYPTED_CLUSTER_ADDRESS;
110
119
  const labels = getClusterLabels();
111
120
 
@@ -131,6 +140,7 @@ export function startClusterClient(mainFilename: string) {
131
140
  await once(rawSocket, 'connect');
132
141
  }
133
142
  catch (e) {
143
+ console.warn('Cluster server not available.', host, port, e);
134
144
  continue;
135
145
  }
136
146
 
@@ -143,6 +153,7 @@ export function startClusterClient(mainFilename: string) {
143
153
  await once(socket, 'secureConnect');
144
154
  }
145
155
  catch (e) {
156
+ console.warn('Cluster server tls failed.', host, port, e);
146
157
  continue;
147
158
  }
148
159
 
@@ -179,12 +190,7 @@ export function startClusterClient(mainFilename: string) {
179
190
  const clusterPeerSetup = setupCluster(peer);
180
191
  await clusterPeerSetup.initializeCluster({ clusterId, clusterSecret });
181
192
 
182
- const clusterForkParam: ClusterForkParam = async (
183
- peerLiveness: PeerLiveness,
184
- runtime: string,
185
- packageJson: any,
186
- zipHash: string,
187
- getZip: () => Promise<Buffer>) => {
193
+ const clusterForkParam: ClusterForkParam = async (runtime, runtimeWorkerOptions, peerLiveness, getZip) => {
188
194
  let runtimeWorker: RuntimeWorker;
189
195
 
190
196
  const builtins = getBuiltinRuntimeHosts();
@@ -192,23 +198,22 @@ export function startClusterClient(mainFilename: string) {
192
198
  if (!rt)
193
199
  throw new Error('unknown runtime ' + runtime);
194
200
 
195
- const pluginId: string = packageJson.name;
196
- const { zipFile, unzippedPath } = await prepareZip(getPluginVolume(pluginId), zipHash, getZip);
201
+ const pluginId: string = runtimeWorkerOptions.packageJson.name;
202
+ const { zipFile, unzippedPath } = await prepareZip(getPluginVolume(pluginId), runtimeWorkerOptions.zipHash, getZip);
197
203
 
198
204
  const volume = getScryptedVolume();
199
205
  const pluginVolume = getPluginVolume(pluginId);
200
206
 
201
- runtimeWorker = rt(mainFilename, pluginId, {
202
- packageJson,
203
- env: {
204
- SCRYPTED_VOLUME: volume,
205
- SCRYPTED_PLUGIN_VOLUME: pluginVolume,
206
- },
207
- pluginDebug: undefined,
208
- zipFile,
209
- unzippedPath,
210
- zipHash,
211
- }, undefined);
207
+ runtimeWorkerOptions.zipFile = zipFile;
208
+ runtimeWorkerOptions.unzippedPath = unzippedPath;
209
+
210
+ runtimeWorkerOptions.env = {
211
+ ...runtimeWorkerOptions.env,
212
+ SCRYPTED_VOLUME: volume,
213
+ SCRYPTED_PLUGIN_VOLUME: pluginVolume,
214
+ };
215
+
216
+ runtimeWorker = rt(mainFilename, runtimeWorkerOptions, undefined);
212
217
  runtimeWorker.stdout.on('data', data => console.log(data.toString()));
213
218
  runtimeWorker.stderr.on('data', data => console.error(data.toString()));
214
219
 
@@ -311,6 +316,7 @@ export function createClusterServer(runtime: ScryptedRuntime, certificate: Retur
311
316
  // generate a random uuid.
312
317
  id,
313
318
  peer,
319
+ address: socket.remoteAddress,
314
320
  forks: new Set(),
315
321
  };
316
322
  runtime.clusterWorkers.set(id, worker);
@@ -1,6 +1,6 @@
1
1
  import bodyParser from 'body-parser';
2
2
  import cookieParser from 'cookie-parser';
3
- import crypto from 'crypto';
3
+ import crypto, { scrypt } from 'crypto';
4
4
  import { once } from 'events';
5
5
  import express, { Request } from 'express';
6
6
  import fs from 'fs';
@@ -45,10 +45,11 @@ installSourceMapSupport({
45
45
  });
46
46
 
47
47
  let workerInspectPort: number = undefined;
48
+ let workerInspectAddress: string = undefined;
48
49
 
49
50
  async function doconnect(): Promise<net.Socket> {
50
51
  return new Promise((resolve, reject) => {
51
- const target = net.connect(workerInspectPort, '127.0.0.1');
52
+ const target = net.connect(workerInspectPort, workerInspectAddress);
52
53
  target.once('error', reject)
53
54
  target.once('connect', () => resolve(target))
54
55
  })
@@ -100,6 +101,7 @@ app.use(bodyParser.raw({ type: 'application/*', limit: 100000000 }) as any)
100
101
  async function start(mainFilename: string, options?: {
101
102
  onRuntimeCreated?: (runtime: ScryptedRuntime) => Promise<void>,
102
103
  }) {
104
+ console.log('Scrypted server starting.');
103
105
  const volumeDir = getScryptedVolume();
104
106
  await fs.promises.mkdir(volumeDir, {
105
107
  recursive: true
@@ -464,11 +466,20 @@ async function start(mainFilename: string, options?: {
464
466
  waitDebug.catch(() => { });
465
467
 
466
468
  workerInspectPort = Math.round(Math.random() * 10000) + 30000;
469
+ workerInspectAddress = '127.0.0.1';
467
470
  try {
468
- await scrypted.installPlugin(plugin, {
471
+ const host = await scrypted.installPlugin(plugin, {
469
472
  waitDebug,
470
473
  inspectPort: workerInspectPort,
471
474
  });
475
+
476
+ const clusterWorkerId = await host.clusterWorkerId;
477
+ if (clusterWorkerId) {
478
+ const clusterWorker = scrypted.clusterWorkers.get(clusterWorkerId);
479
+ if (clusterWorker) {
480
+ workerInspectAddress = clusterWorker.address;
481
+ }
482
+ }
472
483
  }
473
484
  catch (e) {
474
485
  res.header('Content-Type', 'text/plain');
@@ -479,6 +490,7 @@ async function start(mainFilename: string, options?: {
479
490
 
480
491
  res.send({
481
492
  workerInspectPort,
493
+ workerInspectAddress,
482
494
  });
483
495
  });
484
496
 
@@ -726,6 +738,7 @@ async function start(mainFilename: string, options?: {
726
738
 
727
739
  const clusterMode = getScryptedClusterMode();
728
740
  if (clusterMode?.[0] === 'server') {
741
+ console.log('Cluster server starting.');
729
742
  const clusterServer = createClusterServer(scrypted, keyPair);
730
743
  await listenServerPort('SCRYPTED_CLUSTER_SERVER', clusterMode[2], clusterServer);
731
744
  }
@@ -1,11 +1,40 @@
1
1
  import { matchesClusterLabels } from "../cluster/cluster-labels";
2
+ import type { RuntimeWorkerOptions } from "../plugin/runtime/runtime-worker";
3
+ import { RpcPeer } from "../rpc";
2
4
  import type { ScryptedRuntime } from "../runtime";
3
- import type { ClusterForkOptions, ClusterForkParam, PeerLiveness, RunningClusterWorker } from "../scrypted-cluster-main";
5
+ import type { ClusterForkOptions, ClusterForkParam, ClusterForkResultInterface, PeerLiveness, RunningClusterWorker } from "../scrypted-cluster-main";
6
+
7
+ class WrappedForkResult implements ClusterForkResultInterface {
8
+ [RpcPeer.PROPERTY_PROXY_PROPERTIES] = {
9
+ clusterWorkerId: undefined as string,
10
+ };
11
+
12
+ constructor(public clusterWorkerId: string, public forkResult: Promise<ClusterForkResultInterface>) {
13
+ this[RpcPeer.PROPERTY_PROXY_PROPERTIES].clusterWorkerId = clusterWorkerId;
14
+ }
15
+
16
+ async kill() {
17
+ const fr = await this.forkResult.catch(() => {});
18
+ if (!fr)
19
+ return;
20
+ await fr.kill();
21
+ }
22
+
23
+ async getResult() {
24
+ const fr = await this.forkResult;
25
+ return fr.getResult();
26
+ }
27
+
28
+ async waitKilled() {
29
+ const fr = await this.forkResult;
30
+ await fr.waitKilled();
31
+ }
32
+ }
4
33
 
5
34
  export class ClusterForkService {
6
35
  constructor(public runtime: ScryptedRuntime) { }
7
36
 
8
- async fork(peerLiveness: PeerLiveness, options: ClusterForkOptions, packageJson: any, zipHash: string, getZip: () => Promise<Buffer>) {
37
+ async fork(runtimeWorkerOptions: RuntimeWorkerOptions, options: ClusterForkOptions, peerLiveness: PeerLiveness, getZip: () => Promise<Buffer>) {
9
38
  const matchingWorkers = [...this.runtime.clusterWorkers.entries()].map(([id, worker]) => ({
10
39
  worker,
11
40
  matches: matchesClusterLabels(options, worker.labels),
@@ -34,16 +63,21 @@ export class ClusterForkService {
34
63
  }
35
64
 
36
65
  const fork: ClusterForkParam = await worker.peer.getParam('fork');
37
- const forkResult = await fork(peerLiveness, options.runtime, packageJson, zipHash, getZip);
38
- options.id ||= this.runtime.findPluginDevice(packageJson.name)?._id;
66
+ const forkResultPromise = fork(options.runtime, runtimeWorkerOptions, peerLiveness, getZip);
67
+
68
+ options.id ||= this.runtime.findPluginDevice(runtimeWorkerOptions.packageJson.name)?._id;
39
69
  worker.forks.add(options);
40
- forkResult.waitKilled().catch(() => { }).finally(() => {
41
- worker.forks.delete(options);
70
+
71
+ forkResultPromise.then(forkResult => {
72
+ forkResult.clusterWorkerId = worker.id;
73
+ forkResult.waitKilled().catch(() => { }).finally(() => {
74
+ worker.forks.delete(options);
75
+ })
42
76
  });
43
77
 
44
- forkResult.clusterWorkerId = worker.id;
45
- return forkResult;
46
- }
78
+ const ret: ClusterForkResultInterface = new WrappedForkResult(worker.id, forkResultPromise);
79
+ return ret;
80
+ };
47
81
 
48
82
  async getClusterWorkers() {
49
83
  const ret: any = {};