Offload functions to worker threads with shared memory primitives for Node.js.
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

test(serve): fd-passing feasibility spike

+55
+55
test/serve/spike.test.ts
··· 1 + import { describe, it } from 'node:test'; 2 + import assert from 'node:assert/strict'; 3 + import { once } from 'node:events'; 4 + import { createServer, connect } from 'node:net'; 5 + import { Worker } from 'node:worker_threads'; 6 + 7 + describe('fd-passing spike', () => { 8 + it('fd extracted on main and reconstructed as net.Socket on a worker thread', async () => { 9 + // Spawn worker with an inline string source 10 + const workerCode = ` 11 + const { parentPort } = require('node:worker_threads'); 12 + const { Socket } = require('node:net'); 13 + parentPort.on('message', ({ fd }) => { 14 + const sock = new Socket({ fd, readable: true, writable: true }); 15 + sock.setNoDelay(true); 16 + sock.write('hello\\n'); 17 + sock.end(); 18 + }); 19 + `; 20 + const worker = new Worker(workerCode, { eval: true }); 21 + 22 + // Main TCP server 23 + const server = createServer(); 24 + const pending = new Set<any>(); // keep detached handles alive during transit 25 + server.on('connection', (socket) => { 26 + // Extract fd (HarperDB approach) 27 + const handle = (socket as any)._handle; 28 + const fd: number = handle.fd; 29 + socket.pause(); 30 + // Orphan the JS socket so socket.destroy() won't close the fd 31 + (socket as any)._handle = null; 32 + socket.destroy(); 33 + // Keep the native handle rooted so GC doesn't close the fd mid-transit; 34 + // release after a short grace period (worker is guaranteed to have set 35 + // up its own uv_tcp_t well before this). 36 + pending.add(handle); 37 + setTimeout(() => pending.delete(handle), 1000).unref(); 38 + worker.postMessage({ fd }); 39 + }); 40 + server.listen(0); 41 + await once(server, 'listening'); 42 + const port = (server.address() as any).port; 43 + 44 + // Client connects, reads the reply 45 + const client = connect(port); 46 + const chunks: Buffer[] = []; 47 + client.on('data', (c) => chunks.push(c)); 48 + await once(client, 'end'); 49 + 50 + assert.equal(Buffer.concat(chunks).toString('utf8'), 'hello\n'); 51 + 52 + server.close(); 53 + await worker.terminate(); 54 + }); 55 + });