Files
TrueGrowth/scripts/start-funclip-runtime.mjs

72 lines
1.8 KiB
JavaScript

import { spawn } from 'node:child_process';
import fs from 'node:fs';
import http from 'node:http';
import path from 'node:path';
const vendorDir = path.resolve('vendor/funclip');
const entryFile = path.join(vendorDir, 'funclip', 'launch.py');
const projectVenvPython = path.resolve('.venv-funclip/bin/python');
const pythonCommand =
process.env.TRUEGROWTH_FUNCLIP_PYTHON ||
(fs.existsSync(projectVenvPython) ? projectVenvPython : 'python3');
const port = process.env.TRUEGROWTH_FUNCLIP_PORT || '7860';
const lang = process.env.TRUEGROWTH_FUNCLIP_LANG || 'zh';
const serviceUrl = `http://127.0.0.1:${port}`;
function probeFunClip() {
return new Promise((resolve) => {
const request = http.get(serviceUrl, (response) => {
response.resume();
resolve(response.statusCode ? response.statusCode < 500 : true);
});
request.setTimeout(1600, () => {
request.destroy();
resolve(false);
});
request.on('error', () => resolve(false));
});
}
function waitUntilStopped() {
return new Promise((resolve) => {
const timer = setInterval(() => undefined, 60_000);
const stop = () => {
clearInterval(timer);
resolve();
};
process.once('SIGINT', stop);
process.once('SIGTERM', stop);
});
}
if (!fs.existsSync(entryFile)) {
console.error(`FunClip launch.py not found: ${entryFile}`);
process.exit(1);
}
if (await probeFunClip()) {
console.log(
`FunClip already running at ${serviceUrl}; reusing existing service.`
);
await waitUntilStopped();
}
const child = spawn(
pythonCommand,
['funclip/launch.py', '--port', port, '--lang', lang],
{
cwd: vendorDir,
stdio: 'inherit',
}
);
const shutdown = () => {
if (!child.killed) {
child.kill('SIGTERM');
}
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
child.on('exit', (code) => process.exit(code ?? 0));