@yolo-croket-dev/core 1.4.53-slowquery.6 → 1.4.53-slowquery.8

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.
@@ -134,7 +134,7 @@ let RPCInterceptor = class RPCInterceptor {
134
134
  // return data;
135
135
  // }
136
136
  async intercept(context, next) {
137
- var _a;
137
+ var _a, _b;
138
138
  const options = this.reflector.get('rpcInterceptorScope', context.getHandler());
139
139
  const args = context.getArgs();
140
140
  const arg = args[0];
@@ -146,9 +146,13 @@ let RPCInterceptor = class RPCInterceptor {
146
146
  // const traceId = content.data.param ? content.data.param.traceId : null;
147
147
  const isInternal = content.data.param ? content.data.param.isInternal : false;
148
148
  const isAdmin = content.data.param ? content.data.param.isAdmin : false;
149
- // const method = content.pattern;
150
149
  const reDeliveryCount = Number(message.properties.headers['x-delivery-count']) || 0; /** 몇번 재전달되었는지 */
151
150
  const staticRetryCount = Number(options === null || options === void 0 ? void 0 : options.messageRetryCount) || 0; /** 최대 재시도 갯수 */
151
+ const method = content.pattern;
152
+ const execInterceptor = {
153
+ method,
154
+ traceId: ((_a = content.data.param) === null || _a === void 0 ? void 0 : _a.traceId) || '-',
155
+ };
152
156
  // const logParam = {
153
157
  // traceId,
154
158
  // method,
@@ -237,7 +241,7 @@ let RPCInterceptor = class RPCInterceptor {
237
241
  };
238
242
  localErrorProcessor = localErrorProcessor.bind(this);
239
243
  /** 파일 객체 처리 */
240
- (0, functions_1.reWriteFileValue)((_a = content === null || content === void 0 ? void 0 : content.data) === null || _a === void 0 ? void 0 : _a.file);
244
+ (0, functions_1.reWriteFileValue)((_b = content === null || content === void 0 ? void 0 : content.data) === null || _b === void 0 ? void 0 : _b.file);
241
245
  if (options) {
242
246
  if (options.maxLengthKeys && options.maxLengthKeys.length) {
243
247
  for (const key of options.maxLengthKeys) {
@@ -266,8 +270,7 @@ let RPCInterceptor = class RPCInterceptor {
266
270
  else {
267
271
  // logger.debug(`=> (${traceId}): ${JSON.stringify(this.keyCutter(JSON.stringify(content)))}`);
268
272
  }
269
- msaLogger.debug('RPCInterceptor IncActiveInterceptors called', { traceId: 'INC_RPC_ACTIVE_INTERCEPTORS' });
270
- this.gracefulShutdownService.incActiveInterceptors();
273
+ this.gracefulShutdownService.pushActiveInterceptors(execInterceptor);
271
274
  // eslint-disable-next-line consistent-return
272
275
  return next
273
276
  .handle()
@@ -292,8 +295,7 @@ let RPCInterceptor = class RPCInterceptor {
292
295
  },
293
296
  error: localErrorProcessor,
294
297
  }), (0, operators_1.finalize)(() => {
295
- msaLogger.debug('RPCInterceptor DecActiveInterceptors called', { traceId: 'DEC_RPC_ACTIVE_INTERCEPTORS' });
296
- this.gracefulShutdownService.decActiveInterceptors();
298
+ this.gracefulShutdownService.popActiveInterceptors(execInterceptor);
297
299
  }));
298
300
  }
299
301
  };
@@ -0,0 +1,20 @@
1
+ import { RmqOptions, ServerRMQ } from '@nestjs/microservices';
2
+ import { Channel } from 'amqp-connection-manager';
3
+ import { ConsumeMessage } from 'amqplib';
4
+ export type GracefulRmqOptions = RmqOptions['options'] & {
5
+ waitingEndingHandlersTimeoutMs?: number;
6
+ waitingEndingHandlersIntervalMs?: number;
7
+ };
8
+ export declare class GracefulServerRMQ extends ServerRMQ {
9
+ protected readonly options: GracefulRmqOptions;
10
+ protected runningMessages: number;
11
+ protected closing: boolean;
12
+ protected consumerTag: string | null;
13
+ protected readonly waitingEndingHandlersTimeoutMs: number;
14
+ protected readonly waitingEndingHandlersIntervalMs: number;
15
+ constructor(options: GracefulRmqOptions);
16
+ setupChannel(channel: Channel, callback: () => void): Promise<void>;
17
+ protected waitingHandlers(): Promise<void>;
18
+ handleMessage(message: ConsumeMessage, channel: Channel): Promise<void>;
19
+ close(): Promise<void>;
20
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GracefulServerRMQ = void 0;
4
+ const microservices_1 = require("@nestjs/microservices");
5
+ const node_util_1 = require("node:util");
6
+ const sleep = (0, node_util_1.promisify)(setTimeout);
7
+ const RMQ_DEFAULT_WAITING_ENDING_HANDLERS_TIMEOUT_MS = 5000;
8
+ const RMQ_DEFAULT_WAITING_ENDING_HANDLERS_INTERVAL_MS = 500;
9
+ class GracefulServerRMQ extends microservices_1.ServerRMQ {
10
+ constructor(options) {
11
+ super(options);
12
+ this.options = options;
13
+ this.runningMessages = 0;
14
+ this.closing = false;
15
+ this.consumerTag = null;
16
+ this.waitingEndingHandlersTimeoutMs = this.getOptionsProp(this.options, 'waitingEndingHandlersTimeoutMs')
17
+ || RMQ_DEFAULT_WAITING_ENDING_HANDLERS_TIMEOUT_MS;
18
+ this.waitingEndingHandlersIntervalMs = this.getOptionsProp(this.options, 'waitingEndingHandlersIntervalMs')
19
+ || RMQ_DEFAULT_WAITING_ENDING_HANDLERS_INTERVAL_MS;
20
+ }
21
+ async setupChannel(channel, callback) {
22
+ if (this.closing) {
23
+ return;
24
+ }
25
+ if (!this.queueOptions.noAssert) {
26
+ await channel.assertQueue(this.queue, this.queueOptions);
27
+ }
28
+ await channel.prefetch(this.prefetchCount, this.isGlobalPrefetchCount);
29
+ const { consumerTag } = await channel.consume(this.queue, (msg) => this.handleMessage(msg, channel), { noAck: false });
30
+ this.consumerTag = consumerTag;
31
+ callback();
32
+ }
33
+ async waitingHandlers() {
34
+ while (this.runningMessages > 0) {
35
+ await sleep(this.waitingEndingHandlersIntervalMs);
36
+ }
37
+ }
38
+ async handleMessage(message, channel) {
39
+ this.runningMessages += 1;
40
+ return super.handleMessage(message, channel).finally(() => {
41
+ this.runningMessages -= 1;
42
+ });
43
+ }
44
+ async close() {
45
+ this.closing = true;
46
+ if (this.channel) {
47
+ await this.channel.removeSetup(undefined, (channel) => channel.cancel(this.consumerTag));
48
+ }
49
+ this.consumerTag = null;
50
+ await Promise.race([
51
+ this.waitingHandlers(),
52
+ this.waitingEndingHandlersTimeoutMs > 0
53
+ && sleep(this.waitingEndingHandlersTimeoutMs),
54
+ ]);
55
+ this.runningMessages = 0;
56
+ super.close();
57
+ }
58
+ }
59
+ exports.GracefulServerRMQ = GracefulServerRMQ;
@@ -1,10 +1,15 @@
1
1
  import { OnApplicationShutdown, OnModuleDestroy, OnApplicationBootstrap } from '@nestjs/common';
2
+ interface GracefulExecInterceptor {
3
+ method: string;
4
+ traceId?: string;
5
+ }
2
6
  export declare class GracefulShutdownService implements OnApplicationShutdown, OnModuleDestroy, OnApplicationBootstrap {
3
7
  private activeInterceptors;
4
8
  isApplicationExit: boolean;
5
9
  onApplicationBootstrap(): void;
6
- incActiveInterceptors(): void;
7
- decActiveInterceptors(): void;
10
+ pushActiveInterceptors(execInterceptor: GracefulExecInterceptor): void;
11
+ popActiveInterceptors(execInterceptor: GracefulExecInterceptor): void;
8
12
  onApplicationShutdown(signal?: string): Promise<void>;
9
13
  onModuleDestroy(): Promise<void>;
10
14
  }
15
+ export {};
@@ -35,32 +35,40 @@ const msa_logger_1 = __importStar(require("@yolo-croket-dev/msa-logger"));
35
35
  const msaLogger = new msa_logger_1.default(msa_logger_1.ServerTypeEnum.SERVICE);
36
36
  let GracefulShutdownService = class GracefulShutdownService {
37
37
  constructor() {
38
- this.activeInterceptors = 0;
38
+ this.activeInterceptors = [];
39
39
  this.isApplicationExit = false;
40
40
  }
41
41
  onApplicationBootstrap() {
42
- msaLogger.debug('GracefulShutdownService.onApplicationBootstrap', { traceId: 'ON_APPLICATION_BOOTSTRAP' });
43
- this.activeInterceptors = 0;
42
+ this.activeInterceptors = [];
44
43
  }
45
- incActiveInterceptors() {
46
- this.activeInterceptors += 1;
47
- msaLogger.debug(`GracefulShutdownService.incActiveInterceptors: ${this.activeInterceptors}`, { traceId: 'INC_ACTIVE_INTERCEPTORS' });
44
+ pushActiveInterceptors(execInterceptor) {
45
+ this.activeInterceptors.push(execInterceptor);
48
46
  }
49
- decActiveInterceptors() {
50
- this.activeInterceptors -= 1;
51
- msaLogger.debug(`GracefulShutdownService.decActiveInterceptors: ${this.activeInterceptors}`, { traceId: 'DEC_ACTIVE_INTERCEPTORS' });
47
+ popActiveInterceptors(execInterceptor) {
48
+ // eslint-disable-next-line max-len
49
+ this.activeInterceptors = this.activeInterceptors.filter((item) => item.method === execInterceptor.method && item.traceId === execInterceptor.traceId);
52
50
  }
53
51
  async onApplicationShutdown(signal) {
52
+ console.debug(`GracefulShutdownService.onApplicationShutdown signal=${signal}`, { traceId: 'ON_APPLICATION_SHUTDOWN' });
54
53
  msaLogger.debug(`GracefulShutdownService.onApplicationShutdown signal=${signal}`, { traceId: 'ON_APPLICATION_SHUTDOWN' });
55
54
  process.exit(0);
56
55
  }
57
56
  async onModuleDestroy() {
58
57
  this.isApplicationExit = true;
59
58
  msaLogger.debug('GracefulShutdownService.onModuleDestroy', { traceId: 'ON_MODULE_DESTROY' });
60
- msaLogger.debug(`GracefulShutdownService.onModuleDestroy: activeInterceptors=${this.activeInterceptors}`, { traceId: 'ON_MODULE_DESTROY' });
61
- while (this.activeInterceptors > 0) {
62
- // eslint-disable-next-line max-len
63
- msaLogger.debug(`GracefulShutdownService.onModuleDestroy: waiting for ${this.activeInterceptors} interceptors to finish`, { traceId: 'ON_MODULE_DESTROY' });
59
+ // eslint-disable-next-line max-len
60
+ msaLogger.debug('GracefulShutdownService.onModuleDestroy activeInterceptors', { traceId: 'ON_MODULE_DESTROY' }, { activeInterceptors: this.activeInterceptors });
61
+ // eslint-disable-next-line max-len
62
+ console.debug('GracefulShutdownService.onModuleDestroy activeInterceptors', { traceId: 'ON_MODULE_DESTROY' }, { activeInterceptors: this.activeInterceptors });
63
+ let prevExecInterceptorCount = 0;
64
+ while (this.activeInterceptors.length) {
65
+ if (prevExecInterceptorCount !== this.activeInterceptors.length) {
66
+ prevExecInterceptorCount = this.activeInterceptors.length;
67
+ // eslint-disable-next-line max-len
68
+ console.log(`GracefulShutdownService.onModuleDestroy: waiting for ${this.activeInterceptors} interceptors to finish`, { traceId: 'ON_MODULE_DESTROY' }, { activeInterceptors: this.activeInterceptors });
69
+ // eslint-disable-next-line max-len
70
+ msaLogger.debug(`GracefulShutdownService.onModuleDestroy: waiting for ${this.activeInterceptors} interceptors to finish`, { traceId: 'ON_MODULE_DESTROY' }, { activeInterceptors: this.activeInterceptors });
71
+ }
64
72
  await new Promise((resolve) => {
65
73
  setTimeout(resolve, 1000);
66
74
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolo-croket-dev/core",
3
- "version": "1.4.53-slowquery.6",
3
+ "version": "1.4.53-slowquery.8",
4
4
  "author": "Yolo Co., Ltd.",
5
5
  "description": "Yolo commonization module",
6
6
  "main": "index.js",