@atolljs/node
v0.1.6
Published
Node runtime adapter — node:worker_threads pools, no framework
Downloads
873
Readme
@atolljs/node
node:worker_threads runtime adapter for @atolljs/core — lets WorkerPool
and connectWorker run on Node's Worker (an EventEmitter) instead of the
DOM surface they expect. No framework required.
Install
npm install @atolljs/core @atolljs/nodeUsage
// pool.ts — a WorkerPool backed by node:worker_threads
import { Worker } from 'node:worker_threads';
import { createNodePool } from '@atolljs/node';
import { counterMemory } from './counter.memory';
export const pool = createNodePool({
// The factory may return a node:worker_threads.Worker directly — the
// adapter wraps it, so new Worker(new URL(...)) stays bundler-detectable.
worker: () => new Worker(new URL('./counter.worker.js', import.meta.url)),
sharedMemory: counterMemory,
poolSize: 4,
});// counter.worker.ts — the worker entry; the shim binds self = parentPort
// before defineWorker's bootstrap evaluates, so import it first.
import '@atolljs/node/shim';
import { defineWorker } from '@atolljs/core';
import { counterMemory } from './counter.memory';
export const counterWorker = defineWorker({
sharedMemory: counterMemory,
methods: {
increment(delta: number) {
const next = counterMemory.count.read() + delta;
counterMemory.count.write(next);
return next;
},
},
});API
createNodePool({ worker, sharedMemory?, tasks?, … })— aWorkerPoolwith the adapter baked in.workeraccepts a path/URL or a factory returning either a Node or DOM-styleWorker.createNodeWorker(nodeWorker)/NodeWorkerAdapter— wrap a NodeWorker(or worker file path) forconnectWorkeror a hand-builtWorkerPool.@atolljs/node/shim— worker-side entry shim; import first soself = parentPortis bound beforedefineWorker's bootstrap evaluates.withSharedBuffer+bindSharedBuffer— share one contract buffer across pools. Wrap a worker factory withwithSharedBuffer(spawn, bufferOrThunk)so every spawn is fedpool.sharedBuffer(thunk evaluated per spawn — respawns included); the worker entryawaitsbindSharedBuffer()to bind all contracts. For message-only pools whose workers read another pool's memory.@atolljs/node/http— two offload topologies:createHttpCluster(Node ≥ 26): the main thread accepts TCP connections withpauseOnConnectand transfers eachnet.Socketto a pool worker, whereserveHttpfeeds it into anhttp.Serverowned by the worker — parsing, routing, and serialization all off-thread.routeHttpGateway(any Node): path-level ownership — the main thread parses HTTP once and proxies matched prefixes to worker-owned internal listeners (serveHttp(app, { listen: 0 })). Pin/api/a/*to worker A,/api/b/*to worker B, serve the rest on main. WebSocket upgrades match the same prefixes and are tunneled end-to-end; for embedding into a host framework,workerHttpPorts+proxyToWorker(+proxyUpgradeToWorkeron the server'supgradeevent) expose the same machinery as mountable middleware (seeexamples/nestjshoused API). Seeexamples/http-offloadanddocs/frameworks/node.md.
@atolljs/node/redis— shared-memory persistence via Redis (persistSharedMemory/redisMemoryAdapter): field regions mirror to a Redis hash on a version-diff flush, restore into the buffer at boot, and optionally replicate across processes over a pub/sub channel. Pass it aspersistenceoncreateNodePool(orAtollModule.registerPool) — the pool attaches it after bind and callsstop()onterminate().
Notes
SharedArrayBufferworks in Node with no headers — cross-origin isolation is a browser-only requirement.- Building a NestJS app?
@atolljs/nestjswraps this adapter in DI providers and decorator-based method offload.
