@scrypted/server 0.94.27 → 0.94.29
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/bin/packaged-python.d.ts +2 -0
- package/bin/packaged-python.js +23 -0
- package/bin/postinstall +1 -23
- package/dist/plugin/runtime/child-process-worker.d.ts +1 -2
- package/dist/plugin/runtime/child-process-worker.js +0 -3
- package/dist/plugin/runtime/child-process-worker.js.map +1 -1
- package/dist/plugin/runtime/node-thread-worker.d.ts +0 -1
- package/dist/plugin/runtime/node-thread-worker.js +0 -3
- package/dist/plugin/runtime/node-thread-worker.js.map +1 -1
- package/dist/plugin/runtime/python-worker.d.ts +10 -0
- package/dist/plugin/runtime/python-worker.js +72 -32
- package/dist/plugin/runtime/python-worker.js.map +1 -1
- package/dist/plugin/runtime/runtime-worker.d.ts +0 -1
- package/package.json +5 -5
- package/src/plugin/runtime/child-process-worker.ts +1 -5
- package/src/plugin/runtime/node-thread-worker.ts +0 -4
- package/src/plugin/runtime/python-worker.ts +83 -37
- package/src/plugin/runtime/runtime-worker.ts +0 -1
@@ -0,0 +1,23 @@
|
|
1
|
+
const child_process = require('child_process');
|
2
|
+
const { PortablePython } = require('py')
|
3
|
+
const { once } = require('events');
|
4
|
+
|
5
|
+
module.exports = {
|
6
|
+
version: '3.11',
|
7
|
+
}
|
8
|
+
|
9
|
+
async function pipInstall(python, pkg) {
|
10
|
+
const cp = child_process.spawn(python, ['-m', 'pip', 'install', pkg], { stdio: 'inherit' });
|
11
|
+
const [exitCode] = await once(cp, 'exit');
|
12
|
+
if (exitCode)
|
13
|
+
throw new Error('non-zero exit code: ' + exitCode);
|
14
|
+
}
|
15
|
+
|
16
|
+
module.exports.installScryptedServerRequirements = async function installScryptedServerRequirements(version, dest) {
|
17
|
+
const py = new PortablePython(version || require('./packaged-python').version, dest);
|
18
|
+
await py.install();
|
19
|
+
let python = py.executablePath;
|
20
|
+
|
21
|
+
await pipInstall(python, 'debugpy');
|
22
|
+
await pipInstall(python, 'psutil').catch(() => { });
|
23
|
+
}
|
package/bin/postinstall
CHANGED
@@ -1,24 +1,2 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
|
3
|
-
const child_process = require('child_process');
|
4
|
-
const { PortablePython } = require('py')
|
5
|
-
const { once } = require('events');
|
6
|
-
let python;
|
7
|
-
|
8
|
-
async function pipInstall(pkg) {
|
9
|
-
const cp = child_process.spawn(python, ['-m', 'pip', 'install', pkg], { stdio: 'inherit' });
|
10
|
-
const [exitCode] = await once(cp, 'exit');
|
11
|
-
if (exitCode)
|
12
|
-
throw new Error('non-zero exit code: ' + exitCode);
|
13
|
-
}
|
14
|
-
|
15
|
-
async function installScryptedServerRequirements() {
|
16
|
-
const py = new PortablePython("3.9");
|
17
|
-
await py.install();
|
18
|
-
python = py.executablePath;
|
19
|
-
|
20
|
-
await pipInstall('debugpy');
|
21
|
-
await pipInstall('psutil').catch(() => {});
|
22
|
-
}
|
23
|
-
|
24
|
-
installScryptedServerRequirements();
|
2
|
+
require('./packaged-python').installScryptedServerRequirements();
|
@@ -7,13 +7,12 @@ import child_process from 'child_process';
|
|
7
7
|
import { RpcMessage, RpcPeer } from "../../rpc";
|
8
8
|
export declare abstract class ChildProcessWorker extends EventEmitter implements RuntimeWorker {
|
9
9
|
pluginId: string;
|
10
|
-
worker: child_process.ChildProcess;
|
10
|
+
protected worker: child_process.ChildProcess;
|
11
11
|
constructor(pluginId: string, options: RuntimeWorkerOptions);
|
12
12
|
setupWorker(): void;
|
13
13
|
get pid(): number;
|
14
14
|
get stdout(): import("stream").Readable;
|
15
15
|
get stderr(): import("stream").Readable;
|
16
|
-
get killed(): boolean;
|
17
16
|
kill(): void;
|
18
17
|
abstract send(message: RpcMessage, reject?: (e: Error) => void): void;
|
19
18
|
abstract setupRpcPeer(peer: RpcPeer): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"child-process-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/child-process-worker.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAKlC,MAAsB,kBAAmB,SAAQ,iBAAY;IAGtC;
|
1
|
+
{"version":3,"file":"child-process-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/child-process-worker.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAKlC,MAAsB,kBAAmB,SAAQ,iBAAY;IAGtC;IAFT,MAAM,CAA6B;IAE7C,YAAmB,QAAgB,EAAE,OAA6B;QAC9D,KAAK,EAAE,CAAC;QADO,aAAQ,GAAR,QAAQ,CAAQ;IAEnC,CAAC;IAED,WAAW;QACP,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,GAAG;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IAC3B,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI;QACA,IAAI,CAAC,IAAI,CAAC,MAAM;YACZ,OAAO;QACX,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC;CAIJ;AAvCD,gDAuCC"}
|
@@ -13,7 +13,6 @@ export declare class NodeThreadWorker extends EventEmitter implements RuntimeWor
|
|
13
13
|
get pid(): number;
|
14
14
|
get stdout(): import("stream").Readable;
|
15
15
|
get stderr(): import("stream").Readable;
|
16
|
-
get killed(): boolean;
|
17
16
|
kill(): void;
|
18
17
|
send(message: RpcMessage, reject?: (e: Error) => void): void;
|
19
18
|
setupRpcPeer(peer: RpcPeer): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"node-thread-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/node-thread-worker.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,oEAA4C;AAC5C,2BAAkC;AAIlC,MAAa,gBAAiB,SAAQ,iBAAY;IAIL;IAHzC,UAAU,CAAU;IACpB,MAAM,CAAwB;IAE9B,YAAY,YAAoB,EAAS,QAAgB,EAAE,OAA6B;QACpF,KAAK,EAAE,CAAC;QAD6B,aAAQ,GAAR,QAAQ,CAAQ;QAErD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAExB,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAc,CAAC,MAAM,CAAC,YAAY,EAAE;YAClD,IAAI,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC;YACrC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE;YAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,GAAG;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI
|
1
|
+
{"version":3,"file":"node-thread-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/node-thread-worker.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,oEAA4C;AAC5C,2BAAkC;AAIlC,MAAa,gBAAiB,SAAQ,iBAAY;IAIL;IAHzC,UAAU,CAAU;IACpB,MAAM,CAAwB;IAE9B,YAAY,YAAoB,EAAS,QAAgB,EAAE,OAA6B;QACpF,KAAK,EAAE,CAAC;QAD6B,aAAQ,GAAR,QAAQ,CAAQ;QAErD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAExB,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAc,CAAC,MAAM,CAAC,YAAY,EAAE;YAClD,IAAI,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC;YACrC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE;YAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,GAAG;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,IAAI;QACA,IAAI,CAAC,IAAI,CAAC,MAAM;YACZ,OAAO;QACX,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,OAAmB,EAAE,MAA2B;QACjD,IAAI,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM;gBACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,YAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;IACL,CAAC;IAED,YAAY,CAAC,IAAa;QACtB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,YAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;CACJ;AA7DD,4CA6DC"}
|
@@ -1,9 +1,19 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { Readable, Writable, PassThrough } from 'stream';
|
1
3
|
import { RpcMessage, RpcPeer } from "../../rpc";
|
2
4
|
import { createRpcDuplexSerializer } from '../../rpc-serializer';
|
3
5
|
import { ChildProcessWorker } from "./child-process-worker";
|
4
6
|
import { RuntimeWorkerOptions } from "./runtime-worker";
|
5
7
|
export declare class PythonRuntimeWorker extends ChildProcessWorker {
|
6
8
|
serializer: ReturnType<typeof createRpcDuplexSerializer>;
|
9
|
+
peerin: Writable;
|
10
|
+
peerout: Readable;
|
11
|
+
_stdout: PassThrough;
|
12
|
+
_stderr: PassThrough;
|
13
|
+
pythonInstallationComplete: boolean;
|
14
|
+
get pid(): number;
|
15
|
+
get stdout(): PassThrough;
|
16
|
+
get stderr(): PassThrough;
|
7
17
|
constructor(pluginId: string, options: RuntimeWorkerOptions);
|
8
18
|
setupRpcPeer(peer: RpcPeer): void;
|
9
19
|
send(message: RpcMessage, reject?: (e: Error) => void, serializationContext?: any): void;
|
@@ -8,14 +8,17 @@ const child_process_1 = __importDefault(require("child_process"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
9
9
|
const os_1 = __importDefault(require("os"));
|
10
10
|
const path_1 = __importDefault(require("path"));
|
11
|
+
const py_1 = require("py");
|
12
|
+
const stream_1 = require("stream");
|
13
|
+
const packaged_python_1 = require("../../../bin/packaged-python");
|
11
14
|
const rpc_serializer_1 = require("../../rpc-serializer");
|
12
15
|
const child_process_worker_1 = require("./child-process-worker");
|
13
16
|
class PythonRuntimeWorker extends child_process_worker_1.ChildProcessWorker {
|
14
17
|
static {
|
15
18
|
try {
|
16
|
-
const
|
17
|
-
const py = new PortablePython("3.9");
|
19
|
+
const py = new py_1.PortablePython(packaged_python_1.version);
|
18
20
|
const portablePython = py.executablePath;
|
21
|
+
// is this possible?
|
19
22
|
if (fs_1.default.existsSync(portablePython))
|
20
23
|
process.env.SCRYPTED_PYTHON_PATH = portablePython;
|
21
24
|
}
|
@@ -23,6 +26,20 @@ class PythonRuntimeWorker extends child_process_worker_1.ChildProcessWorker {
|
|
23
26
|
}
|
24
27
|
}
|
25
28
|
serializer;
|
29
|
+
peerin;
|
30
|
+
peerout;
|
31
|
+
_stdout = new stream_1.PassThrough();
|
32
|
+
_stderr = new stream_1.PassThrough();
|
33
|
+
pythonInstallationComplete = true;
|
34
|
+
get pid() {
|
35
|
+
return this.worker?.pid || -1;
|
36
|
+
}
|
37
|
+
get stdout() {
|
38
|
+
return this._stdout;
|
39
|
+
}
|
40
|
+
get stderr() {
|
41
|
+
return this._stderr;
|
42
|
+
}
|
26
43
|
constructor(pluginId, options) {
|
27
44
|
super(pluginId, options);
|
28
45
|
const { env, pluginDebug } = options;
|
@@ -32,7 +49,7 @@ class PythonRuntimeWorker extends child_process_worker_1.ChildProcessWorker {
|
|
32
49
|
if (pluginDebug) {
|
33
50
|
args.push('-m', 'debugpy', '--listen', `0.0.0.0:${pluginDebug.inspectPort}`, '--wait-for-client');
|
34
51
|
}
|
35
|
-
args.push(path_1.default.join(__dirname, '../../../python', 'plugin_remote.py'));
|
52
|
+
args.push(path_1.default.join(__dirname, '../../../python', 'plugin_remote.py'), this.pluginId);
|
36
53
|
const gstEnv = {};
|
37
54
|
// hack to fix gst plugin search path on mac...
|
38
55
|
if (os_1.default.platform() === 'darwin') {
|
@@ -52,53 +69,76 @@ class PythonRuntimeWorker extends child_process_worker_1.ChildProcessWorker {
|
|
52
69
|
}
|
53
70
|
let pythonPath = process.env.SCRYPTED_PYTHON_PATH;
|
54
71
|
const pluginPythonVersion = options.packageJson.scrypted.pythonVersion?.[os_1.default.platform()]?.[os_1.default.arch()] || options.packageJson.scrypted.pythonVersion?.default;
|
55
|
-
if (
|
56
|
-
if (
|
72
|
+
if (!pythonPath) {
|
73
|
+
if (os_1.default.platform() === 'win32') {
|
57
74
|
pythonPath = 'py.exe';
|
58
|
-
|
59
|
-
|
60
|
-
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
pythonPath = 'python3';
|
61
78
|
}
|
62
79
|
}
|
63
|
-
|
64
|
-
|
80
|
+
const setup = () => {
|
81
|
+
const types = require.resolve('@scrypted/types');
|
82
|
+
const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length);
|
83
|
+
this.worker = child_process_1.default.spawn(pythonPath, args, {
|
84
|
+
// stdin, stdout, stderr, peer in, peer out
|
85
|
+
stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
|
86
|
+
env: Object.assign({
|
87
|
+
// rev this if the base python version or server characteristics change.
|
88
|
+
SCRYPTED_PYTHON_VERSION: '20240308.1',
|
89
|
+
PYTHONUNBUFFERED: '1',
|
90
|
+
PYTHONPATH,
|
91
|
+
}, gstEnv, process.env, env),
|
92
|
+
});
|
93
|
+
this.worker.stdout.pipe(this.stdout);
|
94
|
+
this.worker.stderr.pipe(this.stderr);
|
95
|
+
};
|
96
|
+
// if the plugin requests a specific python, then install it via portable python
|
97
|
+
if (pluginPythonVersion) {
|
98
|
+
const peerin = this.peerin = new stream_1.PassThrough();
|
99
|
+
const peerout = this.peerout = new stream_1.PassThrough();
|
100
|
+
const py = new py_1.PortablePython(pluginPythonVersion, path_1.default.dirname(options.unzippedPath));
|
101
|
+
this.pythonInstallationComplete = false;
|
102
|
+
py.install()
|
103
|
+
.then(() => {
|
104
|
+
pythonPath = py.executablePath;
|
105
|
+
// is this possible?
|
106
|
+
if (!fs_1.default.existsSync(pythonPath))
|
107
|
+
throw new Error('Installation failed. Portable python not found.');
|
108
|
+
setup();
|
109
|
+
peerin.pipe(this.worker.stdio[3]);
|
110
|
+
this.worker.stdio[4].pipe(peerout);
|
111
|
+
})
|
112
|
+
.catch(() => {
|
113
|
+
process.nextTick(() => {
|
114
|
+
this.emit('error', new Error('Failed to install portable python.'));
|
115
|
+
});
|
116
|
+
})
|
117
|
+
.finally(() => this.pythonInstallationComplete = true);
|
65
118
|
}
|
66
119
|
else {
|
67
|
-
|
120
|
+
setup();
|
121
|
+
this.peerin = this.worker.stdio[3];
|
122
|
+
this.peerout = this.worker.stdio[4];
|
123
|
+
this.setupWorker();
|
68
124
|
}
|
69
|
-
args.push(this.pluginId);
|
70
|
-
const types = require.resolve('@scrypted/types');
|
71
|
-
const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length);
|
72
|
-
this.worker = child_process_1.default.spawn(pythonPath, args, {
|
73
|
-
// stdin, stdout, stderr, peer in, peer out
|
74
|
-
stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
|
75
|
-
env: Object.assign({
|
76
|
-
// rev this if the base python version or server characterstics change.
|
77
|
-
SCRYPTED_PYTHON_VERSION: '20240308.1',
|
78
|
-
PYTHONUNBUFFERED: '1',
|
79
|
-
PYTHONPATH,
|
80
|
-
}, gstEnv, process.env, env),
|
81
|
-
});
|
82
|
-
this.setupWorker();
|
83
125
|
}
|
84
126
|
setupRpcPeer(peer) {
|
85
|
-
const
|
86
|
-
const peerout = this.worker.stdio[4];
|
87
|
-
const serializer = this.serializer = (0, rpc_serializer_1.createRpcDuplexSerializer)(peerin);
|
127
|
+
const serializer = this.serializer = (0, rpc_serializer_1.createRpcDuplexSerializer)(this.peerin);
|
88
128
|
serializer.setupRpcPeer(peer);
|
89
|
-
peerout.on('data', data => serializer.onData(data));
|
90
|
-
peerin.on('error', e => {
|
129
|
+
this.peerout.on('data', data => serializer.onData(data));
|
130
|
+
this.peerin.on('error', e => {
|
91
131
|
this.emit('error', e);
|
92
132
|
serializer.onDisconnected();
|
93
133
|
});
|
94
|
-
peerout.on('error', e => {
|
134
|
+
this.peerout.on('error', e => {
|
95
135
|
this.emit('error', e);
|
96
136
|
serializer.onDisconnected();
|
97
137
|
});
|
98
138
|
}
|
99
139
|
send(message, reject, serializationContext) {
|
100
140
|
try {
|
101
|
-
if (!this.worker)
|
141
|
+
if (this.pythonInstallationComplete && !this.worker)
|
102
142
|
throw new Error('python worker has been killed');
|
103
143
|
this.serializer.sendMessage(message, reject, serializationContext);
|
104
144
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"python-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/python-worker.ts"],"names":[],"mappings":";;;;;;AAAA,kEAA0C;AAC1C,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;
|
1
|
+
{"version":3,"file":"python-worker.js","sourceRoot":"","sources":["../../../src/plugin/runtime/python-worker.ts"],"names":[],"mappings":";;;;;;AAAA,kEAA0C;AAC1C,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,2BAAoC;AACpC,mCAAyD;AACzD,kEAAgF;AAEhF,yDAAiE;AACjE,iEAA4D;AAG5D,MAAa,mBAAoB,SAAQ,yCAAkB;IACvD;QACI,IAAI,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,mBAAc,CAAC,yBAAqB,CAAC,CAAC;YACrD,MAAM,cAAc,GAAG,EAAE,CAAC,cAAc,CAAC;YACzC,oBAAoB;YACpB,IAAI,YAAE,CAAC,UAAU,CAAC,cAAc,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,cAAc,CAAC;QAC1D,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;QACX,CAAC;IACL,CAAC;IAED,UAAU,CAA+C;IACzD,MAAM,CAAW;IACjB,OAAO,CAAW;IAClB,OAAO,GAAG,IAAI,oBAAW,EAAE,CAAC;IAC5B,OAAO,GAAG,IAAI,oBAAW,EAAE,CAAC;IAC5B,0BAA0B,GAAG,IAAI,CAAC;IAElC,IAAI,GAAG;QACH,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,YAAY,QAAgB,EAAE,OAA6B;QACvD,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEzB,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;QACrC,MAAM,IAAI,GAAa;YACnB,IAAI;SACP,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CACL,IAAI,EACJ,SAAS,EACT,UAAU,EACV,WAAW,WAAW,CAAC,WAAW,EAAE,EACpC,mBAAmB,CACtB,CAAA;QACL,CAAC;QAED,IAAI,CAAC,IAAI,CACL,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,EAC3D,IAAI,CAAC,QAAQ,CAChB,CAAA;QAED,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,+CAA+C;QAC/C,IAAI,YAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG;gBACb,iCAAiC;gBACjC,8BAA8B;aACjC,CAAC;YACF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC7B,6BAA6B;gBAC7B,IAAI,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;uBAClD,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;uBACtD,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC,CAAC,EAAE,CAAC;oBACnE,MAAM,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC;oBACpC,MAAM;gBACV,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QAClD,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,YAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,YAAE,CAAC,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;QAE5J,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,IAAI,YAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;gBAC5B,UAAU,GAAG,QAAQ,CAAC;YAC1B,CAAC;iBACI,CAAC;gBACF,UAAU,GAAG,SAAS,CAAC;YAC3B,CAAC;QACL,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,EAAE;YACf,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/E,IAAI,CAAC,MAAM,GAAG,uBAAa,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;gBAChD,2CAA2C;gBAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;gBAC/C,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC;oBACf,wEAAwE;oBACxE,uBAAuB,EAAE,YAAY;oBACrC,gBAAgB,EAAE,GAAG;oBACrB,UAAU;iBACb,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;aAC/B,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC,CAAC;QAGF,gFAAgF;QAChF,IAAI,mBAAmB,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,oBAAW,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAW,EAAE,CAAC;YAEjD,MAAM,EAAE,GAAG,IAAI,mBAAc,CAAC,mBAAmB,EAAE,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,0BAA0B,GAAG,KAAK,CAAC;YACxC,EAAE,CAAC,OAAO,EAAE;iBACP,IAAI,CAAC,GAAG,EAAE;gBACP,UAAU,GAAG,EAAE,CAAC,cAAc,CAAC;gBAC/B,oBAAoB;gBACpB,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC;oBAC1B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBACvE,KAAK,EAAE,CAAC;gBAER,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAa,CAAC,CAAC;gBAC7C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrD,CAAC,CAAC;iBACD,KAAK,CAAC,GAAG,EAAE;gBACR,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;oBAClB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;gBACxE,CAAC,CAAC,CAAA;YACN,CAAC,CAAC;iBACD,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAAC;QAC/D,CAAC;aACI,CAAC;YACF,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAa,CAAC;YAC/C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAa,CAAC;YAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;IAED,YAAY,CAAC,IAAa;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,GAAG,IAAA,0CAAyB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5E,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACtB,UAAU,CAAC,cAAc,EAAE,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACrB,UAAU,CAAC,cAAc,EAAE,CAAC;QAChC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,OAAmB,EAAE,MAA2B,EAAE,oBAA0B;QAC7E,IAAI,CAAC;YACD,IAAI,IAAI,CAAC,0BAA0B,IAAI,CAAC,IAAI,CAAC,MAAM;gBAC/C,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACrD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;IACL,CAAC;CACJ;AAjKD,kDAiKC"}
|
@@ -17,7 +17,6 @@ export interface RuntimeWorker {
|
|
17
17
|
pid: number;
|
18
18
|
stdout: Readable;
|
19
19
|
stderr: Readable;
|
20
|
-
killed: boolean;
|
21
20
|
kill(): void;
|
22
21
|
on(event: 'rpc', listener: (message: any, sendHandle: net.Socket) => void): this;
|
23
22
|
on(event: 'error', listener: (err: Error) => void): this;
|
package/package.json
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
{
|
2
2
|
"name": "@scrypted/server",
|
3
|
-
"version": "0.94.
|
3
|
+
"version": "0.94.29",
|
4
4
|
"description": "",
|
5
5
|
"dependencies": {
|
6
6
|
"@mapbox/node-pre-gyp": "^1.0.11",
|
7
7
|
"@scrypted/ffmpeg-static": "^6.1.0-build1",
|
8
8
|
"@scrypted/types": "^0.3.17",
|
9
|
-
"adm-zip": "^0.5.
|
9
|
+
"adm-zip": "^0.5.12",
|
10
10
|
"body-parser": "^1.20.2",
|
11
11
|
"cookie-parser": "^1.4.6",
|
12
12
|
"engine.io": "^6.5.4",
|
13
13
|
"express": "^4.18.3",
|
14
|
-
"follow-redirects": "^1.15.
|
14
|
+
"follow-redirects": "^1.15.6",
|
15
15
|
"http-auth": "^4.2.0",
|
16
16
|
"ip": "^2.0.1",
|
17
17
|
"level": "^8.0.1",
|
@@ -20,7 +20,7 @@
|
|
20
20
|
"node-dijkstra": "^2.5.0",
|
21
21
|
"node-forge": "^1.3.1",
|
22
22
|
"node-gyp": "^10.0.1",
|
23
|
-
"py": "npm:@bjia56/portable-python@^0.1.
|
23
|
+
"py": "npm:@bjia56/portable-python@^0.1.15",
|
24
24
|
"router": "^1.3.8",
|
25
25
|
"semver": "^7.6.0",
|
26
26
|
"sharp": "^0.33.2",
|
@@ -38,7 +38,7 @@
|
|
38
38
|
"@types/follow-redirects": "^1.14.4",
|
39
39
|
"@types/http-auth": "^4.1.4",
|
40
40
|
"@types/ip": "^1.1.3",
|
41
|
-
"@types/lodash": "^4.
|
41
|
+
"@types/lodash": "^4.17.0",
|
42
42
|
"@types/node-dijkstra": "^2.5.6",
|
43
43
|
"@types/node-forge": "^1.3.11",
|
44
44
|
"@types/semver": "^7.5.8",
|
@@ -4,7 +4,7 @@ import child_process from 'child_process';
|
|
4
4
|
import { RpcMessage, RpcPeer } from "../../rpc";
|
5
5
|
|
6
6
|
export abstract class ChildProcessWorker extends EventEmitter implements RuntimeWorker {
|
7
|
-
worker: child_process.ChildProcess;
|
7
|
+
protected worker: child_process.ChildProcess;
|
8
8
|
|
9
9
|
constructor(public pluginId: string, options: RuntimeWorkerOptions) {
|
10
10
|
super();
|
@@ -30,10 +30,6 @@ export abstract class ChildProcessWorker extends EventEmitter implements Runtime
|
|
30
30
|
return this.worker.stderr;
|
31
31
|
}
|
32
32
|
|
33
|
-
get killed() {
|
34
|
-
return this.worker.killed;
|
35
|
-
}
|
36
|
-
|
37
33
|
kill(): void {
|
38
34
|
if (!this.worker)
|
39
35
|
return;
|
@@ -2,8 +2,9 @@ import child_process from 'child_process';
|
|
2
2
|
import fs from "fs";
|
3
3
|
import os from "os";
|
4
4
|
import path from 'path';
|
5
|
-
import
|
6
|
-
import { Readable, Writable } from 'stream';
|
5
|
+
import { PortablePython } from 'py';
|
6
|
+
import { Readable, Writable, PassThrough } from 'stream';
|
7
|
+
import { version as packagedPythonVersion } from '../../../bin/packaged-python';
|
7
8
|
import { RpcMessage, RpcPeer } from "../../rpc";
|
8
9
|
import { createRpcDuplexSerializer } from '../../rpc-serializer';
|
9
10
|
import { ChildProcessWorker } from "./child-process-worker";
|
@@ -12,9 +13,9 @@ import { RuntimeWorkerOptions } from "./runtime-worker";
|
|
12
13
|
export class PythonRuntimeWorker extends ChildProcessWorker {
|
13
14
|
static {
|
14
15
|
try {
|
15
|
-
const
|
16
|
-
const py = new PortablePython("3.9");
|
16
|
+
const py = new PortablePython(packagedPythonVersion);
|
17
17
|
const portablePython = py.executablePath;
|
18
|
+
// is this possible?
|
18
19
|
if (fs.existsSync(portablePython))
|
19
20
|
process.env.SCRYPTED_PYTHON_PATH = portablePython;
|
20
21
|
}
|
@@ -23,6 +24,23 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
23
24
|
}
|
24
25
|
|
25
26
|
serializer: ReturnType<typeof createRpcDuplexSerializer>;
|
27
|
+
peerin: Writable;
|
28
|
+
peerout: Readable;
|
29
|
+
_stdout = new PassThrough();
|
30
|
+
_stderr = new PassThrough();
|
31
|
+
pythonInstallationComplete = true;
|
32
|
+
|
33
|
+
get pid() {
|
34
|
+
return this.worker?.pid || -1;
|
35
|
+
}
|
36
|
+
|
37
|
+
get stdout() {
|
38
|
+
return this._stdout;
|
39
|
+
}
|
40
|
+
|
41
|
+
get stderr() {
|
42
|
+
return this._stderr;
|
43
|
+
}
|
26
44
|
|
27
45
|
constructor(pluginId: string, options: RuntimeWorkerOptions) {
|
28
46
|
super(pluginId, options);
|
@@ -31,6 +49,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
31
49
|
const args: string[] = [
|
32
50
|
'-u',
|
33
51
|
];
|
52
|
+
|
34
53
|
if (pluginDebug) {
|
35
54
|
args.push(
|
36
55
|
'-m',
|
@@ -40,8 +59,10 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
40
59
|
'--wait-for-client',
|
41
60
|
)
|
42
61
|
}
|
62
|
+
|
43
63
|
args.push(
|
44
64
|
path.join(__dirname, '../../../python', 'plugin_remote.py'),
|
65
|
+
this.pluginId,
|
45
66
|
)
|
46
67
|
|
47
68
|
const gstEnv: NodeJS.ProcessEnv = {};
|
@@ -65,51 +86,76 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
65
86
|
let pythonPath = process.env.SCRYPTED_PYTHON_PATH;
|
66
87
|
const pluginPythonVersion = options.packageJson.scrypted.pythonVersion?.[os.platform()]?.[os.arch()] || options.packageJson.scrypted.pythonVersion?.default;
|
67
88
|
|
68
|
-
if (
|
69
|
-
if (
|
89
|
+
if (!pythonPath) {
|
90
|
+
if (os.platform() === 'win32') {
|
70
91
|
pythonPath = 'py.exe';
|
71
|
-
|
72
|
-
|
73
|
-
|
92
|
+
}
|
93
|
+
else {
|
94
|
+
pythonPath = 'python3';
|
74
95
|
}
|
75
96
|
}
|
76
|
-
|
77
|
-
|
97
|
+
|
98
|
+
const setup = () => {
|
99
|
+
const types = require.resolve('@scrypted/types');
|
100
|
+
const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length);
|
101
|
+
this.worker = child_process.spawn(pythonPath, args, {
|
102
|
+
// stdin, stdout, stderr, peer in, peer out
|
103
|
+
stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
|
104
|
+
env: Object.assign({
|
105
|
+
// rev this if the base python version or server characteristics change.
|
106
|
+
SCRYPTED_PYTHON_VERSION: '20240308.1',
|
107
|
+
PYTHONUNBUFFERED: '1',
|
108
|
+
PYTHONPATH,
|
109
|
+
}, gstEnv, process.env, env),
|
110
|
+
});
|
111
|
+
|
112
|
+
this.worker.stdout.pipe(this.stdout);
|
113
|
+
this.worker.stderr.pipe(this.stderr);
|
114
|
+
};
|
115
|
+
|
116
|
+
|
117
|
+
// if the plugin requests a specific python, then install it via portable python
|
118
|
+
if (pluginPythonVersion) {
|
119
|
+
const peerin = this.peerin = new PassThrough();
|
120
|
+
const peerout = this.peerout = new PassThrough();
|
121
|
+
|
122
|
+
const py = new PortablePython(pluginPythonVersion, path.dirname(options.unzippedPath));
|
123
|
+
this.pythonInstallationComplete = false;
|
124
|
+
py.install()
|
125
|
+
.then(() => {
|
126
|
+
pythonPath = py.executablePath;
|
127
|
+
// is this possible?
|
128
|
+
if (!fs.existsSync(pythonPath))
|
129
|
+
throw new Error('Installation failed. Portable python not found.');
|
130
|
+
setup();
|
131
|
+
|
132
|
+
peerin.pipe(this.worker.stdio[3] as Writable);
|
133
|
+
(this.worker.stdio[4] as Readable).pipe(peerout);
|
134
|
+
})
|
135
|
+
.catch(() => {
|
136
|
+
process.nextTick(() => {
|
137
|
+
this.emit('error', new Error('Failed to install portable python.'));
|
138
|
+
})
|
139
|
+
})
|
140
|
+
.finally(() => this.pythonInstallationComplete = true);
|
78
141
|
}
|
79
142
|
else {
|
80
|
-
|
143
|
+
setup();
|
144
|
+
this.peerin = this.worker.stdio[3] as Writable;
|
145
|
+
this.peerout = this.worker.stdio[4] as Readable;
|
146
|
+
this.setupWorker();
|
81
147
|
}
|
82
|
-
|
83
|
-
args.push(this.pluginId);
|
84
|
-
|
85
|
-
const types = require.resolve('@scrypted/types');
|
86
|
-
const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length);
|
87
|
-
this.worker = child_process.spawn(pythonPath, args, {
|
88
|
-
// stdin, stdout, stderr, peer in, peer out
|
89
|
-
stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
|
90
|
-
env: Object.assign({
|
91
|
-
// rev this if the base python version or server characterstics change.
|
92
|
-
SCRYPTED_PYTHON_VERSION: '20240308.1',
|
93
|
-
PYTHONUNBUFFERED: '1',
|
94
|
-
PYTHONPATH,
|
95
|
-
}, gstEnv, process.env, env),
|
96
|
-
});
|
97
|
-
|
98
|
-
this.setupWorker();
|
99
148
|
}
|
100
149
|
|
101
150
|
setupRpcPeer(peer: RpcPeer): void {
|
102
|
-
const
|
103
|
-
const peerout = this.worker.stdio[4] as Readable;
|
104
|
-
|
105
|
-
const serializer = this.serializer = createRpcDuplexSerializer(peerin);
|
151
|
+
const serializer = this.serializer = createRpcDuplexSerializer(this.peerin);
|
106
152
|
serializer.setupRpcPeer(peer);
|
107
|
-
peerout.on('data', data => serializer.onData(data));
|
108
|
-
peerin.on('error', e => {
|
153
|
+
this.peerout.on('data', data => serializer.onData(data));
|
154
|
+
this.peerin.on('error', e => {
|
109
155
|
this.emit('error', e);
|
110
156
|
serializer.onDisconnected();
|
111
157
|
});
|
112
|
-
peerout.on('error', e => {
|
158
|
+
this.peerout.on('error', e => {
|
113
159
|
this.emit('error', e)
|
114
160
|
serializer.onDisconnected();
|
115
161
|
});
|
@@ -117,7 +163,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
117
163
|
|
118
164
|
send(message: RpcMessage, reject?: (e: Error) => void, serializationContext?: any): void {
|
119
165
|
try {
|
120
|
-
if (!this.worker)
|
166
|
+
if (this.pythonInstallationComplete && !this.worker)
|
121
167
|
throw new Error('python worker has been killed');
|
122
168
|
this.serializer.sendMessage(message, reject, serializationContext);
|
123
169
|
}
|