Application: make start/stop sturdier, catch more stop signals
This commit is contained in:
parent
93e79984e3
commit
f91bd6851f
@ -29,6 +29,8 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
private cacheProvider?: CacheProvider;
|
private cacheProvider?: CacheProvider;
|
||||||
|
|
||||||
private ready: boolean = false;
|
private ready: boolean = false;
|
||||||
|
private started: boolean = false;
|
||||||
|
private busy: boolean = false;
|
||||||
|
|
||||||
protected constructor(version: string, ignoreCommandLine: boolean = false) {
|
protected constructor(version: string, ignoreCommandLine: boolean = false) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@ -59,6 +61,10 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async start(): Promise<void> {
|
public async start(): Promise<void> {
|
||||||
|
if (this.started) throw new Error('Application already started');
|
||||||
|
if (this.busy) throw new Error('Application busy');
|
||||||
|
this.busy = true;
|
||||||
|
|
||||||
// Load core version
|
// Load core version
|
||||||
const file = this.isInNodeModules() ?
|
const file = this.isInNodeModules() ?
|
||||||
path.join(__dirname, '../../package.json') :
|
path.join(__dirname, '../../package.json') :
|
||||||
@ -73,22 +79,28 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
logger.info(`${config.get('app.name')} v${this.version} | swaf v${this.coreVersion}`);
|
logger.info(`${config.get('app.name')} v${this.version} | swaf v${this.coreVersion}`);
|
||||||
|
|
||||||
// Catch interrupt signals
|
// Catch interrupt signals
|
||||||
process.once('SIGINT', () => {
|
const exitHandler = () => {
|
||||||
this.stop().catch(console.error);
|
this.stop().catch(console.error);
|
||||||
});
|
};
|
||||||
|
process.once('exit', exitHandler);
|
||||||
|
process.once('SIGINT', exitHandler);
|
||||||
|
process.once('SIGUSR1', exitHandler);
|
||||||
|
process.once('SIGUSR2', exitHandler);
|
||||||
|
process.once('uncaughtException', exitHandler);
|
||||||
|
|
||||||
// Register migrations
|
// Register migrations
|
||||||
MysqlConnectionManager.registerMigrations(this.getMigrations());
|
MysqlConnectionManager.registerMigrations(this.getMigrations());
|
||||||
|
|
||||||
// Process command line
|
|
||||||
if (!this.ignoreCommandLine && await this.processCommandLine()) {
|
|
||||||
await this.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all components and alike
|
// Register all components and alike
|
||||||
await this.init();
|
await this.init();
|
||||||
|
|
||||||
|
// Process command line
|
||||||
|
if (!this.ignoreCommandLine && await this.processCommandLine()) {
|
||||||
|
this.started = true;
|
||||||
|
this.busy = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Security
|
// Security
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
await this.checkSecuritySettings();
|
await this.checkSecuritySettings();
|
||||||
@ -203,26 +215,54 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
this.routes(initRouter, handleRouter);
|
this.routes(initRouter, handleRouter);
|
||||||
|
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
|
this.started = true;
|
||||||
|
this.busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async processCommandLine(): Promise<boolean> {
|
protected async processCommandLine(): Promise<boolean> {
|
||||||
const args = process.argv;
|
const args = process.argv;
|
||||||
|
// Flags
|
||||||
|
const flags = {
|
||||||
|
verbose: false,
|
||||||
|
fullHttpRequests: false,
|
||||||
|
};
|
||||||
|
let mainCommand: string | null = null;
|
||||||
|
const mainCommandArgs: string[] = [];
|
||||||
for (let i = 2; i < args.length; i++) {
|
for (let i = 2; i < args.length; i++) {
|
||||||
switch (args[i]) {
|
switch (args[i]) {
|
||||||
case '--verbose':
|
case '--verbose':
|
||||||
logger.setSettings({minLevel: "trace"});
|
flags.verbose = true;
|
||||||
break;
|
break;
|
||||||
case '--full-http-requests':
|
case '--full-http-requests':
|
||||||
LogRequestsComponent.logFullHttpRequests();
|
flags.fullHttpRequests = true;
|
||||||
break;
|
break;
|
||||||
case 'migration':
|
case 'migration':
|
||||||
await MysqlConnectionManager.migrationCommand(args.slice(i + 1));
|
if (mainCommand === null) mainCommand = args[i];
|
||||||
return true;
|
else throw new Error(`Only one main command can be used at once (${mainCommand},${args[i]})`);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn('Unrecognized argument', args[i]);
|
if (mainCommand) mainCommandArgs.push(args[i]);
|
||||||
|
else logger.fatal('Unrecognized argument', args[i]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags.verbose) logger.setSettings({minLevel: "trace"});
|
||||||
|
if (flags.fullHttpRequests) LogRequestsComponent.logFullHttpRequests();
|
||||||
|
|
||||||
|
if (mainCommand) {
|
||||||
|
switch (mainCommand) {
|
||||||
|
case 'migration':
|
||||||
|
await MysqlConnectionManager.migrationCommand(mainCommandArgs);
|
||||||
|
await this.stop();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.fatal('Unimplemented main command', mainCommand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,13 +287,18 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async stop(): Promise<void> {
|
public async stop(): Promise<void> {
|
||||||
logger.info('Stopping application...');
|
if (this.started && !this.busy) {
|
||||||
|
this.busy = true;
|
||||||
|
logger.info('Stopping application...');
|
||||||
|
|
||||||
for (const component of this.components) {
|
for (const component of this.components) {
|
||||||
await component.stop?.();
|
await component.stop?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`${this.constructor.name} stopped properly.`);
|
||||||
|
this.started = false;
|
||||||
|
this.busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`${this.constructor.name} v${this.version} - bye`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private routes(initRouter: Router, handleRouter: Router) {
|
private routes(initRouter: Router, handleRouter: Router) {
|
||||||
|
Loading…
Reference in New Issue
Block a user