@mondart/nestjs-common-module-core 3.2.6 → 3.2.7
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/README.md +25 -1
- package/dist/helpers/graceful-shutdown.helper.d.ts +15 -0
- package/dist/helpers/graceful-shutdown.helper.d.ts.map +1 -0
- package/dist/helpers/graceful-shutdown.helper.js +96 -0
- package/dist/helpers/graceful-shutdown.helper.js.map +1 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,7 +79,11 @@ directly:
|
|
|
79
79
|
```ts
|
|
80
80
|
import { ErrorResponse } from '@mondart/nestjs-common-module-core';
|
|
81
81
|
|
|
82
|
-
new ErrorResponse({
|
|
82
|
+
new ErrorResponse({
|
|
83
|
+
name: 'NotFoundException',
|
|
84
|
+
message: 'Not found',
|
|
85
|
+
status: 404,
|
|
86
|
+
});
|
|
83
87
|
```
|
|
84
88
|
|
|
85
89
|
Common request DTOs — `IdDto`, `IdsDto` (comma-separated `ids` query param),
|
|
@@ -208,6 +212,26 @@ for `{0}`-style `SharedMessages` interpolation, `EnvValidator` for validating
|
|
|
208
212
|
`RxjsCatchErrorHelper` / `RxjsCustomTimeoutHelper` RxJS operators for mapping
|
|
209
213
|
errors/timeouts on outbound calls to Nest exceptions.
|
|
210
214
|
|
|
215
|
+
### Graceful HTTP shutdown
|
|
216
|
+
|
|
217
|
+
Use `GracefulShutdownHelper.enable()` instead of `app.enableShutdownHooks()`
|
|
218
|
+
in an HTTP service bootstrap:
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
import { GracefulShutdownHelper } from '@mondart/nestjs-common-module-core';
|
|
222
|
+
|
|
223
|
+
const app = await NestFactory.create(AppModule);
|
|
224
|
+
GracefulShutdownHelper.enable(app);
|
|
225
|
+
await app.listen(appPort);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
On `SIGTERM` or `SIGINT`, the helper rejects new requests with `503` and a
|
|
229
|
+
`Connection: close` header, closes idle keep-alive connections, waits up to
|
|
230
|
+
110 seconds for active responses, and then calls `app.close()` so Nest module,
|
|
231
|
+
Kafka, queue, and database shutdown hooks run. Configure the container stop
|
|
232
|
+
grace period above that deadline (the Swarm deployment uses two minutes).
|
|
233
|
+
Do not register Nest's default shutdown signal handlers alongside this helper.
|
|
234
|
+
|
|
211
235
|
## Kafka-related exports
|
|
212
236
|
|
|
213
237
|
`BaseKafkaEventDto`, `KafkaRequestDto`, `KafkaSuccessResponse`,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { INestApplication, Logger } from '@nestjs/common';
|
|
2
|
+
export interface GracefulShutdownOptions {
|
|
3
|
+
timeoutMs?: number;
|
|
4
|
+
signals?: NodeJS.Signals[];
|
|
5
|
+
logger?: Pick<Logger, 'log' | 'warn' | 'error'>;
|
|
6
|
+
}
|
|
7
|
+
export interface GracefulShutdownController {
|
|
8
|
+
readonly isDraining: () => boolean;
|
|
9
|
+
readonly activeRequests: () => number;
|
|
10
|
+
shutdown(signal?: NodeJS.Signals): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class GracefulShutdownHelper {
|
|
13
|
+
static enable(app: INestApplication, options?: GracefulShutdownOptions): GracefulShutdownController;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=graceful-shutdown.helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graceful-shutdown.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/graceful-shutdown.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAU1D,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAWD,qBAAa,sBAAsB;IACjC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,gBAAgB,EACrB,OAAO,GAAE,uBAA4B,GACpC,0BAA0B;CAwG9B"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GracefulShutdownHelper = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 110_000;
|
|
6
|
+
class GracefulShutdownHelper {
|
|
7
|
+
static enable(app, options = {}) {
|
|
8
|
+
const server = app.getHttpServer();
|
|
9
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
10
|
+
const signals = options.signals ?? ['SIGTERM', 'SIGINT'];
|
|
11
|
+
const logger = options.logger ?? new common_1.Logger('GracefulShutdown');
|
|
12
|
+
let draining = false;
|
|
13
|
+
let activeRequests = 0;
|
|
14
|
+
let shutdownPromise;
|
|
15
|
+
app.use((_request, response, next) => {
|
|
16
|
+
if (draining) {
|
|
17
|
+
response.statusCode = 503;
|
|
18
|
+
response.setHeader('Connection', 'close');
|
|
19
|
+
response.setHeader('Content-Type', 'application/json');
|
|
20
|
+
response.end(JSON.stringify({
|
|
21
|
+
statusCode: 503,
|
|
22
|
+
message: 'Service is shutting down',
|
|
23
|
+
}));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
activeRequests += 1;
|
|
27
|
+
let completed = false;
|
|
28
|
+
const complete = () => {
|
|
29
|
+
if (completed)
|
|
30
|
+
return;
|
|
31
|
+
completed = true;
|
|
32
|
+
activeRequests = Math.max(0, activeRequests - 1);
|
|
33
|
+
};
|
|
34
|
+
response.once('finish', complete);
|
|
35
|
+
response.once('close', complete);
|
|
36
|
+
next();
|
|
37
|
+
});
|
|
38
|
+
const shutdown = async (signal) => {
|
|
39
|
+
if (shutdownPromise)
|
|
40
|
+
return shutdownPromise;
|
|
41
|
+
shutdownPromise = (async () => {
|
|
42
|
+
draining = true;
|
|
43
|
+
logger.log(`${signal ?? 'Shutdown'} received; draining ${activeRequests} active request(s)`);
|
|
44
|
+
let closeServer = () => undefined;
|
|
45
|
+
const serverClosed = new Promise((resolve, reject) => {
|
|
46
|
+
closeServer = (error) => {
|
|
47
|
+
if (error)
|
|
48
|
+
reject(error);
|
|
49
|
+
else
|
|
50
|
+
resolve();
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
server.close(closeServer);
|
|
54
|
+
server.closeIdleConnections?.();
|
|
55
|
+
let timeout;
|
|
56
|
+
try {
|
|
57
|
+
await Promise.race([
|
|
58
|
+
serverClosed,
|
|
59
|
+
new Promise((resolve) => {
|
|
60
|
+
timeout = setTimeout(() => {
|
|
61
|
+
logger.warn(`Graceful shutdown timed out with ${activeRequests} active request(s)`);
|
|
62
|
+
server.closeAllConnections?.();
|
|
63
|
+
resolve();
|
|
64
|
+
}, timeoutMs);
|
|
65
|
+
timeout.unref();
|
|
66
|
+
}),
|
|
67
|
+
]);
|
|
68
|
+
await app.close();
|
|
69
|
+
logger.log('Graceful shutdown completed');
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
logger.error('Graceful shutdown failed', error instanceof Error ? error.stack : String(error));
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
if (timeout)
|
|
78
|
+
clearTimeout(timeout);
|
|
79
|
+
}
|
|
80
|
+
})();
|
|
81
|
+
return shutdownPromise;
|
|
82
|
+
};
|
|
83
|
+
for (const signal of signals) {
|
|
84
|
+
process.once(signal, () => {
|
|
85
|
+
void shutdown(signal).catch(() => undefined);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
isDraining: () => draining,
|
|
90
|
+
activeRequests: () => activeRequests,
|
|
91
|
+
shutdown,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.GracefulShutdownHelper = GracefulShutdownHelper;
|
|
96
|
+
//# sourceMappingURL=graceful-shutdown.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graceful-shutdown.helper.js","sourceRoot":"","sources":["../../src/helpers/graceful-shutdown.helper.ts"],"names":[],"mappings":"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"}
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './cli-command.helper';
|
|
|
3
3
|
export * from './convert-string-case.helper';
|
|
4
4
|
export * from './generate-hash.helper';
|
|
5
5
|
export * from './get-env.helper';
|
|
6
|
+
export * from './graceful-shutdown.helper';
|
|
6
7
|
export * from './hmac.helper';
|
|
7
8
|
export * from './i18n-message.helper';
|
|
8
9
|
export * from './message-formatter.helper';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,cAAc,CAAC"}
|
package/dist/helpers/index.js
CHANGED
|
@@ -19,6 +19,7 @@ __exportStar(require("./cli-command.helper"), exports);
|
|
|
19
19
|
__exportStar(require("./convert-string-case.helper"), exports);
|
|
20
20
|
__exportStar(require("./generate-hash.helper"), exports);
|
|
21
21
|
__exportStar(require("./get-env.helper"), exports);
|
|
22
|
+
__exportStar(require("./graceful-shutdown.helper"), exports);
|
|
22
23
|
__exportStar(require("./hmac.helper"), exports);
|
|
23
24
|
__exportStar(require("./i18n-message.helper"), exports);
|
|
24
25
|
__exportStar(require("./message-formatter.helper"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,uDAAqC;AACrC,+DAA6C;AAC7C,yDAAuC;AACvC,mDAAiC;AACjC,gDAA8B;AAC9B,wDAAsC;AACtC,6DAA2C;AAC3C,kDAAgC;AAChC,6DAA2C;AAC3C,iDAA+B;AAC/B,qDAAmC;AACnC,4DAA0C;AAC1C,wEAAsD;AACtD,wEAAsD;AACtD,+CAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,uDAAqC;AACrC,+DAA6C;AAC7C,yDAAuC;AACvC,mDAAiC;AACjC,6DAA2C;AAC3C,gDAA8B;AAC9B,wDAAsC;AACtC,6DAA2C;AAC3C,kDAAgC;AAChC,6DAA2C;AAC3C,iDAA+B;AAC/B,qDAAmC;AACnC,4DAA0C;AAC1C,wEAAsD;AACtD,wEAAsD;AACtD,+CAA6B"}
|