Worker Thread, other file than self, cannot find module

409 views Asked by At

I want to have my worker thread as an external file from the runtime file.

My current folder structure is

src/
> service.ts // my 'main'
> thread/
>> test.js

inside my service.ts i have the following boilerplate code

import { Worker, isMainThread } from "worker_threads"

if (isMainThread) {
    const testworker = new Worker('./thread/test.js')
    testworker.on('error', err => console.error({ err }))
    testworker.on('message', msg => console.log({ msg }))
    testworker.on('exit', code => code === 0 ? console.log({ code }) : console.error({ code }))
}

inside my thread/test.js i have the following boilerplate code

import { isMainThread, parentPort } from "worker_threads"

console.log({ isMainThread, parentPort })

parentPort.postMessage("RealCookie")

When I attempt to do this, i receive the following error:

Error: Cannot find module '/srv/FOLDERNAME/thread/test.js'
      at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
      at Function.Module._load (node:internal/modules/cjs/loader:778:27)
      at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
      at MessagePort.<anonymous> (node:internal/main/worker_thread:191:24)
      at MessagePort.[nodejs.internal.kHybridDispatch] (node:internal/event_target:643:20)
      at MessagePort.exports.emitMessage (node:internal/per_context/messageport:23:28) {
    code: 'MODULE_NOT_FOUND',
    requireStack: []
  }

IF i however try to run const testworker = new Worker(__filename) then it happily run the code without issues. I do not really understand why?

--node: v17.9.1

--npm: 8.11.0

--tsconfig.json

{
  "extends": "@tsconfig/node16/tsconfig.json",
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist",
    "noImplicitAny": true,
    "lib": [
      "es2021"
    ],
    "module": "Node16",
    "target": "es2021",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node"
  }
}

--packages

{
  "name": "hidden",
  "version": "1.0.0",
  "main": "dist/service.js",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/node": "^20.4.2",
    "@types/node-cron": "^3.0.8",
    "ts-node": "^10.9.1",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.1.6"
  },
  "dependencies": {
    "@prisma/client": "^5.0",
    "@tsconfig/node16": "^16.1.0",
    "axios": "^1.4.0",
    "core-util-is": "^1.0.3",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "node-cron": "^3.0.2",
    "prisma": "^5.0.0",
    "ulid": "^2.3.0"
  },
  "scripts": {
    "prod": "node dist/service.js",
    "dev": "tsnd --clear src/service",
    "build": "tsc"
  }
}

I really hope this is something simply that I am missing, but at the same time I don't, because I do not want to waste anyones time. Hope someone can see what I am doing wrong here!

1

There are 1 answers

3
ghybs On

Your tsconfig.json specifies the build output folder as different from the source:

  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist",
  }

Therefore once you build your project with tsc, your TS files are transpiled into JS files, which are placed into that dist folder. Which you properly take into account in your start script:

  "scripts": {
    "prod": "node dist/service.js",
  }

...but your thread/test.js file is not copied into that dist folder!

Even though you mention its path for the new Worker, tsc does not look it up, and does not handle it at all.

Hence dist/service.js is unable to spawn a Worker using the relative ./thread/test.js path.

Simply make sure that after build, that path is still correct / non built file are copied over, to reproduce your source file structure. For example you could do something in the lines of:

  "scripts": {
    "build": "tsc && cp src/thread/* dist/thread/"
  }