feat: restart the process when plugins are added or removed (#5761)

* feat: restart the process when plugins are added or removed

* fix: debounce

* fix: pm2
This commit is contained in:
chenos 2024-12-01 18:12:27 +08:00 committed by GitHub
parent 9166b7acf3
commit 33bbfeab85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 83 additions and 23 deletions

View File

@ -6,16 +6,21 @@
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
const chalk = require('chalk');
const _ = require('lodash');
const { Command } = require('commander');
const { generatePlugins, run, postCheck, nodeCheck, promptForTs } = require('../util');
const { generatePlugins, run, postCheck, nodeCheck, promptForTs, isPortReachable } = require('../util');
const { getPortPromise } = require('portfinder');
const chokidar = require('chokidar');
const { uid } = require('@formily/shared');
const path = require('path');
const fs = require('fs');
function sleep(ms = 1000) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
/**
*
* @param {Command} cli
@ -31,6 +36,24 @@ module.exports = (cli) => {
.option('--inspect [port]')
.allowUnknownOption()
.action(async (opts) => {
let subprocess;
const runDevClient = () => {
console.log('starting client', 1 * clientPort);
subprocess = run('umi', ['dev'], {
env: {
...process.env,
stdio: 'inherit',
shell: true,
PORT: clientPort,
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
WEBSOCKET_URL:
process.env.WEBSOCKET_URL ||
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
PROXY_TARGET_URL:
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
},
});
};
const watcher = chokidar.watch('./storage/plugins/**/*', {
cwd: process.cwd(),
ignored: /(^|[\/\\])\../, // 忽略隐藏文件
@ -39,15 +62,45 @@ module.exports = (cli) => {
});
await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true });
let isReady = false;
const restartClient = _.debounce(async () => {
if (!isReady) return;
generatePlugins();
if (subprocess) {
console.log('client restarting...');
subprocess.cancel();
let i = 0;
while (true) {
++i;
const result = await isPortReachable(clientPort);
if (!result) {
break;
}
await sleep(500);
if (i > 10) {
break;
}
}
runDevClient();
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
}
}, 500);
watcher
.on('ready', () => {
console.log('Initial scan complete.');
isReady = true;
})
.on('addDir', async (pathname) => {
generatePlugins();
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
console.log('addDir....', isReady);
if (!isReady) return;
restartClient();
})
.on('unlinkDir', async (pathname) => {
generatePlugins();
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
console.log('unlinkDir....', isReady);
if (!isReady) return;
restartClient();
});
promptForTs();
@ -133,18 +186,7 @@ module.exports = (cli) => {
}
if (client || !server) {
console.log('starting client', 1 * clientPort);
run('umi', ['dev'], {
env: {
PORT: clientPort,
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
WEBSOCKET_URL:
process.env.WEBSOCKET_URL ||
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
PROXY_TARGET_URL:
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
},
});
runDevClient();
}
});
};

View File

@ -6,7 +6,7 @@
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
const _ = require('lodash');
const { Command } = require('commander');
const { isDev, run, postCheck, downloadPro, promptForTs } = require('../util');
const { existsSync, rmSync } = require('fs');
@ -51,10 +51,26 @@ module.exports = (cli) => {
depth: 1, // 只监听第一层目录
});
watcher.on('addDir', async (pathname) => {
console.log('pathname', pathname);
const restart = _.debounce(async () => {
console.log('restarting...');
await run('yarn', ['nocobase', 'pm2-restart']);
});
}, 500);
watcher
.on('ready', () => {
console.log('Initial scan complete.');
isReady = true;
})
.on('addDir', async (pathname) => {
console.log('addDir....', isReady);
if (!isReady) return;
restart();
})
.on('unlinkDir', async (pathname) => {
console.log('unlinkDir....', isReady);
if (!isReady) return;
restart();
});
if (opts.port) {
process.env.APP_PORT = opts.port;

View File

@ -346,6 +346,7 @@ exports.initEnv = function initEnv() {
PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), 'storage/playwright/.auth/admin.json'),
CACHE_DEFAULT_STORE: 'memory',
CACHE_MEMORY_MAX: 2000,
BROWSERSLIST_IGNORE_OLD_DATA: true,
PLUGIN_STATICS_PATH: '/static/plugins/',
LOGGER_BASE_PATH: 'storage/logs',
APP_SERVER_BASE_URL: '',

View File

@ -11,6 +11,7 @@
"scripts": {
"nocobase": "nocobase",
"pm": "nocobase pm",
"pm2": "nocobase pm2",
"dev": "nocobase dev",
"start": "nocobase start",
"clean": "nocobase clean",