UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

99 lines (98 loc) 3.42 kB
import { Worker } from 'node:worker_threads'; import * as path from 'path'; import { Configuration } from './configuration.mjs'; import { getModuleDirname, getProjectDirname } from './getDirname.mjs'; import { Logger } from './logger.mjs'; const workers = new Map(); /** * Run the function in a Node.js Worker Thread * @param input * @returns */ async function runInWorker(input) { const func = await Configuration.getLambda(input.fuctionRequest.functionId); return new Promise((resolve, reject) => { let worker = workers.get(input.fuctionRequest.workerId); if (!worker) { worker = startWorker({ handler: func.handler ?? 'handler', artifactFile: input.artifactFile, workerId: input.fuctionRequest.workerId, functionId: input.fuctionRequest.functionId, environment: input.environment, verbose: Configuration.config.verbose, }); } else { Logger.verbose(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Reusing worker`); } worker.on('message', (msg) => { Logger.verbose(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Worker message`, JSON.stringify(msg)); if (msg?.errorType) { reject(msg); } else { resolve(msg); } }); worker.on('error', (err) => { Logger.error(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Error`, err); reject(err); }); worker.postMessage({ env: input.fuctionRequest.env, event: input.fuctionRequest.event, context: input.fuctionRequest.context, }); }); } /** * Start a new Node.js Worker Thread * @param input * @returns */ function startWorker(input) { Logger.verbose(`[Function ${input.functionId}] [Worker ${input.workerId}] Starting worker. Artifact: ${input.artifactFile}`); const localProjectDir = getProjectDirname(); const worker = new Worker(path.resolve(path.join(getModuleDirname(), `./nodeWorkerRunner.mjs`)), { env: { ...input.environment, IS_LOCAL: 'true', LOCAL_PROJECT_DIR: localProjectDir, }, execArgv: ['--enable-source-maps'], workerData: input, stderr: true, stdin: true, stdout: true, //type: "module", }); worker.stdout.on('data', (data) => { Logger.log(`[Function ${input.functionId}]`, data.toString()); }); worker.stderr.on('data', (data) => { Logger.log(`[Function ${input.functionId}]`, data.toString()); }); worker.on('exit', () => { Logger.verbose(`[Function ${input.functionId}] [Worker ${input.workerId}] Worker exited`); workers.delete(input.workerId); }); workers.set(input.workerId, worker); return worker; } /** * Stop all Node.js Worker Threads */ async function stopAllWorkers() { Logger.verbose('Stopping all workers'); const promises = []; for (const worker of workers.values()) { promises.push(worker.terminate()); } workers.clear(); await Promise.all(promises); } export const NodeWorker = { runInWorker, stopAllWorkers, };