@lakutata/nats 2.3.0 → 3.0.0-beta.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.
Files changed (121) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +288 -25
  3. package/dist/cjs/codecs/JSONCodec.d.ts +32 -0
  4. package/dist/cjs/codecs/JSONCodec.js +44 -0
  5. package/dist/cjs/codecs/MessagePackCodec.d.ts +22 -0
  6. package/dist/cjs/codecs/MessagePackCodec.js +35 -0
  7. package/dist/cjs/components/NATS.d.ts +376 -0
  8. package/dist/cjs/components/NATS.js +772 -0
  9. package/dist/cjs/entrypoints/NatsServiceEntrypoint.d.ts +102 -0
  10. package/dist/cjs/entrypoints/NatsServiceEntrypoint.js +127 -0
  11. package/dist/cjs/exceptions/NatsBadRequestException.d.ts +11 -0
  12. package/dist/cjs/exceptions/NatsBadRequestException.js +18 -0
  13. package/dist/cjs/exceptions/NatsBulkException.d.ts +19 -0
  14. package/dist/cjs/exceptions/NatsBulkException.js +26 -0
  15. package/dist/cjs/exceptions/NatsForbiddenException.d.ts +11 -0
  16. package/dist/cjs/exceptions/NatsForbiddenException.js +18 -0
  17. package/dist/cjs/exceptions/NatsInternalServerException.d.ts +12 -0
  18. package/dist/cjs/exceptions/NatsInternalServerException.js +19 -0
  19. package/dist/cjs/exceptions/NatsNoRespondersAvailableException.d.ts +12 -0
  20. package/dist/cjs/exceptions/NatsNoRespondersAvailableException.js +19 -0
  21. package/dist/cjs/exceptions/NatsNotFoundException.d.ts +11 -0
  22. package/dist/cjs/exceptions/NatsNotFoundException.js +18 -0
  23. package/dist/cjs/exceptions/NatsRequestTimeoutException.d.ts +11 -0
  24. package/dist/cjs/exceptions/NatsRequestTimeoutException.js +18 -0
  25. package/dist/cjs/exports/Nats.d.ts +18 -0
  26. package/dist/cjs/exports/Nats.js +39 -0
  27. package/dist/cjs/interfaces/NatsClientOptions.d.ts +106 -0
  28. package/dist/{lib → cjs/lib}/ServiceEventCodec.d.ts +0 -1
  29. package/dist/{lib → cjs/lib}/ServiceEventCodec.js +19 -9
  30. package/dist/cjs/package.json +1 -0
  31. package/dist/cjs/providers/ServiceProxy.d.ts +210 -0
  32. package/dist/cjs/providers/ServiceProxy.js +274 -0
  33. package/dist/cjs/types/SubscribeOptions.d.ts +33 -0
  34. package/dist/esm/codecs/JSONCodec.js +41 -0
  35. package/dist/esm/codecs/MessagePackCodec.js +32 -0
  36. package/dist/esm/components/NATS.js +767 -0
  37. package/dist/esm/entrypoints/NatsServiceEntrypoint.js +123 -0
  38. package/dist/esm/exceptions/NatsBadRequestException.js +14 -0
  39. package/dist/esm/exceptions/NatsBulkException.js +22 -0
  40. package/dist/esm/exceptions/NatsForbiddenException.js +14 -0
  41. package/dist/esm/exceptions/NatsInternalServerException.js +15 -0
  42. package/dist/esm/exceptions/NatsNoRespondersAvailableException.js +15 -0
  43. package/dist/esm/exceptions/NatsNotFoundException.js +14 -0
  44. package/dist/esm/exceptions/NatsRequestTimeoutException.js +14 -0
  45. package/dist/esm/exports/Nats.js +15 -0
  46. package/dist/esm/interfaces/NatsClientOptions.js +1 -0
  47. package/dist/esm/lib/ServiceEventCodec.js +21 -0
  48. package/dist/esm/providers/ServiceProxy.js +270 -0
  49. package/dist/esm/types/SubscribeOptions.js +1 -0
  50. package/dist/types/codecs/JSONCodec.d.ts +32 -0
  51. package/dist/types/codecs/MessagePackCodec.d.ts +22 -0
  52. package/dist/types/components/NATS.d.ts +376 -0
  53. package/dist/types/entrypoints/NatsServiceEntrypoint.d.ts +102 -0
  54. package/dist/types/exceptions/NatsBadRequestException.d.ts +11 -0
  55. package/dist/types/exceptions/NatsBulkException.d.ts +19 -0
  56. package/dist/types/exceptions/NatsForbiddenException.d.ts +11 -0
  57. package/dist/types/exceptions/NatsInternalServerException.d.ts +12 -0
  58. package/dist/types/exceptions/NatsNoRespondersAvailableException.d.ts +12 -0
  59. package/dist/types/exceptions/NatsNotFoundException.d.ts +11 -0
  60. package/dist/types/exceptions/NatsRequestTimeoutException.d.ts +11 -0
  61. package/dist/types/exports/Nats.d.ts +18 -0
  62. package/dist/types/interfaces/NatsClientOptions.d.ts +106 -0
  63. package/dist/types/lib/ServiceEventCodec.d.ts +9 -0
  64. package/dist/types/providers/ServiceProxy.d.ts +210 -0
  65. package/dist/types/types/SubscribeOptions.d.ts +33 -0
  66. package/package.json +42 -33
  67. package/CHANGELOG.md +0 -288
  68. package/dist/CommonExports.d.ts +0 -19
  69. package/dist/CommonExports.d.ts.map +0 -1
  70. package/dist/CommonExports.js +0 -35
  71. package/dist/codecs/JSONCodec.d.ts +0 -3
  72. package/dist/codecs/JSONCodec.d.ts.map +0 -1
  73. package/dist/codecs/JSONCodec.js +0 -15
  74. package/dist/codecs/MessagePackCodec.d.ts +0 -3
  75. package/dist/codecs/MessagePackCodec.d.ts.map +0 -1
  76. package/dist/codecs/MessagePackCodec.js +0 -16
  77. package/dist/components/NATS.d.ts +0 -252
  78. package/dist/components/NATS.d.ts.map +0 -1
  79. package/dist/components/NATS.js +0 -564
  80. package/dist/entrypoints/SetupNatsServiceEntrypoint.d.ts +0 -8
  81. package/dist/entrypoints/SetupNatsServiceEntrypoint.d.ts.map +0 -1
  82. package/dist/entrypoints/SetupNatsServiceEntrypoint.js +0 -41
  83. package/dist/exceptions/NatsBadRequestException.d.ts +0 -7
  84. package/dist/exceptions/NatsBadRequestException.d.ts.map +0 -1
  85. package/dist/exceptions/NatsBadRequestException.js +0 -13
  86. package/dist/exceptions/NatsBulkException.d.ts +0 -11
  87. package/dist/exceptions/NatsBulkException.d.ts.map +0 -1
  88. package/dist/exceptions/NatsBulkException.js +0 -17
  89. package/dist/exceptions/NatsForbiddenException.d.ts +0 -7
  90. package/dist/exceptions/NatsForbiddenException.d.ts.map +0 -1
  91. package/dist/exceptions/NatsForbiddenException.js +0 -13
  92. package/dist/exceptions/NatsInternalServerException.d.ts +0 -7
  93. package/dist/exceptions/NatsInternalServerException.d.ts.map +0 -1
  94. package/dist/exceptions/NatsInternalServerException.js +0 -13
  95. package/dist/exceptions/NatsNoRespondersAvailableException.d.ts +0 -7
  96. package/dist/exceptions/NatsNoRespondersAvailableException.d.ts.map +0 -1
  97. package/dist/exceptions/NatsNoRespondersAvailableException.js +0 -13
  98. package/dist/exceptions/NatsNotFoundException.d.ts +0 -7
  99. package/dist/exceptions/NatsNotFoundException.d.ts.map +0 -1
  100. package/dist/exceptions/NatsNotFoundException.js +0 -13
  101. package/dist/exceptions/NatsRequestTimeoutException.d.ts +0 -7
  102. package/dist/exceptions/NatsRequestTimeoutException.d.ts.map +0 -1
  103. package/dist/exceptions/NatsRequestTimeoutException.js +0 -13
  104. package/dist/exceptions/ServiceInvokeException.d.ts +0 -6
  105. package/dist/exceptions/ServiceInvokeException.d.ts.map +0 -1
  106. package/dist/exceptions/ServiceInvokeException.js +0 -11
  107. package/dist/interfaces/NatsClientOptions.d.ts +0 -26
  108. package/dist/interfaces/NatsClientOptions.d.ts.map +0 -1
  109. package/dist/lib/ServiceEventCodec.d.ts.map +0 -1
  110. package/dist/lib/ServiceResponseCodec.d.ts +0 -22
  111. package/dist/lib/ServiceResponseCodec.d.ts.map +0 -1
  112. package/dist/lib/ServiceResponseCodec.js +0 -50
  113. package/dist/providers/ServiceProxy.d.ts +0 -85
  114. package/dist/providers/ServiceProxy.d.ts.map +0 -1
  115. package/dist/providers/ServiceProxy.js +0 -124
  116. package/dist/types/SubscribeOptions.d.ts +0 -12
  117. package/dist/types/SubscribeOptions.d.ts.map +0 -1
  118. package/docs/large-payload-design.md +0 -199
  119. package/tsconfig.json +0 -8
  120. /package/dist/{interfaces → cjs/interfaces}/NatsClientOptions.js +0 -0
  121. /package/dist/{types → cjs/types}/SubscribeOptions.js +0 -0
@@ -1,199 +0,0 @@
1
- # 大消息传输方案设计(@lakutata/nats)
2
-
3
- > 状态:**架构已定,工程细节待敲定**(见末尾 checklist)。
4
- > 本文档是多轮设计讨论的沉淀,目标是让后续实现不必重推已排除的弯路。
5
-
6
- ## 1. 背景与硬约束
7
-
8
- 这个包用于 K8s 集群中、跨语言服务之间的 RPC 通讯(core NATS request-reply + pub/sub)。
9
- 现实中存在大 payload(查大表、读文件等,8M+)。设计必须同时满足:
10
-
11
- | 约束 | 说明 |
12
- |---|---|
13
- | **业务 API 不变** | 业务两端保持 `invoke(pattern)→完整对象`、`@ServiceAction return 完整对象`、`publish/subscribe`。中间件断面只在传输+调用层。 |
14
- | **跨语言** | 有非 JS 服务,必须保证标准 JSON 子集语义(原生 codec 的 `JSON.parse(JSON.stringify())` 清洗必须保留,不能用 msgpack 富类型)。 |
15
- | **不能 break 已上线服务** | 滚动升级新旧共存,必须向后兼容(能力协商 + 退化)。 |
16
- | **不重复响应** | 多副本下一个请求只能一个副本处理(已由 queue group 保证)。 |
17
-
18
- ## 2. 两个阻塞机制(问题根源)
19
-
20
- | 机制 | 现象 | 本质 | 能否消除 |
21
- |---|---|---|---|
22
- | **机制1:TCP 队头阻塞** | 单条 16M 帧在连接上传输的 ~100ms 里,堵住该连接上后续所有消息 | 单 TCP 连接、协议帧不可交错 | 可隔离(独立连接) |
23
- | **机制2:事件循环卡顿** | `codec.decode`/`encode` 是同步 CPU,16M 各 ~100ms 卡住**整个进程**的事件循环 | 完整对象 materialize 是物理成本 + **V8 对象只能在主线程构建** | **不能消除,只能隔离/分散** |
24
-
25
- 实测(11KB→132µs encode;8.5M→50ms;16M→~100ms),decode/encode 随大小线性增长。
26
-
27
- ## 3. 总体架构
28
-
29
- > **一句话:小消息走现状 core RPC(零影响);大消息自动经 Object Store 中转(独立 bulk 连接 + 可选 bulk 副本双隔离);用 NATS header 协商保证灰度不破坏;业务两端 API 完全不变。**
30
-
31
- ```
32
- ┌─────────────────────────────────────────────────────────┐
33
- │ 常规副本(处理高频小请求) │
34
- │ 连接① nats(core) : invoke/event/publish 的小消息 │
35
- │ 连接② natsBulk : 大数据 Object Store put/get(默认建) │
36
- ├─────────────────────────────────────────────────────────┤
37
- │ bulk 副本(可选,第二层,独立 deployment) │
38
- │ 订阅 serviceId.bulk,用原生 codec,烧自己的事件循环 │
39
- │ → 机制2 的处理隔离(没有它就退化到常规副本处理) │
40
- ├─────────────────────────────────────────────────────────┤
41
- │ NATS + JetStream Object Store(local-path 块存储) │
42
- │ bucket:大对象中转,持久存储(get 不删),短 MaxAge 自动清 │
43
- └─────────────────────────────────────────────────────────┘
44
- ```
45
-
46
- **双隔离:**
47
- - 独立连接(`natsBulk`)→ 解机制1(传输互不挤);
48
- - 独立进程(bulk 副本)→ 解机制2(CPU 互不卡)。
49
- - 两者是两件事,连接独立 ≠ 处理独立。
50
-
51
- ## 4. bulk 连接策略(本次更新重点)
52
-
53
- **`bulk` 默认 `true`:NATS 客户端启动时默认建立 bulk 连接 + 准备 Object Store 旁路。**
54
-
55
- ```ts
56
- nats: buildNatsClientOptions({
57
- servers: '...',
58
- bulk: true // 默认 true:启动即建 bulk 连接 + 准备 Object Store 旁路
59
- })
60
- ```
61
-
62
- 设计要点:
63
- - **预建立**(启动就连,无 cold start),符合 lakutata Component 的 init/destroy 生命周期;
64
- - **连接配置自动复用 core**(servers/认证/codec 继承),**不用重复配**;但仍是**第二条独立 TCP**(隔离需要),不是共用一条;
65
- - **连接与 Object Store 绑定**:默认开 = 连接 + Object Store 旁路一起就绪,**避免建一条空连接**;
66
- - **可关**:`bulk: false` 给明确从不收发大数据的服务关掉省资源;
67
- - **代价**:每副本 2 条连接,NATS server 端连接数翻倍,超大规模需评估;
68
- - **bulk 副本是第二层可选**:没有它,大请求退化到常规副本处理(卡常规副本但功能正常);有它才完整隔离机制2。
69
-
70
- `bulkNatsComponentName` 降级为**可选高级覆盖**:仅当想把 bulk 流量隔离到**另一个 NATS 集群**(不同 servers)时才用;默认同集群、自动复用配置,无需此项。
71
-
72
- ## 5. 阈值:自动从 server 拿,零配置
73
-
74
- 判断标准 = **encode 后的字节长度**(不是对象逻辑大小)。
75
-
76
- ```ts
77
- private get bulkThreshold(): number {
78
- const maxPayload = this.#conn.info?.max_payload ?? 1024 * 1024 // fallback 1M
79
- return Math.floor(maxPayload * 0.9) // 留 framing 余量
80
- }
81
- ```
82
-
83
- - `max_payload` 由 NATS 握手的 `INFO` 消息提供,`nc.info.max_payload` 现成可读(已验证 `ServerInfo.max_payload` 存在);
84
- - 阈值 = `max_payload × 0.9`,**跟随集群配置自动变化**,保证"core 发不出去的必走 bulk";
85
- - 每次读、不缓存(应对 server 运行时重配,成本几乎为零);
86
- - 可由用户配置向下覆盖(极低延迟场景想更激进隔离时)。
87
-
88
- **诚实局限:判断需先 encode,而 encode 大对象本身就卡(机制2)。** 小消息 encode 微秒级无负担;大消息发送侧 encode 那一下卡躲不过(见 §11)。不能靠"预估大小"绕过(遍历估大小也是 O(size) 卡顿)。
89
-
90
- ## 6. 数据流
91
-
92
- ### (A) 小请求 RPC —— 完全是现状,零额外开销
93
- ```
94
- invoke(pattern) → encode < 阈值 → nats.request(serviceId, bytes) → 常规副本 → 响应
95
- ```
96
-
97
- ### (B) 大请求/大响应 RPC —— Object Store 传引用
98
- ```
99
- 客户端: encode ≥ 阈值 → natsBulk.put(TTL)→objId → nats.request(serviceId.bulk, {__ref:objId}, header)
100
- bulk 副本: 收 {__ref} → natsBulk.get → decode → handler(完整对象)
101
- → return 大对象 → put → 回 {__ref:objId2}
102
- 客户端: 收 {__ref:objId2} → natsBulk.get → decode → resolve
103
- ```
104
- - core 连接上只跑**小引用消息**;大数据字节走 natsBulk + Object Store,离开 core;
105
- - decode/encode 卡顿烧在 bulk 副本进程,常规副本无感;
106
- - 业务两端只看到 `invoke(pattern)`/`return 对象`,看不到任何 ref。
107
-
108
- ### (C) 大 publish/event —— Object Store 发引用(一对多更优)
109
- ```
110
- emitServiceEvent(evt, big) → encode ≥ 阈值 → put → publish(subject, {__ref})
111
- 每个订阅方: 收 {__ref} → 按需 get → decode → listener(完整对象)
112
- ```
113
- - 广播的是小引用,所有订阅方 core 连接都不被砸;
114
- - **一份存储多方按需取,没有 N× 流量放大**(优于 natsBulk 直传广播);
115
- - 不关心的订阅方可以不下载。
116
-
117
- ## 7. 协议:全部走 NATS header,payload 不动
118
-
119
- | header 键 | 方向 | 含义 |
120
- |---|---|---|
121
- | `X-Lkt-Chunk: 1` | 请求 | 客户端能力声明:能处理引用中转 |
122
-
123
- - payload 永远是业务数据或 `{__ref}`,协议元信息只在 header → 不污染、跨语言干净;
124
- - `server` 是否支持 header:从 `nc.info.headers` 自动判断,不支持则自动退化。
125
-
126
- ## 8. 向后兼容 + 灰度
127
-
128
- 能力声明 header(`X-Lkt-Bulk`)可选,缺失即"对端不支持"→ 不给它发引用:
129
-
130
- | 客户端 | 服务端 | 行为 |
131
- |---|---|---|
132
- | 旧 | 新 | 旧客户端不带 `X-Lkt-Bulk` → 新服务端响应直传退化 |
133
- | 新 | 旧 | 旧服务端响应不带 `X-Lkt-Bulk` → 新客户端学到"不支持"→ 后续不发引用、直传 |
134
- | 新 | 新 | 双向都声明 → 大数据走 Object Store 引用 |
135
- | 旧 | 旧 | 完全不变 |
136
-
137
- **已验证**:用裸 NATS 模拟真旧版(无 header、无中转),两个方向(旧→新、新→旧)wire 兼容均通过(`compat.test.ts`)。关键保证:**新版只在对端声明能力时才发引用,旧版不声明 → 自动退化直传**,新旧混部署 / 滚动升级不破坏。
138
-
139
- **上线顺序(无 flag day):**
140
- 1. 发新版(带能力,默认旁路可退化),`max_payload` 暂保持现值;
141
- 2. 滚动升级所有服务;
142
- 3. 部署 bulk 副本、开启旁路;
143
- 4. 全升级确认后,把 `max_payload` 调回安全值(如 1M)。
144
-
145
- ## 9. 清理 / 容量(Object Store)
146
-
147
- - JetStream/Object Store **默认不会"消费即删"**(那是 WorkQueue retention);Object Store 是**持久存储,get 不删**;
148
- - 必须配**短 `MaxAge`**(如 5min)兜底自动清;RPC 点对点可加"下载后显式 `delete`"双保险;publish 一对多只能靠 `MaxAge`;
149
- - `max_file_store` 按 `峰值并发大对象数 × 大小 × TTL` 估算,别撑爆 local-path 磁盘。
150
-
151
- ## 10. 分阶段落地
152
-
153
- | 阶段 | 内容 | 状态 |
154
- |---|---|---|
155
- | **S1** | NATS 组件 bulk 基础能力:bulk 连接默认开(复用 core 配置)、Object Store `putBulk`/`getBulk`/`deleteBulk`/`bulkStatus`、阈值(`max_payload×0.9` 从 info)、`headersSupported` 探针、TTL/replicas/bucket 配置 | ✅ 已落地(`bulk.test.ts` 7 例) |
156
- | **S2** | `request`/`subscribe` 透明中转:自适应阈值路由、双向能力协商(`X-Lkt-Bulk`/`X-Lkt-Ref`/`{__ref}`)、客户端缓存对端能力(`#peerCapabilityCache`)、退化兼容、引用用完即删 + TTL 兜底、`NatsBulkException` 错误语义化 | ✅ 已落地(`bulk-rpc.test.ts` 5 例 + `compat.test.ts` 真旧版兼容 2 例) |
157
- | S3 | publish/event 的引用中转(一对多用 Object Store 发引用,不放大流量) | 待做 |
158
- | S4 | bulk 副本(机制2 处理隔离)+ 部署/路由(没有 bulk 副本时退化常规副本) | 待做 |
159
- | S5 | 背压(#1,bulk 副本尤其必要)+ 全集群升级后调回 `max_payload` | 待做 |
160
-
161
- **S1+S2 = MVP 核心链路**:RPC 大请求/大响应透明走 Object Store、双向协商、退化兼容、API 完全不变,全部有测试。每阶段向后兼容、可单独测、不破坏现状。
162
-
163
- ## 11. 已知边界 / 删不掉的代价(诚实记录)
164
-
165
- - **调用方侧机制2躲不过**:调用方 `invoke` 大数据时,它自己 encode 请求 + decode 响应卡**它自己**的事件循环。自适应路由 + bulk 副本只隔离了**被调用方**侧;调用方侧的卡顿是物理成本,且调用方预知不了响应大小,无法提前隔离。**接受它。**
166
- - 大数据请求**本身慢**(Object Store 多一跳 + encode/decode 物理成本)——但被关在 bulk 连接 + bulk 副本里,只烧自己,不连累高频小 RPC。
167
- - bulk 副本需**单独部署**(运维多一份);Object Store 占磁盘 + 需 TTL 管理;依赖 JetStream(已开、底座已修为 local-path)。
168
-
169
- ## 12. 待敲定的工程细节(实现前 checklist)
170
-
171
- - [x] **objId 生命周期**:`randomUUID` 命名;取回后即删(请求 obj 在响应返回后删、响应 obj 客户端 get 后删),均 + 5min TTL 兜底 ✅
172
- - [x] **配置 API**:`bulk`(默认 true)/`bulkBucket`/`bulkTTL`/`bulkReplicas`;`bulkNatsComponentName` 降级为可选高级覆盖 ✅
173
- - [x] **测试策略**:容器加 `-js` 启 JetStream;`bulk.test.ts`(基础 7 例)+ `bulk-rpc.test.ts`(中转/协商/退化 4 例)✅
174
- - [x] **超时/重试**:已在 §14 落地(超时 10min、NoResponders 安全重试)✅
175
- - [x] **错误传播**:`NatsBulkException` 语义化(put/get 失败、引用取不到、未启用);服务端 bulk 失败 → errorResponse → 客户端收带 `E_NATS_BULK` 的 `ServiceInvokeException`;客户端 bulk 失败 → `NatsBulkException`(**不被 #7 重试**);`ServiceResponseCodec.decode` 只读属性 bug 已修。测试:`bulk.test.ts` / `bulk-rpc.test.ts`(端到端不同 bucket)/ 单元。Object Store 完全不可用靠 code review ✅
176
- - [ ] **bulk 副本部署/路由**:常规 vs bulk 副本角色区分;没有 bulk 副本时大请求落哪 —— 留待 **S4**
177
- - [ ] **背压(#1)**:bulk 副本尤其必要 —— 留待 **S5**
178
-
179
- ## 13. 明确排除的弯路(不要重走)
180
-
181
- | 方案 | 为什么不行 |
182
- |---|---|
183
- | 调大 max_payload 单条传 | 机制1 + 机制2 双重打击 |
184
- | 自建 chunking + 流控 | 造轮子;Object Store 已内建分块/流控 |
185
- | worker thread 放 codec | 对象跨边界结构化克隆 ≈ 序列化,还在主线程付账,多构建一次 |
186
- | 异步 JSON 库 / stream-json | "异步"≠不占 CPU;JS 流式实现慢 5–10×;对象只能主线程构建 |
187
- | 给 core RPC 开连接池 | 单线程瓶颈不变,多 socket ≠ 多处理能力 |
188
-
189
- **根本原因**:只要"业务要完整对象 + API 不变",完整对象的 materialize(CPU + 内存)就删不掉、躲不出主线程。序列化层没有银弹,**解法只在架构隔离层**。
190
-
191
- ## 14. 相关的独立改进项(与本方案正交,可先做)
192
-
193
- - **✅ #3 优雅停机(drain)**:`destroy()` 已改为 `drain()` + `close()` 兜底,滚动升级不切断 in-flight(测试 `test/integration/drain.test.ts`)
194
- - **✅ #2 超时默认值**:`invoke` 默认已从 1 小时改为 **10 分钟**(可显式覆盖;慢操作显式传更长值)
195
- - **✅ #7 NoResponders 快速失败(已有)**:`request` 收到 503 立即抛 `NatsNoRespondersAvailableException`,不等超时——故障立即暴露,使 #2 的 10 分钟默认只兜底"处理慢"(测试 `errors.test.ts`)
196
- - **✅ #7 NoResponders 安全重试**:`invoke` 只对 NoResponders(对侧确定没处理)自动重试(默认 3 次、间隔 100ms,均可配);**超时/业务异常一律不重试**,避免"对侧已处理但响应丢失"时重复执行非幂等操作(测试 `retry.test.ts`)
197
- - **#1 背压(待做)**:服务端并发上限(bulk 副本尤其需要)
198
-
199
- drain + 10 分钟超时 + NoResponders 立即失败 + NoResponders 安全重试 已齐,**滚动升级韧性完整**;仅剩 #1 背压作为增强。
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "src",
5
- "outDir": "dist"
6
- },
7
- "exclude": ["dist", "node_modules", "test"]
8
- }
File without changes