@scrypted/server 0.123.0 → 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.
- package/dist/ip.d.ts +2 -0
- package/dist/ip.js +5 -4
- package/dist/ip.js.map +1 -1
- package/dist/listen-zero.d.ts +5 -2
- package/dist/listen-zero.js +2 -1
- package/dist/listen-zero.js.map +1 -1
- package/dist/plugin/plugin-api.d.ts +9 -3
- package/dist/plugin/plugin-api.js +10 -1
- package/dist/plugin/plugin-api.js.map +1 -1
- package/dist/plugin/plugin-console.d.ts +2 -1
- package/dist/plugin/plugin-console.js +27 -6
- package/dist/plugin/plugin-console.js.map +1 -1
- package/dist/plugin/plugin-host-api.js +1 -1
- package/dist/plugin/plugin-host-api.js.map +1 -1
- package/dist/plugin/plugin-host.d.ts +4 -7
- package/dist/plugin/plugin-host.js +76 -62
- package/dist/plugin/plugin-host.js.map +1 -1
- package/dist/plugin/plugin-lazy-remote.d.ts +3 -3
- package/dist/plugin/plugin-lazy-remote.js +2 -2
- package/dist/plugin/plugin-lazy-remote.js.map +1 -1
- package/dist/plugin/plugin-remote-stats.d.ts +2 -2
- package/dist/plugin/plugin-remote-stats.js +4 -2
- package/dist/plugin/plugin-remote-stats.js.map +1 -1
- package/dist/plugin/plugin-remote-worker.d.ts +0 -1
- package/dist/plugin/plugin-remote-worker.js +77 -335
- package/dist/plugin/plugin-remote-worker.js.map +1 -1
- package/dist/plugin/plugin-remote.d.ts +3 -3
- package/dist/plugin/plugin-remote.js +2 -2
- package/dist/plugin/plugin-remote.js.map +1 -1
- package/dist/plugin/plugin-repl.js +2 -1
- package/dist/plugin/plugin-repl.js.map +1 -1
- package/dist/plugin/runtime/cluster-fork.worker.d.ts +9 -0
- package/dist/plugin/runtime/cluster-fork.worker.js +73 -0
- package/dist/plugin/runtime/cluster-fork.worker.js.map +1 -0
- package/dist/plugin/runtime/custom-worker.js +2 -2
- package/dist/plugin/runtime/custom-worker.js.map +1 -1
- package/dist/plugin/runtime/node-fork-worker.js +5 -3
- package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/python-worker.js +2 -2
- package/dist/plugin/runtime/python-worker.js.map +1 -1
- package/dist/rpc.d.ts +1 -0
- package/dist/rpc.js +3 -2
- package/dist/rpc.js.map +1 -1
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.js +16 -2
- package/dist/runtime.js.map +1 -1
- package/dist/scrypted-cluster-common.d.ts +22 -0
- package/dist/scrypted-cluster-common.js +332 -0
- package/dist/scrypted-cluster-common.js.map +1 -0
- package/dist/scrypted-cluster-main.d.ts +2 -0
- package/dist/scrypted-cluster-main.js +12 -0
- package/dist/scrypted-cluster-main.js.map +1 -0
- package/dist/scrypted-cluster.d.ts +38 -0
- package/dist/scrypted-cluster.js +277 -0
- package/dist/scrypted-cluster.js.map +1 -0
- package/dist/scrypted-main-exports.js +20 -14
- package/dist/scrypted-main-exports.js.map +1 -1
- package/dist/scrypted-server-main.js +8 -15
- package/dist/scrypted-server-main.js.map +1 -1
- package/dist/server-settings.d.ts +1 -0
- package/dist/server-settings.js +2 -1
- package/dist/server-settings.js.map +1 -1
- package/dist/services/backup.js.map +1 -1
- package/dist/services/cluster-fork.d.ts +7 -0
- package/dist/services/cluster-fork.js +25 -0
- package/dist/services/cluster-fork.js.map +1 -0
- package/dist/services/plugin.d.ts +2 -7
- package/dist/services/plugin.js +2 -17
- package/dist/services/plugin.js.map +1 -1
- package/package.json +7 -7
- package/python/plugin_remote.py +150 -135
- package/python/rpc_reader.py +3 -19
- package/src/ip.ts +5 -4
- package/src/listen-zero.ts +3 -2
- package/src/plugin/plugin-api.ts +11 -3
- package/src/plugin/plugin-console.ts +29 -7
- package/src/plugin/plugin-host-api.ts +1 -1
- package/src/plugin/plugin-host.ts +92 -77
- package/src/plugin/plugin-lazy-remote.ts +4 -4
- package/src/plugin/plugin-remote-stats.ts +6 -4
- package/src/plugin/plugin-remote-worker.ts +91 -376
- package/src/plugin/plugin-remote.ts +5 -5
- package/src/plugin/plugin-repl.ts +2 -1
- package/src/plugin/runtime/cluster-fork.worker.ts +92 -0
- package/src/plugin/runtime/custom-worker.ts +2 -2
- package/src/plugin/runtime/node-fork-worker.ts +6 -3
- package/src/plugin/runtime/python-worker.ts +2 -2
- package/src/rpc.ts +3 -2
- package/src/runtime.ts +17 -2
- package/src/scrypted-cluster-common.ts +374 -0
- package/src/scrypted-cluster-main.ts +12 -0
- package/src/scrypted-cluster.ts +326 -0
- package/src/scrypted-main-exports.ts +22 -16
- package/src/scrypted-server-main.ts +15 -23
- package/src/server-settings.ts +1 -0
- package/src/services/backup.ts +0 -1
- package/src/services/cluster-fork.ts +22 -0
- 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(
|
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(
|
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
|
-
|
299
|
-
|
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
|
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 {
|
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
|
-
|
63
|
-
|
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
|
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 =
|
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,
|
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
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
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
|
-
|
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 ||=
|
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,
|
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,
|
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
|
-
|
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
|
-
|
40
|
+
cpuUsage,
|
39
41
|
memoryUsage,
|
40
|
-
});
|
42
|
+
}).catch(() => {});
|
41
43
|
}, 10000);
|
42
44
|
}
|