|
|
@ -13,6 +13,18 @@ interface InternalServiceMap { |
|
|
|
*/ |
|
|
|
type InternalServiceConstructor<T extends Microservice = Microservice> = new (app: T) => InternalService<T>; |
|
|
|
|
|
|
|
/** |
|
|
|
* Microservice states |
|
|
|
*/ |
|
|
|
export enum MicroserviceState { |
|
|
|
Idling, |
|
|
|
Booting, |
|
|
|
Starting, |
|
|
|
Running, |
|
|
|
Quitting, |
|
|
|
Finished |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* The main application class |
|
|
|
*/ |
|
|
@ -24,10 +36,20 @@ export class Microservice |
|
|
|
private static __instance: Microservice; |
|
|
|
|
|
|
|
/** |
|
|
|
* All available InternalServices |
|
|
|
* A handler function to quit the microservice application |
|
|
|
*/ |
|
|
|
private __quitHandler!: (value: number | PromiseLike<number>) => void; |
|
|
|
|
|
|
|
/** |
|
|
|
* All available services |
|
|
|
*/ |
|
|
|
protected services: InternalServiceMap = {}; |
|
|
|
|
|
|
|
/** |
|
|
|
* The current state of the microservice |
|
|
|
*/ |
|
|
|
protected state: MicroserviceState; |
|
|
|
|
|
|
|
/** |
|
|
|
* Return the current application instance |
|
|
|
*/ |
|
|
@ -40,6 +62,7 @@ export class Microservice |
|
|
|
*/ |
|
|
|
public constructor() { |
|
|
|
Microservice.__instance = this; |
|
|
|
this.state = MicroserviceState.Idling; |
|
|
|
} |
|
|
|
|
|
|
|
// Overridable --------------------------------------------------------------------------------
|
|
|
@ -52,7 +75,7 @@ export class Microservice |
|
|
|
// Application Management ----------------------------------------------------------------------
|
|
|
|
|
|
|
|
/** |
|
|
|
* Boot the application and all of the InternalServices |
|
|
|
* Boot the application and all of the services |
|
|
|
*/ |
|
|
|
protected async boot() { |
|
|
|
let InternalServices = Object.values(this.services); |
|
|
@ -71,19 +94,49 @@ export class Microservice |
|
|
|
* Start the application |
|
|
|
*/ |
|
|
|
public async exec() { |
|
|
|
await this.boot(); |
|
|
|
await this.onStart(); |
|
|
|
for (let InternalService of Object.values(this.services)) { |
|
|
|
InternalService.start(); |
|
|
|
// Exit if not in an idling state
|
|
|
|
if (this.state !== MicroserviceState.Idling) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// Boot the microservice
|
|
|
|
this.state = MicroserviceState.Booting; |
|
|
|
await this.boot(); |
|
|
|
|
|
|
|
// Start the microservice
|
|
|
|
this.state = MicroserviceState.Starting |
|
|
|
await this.onStart(); |
|
|
|
for (let InternalService of Object.values(this.services)) { |
|
|
|
InternalService.start(); |
|
|
|
} |
|
|
|
} catch(e) { |
|
|
|
console.log("Failed to start the microservice"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
// Run the microservice
|
|
|
|
this.state = MicroserviceState.Running; |
|
|
|
let exitCode = await new Promise<number>((resolve) => this.__quitHandler = resolve); |
|
|
|
|
|
|
|
// Shutdown the microservice
|
|
|
|
await this.shutdown().catch(() => { |
|
|
|
console.log("Error ocurred during shutdown..."); |
|
|
|
exitCode = 1; |
|
|
|
}); |
|
|
|
|
|
|
|
// Return the exit code
|
|
|
|
return exitCode; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Quit the application |
|
|
|
*/ |
|
|
|
public async quit(code: number = 0) { |
|
|
|
await this.shutdown(); |
|
|
|
process.exit(code); |
|
|
|
if (this.state !== MicroserviceState.Running) { |
|
|
|
return; |
|
|
|
} |
|
|
|
this.__quitHandler(code); |
|
|
|
} |
|
|
|
|
|
|
|
// InternalService Management --------------------------------------------------------------------------
|
|
|
@ -91,7 +144,7 @@ export class Microservice |
|
|
|
/** |
|
|
|
* Install InternalServices into the application |
|
|
|
*/ |
|
|
|
protected installServices<T extends Microservice>(this: T, InternalServices: InternalServiceConstructor<T>[]) { |
|
|
|
public installServices<T extends Microservice>(this: T, InternalServices: InternalServiceConstructor<T>[]) { |
|
|
|
for (let InternalServiceClass of InternalServices) { |
|
|
|
this.installService(InternalServiceClass); |
|
|
|
} |
|
|
@ -100,20 +153,20 @@ export class Microservice |
|
|
|
/** |
|
|
|
* Install a InternalService into the application |
|
|
|
*/ |
|
|
|
protected installService<T extends Microservice>(this: T, InternalServiceClass: InternalServiceConstructor<T>) { |
|
|
|
public installService<T extends Microservice>(this: T, InternalServiceClass: InternalServiceConstructor<T>) { |
|
|
|
let InternalService = new InternalServiceClass(this); |
|
|
|
this.services[InternalService.name] = InternalService; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get all available InternalServices |
|
|
|
* Get all available services |
|
|
|
*/ |
|
|
|
public serviceList() { |
|
|
|
return Object.keys(this.services); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get an application InternalService instance |
|
|
|
* Get an application services instance |
|
|
|
*/ |
|
|
|
public service<T extends InternalService<Microservice>>(InternalServiceName: string) { |
|
|
|
assert(InternalServiceName in this.services); |
|
|
|