@tsed/terminus 6.126.1 → 6.128.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.config.js +14 -0
- package/lib/cjs/TerminusModule.js +90 -34
- package/lib/cjs/TerminusModule.js.map +1 -1
- package/lib/cjs/decorators/health.js +4 -6
- package/lib/cjs/decorators/health.js.map +1 -1
- package/lib/cjs/decorators/shutdown.js +12 -10
- package/lib/cjs/decorators/shutdown.js.map +1 -1
- package/lib/cjs/interfaces/TerminusSettings.js.map +1 -1
- package/lib/esm/TerminusModule.js +91 -35
- package/lib/esm/TerminusModule.js.map +1 -1
- package/lib/esm/decorators/health.js +4 -6
- package/lib/esm/decorators/health.js.map +1 -1
- package/lib/esm/decorators/shutdown.js +10 -9
- package/lib/esm/decorators/shutdown.js.map +1 -1
- package/lib/esm/interfaces/TerminusSettings.js.map +1 -1
- package/lib/types/TerminusModule.d.ts +24 -4
- package/lib/types/decorators/shutdown.d.ts +5 -0
- package/lib/types/interfaces/TerminusSettings.d.ts +3 -1
- package/package.json +9 -8
- package/readme.md +72 -32
package/jest.config.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// For a detailed explanation regarding each configuration property, visit:
|
|
2
|
+
// https://jestjs.io/docs/en/configuration.html
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
...require("@tsed/jest-config")(__dirname, "terminus"),
|
|
6
|
+
coverageThreshold: {
|
|
7
|
+
global: {
|
|
8
|
+
statements: 100,
|
|
9
|
+
branches: 100,
|
|
10
|
+
functions: 100,
|
|
11
|
+
lines: 100
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -4,27 +4,61 @@ exports.TerminusModule = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const terminus_1 = require("@godaddy/terminus");
|
|
6
6
|
const di_1 = require("@tsed/di");
|
|
7
|
-
const
|
|
7
|
+
const schema_1 = require("@tsed/schema");
|
|
8
8
|
const http_1 = tslib_1.__importDefault(require("http"));
|
|
9
|
+
const https_1 = tslib_1.__importDefault(require("https"));
|
|
9
10
|
let TerminusModule = class TerminusModule {
|
|
10
|
-
|
|
11
|
+
settings;
|
|
12
|
+
basePath;
|
|
11
13
|
injector;
|
|
12
14
|
httpServer;
|
|
13
15
|
httpsServer;
|
|
14
16
|
$onInit() {
|
|
15
17
|
this.mount();
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
logger: this.injector.logger
|
|
19
|
+
getConfiguration() {
|
|
20
|
+
const { path, ...props } = this.settings;
|
|
21
|
+
return {
|
|
22
|
+
logger: (event, error) => this.injector.logger.info({
|
|
23
|
+
event: event.toUpperCase(),
|
|
24
|
+
error_message: error.message
|
|
25
|
+
}),
|
|
21
26
|
healthChecks: this.getHealths(),
|
|
22
|
-
onSignal: this.
|
|
23
|
-
onShutdown: this.
|
|
24
|
-
beforeShutdown: this.
|
|
25
|
-
onSendFailureDuringShutdown: this.
|
|
26
|
-
...
|
|
27
|
+
onSignal: this.createEmitter("$onSignal"),
|
|
28
|
+
onShutdown: this.createEmitter("$onShutdown"),
|
|
29
|
+
beforeShutdown: this.createEmitter("$beforeShutdown"),
|
|
30
|
+
onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
|
|
31
|
+
...props
|
|
27
32
|
};
|
|
33
|
+
}
|
|
34
|
+
async $logRoutes(routes) {
|
|
35
|
+
return [
|
|
36
|
+
...routes,
|
|
37
|
+
{
|
|
38
|
+
toJSON: () => {
|
|
39
|
+
return {
|
|
40
|
+
method: "GET",
|
|
41
|
+
name: `TerminusModule.dispatch`,
|
|
42
|
+
url: this.basePath
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
...this.getAll("health").map(({ provider, propertyKey, options }) => {
|
|
47
|
+
const path = this.getPath(provider, options.name);
|
|
48
|
+
return {
|
|
49
|
+
toJSON() {
|
|
50
|
+
return {
|
|
51
|
+
method: "GET",
|
|
52
|
+
name: `${provider.className}.${propertyKey}`,
|
|
53
|
+
url: path
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
})
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
mount() {
|
|
61
|
+
const terminusConfig = this.getConfiguration();
|
|
28
62
|
if (this.httpServer) {
|
|
29
63
|
(0, terminus_1.createTerminus)(this.httpServer, terminusConfig);
|
|
30
64
|
}
|
|
@@ -32,39 +66,61 @@ let TerminusModule = class TerminusModule {
|
|
|
32
66
|
(0, terminus_1.createTerminus)(this.httpsServer, terminusConfig);
|
|
33
67
|
}
|
|
34
68
|
}
|
|
35
|
-
|
|
36
|
-
return this.injector.getProviders().
|
|
37
|
-
|
|
69
|
+
getAll(name) {
|
|
70
|
+
return this.injector.getProviders().flatMap((provider) => {
|
|
71
|
+
const metadata = provider.store.get(`terminus:${name}`);
|
|
72
|
+
if (metadata) {
|
|
73
|
+
return Object.entries(metadata).map(([propertyKey, options]) => {
|
|
74
|
+
return {
|
|
75
|
+
provider,
|
|
76
|
+
propertyKey,
|
|
77
|
+
options
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return [];
|
|
38
82
|
});
|
|
39
83
|
}
|
|
40
|
-
getStore(name) {
|
|
41
|
-
return this.injector
|
|
42
|
-
.getProviders()
|
|
43
|
-
.map((provider) => provider.store.get(name))
|
|
44
|
-
.filter((x) => !!x)
|
|
45
|
-
.flat();
|
|
46
|
-
}
|
|
47
84
|
getHealths() {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
85
|
+
const subHealths = this.getAll("health").reduce((healths, { provider, propertyKey, options: { name } }) => {
|
|
86
|
+
const instance = this.injector.get(provider.token);
|
|
87
|
+
const callback = async (...args) => {
|
|
88
|
+
const result = await instance[propertyKey](...args);
|
|
89
|
+
return { [name]: result };
|
|
90
|
+
};
|
|
91
|
+
let path = this.getPath(provider, name);
|
|
92
|
+
return {
|
|
93
|
+
...healths,
|
|
94
|
+
[path]: callback
|
|
95
|
+
};
|
|
96
|
+
}, {});
|
|
97
|
+
const healths = {
|
|
98
|
+
...subHealths,
|
|
99
|
+
[this.basePath]: (state) => {
|
|
100
|
+
const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));
|
|
101
|
+
return Promise.all(promises);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
54
104
|
return healths;
|
|
55
105
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
106
|
+
getPath(provider, name) {
|
|
107
|
+
let path = (0, schema_1.concatPath)(provider.path, name);
|
|
108
|
+
return path.includes("health") ? path : (0, schema_1.concatPath)(path, this.basePath);
|
|
109
|
+
}
|
|
110
|
+
createEmitter(name) {
|
|
111
|
+
return async (...args) => {
|
|
112
|
+
return this.injector.emit(`$${name}`, ...args);
|
|
61
113
|
};
|
|
62
114
|
}
|
|
63
115
|
};
|
|
64
116
|
tslib_1.__decorate([
|
|
65
|
-
(0, di_1.
|
|
117
|
+
(0, di_1.Constant)("terminus", {}),
|
|
66
118
|
tslib_1.__metadata("design:type", Object)
|
|
67
|
-
], TerminusModule.prototype, "
|
|
119
|
+
], TerminusModule.prototype, "settings", void 0);
|
|
120
|
+
tslib_1.__decorate([
|
|
121
|
+
(0, di_1.Constant)("terminus.path", "/health"),
|
|
122
|
+
tslib_1.__metadata("design:type", String)
|
|
123
|
+
], TerminusModule.prototype, "basePath", void 0);
|
|
68
124
|
tslib_1.__decorate([
|
|
69
125
|
(0, di_1.Inject)(),
|
|
70
126
|
tslib_1.__metadata("design:type", di_1.InjectorService)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":";;;;AAAA,gDAAiD;AACjD,
|
|
1
|
+
{"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Constant, Inject, InjectorService, Module, OnInit, Provider} from \"@tsed/di\";\nimport {concatPath} from \"@tsed/schema\";\nimport Http from \"http\";\nimport Https from \"https\";\nimport {TerminusSettings} from \"./interfaces/TerminusSettings\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Constant(\"terminus\", {})\n private settings: TerminusSettings;\n\n @Constant(\"terminus.path\", \"/health\")\n private basePath: string;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n getConfiguration() {\n const {path, ...props} = this.settings;\n\n return {\n logger: (event: string, error: any) =>\n this.injector.logger.info({\n event: event.toUpperCase(),\n error_message: error.message\n }),\n healthChecks: this.getHealths(),\n onSignal: this.createEmitter(\"$onSignal\"),\n onShutdown: this.createEmitter(\"$onShutdown\"),\n beforeShutdown: this.createEmitter(\"$beforeShutdown\"),\n onSendFailureDuringShutdown: this.createEmitter(\"$onSendFailureDuringShutdown\"),\n ...props\n };\n }\n\n async $logRoutes(routes: any[]): Promise<any[]> {\n return [\n ...routes,\n {\n toJSON: () => {\n return {\n method: \"GET\",\n name: `TerminusModule.dispatch`,\n url: this.basePath\n };\n }\n },\n ...this.getAll<{name: string}>(\"health\").map(({provider, propertyKey, options}) => {\n const path = this.getPath(provider, options.name);\n\n return {\n toJSON() {\n return {\n method: \"GET\",\n name: `${provider.className}.${propertyKey}`,\n url: path\n };\n }\n } as any;\n })\n ];\n }\n\n private mount() {\n const terminusConfig = this.getConfiguration();\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getAll<Opts = any>(\n name: string\n ): {\n provider: Provider;\n propertyKey: string;\n options: Opts;\n }[] {\n return this.injector.getProviders().flatMap((provider) => {\n const metadata = provider.store.get(`terminus:${name}`);\n\n if (metadata) {\n return Object.entries(metadata).map(([propertyKey, options]: [string, Opts]) => {\n return {\n provider,\n propertyKey,\n options\n };\n });\n }\n return [];\n });\n }\n\n private getHealths() {\n const subHealths = this.getAll<{name: string}>(\"health\").reduce((healths, {provider, propertyKey, options: {name}}) => {\n const instance = this.injector.get<any>(provider.token)!;\n const callback = async (...args: any[]) => {\n const result = await instance[propertyKey](...args);\n\n return {[name]: result};\n };\n\n let path = this.getPath(provider, name);\n\n return {\n ...healths,\n [path]: callback\n };\n }, {} as Record<string, (state: any) => Promise<any>>);\n\n const healths: Record<string, any> = {\n ...subHealths,\n [this.basePath]: (state: any) => {\n const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));\n\n return Promise.all(promises);\n }\n };\n\n return healths;\n }\n\n private getPath(provider: Provider<any>, name: string) {\n let path = concatPath(provider.path, name);\n return path.includes(\"health\") ? path : concatPath(path, this.basePath);\n }\n\n private createEmitter(name: string) {\n return async (...args: any[]) => {\n return this.injector.emit(`$${name}`, ...args);\n };\n }\n}\n"]}
|
|
@@ -22,12 +22,10 @@ const core_1 = require("@tsed/core");
|
|
|
22
22
|
* @terminus
|
|
23
23
|
*/
|
|
24
24
|
function Health(name) {
|
|
25
|
-
return (target, propertyKey
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
});
|
|
30
|
-
}
|
|
25
|
+
return (target, propertyKey) => {
|
|
26
|
+
core_1.Store.from(target).merge(`terminus:health`, {
|
|
27
|
+
[propertyKey]: { name }
|
|
28
|
+
});
|
|
31
29
|
};
|
|
32
30
|
}
|
|
33
31
|
exports.Health = Health;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,EAAE;QACvD,YAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC1C,CAAC,WAAW,CAAC,EAAE,EAAC,IAAI,EAAC;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAND,wBAMC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string) => {\n Store.from(target).merge(`terminus:health`, {\n [propertyKey]: {name}\n });\n };\n}\n"]}
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OnSendFailureDuringShutdown = exports.OnShutdown = exports.OnSignal = exports.BeforeShutdown = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const values = store.get(name) || [];
|
|
10
|
-
store.merge(name, [...values, descriptor.value]);
|
|
11
|
-
}
|
|
3
|
+
exports.OnSendFailureDuringShutdown = exports.OnShutdown = exports.OnSignal = exports.BeforeShutdown = exports.register = void 0;
|
|
4
|
+
function register(event) {
|
|
5
|
+
return (target, propertyKey, description) => {
|
|
6
|
+
Object.defineProperty(target, `$${event}`, {
|
|
7
|
+
value: description.value
|
|
8
|
+
});
|
|
12
9
|
};
|
|
13
10
|
}
|
|
11
|
+
exports.register = register;
|
|
14
12
|
/**
|
|
15
13
|
* Listen the `beforeShutdown` terminus event.
|
|
16
14
|
*
|
|
17
15
|
* @decorator
|
|
18
16
|
* @terminus
|
|
17
|
+
* @deprecated Use $BeforeShutdown hook
|
|
19
18
|
*/
|
|
20
19
|
function BeforeShutdown() {
|
|
21
20
|
return register("beforeShutdown");
|
|
@@ -26,6 +25,7 @@ exports.BeforeShutdown = BeforeShutdown;
|
|
|
26
25
|
*
|
|
27
26
|
* @decorator
|
|
28
27
|
* @terminus
|
|
28
|
+
* @deprecated Use $onSignal hook
|
|
29
29
|
*/
|
|
30
30
|
function OnSignal() {
|
|
31
31
|
return register("onSignal");
|
|
@@ -36,6 +36,7 @@ exports.OnSignal = OnSignal;
|
|
|
36
36
|
*
|
|
37
37
|
* @decorator
|
|
38
38
|
* @terminus
|
|
39
|
+
* @deprecated Use $onShutdown hook
|
|
39
40
|
*/
|
|
40
41
|
function OnShutdown() {
|
|
41
42
|
return register("onShutdown");
|
|
@@ -46,9 +47,10 @@ exports.OnShutdown = OnShutdown;
|
|
|
46
47
|
*
|
|
47
48
|
* @decorator
|
|
48
49
|
* @terminus
|
|
50
|
+
* @deprecated Use $onSendFailureDuringShutdown hook
|
|
49
51
|
*/
|
|
50
52
|
function OnSendFailureDuringShutdown() {
|
|
51
|
-
return register("
|
|
53
|
+
return register("OnSendFailureDuringShutdown");
|
|
52
54
|
}
|
|
53
55
|
exports.OnSendFailureDuringShutdown = OnSendFailureDuringShutdown;
|
|
54
56
|
//# sourceMappingURL=shutdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":";;;AAAA,SAAgB,QAAQ,CAAC,KAAa;IACpC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,WAA+B,EAAE,EAAE;QACxF,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,EAAE;YACzC,KAAK,EAAE,WAAW,CAAC,KAAK;SACzB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAND,4BAMC;AAED;;;;;;GAMG;AACH,SAAgB,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAFD,wCAEC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAFD,4BAEC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAFD,gCAEC;AAED;;;;;;GAMG;AACH,SAAgB,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC;AAFD,kEAEC","sourcesContent":["export function register(event: string) {\n return <Function>(target: Object, propertyKey: string, description: PropertyDescriptor) => {\n Object.defineProperty(target, `$${event}`, {\n value: description.value\n });\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $BeforeShutdown hook\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSignal hook\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onShutdown hook\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSendFailureDuringShutdown hook\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"OnSendFailureDuringShutdown\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n
|
|
1
|
+
{"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n> & {path?: string};\n"]}
|
|
@@ -1,27 +1,61 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import { createTerminus } from "@godaddy/terminus";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { Constant, Inject, InjectorService, Module } from "@tsed/di";
|
|
4
|
+
import { concatPath } from "@tsed/schema";
|
|
5
5
|
import Http from "http";
|
|
6
|
+
import Https from "https";
|
|
6
7
|
let TerminusModule = class TerminusModule {
|
|
7
|
-
|
|
8
|
+
settings;
|
|
9
|
+
basePath;
|
|
8
10
|
injector;
|
|
9
11
|
httpServer;
|
|
10
12
|
httpsServer;
|
|
11
13
|
$onInit() {
|
|
12
14
|
this.mount();
|
|
13
15
|
}
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
|
|
17
|
-
logger: this.injector.logger
|
|
16
|
+
getConfiguration() {
|
|
17
|
+
const { path, ...props } = this.settings;
|
|
18
|
+
return {
|
|
19
|
+
logger: (event, error) => this.injector.logger.info({
|
|
20
|
+
event: event.toUpperCase(),
|
|
21
|
+
error_message: error.message
|
|
22
|
+
}),
|
|
18
23
|
healthChecks: this.getHealths(),
|
|
19
|
-
onSignal: this.
|
|
20
|
-
onShutdown: this.
|
|
21
|
-
beforeShutdown: this.
|
|
22
|
-
onSendFailureDuringShutdown: this.
|
|
23
|
-
...
|
|
24
|
+
onSignal: this.createEmitter("$onSignal"),
|
|
25
|
+
onShutdown: this.createEmitter("$onShutdown"),
|
|
26
|
+
beforeShutdown: this.createEmitter("$beforeShutdown"),
|
|
27
|
+
onSendFailureDuringShutdown: this.createEmitter("$onSendFailureDuringShutdown"),
|
|
28
|
+
...props
|
|
24
29
|
};
|
|
30
|
+
}
|
|
31
|
+
async $logRoutes(routes) {
|
|
32
|
+
return [
|
|
33
|
+
...routes,
|
|
34
|
+
{
|
|
35
|
+
toJSON: () => {
|
|
36
|
+
return {
|
|
37
|
+
method: "GET",
|
|
38
|
+
name: `TerminusModule.dispatch`,
|
|
39
|
+
url: this.basePath
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
...this.getAll("health").map(({ provider, propertyKey, options }) => {
|
|
44
|
+
const path = this.getPath(provider, options.name);
|
|
45
|
+
return {
|
|
46
|
+
toJSON() {
|
|
47
|
+
return {
|
|
48
|
+
method: "GET",
|
|
49
|
+
name: `${provider.className}.${propertyKey}`,
|
|
50
|
+
url: path
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
})
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
mount() {
|
|
58
|
+
const terminusConfig = this.getConfiguration();
|
|
25
59
|
if (this.httpServer) {
|
|
26
60
|
createTerminus(this.httpServer, terminusConfig);
|
|
27
61
|
}
|
|
@@ -29,39 +63,61 @@ let TerminusModule = class TerminusModule {
|
|
|
29
63
|
createTerminus(this.httpsServer, terminusConfig);
|
|
30
64
|
}
|
|
31
65
|
}
|
|
32
|
-
|
|
33
|
-
return this.injector.getProviders().
|
|
34
|
-
|
|
66
|
+
getAll(name) {
|
|
67
|
+
return this.injector.getProviders().flatMap((provider) => {
|
|
68
|
+
const metadata = provider.store.get(`terminus:${name}`);
|
|
69
|
+
if (metadata) {
|
|
70
|
+
return Object.entries(metadata).map(([propertyKey, options]) => {
|
|
71
|
+
return {
|
|
72
|
+
provider,
|
|
73
|
+
propertyKey,
|
|
74
|
+
options
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return [];
|
|
35
79
|
});
|
|
36
80
|
}
|
|
37
|
-
getStore(name) {
|
|
38
|
-
return this.injector
|
|
39
|
-
.getProviders()
|
|
40
|
-
.map((provider) => provider.store.get(name))
|
|
41
|
-
.filter((x) => !!x)
|
|
42
|
-
.flat();
|
|
43
|
-
}
|
|
44
81
|
getHealths() {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
82
|
+
const subHealths = this.getAll("health").reduce((healths, { provider, propertyKey, options: { name } }) => {
|
|
83
|
+
const instance = this.injector.get(provider.token);
|
|
84
|
+
const callback = async (...args) => {
|
|
85
|
+
const result = await instance[propertyKey](...args);
|
|
86
|
+
return { [name]: result };
|
|
87
|
+
};
|
|
88
|
+
let path = this.getPath(provider, name);
|
|
89
|
+
return {
|
|
90
|
+
...healths,
|
|
91
|
+
[path]: callback
|
|
92
|
+
};
|
|
93
|
+
}, {});
|
|
94
|
+
const healths = {
|
|
95
|
+
...subHealths,
|
|
96
|
+
[this.basePath]: (state) => {
|
|
97
|
+
const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));
|
|
98
|
+
return Promise.all(promises);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
51
101
|
return healths;
|
|
52
102
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
103
|
+
getPath(provider, name) {
|
|
104
|
+
let path = concatPath(provider.path, name);
|
|
105
|
+
return path.includes("health") ? path : concatPath(path, this.basePath);
|
|
106
|
+
}
|
|
107
|
+
createEmitter(name) {
|
|
108
|
+
return async (...args) => {
|
|
109
|
+
return this.injector.emit(`$${name}`, ...args);
|
|
58
110
|
};
|
|
59
111
|
}
|
|
60
112
|
};
|
|
61
113
|
__decorate([
|
|
62
|
-
|
|
114
|
+
Constant("terminus", {}),
|
|
63
115
|
__metadata("design:type", Object)
|
|
64
|
-
], TerminusModule.prototype, "
|
|
116
|
+
], TerminusModule.prototype, "settings", void 0);
|
|
117
|
+
__decorate([
|
|
118
|
+
Constant("terminus.path", "/health"),
|
|
119
|
+
__metadata("design:type", String)
|
|
120
|
+
], TerminusModule.prototype, "basePath", void 0);
|
|
65
121
|
__decorate([
|
|
66
122
|
Inject(),
|
|
67
123
|
__metadata("design:type", InjectorService)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":";AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"TerminusModule.js","sourceRoot":"","sources":["../../src/TerminusModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {createTerminus} from \"@godaddy/terminus\";\nimport {Constant, Inject, InjectorService, Module, OnInit, Provider} from \"@tsed/di\";\nimport {concatPath} from \"@tsed/schema\";\nimport Http from \"http\";\nimport Https from \"https\";\nimport {TerminusSettings} from \"./interfaces/TerminusSettings\";\n\n@Module()\nexport class TerminusModule implements OnInit {\n @Constant(\"terminus\", {})\n private settings: TerminusSettings;\n\n @Constant(\"terminus.path\", \"/health\")\n private basePath: string;\n\n @Inject()\n private injector: InjectorService;\n\n @Inject(Http.Server)\n private httpServer: Http.Server | null;\n\n @Inject(Https.Server)\n private httpsServer: Https.Server | null;\n\n public $onInit() {\n this.mount();\n }\n\n getConfiguration() {\n const {path, ...props} = this.settings;\n\n return {\n logger: (event: string, error: any) =>\n this.injector.logger.info({\n event: event.toUpperCase(),\n error_message: error.message\n }),\n healthChecks: this.getHealths(),\n onSignal: this.createEmitter(\"$onSignal\"),\n onShutdown: this.createEmitter(\"$onShutdown\"),\n beforeShutdown: this.createEmitter(\"$beforeShutdown\"),\n onSendFailureDuringShutdown: this.createEmitter(\"$onSendFailureDuringShutdown\"),\n ...props\n };\n }\n\n async $logRoutes(routes: any[]): Promise<any[]> {\n return [\n ...routes,\n {\n toJSON: () => {\n return {\n method: \"GET\",\n name: `TerminusModule.dispatch`,\n url: this.basePath\n };\n }\n },\n ...this.getAll<{name: string}>(\"health\").map(({provider, propertyKey, options}) => {\n const path = this.getPath(provider, options.name);\n\n return {\n toJSON() {\n return {\n method: \"GET\",\n name: `${provider.className}.${propertyKey}`,\n url: path\n };\n }\n } as any;\n })\n ];\n }\n\n private mount() {\n const terminusConfig = this.getConfiguration();\n\n if (this.httpServer) {\n createTerminus(this.httpServer, terminusConfig);\n }\n\n if (this.httpsServer) {\n createTerminus(this.httpsServer, terminusConfig);\n }\n }\n\n private getAll<Opts = any>(\n name: string\n ): {\n provider: Provider;\n propertyKey: string;\n options: Opts;\n }[] {\n return this.injector.getProviders().flatMap((provider) => {\n const metadata = provider.store.get(`terminus:${name}`);\n\n if (metadata) {\n return Object.entries(metadata).map(([propertyKey, options]: [string, Opts]) => {\n return {\n provider,\n propertyKey,\n options\n };\n });\n }\n return [];\n });\n }\n\n private getHealths() {\n const subHealths = this.getAll<{name: string}>(\"health\").reduce((healths, {provider, propertyKey, options: {name}}) => {\n const instance = this.injector.get<any>(provider.token)!;\n const callback = async (...args: any[]) => {\n const result = await instance[propertyKey](...args);\n\n return {[name]: result};\n };\n\n let path = this.getPath(provider, name);\n\n return {\n ...healths,\n [path]: callback\n };\n }, {} as Record<string, (state: any) => Promise<any>>);\n\n const healths: Record<string, any> = {\n ...subHealths,\n [this.basePath]: (state: any) => {\n const promises = Object.entries(subHealths).map(([path, callback]) => callback(state));\n\n return Promise.all(promises);\n }\n };\n\n return healths;\n }\n\n private getPath(provider: Provider<any>, name: string) {\n let path = concatPath(provider.path, name);\n return path.includes(\"health\") ? path : concatPath(path, this.basePath);\n }\n\n private createEmitter(name: string) {\n return async (...args: any[]) => {\n return this.injector.emit(`$${name}`, ...args);\n };\n }\n}\n"]}
|
|
@@ -19,12 +19,10 @@ import { Store } from "@tsed/core";
|
|
|
19
19
|
* @terminus
|
|
20
20
|
*/
|
|
21
21
|
export function Health(name) {
|
|
22
|
-
return (target, propertyKey
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
}
|
|
22
|
+
return (target, propertyKey) => {
|
|
23
|
+
Store.from(target).merge(`terminus:health`, {
|
|
24
|
+
[propertyKey]: { name }
|
|
25
|
+
});
|
|
28
26
|
};
|
|
29
27
|
}
|
|
30
28
|
//# sourceMappingURL=health.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/decorators/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,EAAE;QACvD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC1C,CAAC,WAAW,CAAC,EAAE,EAAC,IAAI,EAAC;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {Store} from \"@tsed/core\";\n\n/**\n * Create a readiness / liveness checks.\n *\n * ```ts\n * import { Health } from \"@tsed/terminus\";\n *\n * @Controller(\"/mongo\")\n * class MongoCtrl {\n * @Health(\"/health\")\n * health() {\n * // Here check the mongo health\n * return Promise.resolve();\n * }\n * }\n *\n * @param name\n * @decorator\n * @terminus\n */\nexport function Health(name: string): MethodDecorator {\n return <Function>(target: Object, propertyKey: string) => {\n Store.from(target).merge(`terminus:health`, {\n [propertyKey]: {name}\n });\n };\n}\n"]}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const values = store.get(name) || [];
|
|
7
|
-
store.merge(name, [...values, descriptor.value]);
|
|
8
|
-
}
|
|
1
|
+
export function register(event) {
|
|
2
|
+
return (target, propertyKey, description) => {
|
|
3
|
+
Object.defineProperty(target, `$${event}`, {
|
|
4
|
+
value: description.value
|
|
5
|
+
});
|
|
9
6
|
};
|
|
10
7
|
}
|
|
11
8
|
/**
|
|
@@ -13,6 +10,7 @@ function register(name) {
|
|
|
13
10
|
*
|
|
14
11
|
* @decorator
|
|
15
12
|
* @terminus
|
|
13
|
+
* @deprecated Use $BeforeShutdown hook
|
|
16
14
|
*/
|
|
17
15
|
export function BeforeShutdown() {
|
|
18
16
|
return register("beforeShutdown");
|
|
@@ -22,6 +20,7 @@ export function BeforeShutdown() {
|
|
|
22
20
|
*
|
|
23
21
|
* @decorator
|
|
24
22
|
* @terminus
|
|
23
|
+
* @deprecated Use $onSignal hook
|
|
25
24
|
*/
|
|
26
25
|
export function OnSignal() {
|
|
27
26
|
return register("onSignal");
|
|
@@ -31,6 +30,7 @@ export function OnSignal() {
|
|
|
31
30
|
*
|
|
32
31
|
* @decorator
|
|
33
32
|
* @terminus
|
|
33
|
+
* @deprecated Use $onShutdown hook
|
|
34
34
|
*/
|
|
35
35
|
export function OnShutdown() {
|
|
36
36
|
return register("onShutdown");
|
|
@@ -40,8 +40,9 @@ export function OnShutdown() {
|
|
|
40
40
|
*
|
|
41
41
|
* @decorator
|
|
42
42
|
* @terminus
|
|
43
|
+
* @deprecated Use $onSendFailureDuringShutdown hook
|
|
43
44
|
*/
|
|
44
45
|
export function OnSendFailureDuringShutdown() {
|
|
45
|
-
return register("
|
|
46
|
+
return register("OnSendFailureDuringShutdown");
|
|
46
47
|
}
|
|
47
48
|
//# sourceMappingURL=shutdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../src/decorators/shutdown.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,CAAW,MAAc,EAAE,WAAmB,EAAE,WAA+B,EAAE,EAAE;QACxF,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,KAAK,EAAE,EAAE;YACzC,KAAK,EAAE,WAAW,CAAC,KAAK;SACzB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC","sourcesContent":["export function register(event: string) {\n return <Function>(target: Object, propertyKey: string, description: PropertyDescriptor) => {\n Object.defineProperty(target, `$${event}`, {\n value: description.value\n });\n };\n}\n\n/**\n * Listen the `beforeShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $BeforeShutdown hook\n */\nexport function BeforeShutdown(): MethodDecorator {\n return register(\"beforeShutdown\");\n}\n\n/**\n * Listen the `onSignal` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSignal hook\n */\nexport function OnSignal(): MethodDecorator {\n return register(\"onSignal\");\n}\n\n/**\n * Listen the `onShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onShutdown hook\n */\nexport function OnShutdown(): MethodDecorator {\n return register(\"onShutdown\");\n}\n\n/**\n * Listen the `onSendFailureDuringShutdown` terminus event.\n *\n * @decorator\n * @terminus\n * @deprecated Use $onSendFailureDuringShutdown hook\n */\nexport function OnSendFailureDuringShutdown(): MethodDecorator {\n return register(\"OnSendFailureDuringShutdown\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n
|
|
1
|
+
{"version":3,"file":"TerminusSettings.js","sourceRoot":"","sources":["../../../src/interfaces/TerminusSettings.ts"],"names":[],"mappings":"","sourcesContent":["import {TerminusOptions} from \"@godaddy/terminus\";\n\nexport type TerminusSettings = Omit<\n TerminusOptions,\n \"healthChecks\" | \"onSignal\" | \"onSendFailureDuringShutdown\" | \"onShutdown\" | \"beforeShutdown\" | \"onSigterm\"\n> & {path?: string};\n"]}
|
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
import { OnInit } from "@tsed/di";
|
|
2
2
|
export declare class TerminusModule implements OnInit {
|
|
3
|
-
private
|
|
3
|
+
private settings;
|
|
4
|
+
private basePath;
|
|
4
5
|
private injector;
|
|
5
6
|
private httpServer;
|
|
6
7
|
private httpsServer;
|
|
7
8
|
$onInit(): void;
|
|
9
|
+
getConfiguration(): {
|
|
10
|
+
caseInsensitive?: boolean | undefined;
|
|
11
|
+
timeout?: number | undefined;
|
|
12
|
+
signal?: string | undefined;
|
|
13
|
+
signals?: string[] | undefined;
|
|
14
|
+
sendFailuresDuringShutdown?: boolean | undefined;
|
|
15
|
+
statusOk?: number | undefined;
|
|
16
|
+
statusError?: number | undefined;
|
|
17
|
+
logger: (event: string, error: any) => any;
|
|
18
|
+
headers?: {
|
|
19
|
+
[key: string]: string;
|
|
20
|
+
} | undefined;
|
|
21
|
+
healthChecks: Record<string, any>;
|
|
22
|
+
onSignal: (...args: any[]) => Promise<void>;
|
|
23
|
+
onShutdown: (...args: any[]) => Promise<void>;
|
|
24
|
+
beforeShutdown: (...args: any[]) => Promise<void>;
|
|
25
|
+
onSendFailureDuringShutdown: (...args: any[]) => Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
$logRoutes(routes: any[]): Promise<any[]>;
|
|
8
28
|
private mount;
|
|
9
|
-
private
|
|
10
|
-
private getStore;
|
|
29
|
+
private getAll;
|
|
11
30
|
private getHealths;
|
|
12
|
-
private
|
|
31
|
+
private getPath;
|
|
32
|
+
private createEmitter;
|
|
13
33
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export declare function register(event: string): <Function_1>(target: Object, propertyKey: string, description: PropertyDescriptor) => void;
|
|
1
2
|
/**
|
|
2
3
|
* Listen the `beforeShutdown` terminus event.
|
|
3
4
|
*
|
|
4
5
|
* @decorator
|
|
5
6
|
* @terminus
|
|
7
|
+
* @deprecated Use $BeforeShutdown hook
|
|
6
8
|
*/
|
|
7
9
|
export declare function BeforeShutdown(): MethodDecorator;
|
|
8
10
|
/**
|
|
@@ -10,6 +12,7 @@ export declare function BeforeShutdown(): MethodDecorator;
|
|
|
10
12
|
*
|
|
11
13
|
* @decorator
|
|
12
14
|
* @terminus
|
|
15
|
+
* @deprecated Use $onSignal hook
|
|
13
16
|
*/
|
|
14
17
|
export declare function OnSignal(): MethodDecorator;
|
|
15
18
|
/**
|
|
@@ -17,6 +20,7 @@ export declare function OnSignal(): MethodDecorator;
|
|
|
17
20
|
*
|
|
18
21
|
* @decorator
|
|
19
22
|
* @terminus
|
|
23
|
+
* @deprecated Use $onShutdown hook
|
|
20
24
|
*/
|
|
21
25
|
export declare function OnShutdown(): MethodDecorator;
|
|
22
26
|
/**
|
|
@@ -24,5 +28,6 @@ export declare function OnShutdown(): MethodDecorator;
|
|
|
24
28
|
*
|
|
25
29
|
* @decorator
|
|
26
30
|
* @terminus
|
|
31
|
+
* @deprecated Use $onSendFailureDuringShutdown hook
|
|
27
32
|
*/
|
|
28
33
|
export declare function OnSendFailureDuringShutdown(): MethodDecorator;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { TerminusOptions } from "@godaddy/terminus";
|
|
2
|
-
export declare type TerminusSettings = Omit<TerminusOptions, "healthChecks" | "onSignal" | "onSendFailureDuringShutdown" | "onShutdown" | "beforeShutdown" | "onSigterm"
|
|
2
|
+
export declare type TerminusSettings = Omit<TerminusOptions, "healthChecks" | "onSignal" | "onSendFailureDuringShutdown" | "onShutdown" | "beforeShutdown" | "onSigterm"> & {
|
|
3
|
+
path?: string;
|
|
4
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsed/terminus",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.128.1",
|
|
4
4
|
"description": "Adds graceful shutdown and Kubernetes readiness / liveness checks for any HTTP applications.",
|
|
5
5
|
"author": "Romain Lenzotti",
|
|
6
6
|
"private": false,
|
|
@@ -19,22 +19,23 @@
|
|
|
19
19
|
"build:cjs": "tsc --build tsconfig.compile.json",
|
|
20
20
|
"build:esm": "tsc --build tsconfig.compile.esm.json",
|
|
21
21
|
"barrels": "yarn barrelsby --delete -d ./src -e \"\\.spec\\.ts\" -e \"__mock__\" -e \".benchmark.ts\"",
|
|
22
|
-
"start": "ts-node -r tsconfig-paths/register test/app/index.ts"
|
|
22
|
+
"start": "ts-node -r tsconfig-paths/register test/app/index.ts",
|
|
23
|
+
"test": "cross-env NODE_ENV=test yarn jest --max-workers=2"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"tslib": "2.4.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@godaddy/terminus": "^4.7.1",
|
|
29
|
-
"@tsed/core": "6.
|
|
30
|
-
"@tsed/di": "6.
|
|
31
|
-
"@tsed/schema": "6.
|
|
30
|
+
"@tsed/core": "6.128.1",
|
|
31
|
+
"@tsed/di": "6.128.1",
|
|
32
|
+
"@tsed/schema": "6.128.1"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
35
|
"@godaddy/terminus": "^4.7.1",
|
|
35
|
-
"@tsed/core": "^6.
|
|
36
|
-
"@tsed/di": "^6.
|
|
37
|
-
"@tsed/schema": "^6.
|
|
36
|
+
"@tsed/core": "^6.128.1",
|
|
37
|
+
"@tsed/di": "^6.128.1",
|
|
38
|
+
"@tsed/schema": "^6.128.1"
|
|
38
39
|
},
|
|
39
40
|
"peerDependenciesMeta": {
|
|
40
41
|
"@godaddy/terminus": {
|
package/readme.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
<hr />
|
|
30
30
|
|
|
31
|
-
Adds graceful shutdown and Kubernetes readiness /
|
|
31
|
+
Adds graceful shutdown and Kubernetes readiness / liveliness checks for any HTTP applications.
|
|
32
32
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
@@ -74,19 +74,31 @@ export type TerminusSettings = Omit<
|
|
|
74
74
|
|
|
75
75
|
## Usage
|
|
76
76
|
|
|
77
|
-
### Readiness /
|
|
77
|
+
### Readiness / liveliness checks
|
|
78
78
|
|
|
79
|
-
To create a readiness /
|
|
79
|
+
To create a readiness / liveliness checks use the `@Health` decorator.
|
|
80
80
|
|
|
81
81
|
```ts
|
|
82
82
|
import {Health} from "@tsed/terminus";
|
|
83
|
+
import {Injectable, Inject} from "@tsed/di";
|
|
84
|
+
import {HealthCheckError} from "@godaddy/terminus";
|
|
85
|
+
import {REDIS_CONNECTION} from "./RedisConnection";
|
|
86
|
+
|
|
87
|
+
@Injectable()
|
|
88
|
+
class RedisClient {
|
|
89
|
+
@Inject(REDIS_CONNECTION)
|
|
90
|
+
protected redisConnection: REDIS_CONNECTION;
|
|
91
|
+
|
|
92
|
+
@Health("redis")
|
|
93
|
+
async check() {
|
|
94
|
+
if (this.redisConnection.status === "ready") {
|
|
95
|
+
return "OK";
|
|
96
|
+
}
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// Here check the mongo health
|
|
89
|
-
return Promise.resolve();
|
|
98
|
+
// Here check the redis health
|
|
99
|
+
throw new HealthCheckError("failed", {
|
|
100
|
+
redis: this.redisConnection.status
|
|
101
|
+
});
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
104
|
```
|
|
@@ -95,56 +107,84 @@ You can also create an `HealthCheckError` when an error appear during your check
|
|
|
95
107
|
|
|
96
108
|
```ts
|
|
97
109
|
import {Health} from "@tsed/terminus";
|
|
110
|
+
import {Injectable, Inject} from "@tsed/di";
|
|
98
111
|
import {HealthCheckError} from "@godaddy/terminus";
|
|
112
|
+
import {REDIS_CONNECTION} from "./RedisConnection";
|
|
113
|
+
|
|
114
|
+
@Injectable()
|
|
115
|
+
class RedisClient {
|
|
116
|
+
@Inject(REDIS_CONNECTION)
|
|
117
|
+
protected redisConnection: REDIS_CONNECTION;
|
|
118
|
+
|
|
119
|
+
@Health("redis")
|
|
120
|
+
async check() {
|
|
121
|
+
if (this.redisConnection.status === "ready") {
|
|
122
|
+
return "ok";
|
|
123
|
+
}
|
|
99
124
|
|
|
100
|
-
@Controller("/redis")
|
|
101
|
-
class Redis {
|
|
102
|
-
@Health("/health")
|
|
103
|
-
health() {
|
|
104
125
|
// Here check the redis health
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
})
|
|
109
|
-
);
|
|
126
|
+
throw new HealthCheckError("failed", {
|
|
127
|
+
redis: this.redisConnection.status
|
|
128
|
+
});
|
|
110
129
|
}
|
|
111
130
|
}
|
|
112
131
|
```
|
|
113
132
|
|
|
133
|
+
Expected result when calling the "/health":
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"status": "ok",
|
|
138
|
+
"info": [
|
|
139
|
+
{
|
|
140
|
+
"mongo": "ok"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"redis": "ok"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"details": [
|
|
147
|
+
{
|
|
148
|
+
"mongo": "ok"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"redis": "ok"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
114
157
|
### Graceful shutdown
|
|
115
158
|
|
|
116
159
|
`@tsed/terminus` package give some decorators to handle Terminus hooks. These hooks allow you to adds graceful shutdown.
|
|
117
160
|
Here is the list of decorators:
|
|
118
161
|
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
162
|
+
- `$beforeShutdown`: Use this hook if you deploy your application with Kubernetes (see more
|
|
163
|
+
details [here](https://github.com/godaddy/terminus#how-to-set-terminus-up-with-kubernetes)),
|
|
164
|
+
- `$onSignal`: cleanup hook, returning a promise (used to be onSigterm),
|
|
165
|
+
- `$onShutdown`: called right before exiting,
|
|
166
|
+
- `$onSendFailureDuringShutdown`: called before sending each 503 during shutdowns.
|
|
123
167
|
|
|
124
168
|
**Example:**
|
|
125
169
|
|
|
126
170
|
```typescript
|
|
127
|
-
import {
|
|
171
|
+
import {Injectable} from "@tsed/di";
|
|
128
172
|
|
|
129
|
-
@
|
|
173
|
+
@Injectable()
|
|
130
174
|
class RedisCtrl {
|
|
131
|
-
|
|
132
|
-
beforeShutdow() {
|
|
175
|
+
$beforeShutdown() {
|
|
133
176
|
console.log("called before shutdown");
|
|
134
177
|
}
|
|
135
178
|
|
|
136
|
-
|
|
137
|
-
OnSignal() {
|
|
179
|
+
$onSignal() {
|
|
138
180
|
console.log("called on signal");
|
|
139
181
|
}
|
|
140
182
|
|
|
141
|
-
|
|
142
|
-
OnShutdown() {
|
|
183
|
+
$onShutdown() {
|
|
143
184
|
console.log("called on shutdown");
|
|
144
185
|
}
|
|
145
186
|
|
|
146
|
-
|
|
147
|
-
OnSendFailureDuringShutdown() {
|
|
187
|
+
$onSendFailureDuringShutdown() {
|
|
148
188
|
console.log("on send failure during shutdown");
|
|
149
189
|
}
|
|
150
190
|
}
|