diff --git a/packages/core/server/src/__tests__/gateway.test.ts b/packages/core/server/src/__tests__/gateway.test.ts index ad89b21b2..1d76ef003 100644 --- a/packages/core/server/src/__tests__/gateway.test.ts +++ b/packages/core/server/src/__tests__/gateway.test.ts @@ -97,8 +97,7 @@ describe('gateway', () => { expect(data).toMatchObject({ error: { - code: 'APP_INITIALIZED', - message: errors.APP_INITIALIZED.message({ app: main }), + code: 'APP_COMMANDING', status: 503, maintaining: true, }, diff --git a/packages/core/server/src/application.ts b/packages/core/server/src/application.ts index 5318c09e8..bf89c01ee 100644 --- a/packages/core/server/src/application.ts +++ b/packages/core/server/src/application.ts @@ -521,6 +521,7 @@ export class Application exten async stop(options: any = {}) { this.log.debug('stop app...'); this.setMaintainingMessage('stopping app...'); + if (this.stopped) { this.log.warn(`Application ${this.name} already stopped`); return; diff --git a/packages/core/server/src/commands/start.ts b/packages/core/server/src/commands/start.ts index 35899bc08..b27f3b580 100644 --- a/packages/core/server/src/commands/start.ts +++ b/packages/core/server/src/commands/start.ts @@ -8,6 +8,10 @@ export default (app: Application) => { .action(async (...cliArgs) => { const [opts] = cliArgs; + if (app.db.closed()) { + await app.db.reconnect(); + } + if (opts.quickstart) { if (await app.isInstalled()) { app.log.debug('installed....'); diff --git a/packages/core/server/src/gateway/index.ts b/packages/core/server/src/gateway/index.ts index 116a2fd70..528ddbf4d 100644 --- a/packages/core/server/src/gateway/index.ts +++ b/packages/core/server/src/gateway/index.ts @@ -13,7 +13,7 @@ import { parse } from 'url'; import xpipe from 'xpipe'; import { AppSupervisor } from '../app-supervisor'; import { ApplicationOptions } from '../application'; -import { PLUGIN_STATICS_PATH, getPackageDirByExposeUrl, getPackageNameByExposeUrl } from '../plugin-manager'; +import { getPackageDirByExposeUrl, getPackageNameByExposeUrl, PLUGIN_STATICS_PATH } from '../plugin-manager'; import { applyErrorWithArgs, getErrorWithCode } from './errors'; import { IPCSocketClient } from './ipc-socket-client'; import { IPCSocketServer } from './ipc-socket-server'; @@ -188,7 +188,7 @@ export class Gateway extends EventEmitter { void AppSupervisor.getInstance().bootStrapApp(handleApp); } - const appStatus = AppSupervisor.getInstance().getAppStatus(handleApp, 'initializing'); + let appStatus = AppSupervisor.getInstance().getAppStatus(handleApp, 'initializing'); if (appStatus === 'not_found') { this.responseErrorWithCode('APP_NOT_FOUND', res, { appName: handleApp }); @@ -200,6 +200,12 @@ export class Gateway extends EventEmitter { return; } + if (appStatus === 'initialized') { + const appInstance = await AppSupervisor.getInstance().getApp(handleApp); + appInstance.runAsCLI(['start'], { from: 'user' }); + appStatus = AppSupervisor.getInstance().getAppStatus(handleApp); + } + const app = await AppSupervisor.getInstance().getApp(handleApp); if (appStatus !== 'running') { diff --git a/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/__tests__/multiple-apps.test.ts b/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/__tests__/multiple-apps.test.ts index 8a59d423c..4da6024e3 100644 --- a/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/__tests__/multiple-apps.test.ts +++ b/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/__tests__/multiple-apps.test.ts @@ -244,6 +244,7 @@ describe('multiple apps', () => { waitSubAppInstall: true, }, }); + await AppSupervisor.getInstance().removeApp(subAppName); await app.start(); @@ -266,6 +267,51 @@ describe('multiple apps', () => { expect(AppSupervisor.getInstance().hasApp(subAppName)).toBeTruthy(); }); + it('should start automatically with quick start', async () => { + const subAppName = `t_${uid()}`; + + const subApp = await app.db.getRepository('applications').create({ + values: { + name: subAppName, + options: { + plugins: [], + }, + }, + context: { + waitSubAppInstall: true, + }, + }); + + await AppSupervisor.getInstance().removeApp(subAppName); + + await app.start(); + + expect(AppSupervisor.getInstance().hasApp(subAppName)).toBeFalsy(); + + await subApp.update({ + options: { + autoStart: true, + }, + }); + + await AppSupervisor.getInstance().removeApp(subAppName); + + expect(AppSupervisor.getInstance().hasApp(subAppName)).toBeFalsy(); + + await app.stop(); + + await app.db.reconnect(); + await AppSupervisor.getInstance().getApp(subAppName, { + upgrading: true, + }); + + await app.start(); + await sleep(1000); + expect(AppSupervisor.getInstance().hasApp(subAppName)).toBeTruthy(); + const appStatus = AppSupervisor.getInstance().getAppStatus(subAppName); + expect(appStatus).toEqual('running'); + }); + it('should get same obj ref when asynchronously access with same sub app name', async () => { const subAppName = `t_${uid()}`; diff --git a/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/server.ts b/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/server.ts index ed36f1fdf..9b4d8d0eb 100644 --- a/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-multi-app-manager/src/server/server.ts @@ -194,6 +194,8 @@ export class PluginMultiAppManager extends Plugin { appName: string; options: any; }) { + const loadButNotStart = options?.upgrading; + const name = appName; if (appSupervisor.hasApp(name)) { return; @@ -224,7 +226,7 @@ export class PluginMultiAppManager extends Plugin { }); // must skip load on upgrade - if (!options?.upgrading) { + if (!loadButNotStart) { await subApp.runCommand('start'); } } @@ -285,7 +287,11 @@ export class PluginMultiAppManager extends Plugin { for (const subAppInstance of subApps) { promises.push( (async () => { - await AppSupervisor.getInstance().getApp(subAppInstance.name); + if (!appSupervisor.hasApp(subAppInstance.name)) { + await AppSupervisor.getInstance().getApp(subAppInstance.name); + } else if (appSupervisor.getAppStatus(subAppInstance.name) === 'initialized') { + (await AppSupervisor.getInstance().getApp(subAppInstance.name)).runCommand('start'); + } })(), ); }