| /** | |
| * Client-side worker primitives shared by browser, Node, and Bun adapters. | |
| * | |
| * This module defines the platform-neutral `Worker` client, the `WorkerPlatform` | |
| * service that creates workers by numeric id, and the `Spawner` service used to | |
| * find platform-specific worker instances. `makePlatform` wraps platform setup | |
| * and listen hooks into a `WorkerPlatform`, buffers outgoing messages until the | |
| * worker is ready, runs incoming messages with Effect handlers, and ties worker | |
| * cleanup to scope lifetime. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| import * as Context from "../../Context.js"; | |
| import * as Effect from "../../Effect.js"; | |
| import * as FiberSet from "../../FiberSet.js"; | |
| import * as Latch from "../../Latch.js"; | |
| import * as Layer from "../../Layer.js"; | |
| import * as Scope from "../../Scope.js"; | |
| import { WorkerError, WorkerSendError } from "./WorkerError.js"; | |
| /** | |
| * Service that spawns effect `Worker` instances for numeric worker ids using | |
| * the configured `Spawner`. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export class WorkerPlatform extends /*#__PURE__*/Context.Service()("effect/workers/Worker/WorkerPlatform") {} | |
| /** | |
| * Wraps platform-specific send and run functions into a `Worker`, translating | |
| * platform ready/data messages and running the optional `onSpawn` effect when | |
| * the worker reports readiness. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export const makeUnsafe = options => ({ | |
| send: options.send, | |
| run(handler, options_) { | |
| const onSpawn = options_?.onSpawn ?? Effect.void; | |
| return options.run(msg => { | |
| if (msg[0] === 0) return onSpawn; | |
| return handler(msg[1]); | |
| }); | |
| } | |
| }); | |
| /** | |
| * Service tag for the worker `SpawnerFn`. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| export const Spawner = /*#__PURE__*/Context.Service("effect/workers/Worker/Spawner"); | |
| /** | |
| * Creates a layer that provides a worker `Spawner` service from a `SpawnerFn`. | |
| * | |
| * @category layers | |
| * @since 4.0.0 | |
| */ | |
| export const layerSpawner = /*#__PURE__*/Layer.succeed(Spawner); | |
| /** | |
| * Creates a `WorkerPlatform` from platform-specific setup and listen hooks, | |
| * buffering sent messages until the worker is ready and scoping port cleanup to | |
| * the worker run. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makePlatform = () => options => WorkerPlatform.of({ | |
| spawn(id) { | |
| return Effect.gen(function* () { | |
| const spawn = yield* Spawner; | |
| let currentPort; | |
| const buffer = []; | |
| const run = (handler, opts) => Effect.uninterruptibleMask(restore => Effect.scopedWith(Effect.fnUntraced(function* (scope) { | |
| const port = yield* options.setup({ | |
| worker: spawn(id), | |
| scope | |
| }); | |
| yield* Scope.addFinalizer(scope, Effect.sync(() => { | |
| currentPort = undefined; | |
| })); | |
| const fiberSet = yield* FiberSet.make().pipe(Scope.provide(scope)); | |
| const run = yield* FiberSet.runtime(fiberSet)(); | |
| const ready = Latch.makeUnsafe(); | |
| yield* options.listen({ | |
| port, | |
| scope, | |
| emit(data) { | |
| if (data[0] === 0) { | |
| if (opts?.onSpawn) { | |
| run(Effect.ensuring(opts.onSpawn, ready.open)); | |
| } else { | |
| ready.openUnsafe(); | |
| } | |
| return; | |
| } | |
| run(handler(data[1])); | |
| }, | |
| deferred: fiberSet.deferred | |
| }); | |
| yield* ready.await; | |
| currentPort = port; | |
| if (buffer.length > 0) { | |
| for (const [message, transfers] of buffer) { | |
| port.postMessage([0, message], transfers); | |
| } | |
| buffer.length = 0; | |
| } | |
| return yield* restore(FiberSet.join(fiberSet)); | |
| }))); | |
| const send = (message, transfers) => Effect.suspend(() => { | |
| if (currentPort === undefined) { | |
| buffer.push([message, transfers]); | |
| return Effect.void; | |
| } | |
| try { | |
| currentPort.postMessage([0, message], transfers); | |
| return Effect.void; | |
| } catch (cause) { | |
| return Effect.fail(new WorkerError({ | |
| reason: new WorkerSendError({ | |
| message: "Failed to send message to worker", | |
| cause | |
| }) | |
| })); | |
| } | |
| }); | |
| return { | |
| run, | |
| send | |
| }; | |
| }); | |
| } | |
| }); | |
| //# sourceMappingURL=Worker.js.map |
Xet Storage Details
- Size:
- 4.33 kB
- Xet hash:
- 0fb56397f990c4cc4f7b05d9ab1e3ff9018ed0c51bf85b61ac43f15db27748d5
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.