fix(gateway): should not refresh when application start from error recover (#2711)

* fix(gateway): should not refresh when application start from error recover

* chore: recover option
This commit is contained in:
ChengLei Shao 2023-09-25 15:26:52 +08:00 committed by GitHub
parent 89635982b4
commit 376a91b8ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 10 deletions

View File

@ -156,8 +156,12 @@ describe('gateway', () => {
return JSON.parse(messages[messages.length - 1]); return JSON.parse(messages[messages.length - 1]);
}; };
beforeEach(async () => { const clearMessages = () => {
messages = []; messages = [];
};
beforeEach(async () => {
clearMessages();
port = await startServerWithRandomPort(gateway.startHttpServer.bind(gateway)); port = await startServerWithRandomPort(gateway.startHttpServer.bind(gateway));
}); });
@ -173,6 +177,55 @@ describe('gateway', () => {
await waitSecond(); await waitSecond();
}); });
describe('plugin manager api', () => {
let app;
beforeEach(async () => {
await connectClient(port);
app = new Application({
database: {
dialect: 'sqlite',
storage: ':memory:',
},
plugins: ['nocobase'],
});
await waitSecond();
await app.runAsCLI(['install'], { from: 'user' });
await app.runAsCLI(['start'], { from: 'user' });
await waitSecond();
clearMessages();
});
it('should silently handle the exception when the plugin does not exist', async () => {
await app.runAsCLI(['pm', 'add', 'not-exists-plugin'], { from: 'user' });
await waitSecond();
});
it('should display a notification-type error message when plugin installation fails', async () => {
const pluginClass = app.pm.get('mobile-client');
pluginClass.install = async () => {
throw new Error('install error');
};
await app.runAsCLI(['pm', 'enable', 'mobile-client'], { from: 'user' });
await waitSecond();
const runningMessage = messages
.map((m) => {
return JSON.parse(m);
})
.find((m) => {
return m.payload.code == 'APP_RUNNING';
});
expect(runningMessage.payload.refresh).not.toBeTruthy();
});
});
it('should receive app error message', async () => { it('should receive app error message', async () => {
await connectClient(port); await connectClient(port);

View File

@ -260,12 +260,14 @@ export class AppSupervisor extends EventEmitter implements AsyncEmitter {
}); });
app.on('__started', async (_app, options) => { app.on('__started', async (_app, options) => {
const { maintainingStatus } = options; const { maintainingStatus, options: startOptions } = options;
if ( if (
maintainingStatus && maintainingStatus &&
['install', 'upgrade', 'pm.add', 'pm.update', 'pm.enable', 'pm.disable', 'pm.remove'].includes( ['install', 'upgrade', 'pm.add', 'pm.update', 'pm.enable', 'pm.disable', 'pm.remove'].includes(
maintainingStatus.command.name, maintainingStatus.command.name,
) ) &&
!startOptions.recover
) { ) {
this.setAppStatus(app.name, 'running', { this.setAppStatus(app.name, 'running', {
refresh: true, refresh: true,

View File

@ -88,6 +88,7 @@ interface StartOptions {
cliArgs?: any[]; cliArgs?: any[];
dbSync?: boolean; dbSync?: boolean;
checkInstall?: boolean; checkInstall?: boolean;
recover?: boolean;
} }
type MaintainingStatus = 'command_begin' | 'command_end' | 'command_running' | 'command_error'; type MaintainingStatus = 'command_begin' | 'command_end' | 'command_running' | 'command_error';
@ -471,14 +472,15 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
this.setMaintainingMessage('emit afterStart'); this.setMaintainingMessage('emit afterStart');
await this.emitAsync('afterStart', this, options); await this.emitAsync('afterStart', this, options);
await this.emitStartedEvent(); await this.emitStartedEvent(options);
this.stopped = false; this.stopped = false;
} }
async emitStartedEvent() { async emitStartedEvent(options: StartOptions = {}) {
await this.emitAsync('__started', this, { await this.emitAsync('__started', this, {
maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus), maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus),
options,
}); });
} }
@ -486,11 +488,11 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this._started; return this._started;
} }
async tryReloadOrRestart() { async tryReloadOrRestart(options: StartOptions = {}) {
if (this._started) { if (this._started) {
await this.restart(); await this.restart(options);
} else { } else {
await this.reload(); await this.reload(options);
} }
} }

View File

@ -415,7 +415,9 @@ export class PluginManager {
installed: false, installed: false,
}, },
}); });
await this.app.tryReloadOrRestart(); await this.app.tryReloadOrRestart({
recover: true,
});
throw error; throw error;
} }
} }
@ -467,7 +469,9 @@ export class PluginManager {
enabled: true, enabled: true,
}, },
}); });
await this.app.tryReloadOrRestart(); await this.app.tryReloadOrRestart({
recover: true,
});
throw error; throw error;
} }
} }