@effect/platform 0.37.1 → 0.37.2
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/Worker.js.map +1 -1
- package/dist/cjs/WorkerRunner.js +11 -1
- package/dist/cjs/WorkerRunner.js.map +1 -1
- package/dist/cjs/internal/worker.js +40 -37
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/cjs/internal/workerRunner.js +27 -11
- package/dist/cjs/internal/workerRunner.js.map +1 -1
- package/dist/dts/Worker.d.ts +1 -3
- package/dist/dts/Worker.d.ts.map +1 -1
- package/dist/dts/WorkerRunner.d.ts +18 -5
- package/dist/dts/WorkerRunner.d.ts.map +1 -1
- package/dist/esm/Worker.js.map +1 -1
- package/dist/esm/WorkerRunner.js +10 -0
- package/dist/esm/WorkerRunner.js.map +1 -1
- package/dist/esm/internal/worker.js +40 -37
- package/dist/esm/internal/worker.js.map +1 -1
- package/dist/esm/internal/workerRunner.js +24 -10
- package/dist/esm/internal/workerRunner.js.map +1 -1
- package/package.json +1 -1
- package/src/Worker.ts +2 -4
- package/src/WorkerRunner.ts +36 -5
- package/src/internal/worker.ts +85 -67
- package/src/internal/workerRunner.ts +51 -13
package/src/internal/worker.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { identity, pipe } from "effect/Function"
|
|
|
12
12
|
import * as Layer from "effect/Layer"
|
|
13
13
|
import * as Pool from "effect/Pool"
|
|
14
14
|
import * as Queue from "effect/Queue"
|
|
15
|
+
import * as ReadonlyArray from "effect/ReadonlyArray"
|
|
16
|
+
import * as Schedule from "effect/Schedule"
|
|
15
17
|
import type * as Scope from "effect/Scope"
|
|
16
18
|
import * as Stream from "effect/Stream"
|
|
17
19
|
import * as Transferable from "../Transferable.js"
|
|
@@ -66,18 +68,60 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
66
68
|
return Effect.gen(function*(_) {
|
|
67
69
|
const id = idCounter++
|
|
68
70
|
let requestIdCounter = 0
|
|
69
|
-
const readyLatch = yield* _(Deferred.make<never, void>())
|
|
70
71
|
const semaphore = yield* _(Effect.makeSemaphore(permits))
|
|
71
72
|
const requestMap = new Map<
|
|
72
73
|
number,
|
|
73
|
-
readonly [Queue.Queue<Exit.Exit<E | WorkerError, O
|
|
74
|
+
readonly [Queue.Queue<Exit.Exit<E | WorkerError, ReadonlyArray<O>>>, Deferred.Deferred<never, void>]
|
|
74
75
|
>()
|
|
76
|
+
const sendQueue = yield* _(Effect.acquireRelease(
|
|
77
|
+
Queue.unbounded<readonly [message: Worker.Worker.Request, transfers?: ReadonlyArray<unknown>]>(),
|
|
78
|
+
Queue.shutdown
|
|
79
|
+
))
|
|
75
80
|
|
|
76
81
|
const outbound = queue ?? (yield* _(defaultQueue<I>()))
|
|
77
82
|
yield* _(Effect.addFinalizer(() => outbound.shutdown))
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
yield* _(
|
|
85
|
+
Effect.gen(function*(_) {
|
|
86
|
+
const readyLatch = yield* _(Deferred.make<never, void>())
|
|
87
|
+
const backing = yield* _(
|
|
88
|
+
platform.spawn<Worker.Worker.Request, Worker.Worker.Response<E, O>>(spawn(id))
|
|
89
|
+
)
|
|
90
|
+
const send = pipe(
|
|
91
|
+
sendQueue.take,
|
|
92
|
+
Effect.flatMap(([message, transfers]) => backing.send(message, transfers)),
|
|
93
|
+
Effect.forever
|
|
94
|
+
)
|
|
95
|
+
const take = pipe(
|
|
96
|
+
Queue.take(backing.queue),
|
|
97
|
+
Effect.flatMap((msg) => {
|
|
98
|
+
if (msg[0] === 0) {
|
|
99
|
+
return Deferred.complete(readyLatch, Effect.unit)
|
|
100
|
+
}
|
|
101
|
+
return handleMessage(msg[1])
|
|
102
|
+
}),
|
|
103
|
+
Effect.forever
|
|
104
|
+
)
|
|
105
|
+
return yield* _(Effect.all([
|
|
106
|
+
Fiber.join(backing.fiber),
|
|
107
|
+
Effect.zipRight(Deferred.await(readyLatch), send),
|
|
108
|
+
take
|
|
109
|
+
], { concurrency: "unbounded" }))
|
|
110
|
+
}),
|
|
111
|
+
Effect.scoped,
|
|
112
|
+
Effect.onError((cause) =>
|
|
113
|
+
Effect.forEach(requestMap.values(), ([queue]) => Queue.offer(queue, Exit.failCause(cause)))
|
|
114
|
+
),
|
|
115
|
+
Effect.retry(
|
|
116
|
+
Schedule.exponential("250 millis").pipe(
|
|
117
|
+
Schedule.union(Schedule.spaced("30 seconds"))
|
|
118
|
+
)
|
|
119
|
+
),
|
|
120
|
+
Effect.annotateLogs({
|
|
121
|
+
package: "@effect/platform",
|
|
122
|
+
module: "Worker"
|
|
123
|
+
}),
|
|
124
|
+
Effect.forkScoped
|
|
81
125
|
)
|
|
82
126
|
|
|
83
127
|
yield* _(Effect.addFinalizer(() =>
|
|
@@ -89,42 +133,34 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
89
133
|
)
|
|
90
134
|
))
|
|
91
135
|
|
|
92
|
-
const handleMessage = (
|
|
136
|
+
const handleMessage = (response: Worker.Worker.Response<E, O>) =>
|
|
93
137
|
Effect.suspend(() => {
|
|
94
|
-
|
|
138
|
+
const queue = requestMap.get(response[0])
|
|
139
|
+
if (!queue) return Effect.unit
|
|
140
|
+
|
|
141
|
+
switch (response[1]) {
|
|
142
|
+
// data
|
|
95
143
|
case 0: {
|
|
96
|
-
return
|
|
144
|
+
return Queue.offer(queue[0], Exit.succeed(response[2]))
|
|
97
145
|
}
|
|
146
|
+
// end
|
|
98
147
|
case 1: {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
// error / defect
|
|
118
|
-
case 2:
|
|
119
|
-
case 3: {
|
|
120
|
-
return Queue.offer(
|
|
121
|
-
queue[0],
|
|
122
|
-
response[1] === 2
|
|
123
|
-
? Exit.fail(response[2])
|
|
124
|
-
: Exit.die(response[2])
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
}
|
|
148
|
+
return response.length === 2 ?
|
|
149
|
+
Queue.offer(queue[0], Exit.failCause(Cause.empty)) :
|
|
150
|
+
Effect.zipRight(
|
|
151
|
+
Queue.offer(queue[0], Exit.succeed(response[2])),
|
|
152
|
+
Queue.offer(queue[0], Exit.failCause(Cause.empty))
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
// error / defect
|
|
156
|
+
case 2:
|
|
157
|
+
case 3: {
|
|
158
|
+
return Queue.offer(
|
|
159
|
+
queue[0],
|
|
160
|
+
response[1] === 2
|
|
161
|
+
? Exit.fail(response[2])
|
|
162
|
+
: Exit.die(response[2])
|
|
163
|
+
)
|
|
128
164
|
}
|
|
129
165
|
}
|
|
130
166
|
})
|
|
@@ -133,7 +169,7 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
133
169
|
Effect.tap(
|
|
134
170
|
Effect.all([
|
|
135
171
|
Effect.sync(() => requestIdCounter++),
|
|
136
|
-
Queue.unbounded<Exit.Exit<E | WorkerError, O
|
|
172
|
+
Queue.unbounded<Exit.Exit<E | WorkerError, ReadonlyArray<O>>>(),
|
|
137
173
|
Deferred.make<never, void>()
|
|
138
174
|
]),
|
|
139
175
|
([id, queue, deferred]) =>
|
|
@@ -144,7 +180,11 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
144
180
|
)
|
|
145
181
|
|
|
146
182
|
const executeRelease = (
|
|
147
|
-
[id, , deferred]: [
|
|
183
|
+
[id, , deferred]: [
|
|
184
|
+
number,
|
|
185
|
+
Queue.Queue<Exit.Exit<E | WorkerError, ReadonlyArray<O>>>,
|
|
186
|
+
Deferred.Deferred<never, void>
|
|
187
|
+
],
|
|
148
188
|
exit: Exit.Exit<unknown, unknown>
|
|
149
189
|
) => {
|
|
150
190
|
const release = Effect.zipRight(
|
|
@@ -152,10 +192,7 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
152
192
|
Effect.sync(() => requestMap.delete(id))
|
|
153
193
|
)
|
|
154
194
|
return Exit.isInterrupted(exit) ?
|
|
155
|
-
Effect.zipRight(
|
|
156
|
-
Effect.ignore(backing.send([id, 1])),
|
|
157
|
-
release
|
|
158
|
-
) :
|
|
195
|
+
Effect.zipRight(sendQueue.offer([[id, 1]]), release) :
|
|
159
196
|
release
|
|
160
197
|
}
|
|
161
198
|
|
|
@@ -171,7 +208,7 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
171
208
|
Queue.take(queue),
|
|
172
209
|
Exit.match({
|
|
173
210
|
onFailure: (cause) => Cause.isEmpty(cause) ? Channel.unit : Channel.failCause(cause),
|
|
174
|
-
onSuccess: (value) => Channel.flatMap(Channel.write(Chunk.
|
|
211
|
+
onSuccess: (value) => Channel.flatMap(Channel.write(Chunk.unsafeFromArray(value)), () => loop)
|
|
175
212
|
})
|
|
176
213
|
)
|
|
177
214
|
return Stream.fromChannel(loop)
|
|
@@ -181,18 +218,11 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
181
218
|
const executeEffect = (request: I) =>
|
|
182
219
|
Effect.acquireUseRelease(
|
|
183
220
|
executeAcquire(request),
|
|
184
|
-
([, queue]) => Effect.
|
|
221
|
+
([, queue]) => Effect.flatMap(Queue.take(queue), Exit.map(ReadonlyArray.unsafeGet(0))),
|
|
185
222
|
executeRelease
|
|
186
223
|
)
|
|
187
224
|
|
|
188
|
-
|
|
189
|
-
Queue.take(backing.queue),
|
|
190
|
-
Effect.flatMap(handleMessage),
|
|
191
|
-
Effect.forever,
|
|
192
|
-
Effect.forkScoped
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
const postMessages = pipe(
|
|
225
|
+
yield* _(
|
|
196
226
|
semaphore.take(1),
|
|
197
227
|
Effect.zipRight(outbound.take),
|
|
198
228
|
Effect.flatMap(([id, request]) =>
|
|
@@ -204,7 +234,7 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
204
234
|
return pipe(
|
|
205
235
|
Effect.flatMap(
|
|
206
236
|
encode ? encode(request) : Effect.succeed(request),
|
|
207
|
-
(payload) =>
|
|
237
|
+
(payload) => sendQueue.offer([[id, 0, payload], transferables])
|
|
208
238
|
),
|
|
209
239
|
Effect.catchAllCause((cause) => Queue.offer(result[0], Exit.failCause(cause))),
|
|
210
240
|
Effect.zipRight(Deferred.await(result[1]))
|
|
@@ -214,21 +244,10 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
214
244
|
Effect.fork
|
|
215
245
|
)
|
|
216
246
|
),
|
|
217
|
-
Effect.forever
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
const postMessagesFiber = yield* _(
|
|
221
|
-
Deferred.await(readyLatch),
|
|
222
|
-
Effect.zipRight(postMessages),
|
|
247
|
+
Effect.forever,
|
|
223
248
|
Effect.forkScoped
|
|
224
249
|
)
|
|
225
250
|
|
|
226
|
-
const join = Fiber.joinAll([backing.fiber, handleMessages, postMessagesFiber]) as Effect.Effect<
|
|
227
|
-
never,
|
|
228
|
-
WorkerError,
|
|
229
|
-
never
|
|
230
|
-
>
|
|
231
|
-
|
|
232
251
|
if (initialMessage) {
|
|
233
252
|
yield* _(
|
|
234
253
|
Effect.sync(initialMessage),
|
|
@@ -237,7 +256,7 @@ export const makeManager = Effect.gen(function*(_) {
|
|
|
237
256
|
)
|
|
238
257
|
}
|
|
239
258
|
|
|
240
|
-
return { id,
|
|
259
|
+
return { id, execute, executeEffect }
|
|
241
260
|
}).pipe(Effect.parallelFinalizers)
|
|
242
261
|
}
|
|
243
262
|
})
|
|
@@ -343,7 +362,6 @@ export const makeSerialized = <
|
|
|
343
362
|
}
|
|
344
363
|
return identity<Worker.SerializedWorker<I>>({
|
|
345
364
|
id: backing.id,
|
|
346
|
-
join: backing.join,
|
|
347
365
|
execute: execute as any,
|
|
348
366
|
executeEffect: executeEffect as any
|
|
349
367
|
})
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as Schema from "@effect/schema/Schema"
|
|
2
2
|
import * as Serializable from "@effect/schema/Serializable"
|
|
3
3
|
import * as Cause from "effect/Cause"
|
|
4
|
+
import * as Chunk from "effect/Chunk"
|
|
4
5
|
import * as Context from "effect/Context"
|
|
5
6
|
import * as Effect from "effect/Effect"
|
|
6
7
|
import * as Either from "effect/Either"
|
|
7
8
|
import * as Fiber from "effect/Fiber"
|
|
8
9
|
import { pipe } from "effect/Function"
|
|
10
|
+
import * as Layer from "effect/Layer"
|
|
11
|
+
import * as Option from "effect/Option"
|
|
9
12
|
import * as Predicate from "effect/Predicate"
|
|
10
13
|
import * as Queue from "effect/Queue"
|
|
11
14
|
import type * as Scope from "effect/Scope"
|
|
@@ -34,8 +37,9 @@ export const make = <I, R, E, O>(
|
|
|
34
37
|
const platform = yield* _(PlatformRunner)
|
|
35
38
|
const backing = yield* _(platform.start<Worker.Worker.Request<I>, Worker.Worker.Response<E>>())
|
|
36
39
|
const fiberMap = new Map<number, Fiber.Fiber<never, void>>()
|
|
40
|
+
const parentFiber = Option.getOrThrow(Fiber.getCurrentFiber())
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
yield* _(
|
|
39
43
|
Queue.take(backing.queue),
|
|
40
44
|
Effect.tap((req) => {
|
|
41
45
|
const id = req[0]
|
|
@@ -65,17 +69,29 @@ export const make = <I, R, E, O>(
|
|
|
65
69
|
const transfers = options?.transfers ? options.transfers(data) : undefined
|
|
66
70
|
return pipe(
|
|
67
71
|
options?.encodeOutput ? options.encodeOutput(data) : Effect.succeed(data),
|
|
68
|
-
Effect.flatMap((payload) => backing.send([id, 0, payload], transfers)),
|
|
72
|
+
Effect.flatMap((payload) => backing.send([id, 0, [payload]], transfers)),
|
|
69
73
|
Effect.catchAllCause((cause) => backing.send([id, 3, Cause.squash(cause)]))
|
|
70
74
|
)
|
|
71
75
|
}
|
|
72
76
|
}) :
|
|
73
77
|
pipe(
|
|
74
78
|
stream,
|
|
79
|
+
Stream.chunks,
|
|
75
80
|
Stream.tap((data) => {
|
|
76
|
-
|
|
81
|
+
if (options?.encodeOutput === undefined) {
|
|
82
|
+
const payload = Chunk.toReadonlyArray(data)
|
|
83
|
+
const transfers = options?.transfers ? payload.flatMap(options.transfers) : undefined
|
|
84
|
+
return backing.send([id, 0, payload], transfers)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const transfers: Array<unknown> = []
|
|
77
88
|
return Effect.flatMap(
|
|
78
|
-
|
|
89
|
+
Effect.forEach(data, (data) => {
|
|
90
|
+
if (options?.transfers) {
|
|
91
|
+
transfers.push(...options.transfers(data))
|
|
92
|
+
}
|
|
93
|
+
return Effect.orDie(options.encodeOutput!(data))
|
|
94
|
+
}),
|
|
79
95
|
(payload) => backing.send([id, 0, payload], transfers)
|
|
80
96
|
)
|
|
81
97
|
}),
|
|
@@ -104,17 +120,19 @@ export const make = <I, R, E, O>(
|
|
|
104
120
|
Effect.tap((fiber) => Effect.sync(() => fiberMap.set(id, fiber)))
|
|
105
121
|
)
|
|
106
122
|
}),
|
|
107
|
-
Effect.forever
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return yield* _(
|
|
111
|
-
Effect.all([
|
|
112
|
-
handleRequests,
|
|
113
|
-
Fiber.join(backing.fiber)
|
|
114
|
-
], { concurrency: "unbounded", discard: true }) as Effect.Effect<R, WorkerError.WorkerError, never>
|
|
123
|
+
Effect.forever,
|
|
124
|
+
Effect.onInterrupt(() => Fiber.interrupt(parentFiber)),
|
|
125
|
+
Effect.forkScoped
|
|
115
126
|
)
|
|
116
127
|
})
|
|
117
128
|
|
|
129
|
+
/** @internal */
|
|
130
|
+
export const layer = <I, R, E, O>(
|
|
131
|
+
process: (request: I) => Stream.Stream<R, E, O> | Effect.Effect<R, E, O>,
|
|
132
|
+
options?: WorkerRunner.Runner.Options<E, O>
|
|
133
|
+
): Layer.Layer<WorkerRunner.PlatformRunner | R, WorkerError.WorkerError, never> =>
|
|
134
|
+
Layer.scopedDiscard(make(process, options))
|
|
135
|
+
|
|
118
136
|
/** @internal */
|
|
119
137
|
export const makeSerialized = <
|
|
120
138
|
I,
|
|
@@ -133,7 +151,7 @@ export const makeSerialized = <
|
|
|
133
151
|
| Scope.Scope
|
|
134
152
|
| (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
|
|
135
153
|
WorkerError.WorkerError,
|
|
136
|
-
|
|
154
|
+
void
|
|
137
155
|
> => {
|
|
138
156
|
const parseRequest = Schema.decode(schema)
|
|
139
157
|
const effectTags = new Set<string>()
|
|
@@ -178,3 +196,23 @@ export const makeSerialized = <
|
|
|
178
196
|
}
|
|
179
197
|
})
|
|
180
198
|
}
|
|
199
|
+
|
|
200
|
+
/** @internal */
|
|
201
|
+
export const layerSerialized = <
|
|
202
|
+
I,
|
|
203
|
+
A extends Schema.TaggedRequest.Any,
|
|
204
|
+
const Handlers extends {
|
|
205
|
+
readonly [K in A["_tag"]]: Extract<A, { readonly _tag: K }> extends
|
|
206
|
+
Serializable.SerializableWithResult<infer _IS, infer S, infer _IE, infer E, infer _IO, infer O>
|
|
207
|
+
? (_: S) => Stream.Stream<any, E, O> | Effect.Effect<any, E, O> :
|
|
208
|
+
never
|
|
209
|
+
}
|
|
210
|
+
>(
|
|
211
|
+
schema: Schema.Schema<I, A>,
|
|
212
|
+
handlers: Handlers
|
|
213
|
+
): Layer.Layer<
|
|
214
|
+
| WorkerRunner.PlatformRunner
|
|
215
|
+
| (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
|
|
216
|
+
WorkerError.WorkerError,
|
|
217
|
+
never
|
|
218
|
+
> => Layer.scopedDiscard(makeSerialized(schema, handlers))
|