@effect/platform 0.58.27 → 0.59.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.
- package/dist/cjs/Error.js +1 -25
- package/dist/cjs/Error.js.map +1 -1
- package/dist/cjs/HttpApp.js +4 -1
- package/dist/cjs/HttpApp.js.map +1 -1
- package/dist/cjs/HttpClientError.js +5 -6
- package/dist/cjs/HttpClientError.js.map +1 -1
- package/dist/cjs/HttpServerError.js +6 -5
- package/dist/cjs/HttpServerError.js.map +1 -1
- package/dist/cjs/HttpServerResponse.js.map +1 -1
- package/dist/cjs/Multipart.js.map +1 -1
- package/dist/cjs/Socket.js +11 -11
- package/dist/cjs/Socket.js.map +1 -1
- package/dist/cjs/Worker.js +10 -1
- package/dist/cjs/Worker.js.map +1 -1
- package/dist/cjs/WorkerError.js +13 -4
- package/dist/cjs/WorkerError.js.map +1 -1
- package/dist/cjs/WorkerRunner.js +6 -1
- package/dist/cjs/WorkerRunner.js.map +1 -1
- package/dist/cjs/internal/httpClient.js +7 -7
- package/dist/cjs/internal/httpClient.js.map +1 -1
- package/dist/cjs/internal/httpClientResponse.js +13 -13
- package/dist/cjs/internal/httpClientResponse.js.map +1 -1
- package/dist/cjs/internal/httpServerRequest.js +16 -16
- package/dist/cjs/internal/httpServerRequest.js.map +1 -1
- package/dist/cjs/internal/httpServerResponse.js +4 -3
- package/dist/cjs/internal/httpServerResponse.js.map +1 -1
- package/dist/cjs/internal/multipart.js +16 -16
- package/dist/cjs/internal/multipart.js.map +1 -1
- package/dist/cjs/internal/path.js +461 -11
- package/dist/cjs/internal/path.js.map +1 -1
- package/dist/cjs/internal/worker.js +126 -59
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/cjs/internal/workerRunner.js +39 -65
- package/dist/cjs/internal/workerRunner.js.map +1 -1
- package/dist/dts/Error.d.ts +0 -10
- package/dist/dts/Error.d.ts.map +1 -1
- package/dist/dts/HttpApp.d.ts +1 -1
- package/dist/dts/HttpApp.d.ts.map +1 -1
- package/dist/dts/HttpClientError.d.ts +6 -8
- package/dist/dts/HttpClientError.d.ts.map +1 -1
- package/dist/dts/HttpServerError.d.ts +10 -13
- package/dist/dts/HttpServerError.d.ts.map +1 -1
- package/dist/dts/HttpServerResponse.d.ts +5 -1
- package/dist/dts/HttpServerResponse.d.ts.map +1 -1
- package/dist/dts/Multipart.d.ts +3 -2
- package/dist/dts/Multipart.d.ts.map +1 -1
- package/dist/dts/Socket.d.ts +2 -4
- package/dist/dts/Socket.d.ts.map +1 -1
- package/dist/dts/Worker.d.ts +27 -27
- package/dist/dts/Worker.d.ts.map +1 -1
- package/dist/dts/WorkerError.d.ts +2 -2
- package/dist/dts/WorkerError.d.ts.map +1 -1
- package/dist/dts/WorkerRunner.d.ts +8 -5
- package/dist/dts/WorkerRunner.d.ts.map +1 -1
- package/dist/esm/Error.js +0 -23
- package/dist/esm/Error.js.map +1 -1
- package/dist/esm/HttpApp.js +4 -1
- package/dist/esm/HttpApp.js.map +1 -1
- package/dist/esm/HttpClientError.js +5 -6
- package/dist/esm/HttpClientError.js.map +1 -1
- package/dist/esm/HttpServerError.js +7 -6
- package/dist/esm/HttpServerError.js.map +1 -1
- package/dist/esm/HttpServerResponse.js.map +1 -1
- package/dist/esm/Multipart.js.map +1 -1
- package/dist/esm/Socket.js +12 -12
- package/dist/esm/Socket.js.map +1 -1
- package/dist/esm/Worker.js +9 -0
- package/dist/esm/Worker.js.map +1 -1
- package/dist/esm/WorkerError.js +13 -4
- package/dist/esm/WorkerError.js.map +1 -1
- package/dist/esm/WorkerRunner.js +5 -0
- package/dist/esm/WorkerRunner.js.map +1 -1
- package/dist/esm/internal/httpClient.js +7 -7
- package/dist/esm/internal/httpClient.js.map +1 -1
- package/dist/esm/internal/httpClientResponse.js +13 -13
- package/dist/esm/internal/httpClientResponse.js.map +1 -1
- package/dist/esm/internal/httpServerRequest.js +16 -16
- package/dist/esm/internal/httpServerRequest.js.map +1 -1
- package/dist/esm/internal/httpServerResponse.js +4 -3
- package/dist/esm/internal/httpServerResponse.js.map +1 -1
- package/dist/esm/internal/multipart.js +17 -17
- package/dist/esm/internal/multipart.js.map +1 -1
- package/dist/esm/internal/path.js +461 -10
- package/dist/esm/internal/path.js.map +1 -1
- package/dist/esm/internal/worker.js +124 -57
- package/dist/esm/internal/worker.js.map +1 -1
- package/dist/esm/internal/workerRunner.js +38 -65
- package/dist/esm/internal/workerRunner.js.map +1 -1
- package/package.json +5 -6
- package/src/Error.ts +0 -38
- package/src/HttpApp.ts +2 -2
- package/src/HttpClientError.ts +13 -6
- package/src/HttpServerError.ts +17 -6
- package/src/HttpServerResponse.ts +8 -1
- package/src/Multipart.ts +3 -2
- package/src/Socket.ts +10 -9
- package/src/Worker.ts +32 -29
- package/src/WorkerError.ts +15 -8
- package/src/WorkerRunner.ts +15 -8
- package/src/internal/httpClient.ts +7 -7
- package/src/internal/httpClientResponse.ts +13 -13
- package/src/internal/httpServerRequest.ts +15 -15
- package/src/internal/httpServerResponse.ts +7 -3
- package/src/internal/multipart.ts +16 -15
- package/src/internal/path.ts +510 -14
- package/src/internal/worker.ts +193 -146
- package/src/internal/workerRunner.ts +106 -139
package/src/internal/worker.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as Schema from "@effect/schema/Schema"
|
|
2
2
|
import * as Serializable from "@effect/schema/Serializable"
|
|
3
|
-
import * as Arr from "effect/Array"
|
|
4
3
|
import * as Cause from "effect/Cause"
|
|
5
4
|
import * as Channel from "effect/Channel"
|
|
6
5
|
import * as Chunk from "effect/Chunk"
|
|
@@ -8,31 +7,21 @@ import * as Context from "effect/Context"
|
|
|
8
7
|
import * as Deferred from "effect/Deferred"
|
|
9
8
|
import * as Effect from "effect/Effect"
|
|
10
9
|
import * as Exit from "effect/Exit"
|
|
11
|
-
import * as
|
|
10
|
+
import * as FiberRef from "effect/FiberRef"
|
|
11
|
+
import * as FiberSet from "effect/FiberSet"
|
|
12
12
|
import { identity, pipe } from "effect/Function"
|
|
13
13
|
import * as Layer from "effect/Layer"
|
|
14
14
|
import * as Option from "effect/Option"
|
|
15
15
|
import * as Pool from "effect/Pool"
|
|
16
16
|
import * as Queue from "effect/Queue"
|
|
17
17
|
import * as Schedule from "effect/Schedule"
|
|
18
|
-
import
|
|
18
|
+
import * as Scope from "effect/Scope"
|
|
19
19
|
import * as Stream from "effect/Stream"
|
|
20
20
|
import * as Tracer from "effect/Tracer"
|
|
21
21
|
import * as Transferable from "../Transferable.js"
|
|
22
22
|
import type * as Worker from "../Worker.js"
|
|
23
23
|
import { WorkerError } from "../WorkerError.js"
|
|
24
24
|
|
|
25
|
-
/** @internal */
|
|
26
|
-
export const defaultQueue = <I>() =>
|
|
27
|
-
Effect.map(
|
|
28
|
-
Queue.unbounded<readonly [id: number, item: I, span: Option.Option<Tracer.Span>]>(),
|
|
29
|
-
(queue): Worker.WorkerQueue<I> => ({
|
|
30
|
-
offer: (id, item, span) => Queue.offer(queue, [id, item, span]),
|
|
31
|
-
take: Queue.take(queue),
|
|
32
|
-
shutdown: Queue.shutdown(queue)
|
|
33
|
-
})
|
|
34
|
-
)
|
|
35
|
-
|
|
36
25
|
/** @internal */
|
|
37
26
|
export const PlatformWorkerTypeId: Worker.PlatformWorkerTypeId = Symbol.for(
|
|
38
27
|
"@effect/platform/Worker/PlatformWorker"
|
|
@@ -66,22 +55,15 @@ export const makeManager = Effect.gen(function*() {
|
|
|
66
55
|
[WorkerManagerTypeId]: WorkerManagerTypeId,
|
|
67
56
|
spawn<I, O, E>({
|
|
68
57
|
encode,
|
|
69
|
-
initialMessage
|
|
70
|
-
queue,
|
|
71
|
-
transfers = (_) => []
|
|
58
|
+
initialMessage
|
|
72
59
|
}: Worker.Worker.Options<I>) {
|
|
73
60
|
return Effect.gen(function*(_) {
|
|
74
|
-
const spawn = yield* _(Spawner)
|
|
75
61
|
const id = idCounter++
|
|
76
62
|
let requestIdCounter = 0
|
|
77
63
|
const requestMap = new Map<
|
|
78
64
|
number,
|
|
79
|
-
|
|
65
|
+
Queue.Queue<Exit.Exit<ReadonlyArray<O>, E | WorkerError>> | Deferred.Deferred<O, E | WorkerError>
|
|
80
66
|
>()
|
|
81
|
-
const sendQueue = yield* Effect.acquireRelease(
|
|
82
|
-
Queue.unbounded<readonly [message: Worker.Worker.Request, transfers?: ReadonlyArray<unknown>]>(),
|
|
83
|
-
Queue.shutdown
|
|
84
|
-
)
|
|
85
67
|
|
|
86
68
|
const collector = Transferable.unsafeMakeCollector()
|
|
87
69
|
const wrappedEncode = encode ?
|
|
@@ -92,36 +74,20 @@ export const makeManager = Effect.gen(function*() {
|
|
|
92
74
|
)) :
|
|
93
75
|
Effect.succeed
|
|
94
76
|
|
|
95
|
-
const
|
|
96
|
-
yield*
|
|
77
|
+
const readyLatch = yield* Deferred.make<void>()
|
|
78
|
+
const backing = yield* platform.spawn<Worker.Worker.Request, Worker.Worker.Response<E, O>>(id)
|
|
97
79
|
|
|
98
|
-
yield*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
Effect.flatMap(([message, transfers]) => backing.send(message, transfers)),
|
|
104
|
-
Effect.forever
|
|
105
|
-
)
|
|
106
|
-
const take = pipe(
|
|
107
|
-
Queue.take(backing.queue),
|
|
108
|
-
Effect.flatMap((msg) => {
|
|
109
|
-
if (msg[0] === 0) {
|
|
110
|
-
return Deferred.complete(readyLatch, Effect.void)
|
|
111
|
-
}
|
|
112
|
-
return handleMessage(msg[1])
|
|
113
|
-
}),
|
|
114
|
-
Effect.forever
|
|
115
|
-
)
|
|
116
|
-
return yield* Effect.all([
|
|
117
|
-
Fiber.join(backing.fiber),
|
|
118
|
-
Effect.zipRight(Deferred.await(readyLatch), send),
|
|
119
|
-
take
|
|
120
|
-
], { concurrency: "unbounded" })
|
|
80
|
+
yield* backing.run((message) => {
|
|
81
|
+
if (message[0] === 0) {
|
|
82
|
+
return Deferred.complete(readyLatch, Effect.void)
|
|
83
|
+
}
|
|
84
|
+
return handleMessage(message[1])
|
|
121
85
|
}).pipe(
|
|
122
|
-
Effect.scoped,
|
|
123
86
|
Effect.onError((cause) =>
|
|
124
|
-
Effect.forEach(requestMap.values(), (
|
|
87
|
+
Effect.forEach(requestMap.values(), (queue) =>
|
|
88
|
+
Deferred.DeferredTypeId in queue
|
|
89
|
+
? Deferred.failCause(queue, cause)
|
|
90
|
+
: Queue.offer(queue, Exit.failCause(cause)))
|
|
125
91
|
),
|
|
126
92
|
Effect.retry(Schedule.spaced(1000)),
|
|
127
93
|
Effect.annotateLogs({
|
|
@@ -134,7 +100,10 @@ export const makeManager = Effect.gen(function*() {
|
|
|
134
100
|
|
|
135
101
|
yield* Effect.addFinalizer(() =>
|
|
136
102
|
Effect.zipRight(
|
|
137
|
-
Effect.forEach(requestMap.values(), (
|
|
103
|
+
Effect.forEach(requestMap.values(), (queue) =>
|
|
104
|
+
Deferred.DeferredTypeId in queue
|
|
105
|
+
? Deferred.interrupt(queue)
|
|
106
|
+
: Queue.offer(queue, Exit.failCause(Cause.empty)), {
|
|
138
107
|
discard: true
|
|
139
108
|
}),
|
|
140
109
|
Effect.sync(() => requestMap.clear())
|
|
@@ -149,131 +118,117 @@ export const makeManager = Effect.gen(function*() {
|
|
|
149
118
|
switch (response[1]) {
|
|
150
119
|
// data
|
|
151
120
|
case 0: {
|
|
152
|
-
return
|
|
121
|
+
return Deferred.DeferredTypeId in queue
|
|
122
|
+
? Deferred.succeed(queue, response[2][0])
|
|
123
|
+
: Queue.offer(queue, Exit.succeed(response[2]))
|
|
153
124
|
}
|
|
154
125
|
// end
|
|
155
126
|
case 1: {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Queue.offer(queue
|
|
160
|
-
|
|
127
|
+
if (response.length === 2) {
|
|
128
|
+
return Deferred.DeferredTypeId in queue
|
|
129
|
+
? Deferred.interrupt(queue)
|
|
130
|
+
: Queue.offer(queue, Exit.failCause(Cause.empty))
|
|
131
|
+
}
|
|
132
|
+
return Deferred.DeferredTypeId in queue
|
|
133
|
+
? Deferred.succeed(queue, response[2][0])
|
|
134
|
+
: Effect.zipRight(
|
|
135
|
+
Queue.offer(queue, Exit.succeed(response[2])),
|
|
136
|
+
Queue.offer(queue, Exit.failCause(Cause.empty))
|
|
161
137
|
)
|
|
162
138
|
}
|
|
163
139
|
// error / defect
|
|
164
140
|
case 2:
|
|
165
141
|
case 3: {
|
|
166
|
-
|
|
167
|
-
queue
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
142
|
+
if (response[1] === 2) {
|
|
143
|
+
return Deferred.DeferredTypeId in queue
|
|
144
|
+
? Deferred.fail(queue, response[2])
|
|
145
|
+
: Queue.offer(queue, Exit.fail(response[2]))
|
|
146
|
+
}
|
|
147
|
+
const cause = WorkerError.decodeCause(response[2])
|
|
148
|
+
return Deferred.DeferredTypeId in queue
|
|
149
|
+
? Deferred.failCause(queue, cause)
|
|
150
|
+
: Queue.offer(queue, Exit.failCause(cause))
|
|
172
151
|
}
|
|
173
152
|
}
|
|
174
153
|
})
|
|
175
154
|
|
|
176
|
-
const executeAcquire =
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
155
|
+
const executeAcquire = <
|
|
156
|
+
Q extends Queue.Queue<Exit.Exit<ReadonlyArray<O>, E | WorkerError>> | Deferred.Deferred<O, E | WorkerError>
|
|
157
|
+
>(request: I, makeQueue: Effect.Effect<Q>) =>
|
|
158
|
+
Effect.withFiberRuntime<{
|
|
159
|
+
readonly id: number
|
|
160
|
+
readonly queue: Q
|
|
161
|
+
}>((fiber) => {
|
|
162
|
+
const context = fiber.getFiberRef(FiberRef.currentContext)
|
|
163
|
+
const span = Context.getOption(context, Tracer.ParentSpan).pipe(
|
|
164
|
+
Option.filter((span): span is Tracer.Span => span._tag === "Span")
|
|
165
|
+
)
|
|
166
|
+
const id = requestIdCounter++
|
|
167
|
+
return makeQueue.pipe(
|
|
168
|
+
Effect.tap((queue) => {
|
|
169
|
+
requestMap.set(id, queue)
|
|
170
|
+
return wrappedEncode(request).pipe(
|
|
171
|
+
Effect.tap((payload) =>
|
|
172
|
+
backing.send([
|
|
173
|
+
id,
|
|
174
|
+
0,
|
|
175
|
+
payload,
|
|
176
|
+
span._tag === "Some" ? [span.value.traceId, span.value.spanId, span.value.sampled] : undefined
|
|
177
|
+
], collector.unsafeRead())
|
|
178
|
+
),
|
|
179
|
+
Effect.catchAllCause((cause) =>
|
|
180
|
+
Deferred.DeferredTypeId in queue ?
|
|
181
|
+
Deferred.failCause(queue, cause) :
|
|
182
|
+
Queue.offer(queue, Exit.failCause(cause))
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
}),
|
|
186
|
+
Effect.map((queue) => ({ id, queue }))
|
|
187
|
+
)
|
|
188
|
+
})
|
|
193
189
|
|
|
194
|
-
const executeRelease = (
|
|
195
|
-
|
|
196
|
-
number,
|
|
197
|
-
Queue.Queue<Exit.Exit<ReadonlyArray<O>, E | WorkerError>>,
|
|
198
|
-
Deferred.Deferred<void>,
|
|
199
|
-
Option.Option<Tracer.Span>
|
|
200
|
-
],
|
|
201
|
-
exit: Exit.Exit<unknown, unknown>
|
|
202
|
-
) => {
|
|
203
|
-
const release = Effect.zipRight(
|
|
204
|
-
Deferred.complete(deferred, Effect.void),
|
|
205
|
-
Effect.sync(() => requestMap.delete(id))
|
|
206
|
-
)
|
|
190
|
+
const executeRelease = ({ id }: { readonly id: number }, exit: Exit.Exit<unknown, unknown>) => {
|
|
191
|
+
const release = Effect.sync(() => requestMap.delete(id))
|
|
207
192
|
return Exit.isFailure(exit) ?
|
|
208
|
-
Effect.zipRight(
|
|
193
|
+
Effect.zipRight(Effect.orDie(backing.send([id, 1])), release) :
|
|
209
194
|
release
|
|
210
195
|
}
|
|
211
196
|
|
|
212
197
|
const execute = (request: I) =>
|
|
213
|
-
Stream.
|
|
214
|
-
|
|
215
|
-
executeAcquire(request),
|
|
198
|
+
Stream.fromChannel(
|
|
199
|
+
Channel.acquireUseRelease(
|
|
200
|
+
executeAcquire(request, Queue.unbounded<Exit.Exit<ReadonlyArray<O>, E | WorkerError>>()),
|
|
201
|
+
({ queue }) => {
|
|
202
|
+
const loop: Channel.Channel<Chunk.Chunk<O>, unknown, E | WorkerError, unknown, void, unknown> = Channel
|
|
203
|
+
.flatMap(
|
|
204
|
+
Queue.take(queue),
|
|
205
|
+
Exit.match({
|
|
206
|
+
onFailure: (cause) => Cause.isEmpty(cause) ? Channel.void : Channel.failCause(cause),
|
|
207
|
+
onSuccess: (value) => Channel.flatMap(Channel.write(Chunk.unsafeFromArray(value)), () => loop)
|
|
208
|
+
})
|
|
209
|
+
)
|
|
210
|
+
return loop
|
|
211
|
+
},
|
|
216
212
|
executeRelease
|
|
217
|
-
)
|
|
218
|
-
([, queue]) => {
|
|
219
|
-
const loop: Channel.Channel<Chunk.Chunk<O>, unknown, E | WorkerError, unknown, void, unknown> = Channel
|
|
220
|
-
.flatMap(
|
|
221
|
-
Queue.take(queue),
|
|
222
|
-
Exit.match({
|
|
223
|
-
onFailure: (cause) => Cause.isEmpty(cause) ? Channel.void : Channel.failCause(cause),
|
|
224
|
-
onSuccess: (value) => Channel.flatMap(Channel.write(Chunk.unsafeFromArray(value)), () => loop)
|
|
225
|
-
})
|
|
226
|
-
)
|
|
227
|
-
return Stream.fromChannel(loop)
|
|
228
|
-
}
|
|
213
|
+
)
|
|
229
214
|
)
|
|
230
215
|
|
|
231
216
|
const executeEffect = (request: I) =>
|
|
232
217
|
Effect.acquireUseRelease(
|
|
233
|
-
executeAcquire(request),
|
|
234
|
-
(
|
|
218
|
+
executeAcquire(request, Deferred.make<O, WorkerError | E>()),
|
|
219
|
+
({ queue }) => Deferred.await(queue),
|
|
235
220
|
executeRelease
|
|
236
221
|
)
|
|
237
222
|
|
|
238
|
-
yield* outbound.take.pipe(
|
|
239
|
-
Effect.flatMap(([id, request, span]) =>
|
|
240
|
-
Effect.fork(
|
|
241
|
-
Effect.suspend(() => {
|
|
242
|
-
const result = requestMap.get(id)
|
|
243
|
-
if (!result) return Effect.void
|
|
244
|
-
const transferables = transfers(request)
|
|
245
|
-
const spanTuple = Option.getOrUndefined(
|
|
246
|
-
Option.map(span, (span) => [span.traceId, span.spanId, span.sampled] as const)
|
|
247
|
-
)
|
|
248
|
-
return pipe(
|
|
249
|
-
Effect.flatMap(
|
|
250
|
-
wrappedEncode(request),
|
|
251
|
-
(payload) =>
|
|
252
|
-
sendQueue.offer([[id, 0, payload, spanTuple], [
|
|
253
|
-
...transferables,
|
|
254
|
-
...collector.unsafeRead()
|
|
255
|
-
]])
|
|
256
|
-
),
|
|
257
|
-
Effect.catchAllCause((cause) => Queue.offer(result[0], Exit.failCause(cause))),
|
|
258
|
-
Effect.zipRight(Deferred.await(result[1]))
|
|
259
|
-
)
|
|
260
|
-
})
|
|
261
|
-
)
|
|
262
|
-
),
|
|
263
|
-
Effect.forever,
|
|
264
|
-
Effect.forkScoped,
|
|
265
|
-
Effect.interruptible
|
|
266
|
-
)
|
|
267
|
-
|
|
268
223
|
if (initialMessage) {
|
|
269
224
|
yield* Effect.sync(initialMessage).pipe(
|
|
270
225
|
Effect.flatMap(executeEffect),
|
|
271
|
-
Effect.mapError((
|
|
226
|
+
Effect.mapError((cause) => new WorkerError({ reason: "spawn", cause }))
|
|
272
227
|
)
|
|
273
228
|
}
|
|
274
229
|
|
|
275
230
|
return { id, execute, executeEffect }
|
|
276
|
-
})
|
|
231
|
+
})
|
|
277
232
|
}
|
|
278
233
|
})
|
|
279
234
|
})
|
|
@@ -290,8 +245,12 @@ export const makePool = <I, O, E>(
|
|
|
290
245
|
const workers = new Set<Worker.Worker<I, O, E>>()
|
|
291
246
|
const acquire = pipe(
|
|
292
247
|
manager.spawn<I, O, E>(options),
|
|
293
|
-
Effect.tap((worker) =>
|
|
294
|
-
|
|
248
|
+
Effect.tap((worker) =>
|
|
249
|
+
Effect.acquireRelease(
|
|
250
|
+
Effect.sync(() => workers.add(worker)),
|
|
251
|
+
() => Effect.sync(() => workers.delete(worker))
|
|
252
|
+
)
|
|
253
|
+
),
|
|
295
254
|
options.onCreate ? Effect.tap(options.onCreate) : identity
|
|
296
255
|
)
|
|
297
256
|
const backing = "minSize" in options ?
|
|
@@ -353,7 +312,7 @@ export const makeSerialized = <
|
|
|
353
312
|
encode(message) {
|
|
354
313
|
return Effect.mapError(
|
|
355
314
|
Serializable.serialize(message as any),
|
|
356
|
-
(
|
|
315
|
+
(cause) => new WorkerError({ reason: "encode", cause })
|
|
357
316
|
)
|
|
358
317
|
}
|
|
359
318
|
})
|
|
@@ -445,3 +404,91 @@ export const layerSpawner = <W = unknown>(spawner: Worker.SpawnerFn<W>) =>
|
|
|
445
404
|
Spawner,
|
|
446
405
|
spawner
|
|
447
406
|
)
|
|
407
|
+
|
|
408
|
+
/** @internal */
|
|
409
|
+
export const makePlatform = <W>() =>
|
|
410
|
+
<
|
|
411
|
+
P extends {
|
|
412
|
+
readonly postMessage: (message: any, transfers?: any | undefined) => void
|
|
413
|
+
}
|
|
414
|
+
>(options: {
|
|
415
|
+
readonly setup: (options: {
|
|
416
|
+
readonly worker: W
|
|
417
|
+
readonly scope: Scope.Scope
|
|
418
|
+
}) => Effect.Effect<P>
|
|
419
|
+
readonly listen: (options: {
|
|
420
|
+
readonly port: P
|
|
421
|
+
readonly emit: (data: any) => void
|
|
422
|
+
readonly deferred: Deferred.Deferred<never, WorkerError>
|
|
423
|
+
readonly scope: Scope.Scope
|
|
424
|
+
}) => Effect.Effect<void>
|
|
425
|
+
}) =>
|
|
426
|
+
PlatformWorker.of({
|
|
427
|
+
[PlatformWorkerTypeId]: PlatformWorkerTypeId,
|
|
428
|
+
spawn<I, O>(id: number) {
|
|
429
|
+
return Effect.gen(function*(_) {
|
|
430
|
+
const spawn = (yield* Spawner) as Worker.SpawnerFn<W>
|
|
431
|
+
let currentPort: P | undefined
|
|
432
|
+
const buffer: Array<[I, ReadonlyArray<unknown> | undefined]> = []
|
|
433
|
+
|
|
434
|
+
const run = <A, E, R>(handler: (_: Worker.BackingWorker.Message<O>) => Effect.Effect<A, E, R>) =>
|
|
435
|
+
Effect.uninterruptibleMask((restore) =>
|
|
436
|
+
Scope.make().pipe(
|
|
437
|
+
Effect.bindTo("scope"),
|
|
438
|
+
Effect.bind("port", ({ scope }) => options.setup({ worker: spawn(id), scope })),
|
|
439
|
+
Effect.tap(({ port, scope }) => {
|
|
440
|
+
currentPort = port
|
|
441
|
+
return Scope.addFinalizer(
|
|
442
|
+
scope,
|
|
443
|
+
Effect.sync(() => {
|
|
444
|
+
currentPort = undefined
|
|
445
|
+
})
|
|
446
|
+
)
|
|
447
|
+
}),
|
|
448
|
+
Effect.bind("fiberSet", ({ scope }) =>
|
|
449
|
+
FiberSet.make<any, WorkerError | E>().pipe(
|
|
450
|
+
Scope.extend(scope)
|
|
451
|
+
)),
|
|
452
|
+
Effect.bind("runFork", ({ fiberSet }) => FiberSet.runtime(fiberSet)<R>()),
|
|
453
|
+
Effect.tap(({ fiberSet, port, runFork, scope }) =>
|
|
454
|
+
options.listen({
|
|
455
|
+
port,
|
|
456
|
+
scope,
|
|
457
|
+
emit(data) {
|
|
458
|
+
runFork(handler(data))
|
|
459
|
+
},
|
|
460
|
+
deferred: fiberSet.deferred as any
|
|
461
|
+
})
|
|
462
|
+
),
|
|
463
|
+
Effect.tap(({ port }) => {
|
|
464
|
+
if (buffer.length > 0) {
|
|
465
|
+
for (const [message, transfers] of buffer) {
|
|
466
|
+
port.postMessage([0, message], transfers as any)
|
|
467
|
+
}
|
|
468
|
+
buffer.length = 0
|
|
469
|
+
}
|
|
470
|
+
}),
|
|
471
|
+
Effect.flatMap(({ fiberSet, scope }) =>
|
|
472
|
+
(restore(FiberSet.join(fiberSet)) as Effect.Effect<never, WorkerError | E>).pipe(
|
|
473
|
+
Effect.ensuring(Scope.close(scope, Exit.void))
|
|
474
|
+
)
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
const send = (message: I, transfers?: ReadonlyArray<unknown>) =>
|
|
480
|
+
Effect.try({
|
|
481
|
+
try: () => {
|
|
482
|
+
if (currentPort === undefined) {
|
|
483
|
+
buffer.push([message, transfers])
|
|
484
|
+
} else {
|
|
485
|
+
currentPort.postMessage([0, message], transfers as any)
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
catch: (cause) => new WorkerError({ reason: "send", cause })
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
return { run, send }
|
|
492
|
+
})
|
|
493
|
+
}
|
|
494
|
+
})
|