@livestore/common-cf 0.4.0 โ 0.5.0-dev.0
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/dist/.tsbuildinfo +1 -1
- package/dist/declare/cf-declare.d.ts +1 -21
- package/dist/declare/cf-declare.d.ts.map +1 -1
- package/dist/do-rpc/client.d.ts.map +1 -1
- package/dist/do-rpc/client.js +17 -27
- package/dist/do-rpc/client.js.map +1 -1
- package/dist/do-rpc/client.test.d.ts +2 -0
- package/dist/do-rpc/client.test.d.ts.map +1 -0
- package/dist/do-rpc/client.test.js +99 -0
- package/dist/do-rpc/client.test.js.map +1 -0
- package/dist/do-rpc/rpc.test.js +25 -57
- package/dist/do-rpc/rpc.test.js.map +1 -1
- package/dist/do-rpc/server.d.ts +9 -4
- package/dist/do-rpc/server.d.ts.map +1 -1
- package/dist/do-rpc/server.js +84 -43
- package/dist/do-rpc/server.js.map +1 -1
- package/dist/do-rpc/test-fixtures/rpc-schema.d.ts +27 -27
- package/dist/do-rpc/test-fixtures/rpc-schema.js +11 -11
- package/dist/do-rpc/test-fixtures/worker.d.ts.map +1 -1
- package/dist/do-rpc/test-fixtures/worker.js +9 -9
- package/dist/do-rpc/test-fixtures/worker.js.map +1 -1
- package/dist/ws-rpc/test-fixtures/rpc-schema.d.ts +27 -27
- package/dist/ws-rpc/test-fixtures/rpc-schema.js +9 -9
- package/dist/ws-rpc/ws-rpc-server.d.ts +6 -5
- package/dist/ws-rpc/ws-rpc-server.d.ts.map +1 -1
- package/dist/ws-rpc/ws-rpc-server.js +17 -17
- package/dist/ws-rpc/ws-rpc-server.js.map +1 -1
- package/dist/ws-rpc/ws-rpc.test.js +27 -59
- package/dist/ws-rpc/ws-rpc.test.js.map +1 -1
- package/package.json +11 -20
- package/src/declare/cf-declare.ts +1 -1
- package/src/do-rpc/client.test.ts +122 -0
- package/src/do-rpc/client.ts +21 -31
- package/src/do-rpc/rpc.test.ts +29 -59
- package/src/do-rpc/server.ts +119 -54
- package/src/do-rpc/test-fixtures/rpc-schema.ts +11 -11
- package/src/do-rpc/test-fixtures/worker.ts +9 -12
- package/src/ws-rpc/test-fixtures/rpc-schema.ts +9 -9
- package/src/ws-rpc/ws-rpc-server.ts +37 -28
- package/src/ws-rpc/ws-rpc.test.ts +31 -61
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
import { notYetImplemented, omitUndefineds } from '@livestore/utils'
|
|
19
19
|
import {
|
|
20
20
|
Context,
|
|
21
|
-
constVoid,
|
|
22
21
|
Effect,
|
|
22
|
+
Function,
|
|
23
23
|
Exit,
|
|
24
24
|
Layer,
|
|
25
25
|
Logger,
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Queue,
|
|
27
|
+
References,
|
|
28
28
|
RpcMessage,
|
|
29
29
|
RpcSerialization,
|
|
30
30
|
RpcServer,
|
|
@@ -39,7 +39,7 @@ import type * as CfTypes from '../cf-types.ts'
|
|
|
39
39
|
* This is useful for reading WebSocket attachment data (e.g., forwarded headers)
|
|
40
40
|
* inside RPC handlers.
|
|
41
41
|
*/
|
|
42
|
-
export class WsContext extends Context.
|
|
42
|
+
export class WsContext extends Context.Service<WsContext, { readonly ws: CfTypes.WebSocket }>()('WsContext') {}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Configuration options for setting up WebSocket RPC on a Durable Object.
|
|
@@ -55,7 +55,7 @@ export interface DurableObjectWebSocketRpcConfig {
|
|
|
55
55
|
webSocketMode: 'hibernate' | 'accept'
|
|
56
56
|
/**
|
|
57
57
|
* Effect RPC layer that requires `RpcServer.Protocol` (and `WsContext` if used)
|
|
58
|
-
* and provides the RPC server
|
|
58
|
+
* and provides the RPC server services.
|
|
59
59
|
*
|
|
60
60
|
* This is typically created by:
|
|
61
61
|
* ```typescript
|
|
@@ -148,7 +148,7 @@ export const setupDurableObjectWebSocketRpc = ({
|
|
|
148
148
|
const serverCtxMap = new Map<
|
|
149
149
|
CfTypes.WebSocket,
|
|
150
150
|
{
|
|
151
|
-
scope: Scope.
|
|
151
|
+
scope: Scope.Closeable
|
|
152
152
|
onMessage: (message: string | ArrayBuffer) => Promise<void>
|
|
153
153
|
}
|
|
154
154
|
>()
|
|
@@ -163,12 +163,13 @@ export const setupDurableObjectWebSocketRpc = ({
|
|
|
163
163
|
|
|
164
164
|
const scope = yield* Scope.make()
|
|
165
165
|
|
|
166
|
-
const incomingQueue = yield*
|
|
166
|
+
const incomingQueue = yield* Queue.unbounded<Uint8Array | string>()
|
|
167
167
|
|
|
168
|
-
yield* Scope.addFinalizer(scope,
|
|
168
|
+
yield* Scope.addFinalizer(scope, Queue.shutdown(incomingQueue).pipe(Effect.asVoid))
|
|
169
169
|
|
|
170
170
|
const ProtocolLive = layerRpcServerWebsocket({
|
|
171
171
|
ws,
|
|
172
|
+
scope,
|
|
172
173
|
incomingQueue,
|
|
173
174
|
...omitUndefineds({ onMessage }),
|
|
174
175
|
}).pipe(Layer.provide(RpcSerialization.layerJson))
|
|
@@ -177,19 +178,16 @@ export const setupDurableObjectWebSocketRpc = ({
|
|
|
177
178
|
|
|
178
179
|
yield* Layer.launch(ServerLive).pipe(Effect.tapCauseLogPretty, Effect.forkIn(scope))
|
|
179
180
|
|
|
180
|
-
const
|
|
181
|
+
const services = yield* Effect.context()
|
|
181
182
|
|
|
182
183
|
const ctx = {
|
|
183
184
|
scope,
|
|
184
185
|
onMessage: (message: string | ArrayBuffer) =>
|
|
185
|
-
incomingQueue
|
|
186
|
-
.
|
|
187
|
-
.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Effect.provide(runtime),
|
|
191
|
-
Effect.runPromise,
|
|
192
|
-
),
|
|
186
|
+
Queue.offer(incomingQueue, message as Uint8Array | string).pipe(
|
|
187
|
+
Effect.asVoid,
|
|
188
|
+
Effect.withSpan('ws-rpc-server/onMessage', { root: true }),
|
|
189
|
+
Effect.runPromiseWith(services),
|
|
190
|
+
),
|
|
193
191
|
}
|
|
194
192
|
|
|
195
193
|
serverCtxMap.set(ws, ctx)
|
|
@@ -197,8 +195,14 @@ export const setupDurableObjectWebSocketRpc = ({
|
|
|
197
195
|
return ctx
|
|
198
196
|
}).pipe(
|
|
199
197
|
Effect.tapCauseLogPretty,
|
|
200
|
-
|
|
201
|
-
Effect.provide(
|
|
198
|
+
Effect.annotateLogs({ thread: 'ws-rpc-server' }),
|
|
199
|
+
Effect.provide(
|
|
200
|
+
Layer.mergeAll(
|
|
201
|
+
Logger.layer([Logger.consoleStructured]),
|
|
202
|
+
Layer.succeed(References.MinimumLogLevel, 'Debug'), // Useful for debugging
|
|
203
|
+
mainLayer ?? Layer.empty,
|
|
204
|
+
),
|
|
205
|
+
),
|
|
202
206
|
Effect.withSpan('effect-ws-rpc-server'),
|
|
203
207
|
Effect.runPromise,
|
|
204
208
|
)
|
|
@@ -233,9 +237,10 @@ export const setupDurableObjectWebSocketRpc = ({
|
|
|
233
237
|
*/
|
|
234
238
|
export interface WsRpcServerArgs {
|
|
235
239
|
ws: CfTypes.WebSocket
|
|
240
|
+
scope: Scope.Scope
|
|
236
241
|
onMessage?: (message: RpcMessage.FromClientEncoded, ws: CfTypes.WebSocket) => void
|
|
237
|
-
/**
|
|
238
|
-
incomingQueue:
|
|
242
|
+
/** Queue for receiving incoming messages from the WebSocket */
|
|
243
|
+
incomingQueue: Queue.Queue<Uint8Array | string>
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
/**
|
|
@@ -253,7 +258,10 @@ export interface WsRpcServerArgs {
|
|
|
253
258
|
* @internal This is typically used internally by `setupDurableObjectWebSocketRpc`
|
|
254
259
|
*/
|
|
255
260
|
export const layerRpcServerWebsocket = (args: WsRpcServerArgs) =>
|
|
256
|
-
Layer.mergeAll(
|
|
261
|
+
Layer.mergeAll(
|
|
262
|
+
Layer.effect(RpcServer.Protocol, makeSocketProtocol(args)),
|
|
263
|
+
Layer.succeed(WsContext, WsContext.of({ ws: args.ws })),
|
|
264
|
+
)
|
|
257
265
|
|
|
258
266
|
/**
|
|
259
267
|
* Creates the low-level RPC protocol implementation for WebSocket communication.
|
|
@@ -266,16 +274,16 @@ export const layerRpcServerWebsocket = (args: WsRpcServerArgs) =>
|
|
|
266
274
|
*
|
|
267
275
|
* @internal Used internally by `layerRpcServerWebsocket`
|
|
268
276
|
*/
|
|
269
|
-
const makeSocketProtocol = ({ incomingQueue, ws, onMessage }: WsRpcServerArgs) =>
|
|
277
|
+
const makeSocketProtocol = ({ incomingQueue, scope, ws, onMessage }: WsRpcServerArgs) =>
|
|
270
278
|
Effect.gen(function* () {
|
|
271
279
|
const serialization = yield* RpcSerialization.RpcSerialization
|
|
272
|
-
const disconnects = yield*
|
|
280
|
+
const disconnects = yield* Queue.unbounded<number>()
|
|
273
281
|
|
|
274
282
|
const writeRaw = (msg: Uint8Array | string) => Effect.succeed(ws.send(msg))
|
|
275
283
|
|
|
276
284
|
let writeRequest!: (clientId: number, message: RpcMessage.FromClientEncoded) => Effect.Effect<void>
|
|
277
285
|
|
|
278
|
-
const parser = serialization.
|
|
286
|
+
const parser = serialization.makeUnsafe()
|
|
279
287
|
const id = 0
|
|
280
288
|
|
|
281
289
|
const write = (response: RpcMessage.FromServerEncoded) => {
|
|
@@ -294,7 +302,7 @@ const makeSocketProtocol = ({ incomingQueue, ws, onMessage }: WsRpcServerArgs) =
|
|
|
294
302
|
writeRequest = writeRequest_
|
|
295
303
|
|
|
296
304
|
// Start processing messages now that writeRequest is available
|
|
297
|
-
const startProcessing =
|
|
305
|
+
const startProcessing = Stream.fromQueue(incomingQueue).pipe(
|
|
298
306
|
Stream.tap((data) => {
|
|
299
307
|
try {
|
|
300
308
|
const decoded = parser.decode(data) as ReadonlyArray<RpcMessage.FromClientEncoded>
|
|
@@ -309,7 +317,7 @@ const makeSocketProtocol = ({ incomingQueue, ws, onMessage }: WsRpcServerArgs) =
|
|
|
309
317
|
}
|
|
310
318
|
return writeRequest(id, request)
|
|
311
319
|
},
|
|
312
|
-
step: constVoid,
|
|
320
|
+
step: Function.constVoid,
|
|
313
321
|
})
|
|
314
322
|
} catch (cause) {
|
|
315
323
|
return Effect.orDie(writeRaw(parser.encode(RpcMessage.ResponseDefectEncoded(cause))!))
|
|
@@ -317,7 +325,7 @@ const makeSocketProtocol = ({ incomingQueue, ws, onMessage }: WsRpcServerArgs) =
|
|
|
317
325
|
}),
|
|
318
326
|
Stream.runDrain,
|
|
319
327
|
Effect.tapCauseLogPretty,
|
|
320
|
-
Effect.
|
|
328
|
+
Effect.forkIn(scope),
|
|
321
329
|
)
|
|
322
330
|
|
|
323
331
|
// Start the message processing
|
|
@@ -333,6 +341,7 @@ const makeSocketProtocol = ({ incomingQueue, ws, onMessage }: WsRpcServerArgs) =
|
|
|
333
341
|
supportsAck: true,
|
|
334
342
|
supportsTransferables: false,
|
|
335
343
|
supportsSpanPropagation: true,
|
|
344
|
+
supportsNotifications: true,
|
|
336
345
|
}))
|
|
337
346
|
})
|
|
338
347
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { expect } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
4
|
-
import {
|
|
4
|
+
import { WranglerDevServer } from '@livestore/utils-dev/wrangler'
|
|
5
5
|
import {
|
|
6
|
-
Chunk,
|
|
7
6
|
Effect,
|
|
8
7
|
FetchHttpClient,
|
|
9
8
|
Layer,
|
|
10
|
-
Logger,
|
|
11
|
-
LogLevel,
|
|
12
9
|
Option,
|
|
10
|
+
References,
|
|
13
11
|
RpcClient,
|
|
14
12
|
RpcSerialization,
|
|
15
13
|
Socket,
|
|
@@ -24,29 +22,33 @@ const testTimeout = 60_000
|
|
|
24
22
|
const withWranglerTest = Vitest.makeWithTestCtx({
|
|
25
23
|
timeout: testTimeout,
|
|
26
24
|
makeLayer: () =>
|
|
27
|
-
|
|
25
|
+
WranglerDevServer.layer({
|
|
28
26
|
cwd: `${import.meta.dirname}/test-fixtures`,
|
|
29
27
|
}).pipe(
|
|
30
28
|
Layer.provide(
|
|
31
|
-
Layer.mergeAll(
|
|
29
|
+
Layer.mergeAll(
|
|
30
|
+
PlatformNode.NodeServices.layer,
|
|
31
|
+
FetchHttpClient.layer,
|
|
32
|
+
Layer.succeed(References.MinimumLogLevel, 'Debug'),
|
|
33
|
+
),
|
|
32
34
|
),
|
|
33
35
|
),
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
const ProtocolLive = Layer.suspend(() =>
|
|
37
39
|
Effect.gen(function* () {
|
|
38
|
-
const server = yield*
|
|
40
|
+
const server = yield* WranglerDevServer.WranglerDevServer
|
|
39
41
|
return RpcClient.layerProtocolSocket().pipe(
|
|
40
42
|
Layer.provide(Socket.layerWebSocket(`ws://localhost:${server.port}`)),
|
|
41
43
|
Layer.provide(Socket.layerWebSocketConstructorGlobal),
|
|
42
44
|
Layer.provide(RpcSerialization.layerJson),
|
|
43
45
|
)
|
|
44
|
-
}).pipe(Layer.
|
|
46
|
+
}).pipe(Layer.unwrap),
|
|
45
47
|
)
|
|
46
48
|
|
|
47
49
|
Vitest.describe('Durable Object WebSocket RPC', { timeout: testTimeout }, () => {
|
|
48
50
|
// Direct HTTP RPC client tests
|
|
49
|
-
Vitest.
|
|
51
|
+
Vitest.live('should call ping method', (test) =>
|
|
50
52
|
Effect.gen(function* () {
|
|
51
53
|
const client = yield* RpcClient.make(TestRpcs)
|
|
52
54
|
const result = yield* client.Ping({ message: 'Hello HTTP RPC' })
|
|
@@ -54,7 +56,7 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: testTimeout }, () =>
|
|
|
54
56
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
55
57
|
)
|
|
56
58
|
|
|
57
|
-
Vitest.
|
|
59
|
+
Vitest.live('should call echo method', (test) =>
|
|
58
60
|
Effect.gen(function* () {
|
|
59
61
|
const client = yield* RpcClient.make(TestRpcs)
|
|
60
62
|
const result = yield* client.Echo({ text: 'Echo' })
|
|
@@ -62,7 +64,7 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: testTimeout }, () =>
|
|
|
62
64
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
63
65
|
)
|
|
64
66
|
|
|
65
|
-
Vitest.
|
|
67
|
+
Vitest.live('should call add method', (test) =>
|
|
66
68
|
Effect.gen(function* () {
|
|
67
69
|
const client = yield* RpcClient.make(TestRpcs)
|
|
68
70
|
const result = yield* client.Add({ a: 15, b: 25 })
|
|
@@ -70,104 +72,72 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: testTimeout }, () =>
|
|
|
70
72
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
71
73
|
)
|
|
72
74
|
|
|
73
|
-
Vitest.
|
|
75
|
+
Vitest.live('should handle RPC fail method', (test) =>
|
|
74
76
|
Effect.gen(function* () {
|
|
75
77
|
const client = yield* RpcClient.make(TestRpcs)
|
|
76
78
|
const error = yield* client.Fail({ message: 'test http failure' }).pipe(Effect.exit)
|
|
77
79
|
expect(error.toString()).toMatchInlineSnapshot(`
|
|
78
|
-
"
|
|
79
|
-
"_id": "Exit",
|
|
80
|
-
"_tag": "Failure",
|
|
81
|
-
"cause": {
|
|
82
|
-
"_id": "Cause",
|
|
83
|
-
"_tag": "Fail",
|
|
84
|
-
"failure": "RPC failure: test http failure"
|
|
85
|
-
}
|
|
86
|
-
}"
|
|
80
|
+
"Failure(Cause([Fail("RPC failure: test http failure")]))"
|
|
87
81
|
`)
|
|
88
82
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
89
83
|
)
|
|
90
84
|
|
|
91
|
-
Vitest.
|
|
85
|
+
Vitest.live('should handle defect method', (test) =>
|
|
92
86
|
Effect.gen(function* () {
|
|
93
87
|
const client = yield* RpcClient.make(TestRpcs)
|
|
94
88
|
const error = yield* client.Defect({ message: 'test http defect' }).pipe(Effect.exit)
|
|
95
89
|
expect(error.toString()).toMatchInlineSnapshot(`
|
|
96
|
-
"
|
|
97
|
-
"_id": "Exit",
|
|
98
|
-
"_tag": "Failure",
|
|
99
|
-
"cause": {
|
|
100
|
-
"_id": "Cause",
|
|
101
|
-
"_tag": "Die",
|
|
102
|
-
"defect": "some defect: test http defect"
|
|
103
|
-
}
|
|
104
|
-
}"
|
|
90
|
+
"Failure(Cause([Die("some defect: test http defect")]))"
|
|
105
91
|
`)
|
|
106
92
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
107
93
|
)
|
|
108
94
|
|
|
109
|
-
Vitest.
|
|
95
|
+
Vitest.live('should handle streaming RPC via HTTP', (test) =>
|
|
110
96
|
Effect.gen(function* () {
|
|
111
97
|
const client = yield* RpcClient.make(TestRpcs)
|
|
112
98
|
const stream = client.Stream({}).pipe(
|
|
113
99
|
Stream.take(4),
|
|
114
100
|
Stream.map((c) => c.maybeNumber.pipe(Option.getOrUndefined)),
|
|
115
101
|
)
|
|
116
|
-
const
|
|
117
|
-
expect(
|
|
102
|
+
const result = yield* Stream.runCollect(stream)
|
|
103
|
+
expect(result).toEqual([1, 4, 9, 16]) // squares of 1,2,3,4
|
|
118
104
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
119
105
|
)
|
|
120
106
|
|
|
121
|
-
Vitest.
|
|
107
|
+
Vitest.live('should handle streaming RPC with error via HTTP', (test) =>
|
|
122
108
|
Effect.gen(function* () {
|
|
123
109
|
const client = yield* RpcClient.make(TestRpcs)
|
|
124
110
|
const stream = client.StreamError({ count: 5, errorAfter: 4 })
|
|
125
111
|
const error = yield* Stream.runCollect(stream).pipe(Effect.exit)
|
|
126
112
|
expect(error.toString()).toMatchInlineSnapshot(`
|
|
127
|
-
"
|
|
128
|
-
"_id": "Exit",
|
|
129
|
-
"_tag": "Failure",
|
|
130
|
-
"cause": {
|
|
131
|
-
"_id": "Cause",
|
|
132
|
-
"_tag": "Fail",
|
|
133
|
-
"failure": "Stream error after 4: got 9"
|
|
134
|
-
}
|
|
135
|
-
}"
|
|
113
|
+
"Failure(Cause([Fail("Stream error after 4: got 9")]))"
|
|
136
114
|
`)
|
|
137
115
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
138
116
|
)
|
|
139
117
|
|
|
140
|
-
Vitest.
|
|
118
|
+
Vitest.live('should handle streaming RPC with defect via HTTP', (test) =>
|
|
141
119
|
Effect.gen(function* () {
|
|
142
120
|
const client = yield* RpcClient.make(TestRpcs)
|
|
143
121
|
const stream = client.StreamDefect({ count: 4, defectAfter: 1 })
|
|
144
122
|
const error = yield* Stream.runCollect(stream).pipe(Effect.exit)
|
|
145
123
|
expect(error.toString()).toMatchInlineSnapshot(`
|
|
146
|
-
"
|
|
147
|
-
"_id": "Exit",
|
|
148
|
-
"_tag": "Failure",
|
|
149
|
-
"cause": {
|
|
150
|
-
"_id": "Cause",
|
|
151
|
-
"_tag": "Die",
|
|
152
|
-
"defect": "Stream defect after 1: got 4"
|
|
153
|
-
}
|
|
154
|
-
}"
|
|
124
|
+
"Failure(Cause([Die("Stream defect after 1: got 4")]))"
|
|
155
125
|
`)
|
|
156
126
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
157
127
|
)
|
|
158
128
|
|
|
159
|
-
Vitest.
|
|
129
|
+
Vitest.live('should handle stream interruption via HTTP', (test) =>
|
|
160
130
|
Effect.gen(function* () {
|
|
161
131
|
const client = yield* RpcClient.make(TestRpcs)
|
|
162
132
|
const stream = client.StreamInterruptible({ delay: 50, interruptAfterCount: 3 }).pipe(Stream.take(3))
|
|
163
|
-
const
|
|
164
|
-
expect(
|
|
133
|
+
const result = yield* Stream.runCollect(stream)
|
|
134
|
+
expect(result).toEqual([1, 2, 3])
|
|
165
135
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
166
136
|
)
|
|
167
137
|
})
|
|
168
138
|
|
|
169
139
|
Vitest.describe('Hibernation Tests', { timeout: 25000 }, () => {
|
|
170
|
-
Vitest.
|
|
140
|
+
Vitest.live('should maintain RPC functionality after hibernation', (test) =>
|
|
171
141
|
Effect.gen(function* () {
|
|
172
142
|
console.log('๐งช Testing RPC server persistence across hibernation...')
|
|
173
143
|
|
|
@@ -222,15 +192,15 @@ Vitest.describe('Hibernation Tests', { timeout: 25000 }, () => {
|
|
|
222
192
|
Stream.take(3),
|
|
223
193
|
Stream.map((c) => c.maybeNumber.pipe(Option.getOrUndefined)),
|
|
224
194
|
)
|
|
225
|
-
const
|
|
226
|
-
expect(
|
|
195
|
+
const result = yield* Stream.runCollect(stream)
|
|
196
|
+
expect(result).toEqual([1, 4, 9]) // squares of 1,2,3
|
|
227
197
|
console.log('โ
Streaming after hibernation successful')
|
|
228
198
|
|
|
229
199
|
console.log('๐ All RPC operations successful after hibernation!')
|
|
230
200
|
}).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
|
|
231
201
|
)
|
|
232
202
|
|
|
233
|
-
Vitest.
|
|
203
|
+
Vitest.live('should handle rapid operations after hibernation', (test) =>
|
|
234
204
|
Effect.gen(function* () {
|
|
235
205
|
console.log('๐งช Testing rapid operations after hibernation...')
|
|
236
206
|
|