@hile/micro 2.0.7 → 2.0.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 +62 -7
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -136,8 +136,8 @@ const app = new Application({
|
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
// 单次调用覆盖
|
|
139
|
-
await app.call('svc', '/api', data, 5_000);
|
|
140
|
-
await app.call('svc', '/api', data, 1_000, 0); // 1s 超时, 不重试
|
|
139
|
+
await app.call('svc', '/api', data, { timeout: 5_000 }); // 5s 超时, 默认重试 1 次
|
|
140
|
+
await app.call('svc', '/api', data, { timeout: 1_000, retries: 0 }); // 1s 超时, 不重试
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
超时触发时,底层 MessageModem 会向对端发送 **ABORT** 消息取消远程执行。
|
|
@@ -169,13 +169,52 @@ try {
|
|
|
169
169
|
`call()` 默认 retries=1,失败后自动换 peer 重试:
|
|
170
170
|
|
|
171
171
|
```typescript
|
|
172
|
-
await app.call('svc', '/api', data);
|
|
173
|
-
await app.call('svc', '/api', data, 5000, 3); // 超时 5s, 重试 3 次
|
|
174
|
-
await app.call('svc', '/api', data, 5000, 0); // 超时 5s, 不重试
|
|
172
|
+
await app.call('svc', '/api', data); // 默认重试 1 次
|
|
173
|
+
await app.call('svc', '/api', data, { timeout: 5000, retries: 3 }); // 超时 5s, 重试 3 次
|
|
174
|
+
await app.call('svc', '/api', data, { timeout: 5000, retries: 0 }); // 超时 5s, 不重试
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
重试策略:失败 → `recordFailure`(peer 被排除)→ 递归 `call(retries-1)` → `getActiveExcludes` 排除已失败的 peer → Registry `/‑/find` 返回其他 peer。
|
|
178
178
|
|
|
179
|
+
### 流式调用 (Stream)
|
|
180
|
+
|
|
181
|
+
`stream()` 用于**需要持续推送数据**的场景:大数据集、实时事件、LLM token 流、进度上报等。不需要流式传输时优先用 `call()`。
|
|
182
|
+
|
|
183
|
+
**Provider 侧**:消息处理器必须返回 async generator(`async function*`)。
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// 通过 register() 注册
|
|
187
|
+
app.register('/events', async function* () {
|
|
188
|
+
for (let i = 0; i < 100; i++) {
|
|
189
|
+
yield { seq: i, time: Date.now() }
|
|
190
|
+
await new Promise(r => setTimeout(r, 100))
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
// 或通过 .msg 文件定义(推荐)
|
|
195
|
+
// src/messages/events.msg.ts
|
|
196
|
+
import { defineMessage } from '@hile/message-loader'
|
|
197
|
+
export default defineMessage(async function* ({ data }) {
|
|
198
|
+
for (const item of await fetchItems(data.query)) {
|
|
199
|
+
yield item
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Consumer 侧**:`app.stream()` 返回 `Readable` stream,可用 `for await` 逐 chunk 消费。
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
const stream = await app.stream('data-svc', '/events', { query: 'recent' })
|
|
208
|
+
for await (const chunk of stream) {
|
|
209
|
+
console.log(chunk) // { seq: 0, time: 1718000000000 }
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**注意事项**:
|
|
214
|
+
- 普通 handler(返回非 async iterable)被 `stream()` 调用时会报错 `"Invalid async iterable"`
|
|
215
|
+
- 不需要流式传输时用 `call()`,不要用 `stream()` 取单次返回值
|
|
216
|
+
- `stream()` 享有与 `call()` 相同的熔断、重试、超时机制
|
|
217
|
+
|
|
179
218
|
### 健康检查
|
|
180
219
|
|
|
181
220
|
每个 `Application` 自动注册 `/-/health` 端点:
|
|
@@ -363,10 +402,25 @@ class Application extends Server {
|
|
|
363
402
|
namespace: string,
|
|
364
403
|
url: string,
|
|
365
404
|
data: any,
|
|
366
|
-
|
|
367
|
-
|
|
405
|
+
options?: {
|
|
406
|
+
timeout?: number, // 请求超时(ms),默认 requestTimeoutMs
|
|
407
|
+
retries?: number, // 失败重试次数,默认 1
|
|
408
|
+
signal?: AbortSignal, // 手动取消
|
|
409
|
+
},
|
|
368
410
|
): Promise<T>;
|
|
369
411
|
|
|
412
|
+
// 流式调用:get + stream + 熔断 + 重试
|
|
413
|
+
// provider handler 必须返回 async generator,consumer 获得 Readable stream
|
|
414
|
+
stream(
|
|
415
|
+
namespace: string,
|
|
416
|
+
url: string,
|
|
417
|
+
data: any,
|
|
418
|
+
options?: {
|
|
419
|
+
signal?: AbortSignal,
|
|
420
|
+
retries?: number, // 失败重试次数,默认 1
|
|
421
|
+
},
|
|
422
|
+
): Promise<import('stream').Readable>;
|
|
423
|
+
|
|
370
424
|
// 注册路由(provider 侧)
|
|
371
425
|
register<T = any>(url: string, handler: (ctx) => Promise<T>): () => void;
|
|
372
426
|
|
|
@@ -410,6 +464,7 @@ class Server extends MessageLoader {
|
|
|
410
464
|
class Client extends MessageWs {
|
|
411
465
|
request(url: string, data: any, timeout?: number): { abort(): void; response<T>(): Promise<T> };
|
|
412
466
|
push(url: string, data: any, timeout?: number): void;
|
|
467
|
+
stream(url: string, data: any, options?: { signal?: AbortSignal }): Readable;
|
|
413
468
|
dispose(): void;
|
|
414
469
|
}
|
|
415
470
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/micro",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@hile/logger": "^2.0.3",
|
|
27
|
-
"@hile/message-loader": "^2.0.
|
|
28
|
-
"@hile/message-ws": "^2.0.
|
|
27
|
+
"@hile/message-loader": "^2.0.2",
|
|
28
|
+
"@hile/message-ws": "^2.0.4",
|
|
29
29
|
"internal-ip": "^9.0.0",
|
|
30
30
|
"ws": "^8.21.0",
|
|
31
31
|
"yaml": "^2.9.0"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "a7615000fcb87e6bc0e573af760c814ec935bab2"
|
|
34
34
|
}
|