@hile/message-ws 4.0.2 → 4.0.3
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/AI.md +34 -25
- package/README.md +11 -6
- package/package.json +3 -3
package/AI.md
CHANGED
|
@@ -32,13 +32,14 @@ Message handler file:
|
|
|
32
32
|
|
|
33
33
|
```ts
|
|
34
34
|
// src/messages/ping.msg.ts
|
|
35
|
-
import {
|
|
35
|
+
import { defineMicroMessage } from '@hile/micro'
|
|
36
36
|
|
|
37
|
-
export default
|
|
37
|
+
export default defineMicroMessage(async ({ data, params, invocation }) => {
|
|
38
38
|
return {
|
|
39
39
|
type: 'pong',
|
|
40
40
|
data,
|
|
41
41
|
params,
|
|
42
|
+
requestId: invocation.context.values.requestId,
|
|
42
43
|
timestamp: Date.now(),
|
|
43
44
|
}
|
|
44
45
|
})
|
|
@@ -71,7 +72,11 @@ export default defineService('micro.app', async (shutdown) => {
|
|
|
71
72
|
Caller:
|
|
72
73
|
|
|
73
74
|
```ts
|
|
74
|
-
|
|
75
|
+
import { randomUUID } from 'node:crypto'
|
|
76
|
+
import { createExecutionContext } from '@hile/context'
|
|
77
|
+
|
|
78
|
+
const context = createExecutionContext({ requestId: randomUUID() })
|
|
79
|
+
const result = await app.call('example.service', '/ping', { hello: 'world' }, { context })
|
|
75
80
|
```
|
|
76
81
|
|
|
77
82
|
## More Examples
|
|
@@ -80,11 +85,11 @@ Streaming handler:
|
|
|
80
85
|
|
|
81
86
|
```ts
|
|
82
87
|
// src/messages/events.msg.ts
|
|
83
|
-
import {
|
|
88
|
+
import { defineMicroMessage } from '@hile/micro'
|
|
84
89
|
|
|
85
|
-
export default
|
|
90
|
+
export default defineMicroMessage(async function* ({ invocation }) {
|
|
86
91
|
for (let i = 0; i < 3; i++) {
|
|
87
|
-
yield { seq: i }
|
|
92
|
+
yield { seq: i, requestId: invocation.context.values.requestId }
|
|
88
93
|
}
|
|
89
94
|
})
|
|
90
95
|
```
|
|
@@ -92,7 +97,7 @@ export default defineMessage(async function* () {
|
|
|
92
97
|
Streaming caller:
|
|
93
98
|
|
|
94
99
|
```ts
|
|
95
|
-
const stream = await app.stream('example.service', '/events', {})
|
|
100
|
+
const stream = await app.stream('example.service', '/events', {}, { context })
|
|
96
101
|
for await (const chunk of stream) {
|
|
97
102
|
console.log(chunk)
|
|
98
103
|
}
|
|
@@ -129,13 +134,13 @@ Use the message packages for request/response messaging over WebSocket, process
|
|
|
129
134
|
|
|
130
135
|
- Do not use `stream()` for normal single-result calls.
|
|
131
136
|
- Do not rely on message IDs for business idempotency. They are transport IDs.
|
|
132
|
-
-
|
|
137
|
+
- Use `defineMicroMessage()` for Micro business handlers; reserve generic `defineMessage()` for transport-neutral loaders.
|
|
133
138
|
- Do not pass zero, fractional, non-finite, or oversized message timeouts. Explicit timeout values must be safe integers from `1` through `2_147_483_647` milliseconds.
|
|
134
139
|
|
|
135
140
|
## Install
|
|
136
141
|
|
|
137
142
|
```bash
|
|
138
|
-
pnpm add @hile/micro @hile/message-loader @hile/message-ws
|
|
143
|
+
pnpm add @hile/context @hile/micro @hile/message-loader @hile/message-ws
|
|
139
144
|
```
|
|
140
145
|
|
|
141
146
|
Use transport-specific packages only when you need to build custom IPC or worker-thread bridges.
|
|
@@ -144,7 +149,8 @@ Use transport-specific packages only when you need to build custom IPC or worker
|
|
|
144
149
|
|
|
145
150
|
```ts
|
|
146
151
|
import { defineMessage, MessageLoader } from '@hile/message-loader'
|
|
147
|
-
import {
|
|
152
|
+
import { createExecutionContext } from '@hile/context'
|
|
153
|
+
import { Application, defineMicroMessage, Registry, Server } from '@hile/micro'
|
|
148
154
|
import { MessageWs } from '@hile/message-ws'
|
|
149
155
|
import { MessageIpc } from '@hile/message-ipc'
|
|
150
156
|
import { MessageWorkerThread } from '@hile/message-worker-thread'
|
|
@@ -152,7 +158,7 @@ import { MessageWorkerThread } from '@hile/message-worker-thread'
|
|
|
152
158
|
|
|
153
159
|
## Compose With
|
|
154
160
|
|
|
155
|
-
-
|
|
161
|
+
- Pass `ExecutionContext` explicitly in every business call or stream option; the receiver gets it in `invocation.context`.
|
|
156
162
|
- `@hile/redis-idempotency` protects retryable side effects in message handlers.
|
|
157
163
|
- `@hile/redis-stream-queue` is better for durable background jobs.
|
|
158
164
|
|
|
@@ -167,8 +173,8 @@ import { MessageWorkerThread } from '@hile/message-worker-thread'
|
|
|
167
173
|
- Each modem schedules request, total-stream, and idle-stream deadlines through one internal deadline scheduler. This reduces active Node.js timers without changing timeout, cancellation, ordering, or error semantics.
|
|
168
174
|
- `@hile/message-ws` keeps public `decodeMessageFrame()` payloads isolated from caller-owned input by default. Its owned WebSocket `RawData` path uses a zero-copy binary Flight payload view internally.
|
|
169
175
|
- A stream request requires `exec()` to return an async iterable.
|
|
170
|
-
- `Application.call(namespace, url, data, options
|
|
171
|
-
- `Application.stream(namespace, url, data, options
|
|
176
|
+
- `Application.call(namespace, url, data, options)` requires `options.context` and returns a promise.
|
|
177
|
+
- `Application.stream(namespace, url, data, options)` requires `options.context` and returns a readable stream.
|
|
172
178
|
- `Application.publish(topic, payload)` returns an object with `update()` and `unpublish()`.
|
|
173
179
|
- `Application.subscribe(topic, callback)` returns an unsubscribe function.
|
|
174
180
|
- `Registry` stores service addresses and retained config/topic state under `~/.registry`.
|
|
@@ -182,8 +188,8 @@ import { MessageWorkerThread } from '@hile/message-worker-thread'
|
|
|
182
188
|
|
|
183
189
|
## Verification Checklist
|
|
184
190
|
|
|
185
|
-
-
|
|
186
|
-
- RPC callers use `await app.call(
|
|
191
|
+
- Micro message files default-export `defineMicroMessage(...)` and receive `invocation.context`.
|
|
192
|
+
- RPC callers use `await app.call(..., { context })`.
|
|
187
193
|
- Streaming handlers are async generators.
|
|
188
194
|
- Custom modem timeout values use the documented safe-integer range.
|
|
189
195
|
- Registry is started before application nodes need discovery.
|
|
@@ -203,10 +209,10 @@ Provider handler:
|
|
|
203
209
|
|
|
204
210
|
```ts
|
|
205
211
|
// src/messages/charge.msg.ts
|
|
206
|
-
import {
|
|
212
|
+
import { defineMicroMessage } from '@hile/micro'
|
|
207
213
|
|
|
208
|
-
export default
|
|
209
|
-
return { charged: true, input: data }
|
|
214
|
+
export default defineMicroMessage(async ({ data, invocation }) => {
|
|
215
|
+
return { charged: true, input: data, requestId: invocation.context.values.requestId }
|
|
210
216
|
})
|
|
211
217
|
```
|
|
212
218
|
|
|
@@ -234,10 +240,14 @@ export default defineService('billing.micro', async (shutdown) => {
|
|
|
234
240
|
Consumer:
|
|
235
241
|
|
|
236
242
|
```ts
|
|
243
|
+
import { randomUUID } from 'node:crypto'
|
|
244
|
+
import { createExecutionContext } from '@hile/context'
|
|
245
|
+
|
|
246
|
+
const context = createExecutionContext({ requestId: randomUUID(), tenantId: 't1' })
|
|
237
247
|
const result = await app.call('billing', '/charge', {
|
|
238
248
|
tenantId: 't1',
|
|
239
249
|
amount: 100,
|
|
240
|
-
})
|
|
250
|
+
}, { context })
|
|
241
251
|
```
|
|
242
252
|
|
|
243
253
|
## File Layout
|
|
@@ -257,16 +267,15 @@ Use this recipe when services communicate over Hile registry-backed RPC.
|
|
|
257
267
|
## Packages To Use
|
|
258
268
|
|
|
259
269
|
- `@hile/micro`
|
|
260
|
-
- `@hile/
|
|
261
|
-
- `@hile/context` when context must cross service boundaries
|
|
270
|
+
- `@hile/context` for the required explicit execution context carrier
|
|
262
271
|
- `@hile/redis-idempotency` for retryable side effects
|
|
263
272
|
|
|
264
273
|
## Implementation Steps
|
|
265
274
|
|
|
266
275
|
1. Start a Registry with `hile registry`.
|
|
267
276
|
2. Start providers with stable namespaces.
|
|
268
|
-
3.
|
|
269
|
-
4.
|
|
277
|
+
3. Default-export `defineMicroMessage()` handlers and load them through `app.load()`.
|
|
278
|
+
4. Create context at ingress and call providers with `await app.call(namespace, url, data, { context })`.
|
|
270
279
|
5. Use `app.stream()` only for async-generator handlers.
|
|
271
280
|
|
|
272
281
|
## Failure And Cleanup Behavior
|
|
@@ -279,8 +288,8 @@ Use this recipe when services communicate over Hile registry-backed RPC.
|
|
|
279
288
|
|
|
280
289
|
- Registry is reachable.
|
|
281
290
|
- Provider namespace matches consumer call.
|
|
282
|
-
- Handlers default-export `
|
|
283
|
-
- Consumer code awaits `app.call(
|
|
291
|
+
- Handlers default-export `defineMicroMessage()` and consume explicit invocation context when needed.
|
|
292
|
+
- Consumer code awaits `app.call(..., { context })` directly.
|
|
284
293
|
|
|
285
294
|
|
|
286
295
|
|
package/README.md
CHANGED
|
@@ -22,13 +22,14 @@ Message handler file:
|
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
24
|
// src/messages/ping.msg.ts
|
|
25
|
-
import {
|
|
25
|
+
import { defineMicroMessage } from '@hile/micro'
|
|
26
26
|
|
|
27
|
-
export default
|
|
27
|
+
export default defineMicroMessage(async ({ data, params, invocation }) => {
|
|
28
28
|
return {
|
|
29
29
|
type: 'pong',
|
|
30
30
|
data,
|
|
31
31
|
params,
|
|
32
|
+
requestId: invocation.context.values.requestId,
|
|
32
33
|
timestamp: Date.now(),
|
|
33
34
|
}
|
|
34
35
|
})
|
|
@@ -61,14 +62,18 @@ export default defineService('micro.app', async (shutdown) => {
|
|
|
61
62
|
Caller:
|
|
62
63
|
|
|
63
64
|
```ts
|
|
64
|
-
|
|
65
|
+
import { randomUUID } from 'node:crypto'
|
|
66
|
+
import { createExecutionContext } from '@hile/context'
|
|
67
|
+
|
|
68
|
+
const context = createExecutionContext({ requestId: randomUUID() })
|
|
69
|
+
const result = await app.call('example.service', '/ping', { hello: 'world' }, { context })
|
|
65
70
|
```
|
|
66
71
|
|
|
67
72
|
## Boundaries
|
|
68
73
|
|
|
69
74
|
- Do not use `stream()` for normal single-result calls.
|
|
70
75
|
- Do not rely on message IDs for business idempotency. They are transport IDs.
|
|
71
|
-
-
|
|
76
|
+
- Use `defineMicroMessage()` for Micro business handlers; reserve generic `defineMessage()` for transport-neutral loaders.
|
|
72
77
|
- Do not pass zero, fractional, non-finite, or oversized message timeouts. Explicit timeout values must be safe integers from `1` through `2_147_483_647` milliseconds.
|
|
73
78
|
|
|
74
79
|
- Appending a secondary response getter to `client.request('/x', data)`
|
|
@@ -78,8 +83,8 @@ const result = await app.call('example.service', '/ping', { hello: 'world' })
|
|
|
78
83
|
|
|
79
84
|
## Verify
|
|
80
85
|
|
|
81
|
-
-
|
|
82
|
-
- RPC callers use `await app.call(
|
|
86
|
+
- Micro message files default-export `defineMicroMessage(...)` and receive `invocation.context`.
|
|
87
|
+
- RPC callers use `await app.call(..., { context })`.
|
|
83
88
|
- Streaming handlers are async generators.
|
|
84
89
|
- Custom modem timeout values use the documented safe-integer range.
|
|
85
90
|
- Registry is started before application nodes need discovery.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/message-ws",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"vitest": "^4.0.18"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@hile/message-modem": "^4.0.
|
|
27
|
+
"@hile/message-modem": "^4.0.3",
|
|
28
28
|
"ws": "^8.21.0"
|
|
29
29
|
},
|
|
30
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "3ea69973f9373ddb1f7d5d37338966fd7d081d66"
|
|
31
31
|
}
|