mega-framework 0.1.7 → 0.1.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.
- package/README.md +9 -0
- package/package.json +3 -3
- package/sample/crud/.env +9 -0
- package/sample/crud/.env.example +9 -0
- package/sample/crud/apps/main/locales/server/en.json +12 -1
- package/sample/crud/apps/main/locales/server/ko.json +12 -1
- package/sample/crud/mega.config.js +7 -0
- package/sample/crud/package.json +2 -2
- package/sample/crud/scripts/start-ws-hub.sh +18 -4
- package/sample/simple/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/src/adapters/adapter-options.js +14 -3
- package/src/adapters/file-adapter.js +9 -5
- package/src/adapters/file-session-adapter.js +4 -3
- package/src/adapters/maria-adapter.js +7 -4
- package/src/adapters/mega-cache-adapter.js +83 -6
- package/src/adapters/mega-db-adapter.js +4 -1
- package/src/adapters/mongo-adapter.js +21 -7
- package/src/adapters/postgres-adapter.js +8 -4
- package/src/adapters/redis-adapter.js +7 -3
- package/src/adapters/sqlite-adapter.js +6 -2
- package/src/cli/commands/console-cmd.js +3 -1
- package/src/cli/commands/scaffold.js +38 -2
- package/src/cli/generators/index.js +58 -1
- package/src/cli/index.js +88 -59
- package/src/cli/watch.js +188 -0
- package/src/core/ajv-mapper.js +3 -1
- package/src/core/ctx-builder.js +59 -1
- package/src/core/envelope.js +9 -2
- package/src/core/hub-link.js +24 -14
- package/src/core/index.js +1 -1
- package/src/core/mega-app.js +55 -45
- package/src/core/pipeline.js +8 -6
- package/src/core/scope-registry.js +1 -0
- package/src/core/security.js +3 -3
- package/src/core/session-store.js +14 -1
- package/src/core/ws-presence.js +17 -5
- package/src/core/ws-roster.js +49 -10
- package/src/core/ws-upgrade.js +105 -0
- package/src/lib/mega-circuit-breaker.js +5 -3
- package/src/lib/mega-health.js +10 -0
- package/src/lib/mega-job-queue.js +53 -13
- package/src/lib/mega-job.js +8 -1
- package/src/lib/mega-metrics.js +28 -1
- package/src/lib/mega-plugin.js +2 -2
- package/src/lib/mega-worker.js +28 -5
- package/src/lib/ws-hub.js +90 -9
- package/templates/adr/code.tpl +23 -0
- package/types/adapters/adapter-options.d.ts +2 -0
- package/types/adapters/file-adapter.d.ts +12 -1
- package/types/adapters/file-session-adapter.d.ts +4 -2
- package/types/adapters/maria-adapter.d.ts +5 -3
- package/types/adapters/mega-cache-adapter.d.ts +27 -1
- package/types/adapters/mega-db-adapter.d.ts +4 -1
- package/types/adapters/mongo-adapter.d.ts +13 -2
- package/types/adapters/postgres-adapter.d.ts +4 -2
- package/types/adapters/redis-adapter.d.ts +8 -0
- package/types/adapters/sqlite-adapter.d.ts +8 -2
- package/types/cli/generators/index.d.ts +11 -1
- package/types/cli/index.d.ts +12 -27
- package/types/cli/watch.d.ts +59 -0
- package/types/core/ctx-builder.d.ts +23 -0
- package/types/core/hub-link.d.ts +3 -1
- package/types/core/index.d.ts +1 -1
- package/types/core/mega-app.d.ts +1 -1
- package/types/core/pipeline.d.ts +2 -1
- package/types/core/security.d.ts +3 -3
- package/types/core/session-store.d.ts +7 -0
- package/types/core/ws-roster.d.ts +13 -1
- package/types/core/ws-upgrade.d.ts +29 -0
- package/types/lib/mega-circuit-breaker.d.ts +4 -2
- package/types/lib/mega-health.d.ts +7 -0
- package/types/lib/mega-job-queue.d.ts +16 -4
- package/types/lib/mega-job.d.ts +8 -1
- package/types/lib/mega-plugin.d.ts +1 -1
- package/types/lib/mega-worker.d.ts +3 -1
- package/types/lib/ws-hub.d.ts +27 -2
|
@@ -65,6 +65,8 @@ export function normalizePool(pool: unknown, spec: Record<string, {
|
|
|
65
65
|
key: string;
|
|
66
66
|
divideBy?: number;
|
|
67
67
|
} | null>, driver: string): Record<string, number>;
|
|
68
|
+
/** pool acquire 대기 한도 프레임워크 디폴트(ms) — 명시 0 으로 드라이버 무한 대기 옵트인(ADR-216). */
|
|
69
|
+
export const DEFAULT_ACQUIRE_TIMEOUT_MS: 10000;
|
|
68
70
|
/**
|
|
69
71
|
* pg 풀 매핑 — 값이 null 이면 미지원(throw), `{ key, divideBy? }` 면 키 이름 변경(+단위 변환).
|
|
70
72
|
* @type {Record<string, { key: string, divideBy?: number } | null>}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @property {string} [basePath] - 캐시 파일 저장 디렉토리 (필수).
|
|
5
5
|
* @property {string} [dir] - `basePath` 의 별칭 (ADR-082 정합, 하위 호환).
|
|
6
6
|
* @property {{ serializer?: 'json' | 'raw', extension?: string }} [options]
|
|
7
|
+
* @property {string} [namespace] - 캐시 키 자동 prefix `mega:cache:<namespace>:` (ADR-064/213, 베이스 처리).
|
|
8
|
+
* @property {number} [defaultTtlSec] - `set` ttl 미지정 시 디폴트(초). 0 = 무한 옵트인. (ADR-216, 베이스 처리)
|
|
7
9
|
*/
|
|
8
10
|
/**
|
|
9
11
|
* @typedef {object} CacheEnvelope - 디스크에 저장되는 단일 파일 포맷.
|
|
@@ -14,7 +16,8 @@
|
|
|
14
16
|
*/
|
|
15
17
|
export class MegaFileAdapter extends MegaCacheAdapter {
|
|
16
18
|
/**
|
|
17
|
-
* @param {FileConfig} [config] - services.caches.<key> 설정.
|
|
19
|
+
* @param {FileConfig} [config] - services.caches.<key> 설정. 베이스(MegaCacheAdapter)의
|
|
20
|
+
* `namespace`(ADR-064 자동 prefix)/`defaultTtlSec`(ADR-216) 도 여기서 받는다.
|
|
18
21
|
* @throws {MegaValidationError} `adapter.basepath_required` - basePath/dir 누락.
|
|
19
22
|
* @throws {MegaValidationError} `adapter.invalid_option` - 옵션 타입/미지원 키 오류.
|
|
20
23
|
*/
|
|
@@ -69,6 +72,14 @@ export type FileConfig = {
|
|
|
69
72
|
serializer?: "json" | "raw";
|
|
70
73
|
extension?: string;
|
|
71
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* - 캐시 키 자동 prefix `mega:cache:<namespace>:` (ADR-064/213, 베이스 처리).
|
|
77
|
+
*/
|
|
78
|
+
namespace?: string;
|
|
79
|
+
/**
|
|
80
|
+
* - `set` ttl 미지정 시 디폴트(초). 0 = 무한 옵트인. (ADR-216, 베이스 처리)
|
|
81
|
+
*/
|
|
82
|
+
defaultTtlSec?: number;
|
|
72
83
|
};
|
|
73
84
|
/**
|
|
74
85
|
* - 디스크에 저장되는 단일 파일 포맷.
|
|
@@ -41,13 +41,15 @@ export class MegaFileSessionAdapter extends MegaSessionAdapter {
|
|
|
41
41
|
error?: string;
|
|
42
42
|
}>;
|
|
43
43
|
/**
|
|
44
|
-
* 누적 통계 + file 세션 특화.
|
|
45
|
-
*
|
|
44
|
+
* 누적 통계 + file 세션 특화. `cleanupIntervalMs` 노출(0=내부 타이머 off) — 만료 스캔 주기의
|
|
45
|
+
* 적용 여부를 운영/테스트가 확인하는 단일 창구(ADR-215).
|
|
46
|
+
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, basePath: string, ttlMs: number, cleanupIntervalMs: number }}
|
|
46
47
|
*/
|
|
47
48
|
getStats(): ReturnType<import("./mega-adapter.js").MegaAdapter["getStats"]> & {
|
|
48
49
|
driver: string;
|
|
49
50
|
basePath: string;
|
|
50
51
|
ttlMs: number;
|
|
52
|
+
cleanupIntervalMs: number;
|
|
51
53
|
};
|
|
52
54
|
#private;
|
|
53
55
|
}
|
|
@@ -27,15 +27,17 @@ export class MegaMariaAdapter extends MegaDbAdapter {
|
|
|
27
27
|
error?: string;
|
|
28
28
|
}>;
|
|
29
29
|
/**
|
|
30
|
-
* 누적 통계 + 풀 통계
|
|
31
|
-
*
|
|
30
|
+
* 누적 통계 + 풀 통계 — 공통 코어 키 `{ total, active, idle, waiting }` 은 4 driver 동일
|
|
31
|
+
* 형태(ADR-216 G2 H-2). `queue` 는 기존 소비자 하위 호환 별칭(= waiting). 연결 전이면 0.
|
|
32
|
+
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, pool: { total: number, active: number, idle: number, waiting: number, queue: number } }}
|
|
32
33
|
*/
|
|
33
34
|
getStats(): ReturnType<import("./mega-adapter.js").MegaAdapter["getStats"]> & {
|
|
34
35
|
driver: string;
|
|
35
36
|
pool: {
|
|
36
37
|
total: number;
|
|
37
|
-
idle: number;
|
|
38
38
|
active: number;
|
|
39
|
+
idle: number;
|
|
40
|
+
waiting: number;
|
|
39
41
|
queue: number;
|
|
40
42
|
};
|
|
41
43
|
};
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
export class MegaCacheAdapter extends MegaAdapter {
|
|
2
|
+
/**
|
|
3
|
+
* @param {{ namespace?: string, defaultTtlSec?: number } & Record<string, any>} [config]
|
|
4
|
+
* @throws {MegaValidationError} `adapter.invalid_option` - namespace/defaultTtlSec 형식 오류.
|
|
5
|
+
*/
|
|
6
|
+
constructor(config?: {
|
|
7
|
+
namespace?: string;
|
|
8
|
+
defaultTtlSec?: number;
|
|
9
|
+
} & Record<string, any>);
|
|
10
|
+
/**
|
|
11
|
+
* 네임스페이스 적용 키 — 구체 어댑터의 get/set/del/has 가 저장소 접근 직전에 경유한다(ADR-064).
|
|
12
|
+
* @protected
|
|
13
|
+
* @param {string} key
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
protected _cacheKey(key: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* `set` 의 유효 TTL 해석 — 명시 ttl 우선, 없으면 defaultTtlSec. 둘 다 없으면 무한 저장이며
|
|
19
|
+
* `defaultTtlSec: 0` 옵트인이 아닌 한 인스턴스당 1회 경고를 낸다(키 무한 증가 풋건 표면화 —
|
|
20
|
+
* 동작은 기존과 동일, ADR-216).
|
|
21
|
+
* @protected
|
|
22
|
+
* @param {number} [ttl] - 호출자가 명시한 ttl(초).
|
|
23
|
+
* @param {string} [key] - 경고 메시지용 예시 키.
|
|
24
|
+
* @returns {number | undefined} 적용할 ttl(초) — undefined 면 무한.
|
|
25
|
+
*/
|
|
26
|
+
protected _resolveTtl(ttl?: number, key?: string): number | undefined;
|
|
2
27
|
/**
|
|
3
28
|
* @param {string} _key
|
|
4
29
|
* @returns {Promise<any>} 값 — 없으면 `null` (throw X).
|
|
@@ -7,7 +32,7 @@ export class MegaCacheAdapter extends MegaAdapter {
|
|
|
7
32
|
/**
|
|
8
33
|
* @param {string} _key
|
|
9
34
|
* @param {any} _value
|
|
10
|
-
* @param {{ ttl?: number }} [_opts] - `ttl` 미지정 시 무한
|
|
35
|
+
* @param {{ ttl?: number }} [_opts] - `ttl` 미지정 시 defaultTtlSec, 그것도 없으면 무한(초 단위, ADR-216).
|
|
11
36
|
* @returns {Promise<void>}
|
|
12
37
|
*/
|
|
13
38
|
set(_key: string, _value: any, _opts?: {
|
|
@@ -43,5 +68,6 @@ export class MegaCacheAdapter extends MegaAdapter {
|
|
|
43
68
|
allowZero?: boolean;
|
|
44
69
|
allowInfinity?: boolean;
|
|
45
70
|
}): void;
|
|
71
|
+
#private;
|
|
46
72
|
}
|
|
47
73
|
import { MegaAdapter } from './mega-adapter.js';
|
|
@@ -4,7 +4,10 @@ export class MegaDbAdapter extends MegaAdapter {
|
|
|
4
4
|
* driver 별 구현 (postgres `BEGIN/COMMIT/ROLLBACK`, MongoDB `session.withTransaction`).
|
|
5
5
|
* nested 호출은 driver 별 (postgres SAVEPOINT, MongoDB throw `adapter.nested_transaction_unsupported`).
|
|
6
6
|
*
|
|
7
|
-
* `opts.isolation`(ADR-190) — SQL 격리수준 옵트인.
|
|
7
|
+
* `opts.isolation`(ADR-190) — SQL 격리수준 옵트인. **미지정이면 driver 디폴트가 적용되며 그
|
|
8
|
+
* 디폴트는 driver 마다 다르다**(ADR-216 G2 M-2): postgres = READ COMMITTED,
|
|
9
|
+
* mariadb(InnoDB) = REPEATABLE READ — 같은 `withTransaction(fn)` 코드가 driver 에 따라 다른
|
|
10
|
+
* 동시성 의미를 가진다. 이식성 있는 동시성 가정이 필요하면 isolation 을 명시할 것. driver 별 지원:
|
|
8
11
|
* postgres/maria 는 top-level 트랜잭션에 `SET TRANSACTION ISOLATION LEVEL` 로 반영(nested 엔 불가 —
|
|
9
12
|
* `adapter.nested_isolation_unsupported`), sqlite 는 항상 SERIALIZABLE 동작이라 'serializable' 만 수용,
|
|
10
13
|
* mongodb 는 SQL 격리수준 개념이 없어 지정 시 `adapter.invalid_option`.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @typedef {object} PoolCounters
|
|
10
10
|
* @property {number} created @property {number} closed
|
|
11
11
|
* @property {number} checkedOut @property {number} checkedIn
|
|
12
|
+
* @property {number} checkOutStarted @property {number} checkOutFailed
|
|
12
13
|
*/
|
|
13
14
|
export class MegaMongoAdapter extends MegaDbAdapter {
|
|
14
15
|
/**
|
|
@@ -41,13 +42,21 @@ export class MegaMongoAdapter extends MegaDbAdapter {
|
|
|
41
42
|
error?: string;
|
|
42
43
|
}>;
|
|
43
44
|
/**
|
|
44
|
-
* 누적 통계 + mongo 특화(driver/dbName + CMAP 풀 카운터).
|
|
45
|
-
*
|
|
45
|
+
* 누적 통계 + mongo 특화(driver/dbName + CMAP 풀 카운터). 공통 코어 키
|
|
46
|
+
* `{ total, active, idle, waiting }` 은 4 driver 동일 형태(ADR-216 G2 H-2 — CMAP 누적
|
|
47
|
+
* 카운터에서 파생: total=created-closed, active=checkedOut-checkedIn,
|
|
48
|
+
* waiting=checkOutStarted-(checkedOut+checkOutFailed)). 누적 원본도 유지(하위 호환).
|
|
49
|
+
* 연결 전이면 전부 0.
|
|
50
|
+
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, dbName: string, pool: { total: number, active: number, idle: number, waiting: number, created: number, closed: number, checkedOut: number, checkedIn: number, open: number, inUse: number } }}
|
|
46
51
|
*/
|
|
47
52
|
getStats(): ReturnType<import("./mega-adapter.js").MegaAdapter["getStats"]> & {
|
|
48
53
|
driver: string;
|
|
49
54
|
dbName: string;
|
|
50
55
|
pool: {
|
|
56
|
+
total: number;
|
|
57
|
+
active: number;
|
|
58
|
+
idle: number;
|
|
59
|
+
waiting: number;
|
|
51
60
|
created: number;
|
|
52
61
|
closed: number;
|
|
53
62
|
checkedOut: number;
|
|
@@ -135,5 +144,7 @@ export type PoolCounters = {
|
|
|
135
144
|
closed: number;
|
|
136
145
|
checkedOut: number;
|
|
137
146
|
checkedIn: number;
|
|
147
|
+
checkOutStarted: number;
|
|
148
|
+
checkOutFailed: number;
|
|
138
149
|
};
|
|
139
150
|
import { MegaDbAdapter } from './mega-db-adapter.js';
|
|
@@ -42,13 +42,15 @@ export class MegaPostgresAdapter extends MegaDbAdapter {
|
|
|
42
42
|
error?: string;
|
|
43
43
|
}>;
|
|
44
44
|
/**
|
|
45
|
-
* 누적 통계 + 풀 통계
|
|
46
|
-
*
|
|
45
|
+
* 누적 통계 + 풀 통계 — 공통 코어 키 `{ total, active, idle, waiting }` 은 4 driver 동일
|
|
46
|
+
* 형태(ADR-216 G2 H-2: 운영 대시보드가 driver 무관 코드로 "풀 포화" 를 묻게). 연결 전이면 0.
|
|
47
|
+
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, pool: { total: number, active: number, idle: number, waiting: number } }}
|
|
47
48
|
*/
|
|
48
49
|
getStats(): ReturnType<import("./mega-adapter.js").MegaAdapter["getStats"]> & {
|
|
49
50
|
driver: string;
|
|
50
51
|
pool: {
|
|
51
52
|
total: number;
|
|
53
|
+
active: number;
|
|
52
54
|
idle: number;
|
|
53
55
|
waiting: number;
|
|
54
56
|
};
|
|
@@ -62,6 +62,14 @@ export type RedisConfig = {
|
|
|
62
62
|
* - 미지원 — 지정 시 `adapter.invalid_option` throw (Redis 는 풀 모델 아님, ADR-110).
|
|
63
63
|
*/
|
|
64
64
|
pool?: any;
|
|
65
|
+
/**
|
|
66
|
+
* - 캐시 키 자동 prefix `mega:cache:<namespace>:` (ADR-064/213 — 멀티앱 충돌 차단, 옵트인).
|
|
67
|
+
*/
|
|
68
|
+
namespace?: string;
|
|
69
|
+
/**
|
|
70
|
+
* - `set` 의 ttl 미지정 시 적용할 디폴트(초). 0 = 무한 저장 옵트인(경고 억제). (ADR-216)
|
|
71
|
+
*/
|
|
72
|
+
defaultTtlSec?: number;
|
|
65
73
|
/**
|
|
66
74
|
* - ioredis passthrough (keyPrefix, commandTimeout, tls, retryStrategy, keepAlive, …).
|
|
67
75
|
*/
|
|
@@ -37,8 +37,8 @@ export class MegaSqliteAdapter extends MegaDbAdapter {
|
|
|
37
37
|
error?: string;
|
|
38
38
|
}>;
|
|
39
39
|
/**
|
|
40
|
-
* 누적 통계 + sqlite 특화
|
|
41
|
-
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, filename: string, inMemory: boolean, readonly: boolean, journalMode: string | undefined }}
|
|
40
|
+
* 누적 통계 + sqlite 특화 필드 + 공통 풀 코어 키(합성 — 단일 연결, ADR-216).
|
|
41
|
+
* @returns {ReturnType<import('./mega-adapter.js').MegaAdapter['getStats']> & { driver: string, filename: string, inMemory: boolean, readonly: boolean, journalMode: string | undefined, pool: { total: number, active: number, idle: number, waiting: number } }}
|
|
42
42
|
*/
|
|
43
43
|
getStats(): ReturnType<import("./mega-adapter.js").MegaAdapter["getStats"]> & {
|
|
44
44
|
driver: string;
|
|
@@ -46,6 +46,12 @@ export class MegaSqliteAdapter extends MegaDbAdapter {
|
|
|
46
46
|
inMemory: boolean;
|
|
47
47
|
readonly: boolean;
|
|
48
48
|
journalMode: string | undefined;
|
|
49
|
+
pool: {
|
|
50
|
+
total: number;
|
|
51
|
+
active: number;
|
|
52
|
+
idle: number;
|
|
53
|
+
waiting: number;
|
|
54
|
+
};
|
|
49
55
|
};
|
|
50
56
|
/**
|
|
51
57
|
* 명시적 트랜잭션 경계 (ADR-010, ADR-105). manual `BEGIN/COMMIT/ROLLBACK` 으로
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
* @returns {Artifact[]}
|
|
14
14
|
*/
|
|
15
15
|
export function planArtifacts(kind: string, rawName: string, opts: Record<string, any>, projectRoot: string): Artifact[];
|
|
16
|
+
/**
|
|
17
|
+
* 다음 ADR 번호를 해석한다 — `docs/adr/NNNN-*.md` 파일명 + 레거시 `docs/09` 헤딩(`### ADR-N:`) +
|
|
18
|
+
* 호출측이 모은 추가 번호(예: `git ls-tree origin/main` 의 원격 파일 — 병렬 task 충돌 회피)의
|
|
19
|
+
* 최댓값 + 1. 아무 ADR 도 없으면 1.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} projectRoot
|
|
22
|
+
* @param {number[]} [extraNumbers] - 로컬 밖에서 관측한 번호(원격 스캔 등).
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
export function nextAdrNumber(projectRoot: string, extraNumbers?: number[]): number;
|
|
16
26
|
/**
|
|
17
27
|
* 계획된 artifact 를 디스크에 쓴다. 이미 있으면 건너뛴다(force 면 덮어씀).
|
|
18
28
|
* @param {Artifact[]} artifacts
|
|
@@ -83,7 +93,7 @@ export function generate(kind: string, rawName: string, opts?: object, projectRo
|
|
|
83
93
|
skipped: string[];
|
|
84
94
|
};
|
|
85
95
|
/** 지원 generator 종류(roadmap §337 — 13종). */
|
|
86
|
-
export const GENERATOR_KINDS: readonly ["app", "controller", "channel", "service", "model", "middleware", "route", "schedule", "job", "worker", "locale", "adapter", "migration"];
|
|
96
|
+
export const GENERATOR_KINDS: readonly ["app", "controller", "channel", "service", "model", "middleware", "route", "schedule", "job", "worker", "locale", "adapter", "migration", "adr"];
|
|
87
97
|
/**
|
|
88
98
|
* 플러그인 scaffold manifest 의 토큰 계약(ADR-199) — `files[].path`/`files[].template` 의 `{{token}}`
|
|
89
99
|
* 에 쓸 수 있는 이름과 의미. 빌트인 generator 의 base 토큰과 동일 집합이라 템플릿 작성 관례가 하나다.
|
package/types/cli/index.d.ts
CHANGED
|
@@ -96,29 +96,16 @@ export function resolveDb(setting: string | boolean | undefined | null): string
|
|
|
96
96
|
*/
|
|
97
97
|
export function shouldReexecForWatch(flags: Record<string, string | boolean>, env: Record<string, string | undefined>): boolean;
|
|
98
98
|
/**
|
|
99
|
-
* `mega start --watch`
|
|
99
|
+
* `mega start --watch` supervisor 의 **자식 인자**를 빌드한다 (ADR-220, ADR-182 개정).
|
|
100
100
|
*
|
|
101
|
-
* - `--watch`
|
|
101
|
+
* - `--watch`/`--watch-ignore`(값 포함)는 부모(supervisor) 전용 — 자식 인자에서 제거한다
|
|
102
|
+
* (가드 env 와 이중 안전으로 무한재귀 방지).
|
|
102
103
|
* - **단일 프로세스 강제**(`--cluster 1`) — 멀티워커 watch 카오스 방지(기존 `--cluster` 값은 무시).
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
* @param {string[]} o.watchPaths - 감시할 절대경로(존재하는 것만).
|
|
109
|
-
* @param {string} o.selfPath - mega 진입 스크립트(`process.argv[1]`).
|
|
110
|
-
* @param {string} o.execPath - node 바이너리(`process.execPath`).
|
|
111
|
-
* @returns {{ command: string, args: string[] }}
|
|
112
|
-
*/
|
|
113
|
-
export function buildWatchCommand({ argv, watchPaths, selfPath, execPath }: {
|
|
114
|
-
argv: string[];
|
|
115
|
-
watchPaths: string[];
|
|
116
|
-
selfPath: string;
|
|
117
|
-
execPath: string;
|
|
118
|
-
}): {
|
|
119
|
-
command: string;
|
|
120
|
-
args: string[];
|
|
121
|
-
};
|
|
104
|
+
*
|
|
105
|
+
* @param {string[]} argv - 원본 mega argv(예: `['start','--watch','--port','3000']`).
|
|
106
|
+
* @returns {string[]} 자식 `mega` 인자(예: `['start','--port','3000','--cluster','1']`).
|
|
107
|
+
*/
|
|
108
|
+
export function buildWatchChildArgs(argv: string[]): string[];
|
|
122
109
|
/**
|
|
123
110
|
* `mega` CLI 진입점. 파싱 → 명령 분기. **이 함수는 process.exit 를 호출하지 않는다**(테스트 가능) —
|
|
124
111
|
* exit code 를 반환하고, bin 래퍼가 `process.exitCode` 로 반영한다.
|
|
@@ -178,24 +165,24 @@ export function collectRegistrations(global: Object, host: import("../lib/mega-p
|
|
|
178
165
|
* 등록 소스 = `config.jobs` + 플러그인 `mega.jobs.register` 분(`collectRegistrations`, ADR-123).
|
|
179
166
|
* @param {string} projectRoot
|
|
180
167
|
* @param {{ debug?: Function, info?: Function, warn?: Function }} [logger]
|
|
181
|
-
* @returns {Promise<MegaJobWorker>}
|
|
168
|
+
* @returns {Promise<import('../lib/mega-job-worker.js').MegaJobWorker>}
|
|
182
169
|
*/
|
|
183
170
|
export function runWorkerHost(projectRoot: string, logger?: {
|
|
184
171
|
debug?: Function;
|
|
185
172
|
info?: Function;
|
|
186
173
|
warn?: Function;
|
|
187
|
-
}): Promise<MegaJobWorker>;
|
|
174
|
+
}): Promise<import("../lib/mega-job-worker.js").MegaJobWorker>;
|
|
188
175
|
/**
|
|
189
176
|
* `mega scheduler` 호스트 골격 — config + 어댑터 connect + ctx + `MegaScheduler` 인스턴스 + graceful.
|
|
190
177
|
* @param {string} projectRoot
|
|
191
178
|
* @param {{ debug?: Function, info?: Function, warn?: Function }} [logger]
|
|
192
|
-
* @returns {Promise<MegaScheduler>}
|
|
179
|
+
* @returns {Promise<import('../lib/mega-schedule.js').MegaScheduler>}
|
|
193
180
|
*/
|
|
194
181
|
export function runSchedulerHost(projectRoot: string, logger?: {
|
|
195
182
|
debug?: Function;
|
|
196
183
|
info?: Function;
|
|
197
184
|
warn?: Function;
|
|
198
|
-
}): Promise<MegaScheduler>;
|
|
185
|
+
}): Promise<import("../lib/mega-schedule.js").MegaScheduler>;
|
|
199
186
|
/**
|
|
200
187
|
* 마이그레이션 대상 DB 어댑터 해석 — `services.databases` 의 globalKey 로 조회한다. `--db <key>` 미지정
|
|
201
188
|
* 시 유일 선언 db, 그게 아니면 `primary`, 둘 다 아니면(다중·미선언) fail-fast 로 명시를 요구한다.
|
|
@@ -245,5 +232,3 @@ export const BUILTIN_COMMANDS: Set<string>;
|
|
|
245
232
|
/** CLI 사용법 텍스트 — commander 자동 생성(ADR-195) + 플러그인 명령 안내. 명령·옵션 정의가 곧 도움말의
|
|
246
233
|
* 단일 정본이라 수기 USAGE 와의 드리프트가 없다. */
|
|
247
234
|
export const USAGE: string;
|
|
248
|
-
import { MegaJobWorker } from '../lib/mega-job-worker.js';
|
|
249
|
-
import { MegaScheduler } from '../lib/mega-schedule.js';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 미니 glob → RegExp. 지원: 더블스타+슬래시(0개 이상의 디렉토리), 더블스타(경로 전체), `*`(세그먼트
|
|
3
|
+
* 내), `?`(1글자). 그 외 문자는 리터럴(정규식 특수문자 escape). 매칭 대상은 루트 상대 POSIX 경로
|
|
4
|
+
* 전체(^…$). 패턴 예시는 스캐폴드 `.env` 의 `WATCH_IGNORE` 참조 — JS 블록 주석 안에는
|
|
5
|
+
* 더블스타+슬래시 시퀀스를 쓸 수 없어(주석 조기 종료) 여기 직접 못 적는다.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} pattern - glob 패턴(예 `.env.*`).
|
|
8
|
+
* @returns {RegExp}
|
|
9
|
+
*/
|
|
10
|
+
export function globToRegExp(pattern: string): RegExp;
|
|
11
|
+
/**
|
|
12
|
+
* ignore 패턴 합성 — config(`watch.ignore`) + CLI(`--watch-ignore a,b`). 숨은 디폴트 없음(모듈
|
|
13
|
+
* docstring 참조). 잘못된 모양은 fail-fast(silent 무시 금지).
|
|
14
|
+
*
|
|
15
|
+
* @param {{ ignore?: unknown }} [watchConfig] - mega.config.js 의 `watch`.
|
|
16
|
+
* @param {string | undefined} [cliIgnore] - `--watch-ignore` 값(콤마 구분).
|
|
17
|
+
* @returns {string[]}
|
|
18
|
+
* @throws {TypeError} config `watch.ignore` 가 문자열 배열이 아닐 때.
|
|
19
|
+
*/
|
|
20
|
+
export function mergeWatchIgnore(watchConfig?: {
|
|
21
|
+
ignore?: unknown;
|
|
22
|
+
}, cliIgnore?: string | undefined): string[];
|
|
23
|
+
/**
|
|
24
|
+
* 루트 상대 경로가 ignore 에 걸리는지 (Boolean — `is*`).
|
|
25
|
+
* @param {string} rel - 루트 상대 POSIX 경로(예 `apps/main/locales/ko.json`).
|
|
26
|
+
* @param {RegExp[]} regexps - {@link globToRegExp} 컴파일 결과.
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
export function isIgnoredPath(rel: string, regexps: RegExp[]): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* watch supervisor — 감시 경로의 변경(ignore 통과분)을 debounce 후 자식(`mega start`)을
|
|
32
|
+
* SIGTERM → respawn 한다. 자식이 스스로 죽으면(crash) 재시작하지 않고 다음 변경을 기다린다
|
|
33
|
+
* (crash-loop 방지 — nodemon 의 "app crashed - waiting for file changes" 와 동형).
|
|
34
|
+
*
|
|
35
|
+
* @param {object} o
|
|
36
|
+
* @param {string} o.projectRoot
|
|
37
|
+
* @param {string[]} o.watchPaths - 감시할 절대경로(존재하는 것만 — 호출측이 필터).
|
|
38
|
+
* @param {string[]} o.ignore - glob 패턴 목록.
|
|
39
|
+
* @param {() => import('node:child_process').ChildProcess} o.spawnChild - 자식 기동 팩토리(주입 — 테스트).
|
|
40
|
+
* @param {(msg: string) => void} o.out
|
|
41
|
+
* @param {number} [o.debounceMs=500] - 연속 변경 디바운스.
|
|
42
|
+
* @param {(dir: string, opts: object, cb: (event: string, filename: string | Buffer | null) => void) => { close(): void }} [o.watchFn] -
|
|
43
|
+
* fs.watch 주입(테스트). 기본 node:fs watch.
|
|
44
|
+
* @returns {Promise<number>} 부모(supervisor)의 exit code — SIGINT/SIGTERM 수신 시 자식 정리 후 0.
|
|
45
|
+
*/
|
|
46
|
+
export function startWatchSupervisor({ projectRoot, watchPaths, ignore, spawnChild, out, debounceMs, watchFn }: {
|
|
47
|
+
projectRoot: string;
|
|
48
|
+
watchPaths: string[];
|
|
49
|
+
ignore: string[];
|
|
50
|
+
spawnChild: () => import("node:child_process").ChildProcess;
|
|
51
|
+
out: (msg: string) => void;
|
|
52
|
+
debounceMs?: number;
|
|
53
|
+
watchFn?: (dir: string, opts: object, cb: (event: string, filename: string | Buffer | null) => void) => {
|
|
54
|
+
close(): void;
|
|
55
|
+
};
|
|
56
|
+
}): Promise<number>;
|
|
57
|
+
/** {@link startWatchSupervisor} 의 watchPaths 기본 집합 — 존재하는 것만.
|
|
58
|
+
* @param {string} projectRoot @returns {string[]} */
|
|
59
|
+
export function defaultWatchPaths(projectRoot: string): string[];
|
|
@@ -63,6 +63,29 @@ export function getHttpCtx({ app, req, reply }: {
|
|
|
63
63
|
req: import("fastify").FastifyRequest;
|
|
64
64
|
reply: import("fastify").FastifyReply;
|
|
65
65
|
}): Record<string, any>;
|
|
66
|
+
/**
|
|
67
|
+
* **lazy** HTTP ctx — 실제 ctx 빌드를 첫 속성 접근 시점까지 미루는 요청당 프록시 (G1 H-1, ADR-214).
|
|
68
|
+
*
|
|
69
|
+
* hot path 단일 최대 프레임워크 비용이 "핸들러가 ctx 를 안 써도 매 요청 무조건 buildHttpCtx"
|
|
70
|
+
* (1,615 B + ≈0.7 µs/req, CPU 2.3% — audit-G1 실측)였다. 이 프록시는 생성 비용이 객체 1개 수준이고,
|
|
71
|
+
* 핸들러·미들웨어가 ctx 의 속성을 **처음 만질 때만** {@link getHttpCtx} 로 실 ctx 를 만든다(이후 캐시).
|
|
72
|
+
*
|
|
73
|
+
* 호환성: canonical 시그니처 `(req, reply, ctx)` 는 그대로 — 모든 핸들러가 여전히 3번째 인자를 받고,
|
|
74
|
+
* 참조하는 순간부터는 기존과 동일한 실 ctx 표면(ADR-134 요청당 공유 포함)이다. 프록시 자체도 요청당
|
|
75
|
+
* 1개로 캐시되어 미들웨어와 핸들러가 **동일 객체**(`===`)를 받는다. 모든 트랩이 실 ctx 로 위임되므로
|
|
76
|
+
* `in`/spread/`Object.keys`/getter·setter(`ctx.user=`) 동작이 보존된다.
|
|
77
|
+
*
|
|
78
|
+
* @param {object} args
|
|
79
|
+
* @param {import('./mega-app.js').MegaApp | null} args.app
|
|
80
|
+
* @param {import('fastify').FastifyRequest} args.req
|
|
81
|
+
* @param {import('fastify').FastifyReply} args.reply
|
|
82
|
+
* @returns {Record<string, any>}
|
|
83
|
+
*/
|
|
84
|
+
export function getLazyHttpCtx({ app, req, reply }: {
|
|
85
|
+
app: import("./mega-app.js").MegaApp | null;
|
|
86
|
+
req: import("fastify").FastifyRequest;
|
|
87
|
+
reply: import("fastify").FastifyReply;
|
|
88
|
+
}): Record<string, any>;
|
|
66
89
|
/**
|
|
67
90
|
* - 앱의 `app.config.js` 별명 선언 (alias → globalKey).
|
|
68
91
|
*/
|
package/types/core/hub-link.d.ts
CHANGED
|
@@ -117,7 +117,9 @@ export class MegaHubLink {
|
|
|
117
117
|
/**
|
|
118
118
|
* hub 연결 + REGISTER 핸드셰이크. register_ok 수신 시 resolve.
|
|
119
119
|
*
|
|
120
|
-
*
|
|
120
|
+
* 초기 연결은 retry 유무와 무관하게 **단 1회** 시도한다. `retry` 옵션이 있으면 실패 시 백그라운드
|
|
121
|
+
* 재연결(지수 백오프)로 전환하고 reject 한다 — 성공 시 RECONNECTED, 소진 시 RECONNECT_FAILED emit.
|
|
122
|
+
* 호출부(boot)는 reject 를 warn 으로 받고 부팅을 계속한다(허브 다운이 부팅을 막지 않는 계약).
|
|
121
123
|
*
|
|
122
124
|
* @param {Object} [opts]
|
|
123
125
|
* @param {number} [opts.connectTimeoutMs] - register_ok 대기 한도 override(M4). **이 값은 인스턴스에
|
package/types/core/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { bootApp, buildBootContext } from "./boot.js";
|
|
|
14
14
|
export { wrapEnvelope, errorEnvelope, synthesizeEnvelopeResponseSchema, ENVELOPE_MARK } from "./envelope.js";
|
|
15
15
|
export { buildHttpPipeline, wrapPreHandler, composeTransform, composeAfter } from "./pipeline.js";
|
|
16
16
|
export { ajvErrorToValidationError, MAX_VALIDATION_DETAILS } from "./ajv-mapper.js";
|
|
17
|
-
export { buildHttpCtx, getHttpCtx, buildAdapterAccessors } from "./ctx-builder.js";
|
|
17
|
+
export { buildHttpCtx, getHttpCtx, getLazyHttpCtx, buildAdapterAccessors } from "./ctx-builder.js";
|
|
18
18
|
export { createWsMessage, validateWsMessage, parseWsMessage, generateMessageId, WS_MESSAGE_SCHEMA, WS_PROTOCOL_VERSION, WS_TYPE_PATTERN } from "./ws-message.js";
|
|
19
19
|
export { MegaWsConnection, driveWsConnection, createPlainCodec, createAspCodec, rejectUpgrade, CLOSE_CODE_DECRYPT_FAILED, CLOSE_CODE_INTERNAL_ERROR } from "./ws-upgrade.js";
|
|
20
20
|
export { buildPerMessageDeflate, checkCompressionConfig, COMPRESSION_DEFAULTS } from "./ws-compression.js";
|
package/types/core/mega-app.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export class MegaApp {
|
|
|
35
35
|
* @param {Object|false} [opts.helmet] - fastify-helmet 옵션 (보안 헤더). false=미등록, undefined=디폴트 ON
|
|
36
36
|
* (ADR-047/127). 라우트 옵션 오버라이드는 완전 교체(ADR-073).
|
|
37
37
|
* @param {Object|false} [opts.cors] - fastify-cors 옵션. false=미등록, undefined=origin:false(교차출처 거부, 안전 디폴트).
|
|
38
|
-
* @param {Object|false} [opts.rateLimit] - fastify-rate-limit 옵션. false=미등록, undefined=디폴트(IP당
|
|
38
|
+
* @param {Object|false} [opts.rateLimit] - fastify-rate-limit 옵션. false=미등록, undefined=디폴트(IP당 1000/min, ADR-048/197).
|
|
39
39
|
* 멀티 인스턴스 분산 카운팅은 `caches.rate` 별명(Redis), 미선언 시 in-memory 폴백.
|
|
40
40
|
* @param {Object|false} [opts.csrf] - fastify-csrf-protection 옵션. false=미등록, undefined=디폴트 ON.
|
|
41
41
|
* ADR-051: JSON 요청은 토큰 면제+Origin 검증, 폼 요청만 토큰 검증.
|
package/types/core/pipeline.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 미들웨어를 Fastify 가 async preHandler 로 인식하는 arity-2 래퍼로 감싸고, canonical ctx 를
|
|
3
3
|
* 3번째 인자로 주입한다 — 핸들러·글로벌 미들웨어와 동일한 `(req, reply, ctx)` 계약(ADR-134/184).
|
|
4
|
-
*
|
|
4
|
+
* ctx 는 **lazy 프록시**(ADR-214) — 미들웨어가 실제로 속성을 만질 때만 빌드되고, 요청당 캐싱이라
|
|
5
|
+
* 같은 요청의 모든 미들웨어·핸들러가 동일 ctx 객체를 공유한다.
|
|
5
6
|
*
|
|
6
7
|
* @param {Function} fn - `(req, reply, ctx?)` 미들웨어 (arity-2 도 하위 호환 — 3번째 인자 무시).
|
|
7
8
|
* @param {import('./mega-app.js').MegaApp | null} [app] - ctx 의 어댑터·서비스 접근자 출처(없으면 null).
|
package/types/core/security.d.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* @param {string[]} [opts.hosts] - 앱 도메인 목록(CSRF Origin 검증 allowlist, ADR-051).
|
|
22
22
|
* @param {Object|false} [opts.helmet] - fastify-helmet 옵션. false=미등록, undefined=디폴트 ON.
|
|
23
23
|
* @param {Object|false} [opts.cors] - fastify-cors 옵션. false=미등록, undefined=origin:false(교차출처 거부).
|
|
24
|
-
* @param {Object|false} [opts.rateLimit] - fastify-rate-limit 옵션. false=미등록, undefined=디폴트(
|
|
24
|
+
* @param {Object|false} [opts.rateLimit] - fastify-rate-limit 옵션. false=미등록, undefined=디폴트(1000/min, ADR-214).
|
|
25
25
|
* @param {Object|false} [opts.csrf] - fastify-csrf-protection 옵션. false=미등록, undefined=디폴트 ON.
|
|
26
26
|
* @param {{ masterSecret?: string, http?: { enabledPaths?: string[], driftMs?: number, headerSignal?: string, timestampHeader?: string, nonceCache?: any } }} [opts.asp] -
|
|
27
27
|
* ASP 설정. `masterSecret` + `http.enabledPaths`(비어있지 않음)가 둘 다 있을 때만 HTTP ASP 등록.
|
|
@@ -53,9 +53,9 @@ export function registerSecurityPlugins(fastify: import("fastify").FastifyInstan
|
|
|
53
53
|
warn?: Function;
|
|
54
54
|
};
|
|
55
55
|
}): SecuritySummary;
|
|
56
|
-
/** rate-limit 기본값 (
|
|
56
|
+
/** rate-limit 기본값 (IP 당 1000 req/min — ADR-048 의 100/min 은 평상 트래픽도 429 를 만드는 운영 함정이라 상향, ADR-214). 사용자 config 로 완전 교체(ADR-073). */
|
|
57
57
|
export const DEFAULT_RATE_LIMIT: Readonly<{
|
|
58
|
-
max:
|
|
58
|
+
max: 1000;
|
|
59
59
|
timeWindow: "1 minute";
|
|
60
60
|
}>;
|
|
61
61
|
/**
|
|
@@ -14,5 +14,12 @@ export function createSessionStore(storeConfig: {
|
|
|
14
14
|
}, defaults?: {
|
|
15
15
|
ttlMs?: number;
|
|
16
16
|
}): import("../adapters/mega-session-adapter.js").MegaSessionAdapter;
|
|
17
|
+
/**
|
|
18
|
+
* file driver 만료 스캔 cleanup 기본 주기(1시간, ms) — ADR-046 의 "file 모드 cleanup 자동" 약속 구현(ADR-215).
|
|
19
|
+
* 어댑터 자체 디폴트는 0(off)이라, 팩토리 경유 생성(=프레임워크 부팅 경로)에서만 기본 주기를 주입한다.
|
|
20
|
+
* 만료 파일의 lazy 삭제는 같은 sid 재접근 시에만 일어나므로, 주기 스캔이 없으면 미접근 만료 세션이
|
|
21
|
+
* 디스크에 무한 누적된다(G5 audit M-3). `cleanupIntervalMs: 0` 명시로 옵트아웃(외부 cron/scheduler 운용 시).
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_FILE_CLEANUP_INTERVAL_MS: 3600000;
|
|
17
24
|
/** 지원 세션 driver 목록(테스트·문서용). */
|
|
18
25
|
export const SESSION_STORE_DRIVERS: readonly string[];
|
|
@@ -57,6 +57,15 @@ export class MegaWsRedisRoster {
|
|
|
57
57
|
* @param {string} channel @param {string} sessionId @param {RosterMember} member @returns {Promise<void>}
|
|
58
58
|
*/
|
|
59
59
|
add(channel: string, sessionId: string, member: RosterMember): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* ioredis pipeline.exec() 결과(`[err, res][]`)에서 첫 명령 오류를 throw 한다 — pipeline 은 명령별
|
|
62
|
+
* 오류를 reject 가 아니라 결과 배열에 싣기 때문에, 묵히면 호출부의 기존 실패 처리(catch+warn)가
|
|
63
|
+
* 더는 동작하지 않는다(직렬 await 시절의 throw 계약 유지).
|
|
64
|
+
* @param {Array<[Error | null, any]> | null} results
|
|
65
|
+
* @returns {void}
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
private _throwFirstPipelineError;
|
|
60
69
|
/**
|
|
61
70
|
* 채널 roster 에서 멤버 제거(disconnect).
|
|
62
71
|
* @param {string} channel @param {string} sessionId @returns {Promise<void>}
|
|
@@ -78,7 +87,10 @@ export class MegaWsRedisRoster {
|
|
|
78
87
|
*/
|
|
79
88
|
startHeartbeat(): void;
|
|
80
89
|
/**
|
|
81
|
-
* 로컬 멤버
|
|
90
|
+
* 로컬 멤버 전체의 `expiresAt` 을 한 pipeline 으로 일괄 갱신. 직렬 add 루프(멤버당 2 RT)는 멤버
|
|
91
|
+
* 1,000 에 주기당 수백 ms — 갱신 지연이 TTL 윈도를 침식해 살아있는 세션이 lazy 만료될 수 있었다.
|
|
92
|
+
* pipeline 이면 단일 왕복 수준(실측 ~200×). 채널 키 PEXPIRE 는 채널당 1회만 싣는다.
|
|
93
|
+
* @returns {Promise<void>} @private
|
|
82
94
|
*/
|
|
83
95
|
private _refreshLocal;
|
|
84
96
|
/**
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 프로세스 합산 send budget 을 조정한다(ADR-215). 부팅/운영 튜닝 진입점.
|
|
3
|
+
* @param {{ maxTotalBufferedBytes?: number }} [opts] - 바이트 budget. `0` = 무제한(옵트아웃).
|
|
4
|
+
* @returns {{ maxTotalBufferedBytes: number }} 적용된 현재 값.
|
|
5
|
+
* @throws {TypeError} 음수/비숫자 — 설정 실수 fail-fast.
|
|
6
|
+
*/
|
|
7
|
+
export function configureWsSendBudget({ maxTotalBufferedBytes: max }?: {
|
|
8
|
+
maxTotalBufferedBytes?: number;
|
|
9
|
+
}): {
|
|
10
|
+
maxTotalBufferedBytes: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* 테스트 격리용 — budget 상태 초기화(추적 Set·스로틀·budget 디폴트 복원).
|
|
14
|
+
* @returns {void}
|
|
15
|
+
*/
|
|
16
|
+
export function _resetWsSendBudget(): void;
|
|
17
|
+
/** 테스트용 — 연결을 budget 추적에 등록. @param {MegaWsConnection} conn @returns {void} */
|
|
18
|
+
export function _trackWsSendBudget(conn: MegaWsConnection): void;
|
|
19
|
+
/** 테스트용 — 스로틀 우회 가능한 스윕 직접 호출. @param {number} [now] @returns {void} */
|
|
20
|
+
export function _sweepWsSendBudget(now?: number): void;
|
|
1
21
|
/**
|
|
2
22
|
* 라우트 opts 의 `heartbeatMs` 를 검증해 반환한다. 미지정 → 기본 30초, `0` = liveness 끔.
|
|
3
23
|
* 무효값(음수/비정수/비숫자)은 운영 실수 — 조용히 보정하지 않고 warn 로그 후 기본값을 쓴다
|
|
@@ -116,6 +136,15 @@ export const CLOSE_CODE_SLOW_CONSUMER: 1013;
|
|
|
116
136
|
export const CLOSE_CODE_REQUEUE: 4503;
|
|
117
137
|
/** send 버퍼(bufferedAmount) 기본 상한(바이트). 초과 = 소비자가 ack 를 못 따라옴 → 연결 종료(서버 OOM 방지). */
|
|
118
138
|
export const DEFAULT_MAX_BUFFERED_BYTES: number;
|
|
139
|
+
/**
|
|
140
|
+
* 프로세스 **합산** send 버퍼 기본 budget(바이트, ADR-215 — G5 audit M-6).
|
|
141
|
+
*
|
|
142
|
+
* per-conn 상한(위 16MiB)은 연결 1개의 OOM 방어일 뿐이라, 느린 소비자 N 개가 각자 cap 직전까지
|
|
143
|
+
* 쌓으면 합산은 무제한이었다(이론상 1,000개 × 16MiB = 16GB). 합산이 본 budget 을 넘으면 **가장 큰
|
|
144
|
+
* 송신 큐를 보유한 연결부터** 1013(slow consumer)으로 종료해 budget 아래로 회수한다.
|
|
145
|
+
* `configureWsSendBudget({ maxTotalBufferedBytes: 0 })` 으로 무제한 옵트아웃.
|
|
146
|
+
*/
|
|
147
|
+
export const DEFAULT_MAX_TOTAL_BUFFERED_BYTES: number;
|
|
119
148
|
/**
|
|
120
149
|
* 클라↔bridge ping/pong liveness 기본 주기(ms) — 30초. 주기마다 ping 을 보내고 직전 주기의 pong 이
|
|
121
150
|
* 없으면 half-open(상대 사망·네트워크 단절) 으로 보고 terminate 한다 — 좀비 연결이 OS TCP 타임아웃까지
|
|
@@ -182,8 +182,10 @@ export type MegaCircuitBreakerOptions = {
|
|
|
182
182
|
*/
|
|
183
183
|
rollingCountBuckets?: number;
|
|
184
184
|
/**
|
|
185
|
-
* - 이 횟수만큼 호출이 쌓이기 전엔 실패율이
|
|
186
|
-
* (표본
|
|
185
|
+
* - 롤링 윈도우에 이 횟수만큼 호출이 쌓이기 전엔 실패율이
|
|
186
|
+
* 높아도 open 안 함(표본 부족 조기 trip 방지). 0=비활성. ⚠️ opossum 정본값(0)과 다른 프레임워크
|
|
187
|
+
* 디폴트 — 0 이면 부팅 직후/저빈도 호출에서 **첫 실패 1건**이 실패율 100% 가 돼 즉시 30s 차단되는
|
|
188
|
+
* 풋건이라 5 로 올렸다. opossum 원 동작이 필요하면 명시적으로 0 을 지정.
|
|
187
189
|
*/
|
|
188
190
|
volumeThreshold?: number;
|
|
189
191
|
/**
|
|
@@ -12,6 +12,13 @@ export function register(name: string, fn: () => Promise<{
|
|
|
12
12
|
}, opts?: {
|
|
13
13
|
timeoutMs?: number;
|
|
14
14
|
}): void;
|
|
15
|
+
/**
|
|
16
|
+
* 등록된 체크 제거(이름 기준). 닫힌 자원(예: hub link)의 체크가 stale 클로저로 남지 않게
|
|
17
|
+
* 소유자가 register 와 짝맞춰 부른다.
|
|
18
|
+
* @param {string} name
|
|
19
|
+
* @returns {boolean} 제거됐으면 true(미등록 이름이면 false).
|
|
20
|
+
*/
|
|
21
|
+
export function unregister(name: string): boolean;
|
|
15
22
|
/**
|
|
16
23
|
* 모든 체크 실행 (병렬). 하나라도 false 면 전체 ok=false.
|
|
17
24
|
* @returns {Promise<{ ok: boolean, checks: Record<string, { ok: boolean, error?: string, [key: string]: any }> }>}
|