@effect/platform 0.37.1 → 0.37.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.
@@ -5,7 +5,7 @@ import type * as Schema from "@effect/schema/Schema"
5
5
  import type * as Serializable from "@effect/schema/Serializable"
6
6
  import type * as Context from "effect/Context"
7
7
  import type * as Effect from "effect/Effect"
8
- import type * as Fiber from "effect/Fiber"
8
+ import type * as Layer from "effect/Layer"
9
9
  import type * as Queue from "effect/Queue"
10
10
  import type * as Scope from "effect/Scope"
11
11
  import type * as Stream from "effect/Stream"
@@ -17,7 +17,6 @@ import type { WorkerError } from "./WorkerError.js"
17
17
  * @category models
18
18
  */
19
19
  export interface BackingRunner<I, O> {
20
- readonly fiber: Fiber.Fiber<WorkerError, never>
21
20
  readonly queue: Queue.Dequeue<I>
22
21
  readonly send: (message: O, transfers?: ReadonlyArray<unknown>) => Effect.Effect<never, never, void>
23
22
  }
@@ -70,9 +69,10 @@ export declare namespace Runner {
70
69
  * @since 1.0.0
71
70
  * @category models
72
71
  */
73
- export interface Options<E, O> {
74
- readonly encodeOutput?: (message: O) => Effect.Effect<never, WorkerError, unknown>
75
- readonly encodeError?: (message: E) => Effect.Effect<never, WorkerError, unknown>
72
+ export interface Options<I, E, O> {
73
+ readonly decode?: (message: unknown) => Effect.Effect<never, WorkerError, I>
74
+ readonly encodeOutput?: (request: I, message: O) => Effect.Effect<never, WorkerError, unknown>
75
+ readonly encodeError?: (request: I, error: E) => Effect.Effect<never, WorkerError, unknown>
76
76
  readonly transfers?: (message: O | E) => ReadonlyArray<unknown>
77
77
  }
78
78
  }
@@ -83,8 +83,17 @@ export declare namespace Runner {
83
83
  */
84
84
  export const make: <I, R, E, O>(
85
85
  process: (request: I) => Stream.Stream<R, E, O> | Effect.Effect<R, E, O>,
86
- options?: Runner.Options<E, O> | undefined
87
- ) => Effect.Effect<Scope.Scope | R | PlatformRunner, WorkerError, never> = internal.make
86
+ options?: Runner.Options<I, E, O> | undefined
87
+ ) => Effect.Effect<Scope.Scope | R | PlatformRunner, WorkerError, void> = internal.make
88
+
89
+ /**
90
+ * @since 1.0.0
91
+ * @category layers
92
+ */
93
+ export const layer: <I, R, E, O>(
94
+ process: (request: I) => Stream.Stream<R, E, O> | Effect.Effect<R, E, O>,
95
+ options?: Runner.Options<I, E, O> | undefined
96
+ ) => Layer.Layer<R | PlatformRunner, WorkerError, never> = internal.layer
88
97
 
89
98
  /**
90
99
  * @since 1.0.0
@@ -93,7 +102,7 @@ export const make: <I, R, E, O>(
93
102
  export const makeSerialized: <
94
103
  I,
95
104
  A extends Schema.TaggedRequest.Any,
96
- Handlers extends {
105
+ const Handlers extends {
97
106
  readonly [K in A["_tag"]]: Extract<A, { readonly _tag: K }> extends
98
107
  Serializable.SerializableWithResult<infer _IS, infer S, infer _IE, infer E, infer _IO, infer O>
99
108
  ? (_: S) => Stream.Stream<any, E, O> | Effect.Effect<any, E, O> :
@@ -107,5 +116,28 @@ export const makeSerialized: <
107
116
  | Scope.Scope
108
117
  | (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
109
118
  WorkerError,
110
- never
119
+ void
111
120
  > = internal.makeSerialized
121
+
122
+ /**
123
+ * @since 1.0.0
124
+ * @category layers
125
+ */
126
+ export const layerSerialized: <
127
+ I,
128
+ A extends Schema.TaggedRequest.Any,
129
+ const Handlers extends {
130
+ readonly [K in A["_tag"]]: Extract<A, { readonly _tag: K }> extends
131
+ Serializable.SerializableWithResult<infer _IS, infer S, infer _IE, infer E, infer _IO, infer O>
132
+ ? (_: S) => Stream.Stream<any, E, O> | Effect.Effect<any, E, O> :
133
+ never
134
+ }
135
+ >(
136
+ schema: Schema.Schema<I, A>,
137
+ handlers: Handlers
138
+ ) => Layer.Layer<
139
+ | PlatformRunner
140
+ | (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
141
+ WorkerError,
142
+ never
143
+ > = internal.layerSerialized
@@ -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>>, Deferred.Deferred<never, void>]
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
- const backing = yield* _(
80
- platform.spawn<Worker.Worker.Request, Worker.Worker.Response<E, O>>(spawn(id))
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 = (msg: Worker.BackingWorker.Message<Worker.Worker.Response<E, O>>) =>
136
+ const handleMessage = (response: Worker.Worker.Response<E, O>) =>
93
137
  Effect.suspend(() => {
94
- switch (msg[0]) {
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 Deferred.complete(readyLatch, Effect.unit)
144
+ return Queue.offer(queue[0], Exit.succeed(response[2]))
97
145
  }
146
+ // end
98
147
  case 1: {
99
- const response = msg[1]
100
- const queue = requestMap.get(response[0])
101
- if (!queue) return Effect.unit
102
-
103
- switch (response[1]) {
104
- // data
105
- case 0: {
106
- return Queue.offer(queue[0], Exit.succeed(response[2]))
107
- }
108
- // end
109
- case 1: {
110
- return response.length === 2 ?
111
- Queue.offer(queue[0], Exit.failCause(Cause.empty)) :
112
- Effect.zipRight(
113
- Queue.offer(queue[0], Exit.succeed(response[2])),
114
- Queue.offer(queue[0], Exit.failCause(Cause.empty))
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]: [number, Queue.Queue<Exit.Exit<E | WorkerError, O>>, Deferred.Deferred<never, void>],
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.of(value)), () => loop)
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.flatten(Queue.take(queue)),
221
+ ([, queue]) => Effect.flatMap(Queue.take(queue), Exit.map(ReadonlyArray.unsafeGet(0))),
185
222
  executeRelease
186
223
  )
187
224
 
188
- const handleMessages = yield* _(
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) => backing.send([id, 0, payload], transferables)
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, join, execute, executeEffect }
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,18 +1,20 @@
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
- import { pipe } from "effect/Function"
9
- import * as Predicate from "effect/Predicate"
9
+ import { identity, pipe } from "effect/Function"
10
+ import * as Layer from "effect/Layer"
11
+ import * as Option from "effect/Option"
10
12
  import * as Queue from "effect/Queue"
11
13
  import type * as Scope from "effect/Scope"
12
14
  import * as Stream from "effect/Stream"
13
15
  import * as Transferable from "../Transferable.js"
14
16
  import type * as Worker from "../Worker.js"
15
- import type * as WorkerError from "../WorkerError.js"
17
+ import * as WorkerError from "../WorkerError.js"
16
18
  import type * as WorkerRunner from "../WorkerRunner.js"
17
19
 
18
20
  /** @internal */
@@ -28,15 +30,25 @@ export const PlatformRunner = Context.Tag<WorkerRunner.PlatformRunner>(
28
30
  /** @internal */
29
31
  export const make = <I, R, E, O>(
30
32
  process: (request: I) => Stream.Stream<R, E, O> | Effect.Effect<R, E, O>,
31
- options?: WorkerRunner.Runner.Options<E, O>
33
+ options?: WorkerRunner.Runner.Options<I, E, O>
32
34
  ) =>
33
35
  Effect.gen(function*(_) {
34
36
  const platform = yield* _(PlatformRunner)
35
37
  const backing = yield* _(platform.start<Worker.Worker.Request<I>, Worker.Worker.Response<E>>())
36
38
  const fiberMap = new Map<number, Fiber.Fiber<never, void>>()
39
+ const parentFiber = Option.getOrThrow(Fiber.getCurrentFiber())
37
40
 
38
- const handleRequests = pipe(
41
+ yield* _(
39
42
  Queue.take(backing.queue),
43
+ options?.decode ?
44
+ Effect.flatMap((req): Effect.Effect<never, WorkerError.WorkerError, Worker.Worker.Request<I>> => {
45
+ if (req[1] === 1) {
46
+ return Effect.succeed(req)
47
+ }
48
+
49
+ return Effect.map(options.decode!(req[2]), (data) => [req[0], req[1], data])
50
+ }) :
51
+ identity,
40
52
  Effect.tap((req) => {
41
53
  const id = req[0]
42
54
  if (req[1] === 1) {
@@ -54,7 +66,7 @@ export const make = <I, R, E, O>(
54
66
  onLeft: (error) => {
55
67
  const transfers = options?.transfers ? options.transfers(error) : undefined
56
68
  return pipe(
57
- options?.encodeError ? options.encodeError(error) : Effect.succeed(error),
69
+ options?.encodeError ? options.encodeError(req[2], error) : Effect.succeed(error),
58
70
  Effect.flatMap((payload) => backing.send([id, 2, payload as any], transfers)),
59
71
  Effect.catchAllCause((cause) => backing.send([id, 3, Cause.squash(cause)]))
60
72
  )
@@ -64,18 +76,30 @@ export const make = <I, R, E, O>(
64
76
  onSuccess: (data) => {
65
77
  const transfers = options?.transfers ? options.transfers(data) : undefined
66
78
  return pipe(
67
- options?.encodeOutput ? options.encodeOutput(data) : Effect.succeed(data),
68
- Effect.flatMap((payload) => backing.send([id, 0, payload], transfers)),
79
+ options?.encodeOutput ? options.encodeOutput(req[2], data) : Effect.succeed(data),
80
+ Effect.flatMap((payload) => backing.send([id, 0, [payload]], transfers)),
69
81
  Effect.catchAllCause((cause) => backing.send([id, 3, Cause.squash(cause)]))
70
82
  )
71
83
  }
72
84
  }) :
73
85
  pipe(
74
86
  stream,
87
+ Stream.chunks,
75
88
  Stream.tap((data) => {
76
- const transfers = options?.transfers ? options.transfers(data) : undefined
89
+ if (options?.encodeOutput === undefined) {
90
+ const payload = Chunk.toReadonlyArray(data)
91
+ const transfers = options?.transfers ? payload.flatMap(options.transfers) : undefined
92
+ return backing.send([id, 0, payload], transfers)
93
+ }
94
+
95
+ const transfers: Array<unknown> = []
77
96
  return Effect.flatMap(
78
- options?.encodeOutput ? Effect.orDie(options.encodeOutput(data)) : Effect.succeed(data),
97
+ Effect.forEach(data, (data) => {
98
+ if (options?.transfers) {
99
+ transfers.push(...options.transfers(data))
100
+ }
101
+ return Effect.orDie(options.encodeOutput!(req[2], data))
102
+ }),
79
103
  (payload) => backing.send([id, 0, payload], transfers)
80
104
  )
81
105
  }),
@@ -86,7 +110,7 @@ export const make = <I, R, E, O>(
86
110
  onLeft: (error) => {
87
111
  const transfers = options?.transfers ? options.transfers(error) : undefined
88
112
  return pipe(
89
- options?.encodeError ? options.encodeError(error) : Effect.succeed(error),
113
+ options?.encodeError ? options.encodeError(req[2], error) : Effect.succeed(error),
90
114
  Effect.flatMap((payload) => backing.send([id, 2, payload as any], transfers)),
91
115
  Effect.catchAllCause((cause) => backing.send([id, 3, Cause.squash(cause)]))
92
116
  )
@@ -104,17 +128,19 @@ export const make = <I, R, E, O>(
104
128
  Effect.tap((fiber) => Effect.sync(() => fiberMap.set(id, fiber)))
105
129
  )
106
130
  }),
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>
131
+ Effect.forever,
132
+ Effect.onInterrupt(() => Fiber.interrupt(parentFiber)),
133
+ Effect.forkScoped
115
134
  )
116
135
  })
117
136
 
137
+ /** @internal */
138
+ export const layer = <I, R, E, O>(
139
+ process: (request: I) => Stream.Stream<R, E, O> | Effect.Effect<R, E, O>,
140
+ options?: WorkerRunner.Runner.Options<I, E, O>
141
+ ): Layer.Layer<WorkerRunner.PlatformRunner | R, WorkerError.WorkerError, never> =>
142
+ Layer.scopedDiscard(make(process, options))
143
+
118
144
  /** @internal */
119
145
  export const makeSerialized = <
120
146
  I,
@@ -133,48 +159,50 @@ export const makeSerialized = <
133
159
  | Scope.Scope
134
160
  | (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
135
161
  WorkerError.WorkerError,
136
- never
162
+ void
137
163
  > => {
138
- const parseRequest = Schema.decode(schema)
139
- const effectTags = new Set<string>()
140
- return make((request: I) => {
141
- if (Predicate.hasProperty(request, "_tag") && effectTags.has(request._tag as string)) {
142
- return Effect.flatMap(parseRequest(request), (request: A) => {
143
- const handler =
144
- (handlers as unknown as Record<string, (req: unknown) => Effect.Effect<never, any, any>>)[request._tag]
145
- if (!handler) {
146
- return Effect.dieMessage(`No handler for ${request._tag}`)
147
- }
148
- const encodeSuccess = Schema.encode(Serializable.successSchema(request as any))
149
- return pipe(
150
- Effect.matchEffect(handler(request), {
151
- onFailure: (error) => Effect.flatMap(Serializable.serializeFailure(request as any, error), Effect.fail),
152
- onSuccess: encodeSuccess
153
- })
154
- )
155
- })
156
- }
157
-
158
- return Stream.flatMap(parseRequest(request), (request: A) => {
159
- const handler =
160
- (handlers as unknown as Record<string, (req: unknown) => Stream.Stream<never, any, any>>)[request._tag]
161
- if (!handler) {
162
- return Stream.dieMessage(`No handler for ${request._tag}`)
163
- }
164
- const encodeSuccess = Schema.encode(Serializable.successSchema(request as any))
165
- const stream = handler(request)
166
- if (Effect.isEffect(stream)) {
167
- effectTags.add(request._tag)
168
- }
169
- return pipe(
170
- stream,
171
- Stream.catchAll((error) => Effect.flatMap(Serializable.serializeFailure(request as any, error), Effect.fail)),
172
- Stream.mapEffect(encodeSuccess)
173
- )
174
- })
175
- }, {
164
+ const parseRequest = Schema.parse(schema)
165
+ return make((request: A) => (handlers as any)[request._tag](request), {
176
166
  transfers(message) {
177
167
  return Transferable.get(message)
168
+ },
169
+ decode(message) {
170
+ return Effect.mapError(
171
+ parseRequest(message),
172
+ (error) => WorkerError.WorkerError("decode", error)
173
+ )
174
+ },
175
+ encodeError(request, message) {
176
+ return Effect.mapError(
177
+ Serializable.serializeFailure(request as any, message),
178
+ (error) => WorkerError.WorkerError("encode", error)
179
+ )
180
+ },
181
+ encodeOutput(request, message) {
182
+ return Effect.mapError(
183
+ Serializable.serializeSuccess(request as any, message),
184
+ (error) => WorkerError.WorkerError("encode", error)
185
+ )
178
186
  }
179
187
  })
180
188
  }
189
+
190
+ /** @internal */
191
+ export const layerSerialized = <
192
+ I,
193
+ A extends Schema.TaggedRequest.Any,
194
+ const Handlers extends {
195
+ readonly [K in A["_tag"]]: Extract<A, { readonly _tag: K }> extends
196
+ Serializable.SerializableWithResult<infer _IS, infer S, infer _IE, infer E, infer _IO, infer O>
197
+ ? (_: S) => Stream.Stream<any, E, O> | Effect.Effect<any, E, O> :
198
+ never
199
+ }
200
+ >(
201
+ schema: Schema.Schema<I, A>,
202
+ handlers: Handlers
203
+ ): Layer.Layer<
204
+ | WorkerRunner.PlatformRunner
205
+ | (ReturnType<Handlers[keyof Handlers]> extends Stream.Stream<infer R, infer _E, infer _A> ? R : never),
206
+ WorkerError.WorkerError,
207
+ never
208
+ > => Layer.scopedDiscard(makeSerialized(schema, handlers))