@scrypted/server 0.123.1 → 0.123.2

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 (98) hide show
  1. package/dist/ip.d.ts +2 -0
  2. package/dist/ip.js +5 -4
  3. package/dist/ip.js.map +1 -1
  4. package/dist/listen-zero.d.ts +5 -2
  5. package/dist/listen-zero.js +2 -1
  6. package/dist/listen-zero.js.map +1 -1
  7. package/dist/plugin/plugin-api.d.ts +9 -3
  8. package/dist/plugin/plugin-api.js +10 -1
  9. package/dist/plugin/plugin-api.js.map +1 -1
  10. package/dist/plugin/plugin-console.d.ts +2 -1
  11. package/dist/plugin/plugin-console.js +27 -6
  12. package/dist/plugin/plugin-console.js.map +1 -1
  13. package/dist/plugin/plugin-host-api.js +1 -1
  14. package/dist/plugin/plugin-host-api.js.map +1 -1
  15. package/dist/plugin/plugin-host.d.ts +4 -7
  16. package/dist/plugin/plugin-host.js +76 -62
  17. package/dist/plugin/plugin-host.js.map +1 -1
  18. package/dist/plugin/plugin-lazy-remote.d.ts +3 -3
  19. package/dist/plugin/plugin-lazy-remote.js +2 -2
  20. package/dist/plugin/plugin-lazy-remote.js.map +1 -1
  21. package/dist/plugin/plugin-remote-stats.d.ts +2 -2
  22. package/dist/plugin/plugin-remote-stats.js +4 -2
  23. package/dist/plugin/plugin-remote-stats.js.map +1 -1
  24. package/dist/plugin/plugin-remote-worker.d.ts +0 -1
  25. package/dist/plugin/plugin-remote-worker.js +77 -335
  26. package/dist/plugin/plugin-remote-worker.js.map +1 -1
  27. package/dist/plugin/plugin-remote.d.ts +3 -3
  28. package/dist/plugin/plugin-remote.js +2 -2
  29. package/dist/plugin/plugin-remote.js.map +1 -1
  30. package/dist/plugin/plugin-repl.js +2 -1
  31. package/dist/plugin/plugin-repl.js.map +1 -1
  32. package/dist/plugin/runtime/cluster-fork.worker.d.ts +9 -0
  33. package/dist/plugin/runtime/cluster-fork.worker.js +73 -0
  34. package/dist/plugin/runtime/cluster-fork.worker.js.map +1 -0
  35. package/dist/plugin/runtime/custom-worker.js +2 -2
  36. package/dist/plugin/runtime/custom-worker.js.map +1 -1
  37. package/dist/plugin/runtime/node-fork-worker.js +5 -3
  38. package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
  39. package/dist/plugin/runtime/python-worker.js +2 -2
  40. package/dist/plugin/runtime/python-worker.js.map +1 -1
  41. package/dist/rpc.d.ts +1 -0
  42. package/dist/rpc.js +3 -2
  43. package/dist/rpc.js.map +1 -1
  44. package/dist/runtime.d.ts +4 -0
  45. package/dist/runtime.js +16 -2
  46. package/dist/runtime.js.map +1 -1
  47. package/dist/scrypted-cluster-common.d.ts +22 -0
  48. package/dist/scrypted-cluster-common.js +332 -0
  49. package/dist/scrypted-cluster-common.js.map +1 -0
  50. package/dist/scrypted-cluster-main.d.ts +2 -0
  51. package/dist/scrypted-cluster-main.js +12 -0
  52. package/dist/scrypted-cluster-main.js.map +1 -0
  53. package/dist/scrypted-cluster.d.ts +38 -0
  54. package/dist/scrypted-cluster.js +277 -0
  55. package/dist/scrypted-cluster.js.map +1 -0
  56. package/dist/scrypted-main-exports.js +20 -14
  57. package/dist/scrypted-main-exports.js.map +1 -1
  58. package/dist/scrypted-server-main.js +8 -15
  59. package/dist/scrypted-server-main.js.map +1 -1
  60. package/dist/server-settings.d.ts +1 -0
  61. package/dist/server-settings.js +2 -1
  62. package/dist/server-settings.js.map +1 -1
  63. package/dist/services/backup.js.map +1 -1
  64. package/dist/services/cluster-fork.d.ts +7 -0
  65. package/dist/services/cluster-fork.js +25 -0
  66. package/dist/services/cluster-fork.js.map +1 -0
  67. package/dist/services/plugin.d.ts +2 -7
  68. package/dist/services/plugin.js +2 -17
  69. package/dist/services/plugin.js.map +1 -1
  70. package/package.json +2 -2
  71. package/python/plugin_remote.py +150 -135
  72. package/python/rpc_reader.py +3 -19
  73. package/src/ip.ts +5 -4
  74. package/src/listen-zero.ts +3 -2
  75. package/src/plugin/plugin-api.ts +11 -3
  76. package/src/plugin/plugin-console.ts +29 -7
  77. package/src/plugin/plugin-host-api.ts +1 -1
  78. package/src/plugin/plugin-host.ts +92 -77
  79. package/src/plugin/plugin-lazy-remote.ts +4 -4
  80. package/src/plugin/plugin-remote-stats.ts +6 -4
  81. package/src/plugin/plugin-remote-worker.ts +91 -376
  82. package/src/plugin/plugin-remote.ts +5 -5
  83. package/src/plugin/plugin-repl.ts +2 -1
  84. package/src/plugin/runtime/cluster-fork.worker.ts +92 -0
  85. package/src/plugin/runtime/custom-worker.ts +2 -2
  86. package/src/plugin/runtime/node-fork-worker.ts +6 -3
  87. package/src/plugin/runtime/python-worker.ts +2 -2
  88. package/src/rpc.ts +3 -2
  89. package/src/runtime.ts +17 -2
  90. package/src/scrypted-cluster-common.ts +374 -0
  91. package/src/scrypted-cluster-main.ts +12 -0
  92. package/src/scrypted-cluster.ts +326 -0
  93. package/src/scrypted-main-exports.ts +22 -16
  94. package/src/scrypted-server-main.ts +15 -23
  95. package/src/server-settings.ts +1 -0
  96. package/src/services/backup.ts +0 -1
  97. package/src/services/cluster-fork.ts +22 -0
  98. package/src/services/plugin.ts +3 -21
@@ -2,8 +2,9 @@ import { DeviceManager, ScryptedNativeId, SystemManager } from '@scrypted/types'
2
2
  import { Console } from 'console';
3
3
  import { once } from 'events';
4
4
  import net, { Server } from 'net';
5
- import { PassThrough, Readable } from 'stream';
5
+ import { PassThrough, Readable, Writable } from 'stream';
6
6
  import { listenZero } from '../listen-zero';
7
+ import { isClusterAddress } from '../scrypted-cluster-common';
7
8
 
8
9
  export interface ConsoleServer {
9
10
  pluginConsole: Console;
@@ -76,8 +77,11 @@ export function prepareConsoles(getConsoleName: () => string, systemManager: ()
76
77
  ret = getConsole(async (stdout, stderr) => {
77
78
  const connect = async () => {
78
79
  const plugins = await getPlugins();
79
- const port = await plugins.getRemoteServicePort(getConsoleName(), 'console-writer');
80
- const socket = net.connect(port);
80
+ const [port,host] = await plugins.getRemoteServicePort(getConsoleName(), 'console-writer');
81
+ const socket = net.connect({
82
+ port,
83
+ host,
84
+ });
81
85
  socket.write(nativeId + '\n');
82
86
  const writer = (data: Buffer) => {
83
87
  socket.write(data);
@@ -136,8 +140,12 @@ export function prepareConsoles(getConsoleName: () => string, systemManager: ()
136
140
  if (!mixin)
137
141
  return;
138
142
  const { pluginId, nativeId: mixinNativeId } = mixin;
139
- const port = await plugins.getRemoteServicePort(pluginId, 'console-writer');
140
- const socket = net.connect(port);
143
+ const [port, host] = await plugins.getRemoteServicePort(pluginId, 'console-writer');
144
+ const socket = net.connect({
145
+ port,
146
+ host,
147
+ });
148
+ socket.on('error', () => { });
141
149
  socket.write(mixinNativeId + '\n');
142
150
  const writer = (data: Buffer) => {
143
151
  let str = data.toString().trim();
@@ -295,8 +303,12 @@ export async function createConsoleServer(remoteStdout: Readable, remoteStderr:
295
303
  socket.once('error', cleanup);
296
304
  socket.once('end', cleanup);
297
305
  });
298
- const readPort = await listenZero(readServer, '127.0.0.1');
299
- const writePort = await listenZero(writeServer, '127.0.0.1');
306
+
307
+ let address = '0.0.0.0';
308
+ if (isClusterAddress(address))
309
+ address = '127.0.0.1';
310
+ const readPort = await listenZero(readServer, address);
311
+ const writePort = await listenZero(writeServer, address);
300
312
 
301
313
  return {
302
314
  clear(nativeId: ScryptedNativeId) {
@@ -333,3 +345,13 @@ export function pipeWorkerConsole(nativeWorker: { stdout: Readable, stderr: Read
333
345
  useConsole.error(data.toString());
334
346
  });
335
347
  }
348
+
349
+ export async function writeWorkerGenerator(asyncIterator: AsyncGenerator<Buffer>, writable: Writable) {
350
+ try {
351
+ for await (const data of asyncIterator) {
352
+ writable.write(data);
353
+ }
354
+ }
355
+ catch (e) {
356
+ }
357
+ }
@@ -186,7 +186,7 @@ export class PluginHostAPI extends PluginAPIManagedListeners implements PluginAP
186
186
 
187
187
  async requestRestart() {
188
188
  const logger = await this.getLogger(undefined);
189
- logger.log('i', 'plugin restart was requested');
189
+ logger?.log('i', 'plugin restart was requested');
190
190
  return this.restartDebounced();
191
191
  }
192
192
 
@@ -2,27 +2,28 @@ import { Device, EngineIOHandler, ScryptedInterface } from '@scrypted/types';
2
2
  import crypto from 'crypto';
3
3
  import * as io from 'engine.io';
4
4
  import fs from 'fs';
5
- import net from 'net';
6
5
  import os from 'os';
7
- import { Duplex } from 'stream';
8
6
  import WebSocket from 'ws';
9
7
  import { Plugin } from '../db-types';
10
8
  import { IOServer, IOServerSocket } from '../io';
11
9
  import { Logger } from '../logger';
12
- import { RpcPeer } from '../rpc';
13
- import { createDuplexRpcPeer, createRpcSerializer } from '../rpc-serializer';
10
+ import { RpcPeer, RPCResultError } from '../rpc';
11
+ import { createRpcSerializer } from '../rpc-serializer';
14
12
  import { ScryptedRuntime } from '../runtime';
13
+ import { prepareClusterPeer } from '../scrypted-cluster-common';
15
14
  import { sleep } from '../sleep';
16
15
  import { AccessControls } from './acl';
17
16
  import { MediaManagerHostImpl } from './media';
18
- import { PluginAPIProxy, PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api';
17
+ import { PluginAPIProxy, PluginRemote, PluginRemoteLoadZipOptions, PluginZipAPI } from './plugin-api';
19
18
  import { ConsoleServer, createConsoleServer } from './plugin-console';
20
19
  import { PluginDebug } from './plugin-debug';
21
20
  import { PluginHostAPI } from './plugin-host-api';
22
21
  import { LazyRemote } from './plugin-lazy-remote';
23
22
  import { setupPluginRemote } from './plugin-remote';
23
+ import { PluginStats } from './plugin-remote-stats';
24
24
  import { WebSocketConnection } from './plugin-remote-websocket';
25
25
  import { ensurePluginVolume, getScryptedVolume } from './plugin-volume';
26
+ import { createClusterForkWorker, needsClusterForkWorker } from './runtime/cluster-fork.worker';
26
27
  import { prepareZipSync } from './runtime/node-worker-common';
27
28
  import { RuntimeWorker } from './runtime/runtime-worker';
28
29
 
@@ -59,10 +60,8 @@ export class PluginHost {
59
60
  api: PluginHostAPI;
60
61
  pluginName: string;
61
62
  packageJson: any;
62
- stats: {
63
- cpuUsage: NodeJS.CpuUsage,
64
- memoryUsage: NodeJS.MemoryUsage,
65
- };
63
+ lastStats: number;
64
+ stats: PluginStats;
66
65
  killed = false;
67
66
  consoleServer: Promise<ConsoleServer>;
68
67
  zipHash: string;
@@ -145,7 +144,7 @@ export class PluginHost {
145
144
  this.unzippedPath = unzippedPath;
146
145
  }
147
146
 
148
- this.startPluginHost(logger, {
147
+ const peerPromise = this.startPluginHost(logger, {
149
148
  SCRYPTED_VOLUME: volume,
150
149
  SCRYPTED_PLUGIN_VOLUME: pluginVolume,
151
150
  }, pluginDebug);
@@ -206,7 +205,7 @@ export class PluginHost {
206
205
  const self = this;
207
206
 
208
207
  const { runtime } = this.packageJson.scrypted;
209
- const mediaManager = runtime === 'python'
208
+ const mediaManager = runtime && runtime !== 'node'
210
209
  ? new MediaManagerHostImpl(pluginDeviceId, () => scrypted.stateManager.getSystemState(), console, id => scrypted.getDevice(id))
211
210
  : undefined;
212
211
 
@@ -215,7 +214,18 @@ export class PluginHost {
215
214
  logger.log('i', `loading ${this.pluginName}`);
216
215
  logger.log('i', 'pid ' + this.worker?.pid);
217
216
 
218
- const remotePromise = setupPluginRemote(this.peer, this.api, self.pluginId, { serverVersion }, () => this.scrypted.stateManager.getSystemState());
217
+ const remotePromise = (async () => {
218
+ let peer: RpcPeer;
219
+ try {
220
+ peer = await peerPromise;
221
+ }
222
+ catch (e) {
223
+ logger.log('e', 'plugin failed to start ' + e);
224
+ throw new RPCResultError(this.peer, 'cluster plugin start failed', e);
225
+ }
226
+ return setupPluginRemote(peer, this.api, self.pluginId, { serverVersion }, () => this.scrypted.stateManager.getSystemState());
227
+ })();
228
+
219
229
  const init = (async () => {
220
230
  const remote = await remotePromise;
221
231
 
@@ -248,7 +258,14 @@ export class PluginHost {
248
258
  };
249
259
  // original implementation sent the zipBuffer, sending the zipFile name now.
250
260
  // can switch back for non-local plugins.
251
- const modulePromise = remote.loadZip(this.packageJson, async () => fs.promises.readFile(this.zipFile), loadZipOptions);
261
+ const modulePromise = remote.loadZip(this.packageJson,
262
+ // the plugin is expected to send process stats every 10 seconds.
263
+ // this can be used as a check for liveness.
264
+ new PluginZipAPI(async () => fs.promises.readFile(this.zipFile), async (stats: PluginStats) => {
265
+ this.lastStats = Date.now();
266
+ this.stats = stats;
267
+ }),
268
+ loadZipOptions);
252
269
  // allow garbage collection of the zip buffer
253
270
  const module = await modulePromise;
254
271
  logger.log('i', `loaded ${this.pluginName}`);
@@ -288,28 +305,65 @@ export class PluginHost {
288
305
  if (!workerHost)
289
306
  throw new UnsupportedRuntimeError(this.packageJson.scrypted.runtime);
290
307
 
291
- this.worker = workerHost(this.scrypted.mainFilename, this.pluginId, {
292
- packageJson: this.packageJson,
293
- env,
294
- pluginDebug,
295
- unzippedPath: this.unzippedPath,
296
- zipFile: this.zipFile,
297
- zipHash: this.zipHash,
298
- }, this.scrypted);
299
-
300
- this.peer = new RpcPeer('host', this.pluginId, (message, reject, serializationContext) => {
301
- if (connected) {
302
- this.worker.send(message, reject, serializationContext);
303
- }
304
- else if (reject) {
305
- reject(new Error('peer disconnected'));
306
- }
307
- });
308
+ let peer: Promise<RpcPeer>
309
+ if (!needsClusterForkWorker(this.packageJson.scrypted)) {
310
+ this.peer = new RpcPeer('host', this.pluginId, (message, reject, serializationContext) => {
311
+ if (connected) {
312
+ this.worker.send(message, reject, serializationContext);
313
+ }
314
+ else if (reject) {
315
+ reject(new Error('peer disconnected'));
316
+ }
317
+ });
308
318
 
309
- this.worker.setupRpcPeer(this.peer);
319
+ peer = Promise.resolve(this.peer);
320
+
321
+ this.worker = workerHost(this.scrypted.mainFilename, this.pluginId, {
322
+ packageJson: this.packageJson,
323
+ env,
324
+ pluginDebug,
325
+ unzippedPath: this.unzippedPath,
326
+ zipFile: this.zipFile,
327
+ zipHash: this.zipHash,
328
+ }, this.scrypted);
329
+
330
+ this.worker.setupRpcPeer(this.peer);
331
+
332
+ this.worker.stdout.on('data', data => console.log(data.toString()));
333
+ this.worker.stderr.on('data', data => console.error(data.toString()));
334
+ }
335
+ else {
336
+ this.peer = new RpcPeer('host', this.pluginId, (message, reject, serializationContext) => {
337
+ if (connected) {
338
+ console.warn('unexpected message to cluster fork worker', message);
339
+ }
340
+ else if (reject) {
341
+ reject(new Error('peer disconnected'));
342
+ }
343
+ });
344
+
345
+ const clusterSetup = prepareClusterPeer(this.peer);
346
+ const { runtimeWorker, forkPeer } = createClusterForkWorker((async () => {
347
+ await clusterSetup.initializeCluster({
348
+ clusterId: this.scrypted.clusterId,
349
+ clusterSecret: this.scrypted.clusterSecret,
350
+ });
351
+ return this.scrypted.clusterFork;
352
+ })(),
353
+ this.zipHash, async () => fs.promises.readFile(this.zipFile),
354
+ this.packageJson.scrypted, this.packageJson, clusterSetup.connectRPCObject);
355
+
356
+ forkPeer.then(peer => {
357
+ const originalPeer = this.peer;
358
+ originalPeer.killed.then(s => peer.kill(s)).catch(e => peer.kill(e));
359
+ this.peer = peer;
360
+ peer.killed.catch(() =>{} ).finally(() => originalPeer.kill());
361
+ }).catch(() => {});
362
+
363
+ this.worker = runtimeWorker;
364
+ peer = forkPeer;
365
+ }
310
366
 
311
- this.worker.stdout.on('data', data => console.log(data.toString()));
312
- this.worker.stderr.on('data', data => console.error(data.toString()));
313
367
  let consoleHeader = `${os.platform()} ${os.arch()} ${os.version()}\nserver version: ${serverVersion}\nplugin version: ${this.pluginId} ${this.packageJson.version}\n`;
314
368
  if (process.env.SCRYPTED_DOCKER_FLAVOR)
315
369
  consoleHeader += `${process.env.SCRYPTED_DOCKER_FLAVOR}\n`;
@@ -333,33 +387,7 @@ export class PluginHost {
333
387
  disconnect();
334
388
  });
335
389
 
336
- this.worker.on('rpc', async (message, sendHandle) => {
337
- const socket = sendHandle as net.Socket;
338
- const { pluginId, username } = message;
339
- const host = this.scrypted.plugins[pluginId];
340
- if (!host) {
341
- socket.destroy();
342
- return;
343
- }
344
- try {
345
- const accessControls = await this.scrypted.getAccessControls(username)
346
- host.createRpcPeer(socket, accessControls);
347
- }
348
- catch (e) {
349
- socket.destroy();
350
- return;
351
- }
352
- });
353
-
354
390
  const startupTime = Date.now();
355
- // the plugin is expected to send process stats every 10 seconds.
356
- // this can be used as a check for liveness.
357
- let lastStats: number;
358
- this.peer.params.updateStats = (stats: any) => {
359
- lastStats = Date.now();
360
- this.stats = stats;
361
- }
362
-
363
391
  let lastPong: number;
364
392
  this.peer.params.pong = (time: number) => {
365
393
  lastPong = time;
@@ -371,7 +399,7 @@ export class PluginHost {
371
399
  await sleep(30000);
372
400
  if (this.killed)
373
401
  return;
374
- pingPromise ||= await this.peer.getParam('ping');
402
+ pingPromise ||= peer.then(p => p.getParam('ping'));
375
403
  const ping = await pingPromise;
376
404
  await ping(Date.now());
377
405
  }
@@ -386,7 +414,7 @@ export class PluginHost {
386
414
  const now = Date.now();
387
415
  // plugin may take a while to install, so wait 10 minutes.
388
416
  // after that, require 1 minute checkins.
389
- if (!lastStats || !lastPong) {
417
+ if (!this.lastStats || !lastPong) {
390
418
  if (now - startupTime > 10 * 60 * 1000) {
391
419
  const logger = await this.api.getLogger(undefined);
392
420
  logger.log('e', 'plugin failed to start in a timely manner. restarting.');
@@ -394,7 +422,7 @@ export class PluginHost {
394
422
  }
395
423
  return;
396
424
  }
397
- if (!pluginDebug && (lastStats + 60000 < now)) {
425
+ if (!pluginDebug && (this.lastStats + 60000 < now)) {
398
426
  const logger = await this.api.getLogger(undefined);
399
427
  logger.log('e', 'plugin is not reporting stats. restarting.');
400
428
  this.api.requestRestart();
@@ -406,6 +434,8 @@ export class PluginHost {
406
434
  }
407
435
  }, 60000);
408
436
  this.peer.killed.finally(() => clearInterval(healthInterval));
437
+
438
+ return peer;
409
439
  }
410
440
 
411
441
  async createRpcIoPeer(socket: IOServerSocket, accessControls: AccessControls) {
@@ -447,19 +477,4 @@ export class PluginHost {
447
477
 
448
478
  return setupPluginRemote(rpcPeer, api, null, { serverVersion }, () => this.scrypted.stateManager.getSystemState());
449
479
  }
450
-
451
- async createRpcPeer(duplex: Duplex, accessControls: AccessControls) {
452
- const rpcPeer = createDuplexRpcPeer(`api/${this.pluginId}`, 'duplex', duplex, duplex);
453
- rpcPeer.tags.acl = accessControls;
454
-
455
- // wrap the host api with a connection specific api that can be torn down on disconnect
456
- const createMediaManager = await this.peer.getParam('createMediaManager');
457
- const api = new PluginAPIProxy(this.api, await createMediaManager());
458
- const kill = () => {
459
- api.removeListeners();
460
- };
461
- duplex.on('close', kill);
462
-
463
- return setupPluginRemote(rpcPeer, api, null, { serverVersion }, () => this.scrypted.stateManager.getSystemState());
464
- }
465
480
  }
@@ -1,5 +1,5 @@
1
1
  import { EventDetails, ScryptedNativeId, SystemDeviceState } from '@scrypted/types'
2
- import { PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api';
2
+ import { PluginRemote, PluginRemoteLoadZipOptions, PluginZipAPI } from './plugin-api';
3
3
 
4
4
  /**
5
5
  * This remote is necessary as the host needs to create a remote synchronously
@@ -17,10 +17,10 @@ import { PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api';
17
17
  })();
18
18
  }
19
19
 
20
- async loadZip(packageJson: any, getZip: () => Promise<Buffer>, options?: PluginRemoteLoadZipOptions): Promise<any> {
20
+ async loadZip(packageJson: any, zipAPI: PluginZipAPI, options?: PluginRemoteLoadZipOptions): Promise<any> {
21
21
  if (!this.remote)
22
22
  await this.remoteReadyPromise;
23
- return this.remote.loadZip(packageJson, getZip, options);
23
+ return this.remote.loadZip(packageJson, zipAPI, options);
24
24
  }
25
25
  async setSystemState(state: { [id: string]: { [property: string]: SystemDeviceState; }; }): Promise<void> {
26
26
  if (!this.remote)
@@ -65,7 +65,7 @@ import { PluginRemote, PluginRemoteLoadZipOptions } from './plugin-api';
65
65
  return this.remote.createDeviceState(id, setState);
66
66
  }
67
67
 
68
- async getServicePort(name: string, ...args: any[]): Promise<number> {
68
+ async getServicePort(name: string, ...args: any[]): Promise<[number, string]> {
69
69
  const remote = await this.remotePromise;
70
70
  return remote.getServicePort(name, ...args);
71
71
  }
@@ -2,11 +2,13 @@ import { RuntimeWorker } from "./runtime/runtime-worker";
2
2
 
3
3
  export interface PluginStats {
4
4
  type: 'stats',
5
- cpu: NodeJS.CpuUsage;
5
+ cpuUsage: NodeJS.CpuUsage;
6
6
  memoryUsage: NodeJS.MemoryUsage;
7
7
  }
8
8
 
9
- export function startStatsUpdater(allMemoryStats: Map<RuntimeWorker, NodeJS.MemoryUsage>, updateStats: (stats: PluginStats) => void) {
9
+ export function startStatsUpdater(allMemoryStats: Map<RuntimeWorker, NodeJS.MemoryUsage>, updateStats: (stats: PluginStats) => Promise<void>) {
10
+ if (!updateStats)
11
+ console.warn('wtf')
10
12
  setInterval(() => {
11
13
  let cpuUsage: NodeJS.CpuUsage;
12
14
  let memoryUsage: NodeJS.MemoryUsage;
@@ -35,8 +37,8 @@ export function startStatsUpdater(allMemoryStats: Map<RuntimeWorker, NodeJS.Memo
35
37
 
36
38
  updateStats({
37
39
  type: 'stats',
38
- cpu: cpuUsage,
40
+ cpuUsage,
39
41
  memoryUsage,
40
- });
42
+ }).catch(() => {});
41
43
  }, 10000);
42
44
  }