@yolo-croket-dev/core 1.7.43 → 1.7.44-slowquery.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.
@@ -16,6 +16,7 @@ export declare class AbortContext {
16
16
  requestId: string;
17
17
  } | null;
18
18
  static disable(): void;
19
+ static disableDeferred(): void;
19
20
  static endContext(context?: RequestContext): void;
20
21
  static updateContext(updatedData: Partial<RequestContext>): void;
21
22
  /**
@@ -35,6 +35,11 @@ class AbortContext {
35
35
  static disable() {
36
36
  this.asyncLocalStorage.disable();
37
37
  }
38
+ static disableDeferred() {
39
+ setTimeout(() => {
40
+ this.asyncLocalStorage.disable();
41
+ }, 0);
42
+ }
38
43
  // 컨텍스트 종료
39
44
  // eslint-disable-next-line consistent-return
40
45
  static endContext(context) {
@@ -1,7 +1,12 @@
1
1
  export declare class ContextPromisePatch {
2
2
  private static isPatched;
3
3
  private static originalPromise;
4
+ private static originalSetTimeout;
5
+ private static originalSetInterval;
6
+ private static originalClearTimeout;
7
+ private static originalClearInterval;
4
8
  static patch(): void;
5
9
  private static patchPromise;
10
+ private static patchTimeouts;
6
11
  static unpatch(): void;
7
12
  }
@@ -8,7 +8,12 @@ class ContextPromisePatch {
8
8
  return;
9
9
  }
10
10
  this.originalPromise = global.Promise;
11
+ this.originalSetTimeout = global.setTimeout;
12
+ this.originalSetInterval = global.setInterval;
13
+ this.originalClearTimeout = global.clearTimeout;
14
+ this.originalClearInterval = global.clearInterval;
11
15
  this.patchPromise();
16
+ this.patchTimeouts();
12
17
  this.isPatched = true;
13
18
  }
14
19
  static patchPromise() {
@@ -103,11 +108,126 @@ class ContextPromisePatch {
103
108
  return originalReject.call(global.Promise, reason);
104
109
  };
105
110
  }
111
+ static patchTimeouts() {
112
+ // 각 컨텍스트별로 활성 타이머를 추적
113
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
114
+ const activeTimers = new Map();
115
+ // setTimeout 패치
116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
+ global.setTimeout = (handler, timeout,
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ ...args
120
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
+ ) => {
122
+ const currentContext = abort_context_1.AbortContext.getCurrentContext();
123
+ if (!currentContext) {
124
+ // 원본 함수에 args 전달 (타입 안전하게)
125
+ if (args.length > 0) {
126
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
+ return this.originalSetTimeout(handler, timeout, ...args);
128
+ }
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ return this.originalSetTimeout(handler, timeout);
131
+ }
132
+ const abortSignal = currentContext.abortSignal;
133
+ const contextId = currentContext.requestId;
134
+ if (abortSignal.aborted) {
135
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
+ throw new Error(`REQUEST_ABORTED: setTimeout이 중단되었습니다 (${contextId})`);
137
+ }
138
+ const originalHandler = typeof handler === 'function' ? handler : undefined;
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
+ const wrappedHandler = () => {
141
+ // 타이머 실행 시점에 abort 여부 확인
142
+ if (abortSignal.aborted) {
143
+ return;
144
+ }
145
+ if (originalHandler) {
146
+ originalHandler();
147
+ }
148
+ };
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ const timeoutId = this.originalSetTimeout(wrappedHandler, timeout);
151
+ activeTimers.set(timeoutId, {
152
+ contextId,
153
+ abortSignal,
154
+ });
155
+ const onAbort = () => {
156
+ this.originalClearTimeout(timeoutId);
157
+ activeTimers.delete(timeoutId);
158
+ };
159
+ abortSignal.addEventListener('abort', onAbort, { once: true });
160
+ return timeoutId;
161
+ };
162
+ // setInterval 패치
163
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
+ global.setInterval = (handler, timeout,
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ ...args
167
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
+ ) => {
169
+ const currentContext = abort_context_1.AbortContext.getCurrentContext();
170
+ if (!currentContext) {
171
+ // 원본 함수에 args 전달 (타입 안전하게)
172
+ if (args.length > 0) {
173
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
174
+ return this.originalSetInterval(handler, timeout, ...args);
175
+ }
176
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
+ return this.originalSetInterval(handler, timeout);
178
+ }
179
+ const abortSignal = currentContext.abortSignal;
180
+ const contextId = currentContext.requestId;
181
+ if (abortSignal.aborted) {
182
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
+ throw new Error(`REQUEST_ABORTED: setInterval이 중단되었습니다 (${contextId})`);
184
+ }
185
+ const originalHandler = typeof handler === 'function' ? handler : undefined;
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ const wrappedHandler = () => {
188
+ // 타이머 실행 시점에 abort 여부 확인
189
+ if (abortSignal.aborted) {
190
+ return;
191
+ }
192
+ if (originalHandler) {
193
+ originalHandler();
194
+ }
195
+ };
196
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
197
+ const intervalId = this.originalSetInterval(wrappedHandler, timeout);
198
+ activeTimers.set(intervalId, {
199
+ contextId,
200
+ abortSignal,
201
+ });
202
+ const onAbort = () => {
203
+ this.originalClearInterval(intervalId);
204
+ activeTimers.delete(intervalId);
205
+ };
206
+ abortSignal.addEventListener('abort', onAbort, { once: true });
207
+ return intervalId;
208
+ };
209
+ // clearTimeout 패치
210
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
211
+ global.clearTimeout = (timerId) => {
212
+ activeTimers.delete(timerId);
213
+ this.originalClearTimeout(timerId);
214
+ };
215
+ // clearInterval 패치
216
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
217
+ global.clearInterval = (timerId) => {
218
+ activeTimers.delete(timerId);
219
+ this.originalClearInterval(timerId);
220
+ };
221
+ }
106
222
  static unpatch() {
107
223
  if (!this.isPatched) {
108
224
  return;
109
225
  }
110
226
  global.Promise = this.originalPromise;
227
+ global.setTimeout = this.originalSetTimeout;
228
+ global.setInterval = this.originalSetInterval;
229
+ global.clearTimeout = this.originalClearTimeout;
230
+ global.clearInterval = this.originalClearInterval;
111
231
  this.isPatched = false;
112
232
  }
113
233
  }
@@ -57,6 +57,7 @@ let RPCInterceptor = class RPCInterceptor {
57
57
  this.gracefulShutdownService = gracefulShutdownService;
58
58
  this.DEFAULT_TIMEOUT = 1000 * 60 * 29; // 29분 타임아웃
59
59
  this.DEFAULT_TIMEOUT_MESSAGE = '요청이 타임아웃되었습니다.';
60
+ context_promise_patch_1.ContextPromisePatch.patch();
60
61
  }
61
62
  maxLengthOverShorten(data) {
62
63
  if (typeof data !== 'string') {
@@ -169,7 +170,6 @@ let RPCInterceptor = class RPCInterceptor {
169
170
  correlationId,
170
171
  isMessageAck: false,
171
172
  };
172
- context_promise_patch_1.ContextPromisePatch.patch();
173
173
  let abortController = new AbortController();
174
174
  /** consume 메시지 전부 cancel */
175
175
  if (this.gracefulShutdownService.isApplicationExit) {
@@ -357,7 +357,7 @@ let RPCInterceptor = class RPCInterceptor {
357
357
  error: localErrorProcessor,
358
358
  }), (0, operators_1.finalize)(() => {
359
359
  this.gracefulShutdownService.popActiveInterceptors(execInterceptor);
360
- functions_1.AbortContext.disable();
360
+ functions_1.AbortContext.disableDeferred();
361
361
  abortController = null;
362
362
  return rxjs_1.EMPTY;
363
363
  })));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolo-croket-dev/core",
3
- "version": "1.7.43",
3
+ "version": "1.7.44-slowquery.1",
4
4
  "author": "Yolo Co., Ltd.",
5
5
  "description": "Yolo commonization module",
6
6
  "main": "index.js",