Created
October 13, 2025 21:53
-
-
Save robertkraig/041e4e9f758055e33aa1fd1f1e9ff00c to your computer and use it in GitHub Desktop.
NestJS Setting up a node:worker_thread
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { parentPort, workerData } from 'node:worker_threads'; | |
import { NestFactory } from '@nestjs/core'; | |
import { EtlWorkerModule } from './etl.worker.module'; | |
import { EtlWorkerService } from './etl.worker.service'; | |
(async () => { | |
if (!parentPort) throw new Error('Must be run as a worker thread'); | |
const app = await NestFactory.createApplicationContext(EtlWorkerModule, { | |
logger: ['error', 'warn'], | |
}); | |
try { | |
const svc = app.get(EtlWorkerService); | |
const result = await svc.process(workerData as { rows: number[] }); | |
parentPort.postMessage({ ok: true, result }); | |
} catch (err) { | |
parentPort.postMessage({ ok: false, error: (err as Error).message }); | |
} finally { | |
await app.close(); | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Module } from '@nestjs/common'; | |
import { EtlWorkerService } from './etl.worker.service'; | |
@Module({ | |
providers: [EtlWorkerService], | |
exports: [EtlWorkerService], | |
}) | |
export class EtlWorkerModule {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable, Logger } from '@nestjs/common'; | |
@Injectable() | |
export class EtlWorkerService { | |
private readonly logger = new Logger(EtlWorkerService.name); | |
async process(payload: { rows: number[] }) { | |
this.logger.log(`Processing ${payload.rows.length} rows`); | |
// CPU-ish work goes here | |
const data = payload.rows.map((n) => n * 2); | |
return { count: data.length, data }; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable, Logger } from '@nestjs/common'; | |
import { Worker } from 'node:worker_threads'; | |
import { join } from 'node:path'; | |
@Injectable() | |
export class WorkerManagerService { | |
private readonly logger = new Logger(WorkerManagerService.name); | |
runEtl(rows: number[]): Promise<{ count: number; data: number[] }> { | |
// points to the compiled JS in dist/ | |
const workerPath = join(__dirname, 'workers', 'etl.worker.entry.js'); | |
return new Promise((resolve, reject) => { | |
const worker = new Worker(workerPath, { workerData: { rows } }); | |
worker.once('message', (msg: any) => { | |
if (msg?.ok) resolve(msg.result); | |
else reject(new Error(msg?.error ?? 'Worker failed')); | |
}); | |
worker.once('error', (err) => { | |
this.logger.error(err); | |
reject(err); | |
}); | |
worker.once('exit', (code) => { | |
if (code !== 0) this.logger.warn(`Worker exited with code ${code}`); | |
}); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment