nestworker 2.0.4 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -137,34 +137,6 @@ export class ImageController {
137
137
  ```
138
138
  ---
139
139
 
140
- ## Using Modules Inside Task Methods
141
-
142
- Worker tasks are reconstructed from class source via `eval()`. Top-level `import` statements from your file are **not available** inside the worker. Use one of these two patterns instead.
143
-
144
- ### Dynamic import — preferred
145
-
146
- `import()` is a language keyword, not a variable. It works natively inside `eval()`'d code with no setup, and is compatible with both ESM and CommonJS projects.
147
-
148
- ```ts
149
- @WorkerTask()
150
- async moduleImport(): Promise<string> {
151
- const os = await import('node:os');
152
- return `Import os size ${os.cpus().length}`
153
- }
154
- ```
155
-
156
- ### Inline `require()` — CJS projects only
157
-
158
- `require` is injected into the eval scope by `WorkerContainer`, so it works in CommonJS projects.
159
-
160
- ```ts
161
- @WorkerTask()
162
- async moduleRequire(): Promise<string> {
163
- const os = require('node:os');
164
- return `Require os size ${os.cpus().length}`
165
- }
166
- ```
167
-
168
140
  ### What is safe to import inside a worker
169
141
 
170
142
  | ✅ Safe | ❌ Not safe |
@@ -252,42 +224,43 @@ Returns a `Promise<T>` that resolves with the method's return value.
252
224
 
253
225
  ## How DI in Workers Works
254
226
 
255
- Worker threads run in an isolated V8 context — they share no heap with the main thread. Passing live NestJS services across the boundary is impossible.
227
+ Worker threads run in an isolated V8 context — they share no heap with the main thread. Passing live NestJS services across the boundary is not possible directly.
228
+
229
+ nestworker solves it in three steps:
256
230
 
257
- This module solves it in three steps:
231
+ **1. Main thread locate compiled files**
258
232
 
259
- **1. Main thread `serializeForWorker()`**
233
+ `serializeForWorker()` walks `require.cache` to find the compiled `.js` file path for each dep constructor. It also snapshots each dep's own properties via `structuredClone` to capture runtime state (e.g. loaded config values).
260
234
 
261
- `Class.toString()` extracts each class as a plain JS source string (no imports, no decorators). Each dep's data properties are snapshotted via `structuredClone`. Both are sent to workers via `workerData`.
235
+ **2. Worker thread `vm.runInContext()`**
262
236
 
263
- **2. Worker thread`WorkerContainer`**
237
+ Each compiled `.js` file is executed inside a `vm` context with a custom `require()` that stubs NestJS decorator packages (`@nestjs/common`, `@nestjs/core`, etc.) so that decorator calls at file-eval time are silent no-ops. All other imports resolve normally through Node's module system including Node built-ins and third-party packages.
264
238
 
265
- The class source strings are `eval()`'d back into constructors. Each dep is reconstructed as `Object.create(DepClass.prototype) + Object.assign(snapshot)` restoring prototype methods AND runtime state. The service class is then `new ServiceClass(...depInstances)`.
239
+ Each dep is reconstructed as `Object.create(DepClass.prototype)` + `Object.assign(snapshot)`, restoring both prototype methods and runtime state. The dep is then assigned to the service instance by property key.
266
240
 
267
241
  **3. Result**
268
242
 
269
- `this.configService.get('KEY')` inside a worker task works exactly as on the main thread — as long as the dep reads from plain data (no DB connections, no HTTP clients).
243
+ `this.configService.get('KEY')` inside a worker task works exactly as on the main thread.
270
244
 
271
245
  ```
272
- MAIN THREAD WORKER THREAD
273
- ──────────────────────────────── ────────────────────────────────────
274
- WorkerService.run()
275
- discovery.scan()
276
- ConfigService live instance
277
- → snapshot: { config: {...} } → Object.create(ConfigService.prototype)
278
- classSource: "class Cfg..." eval("class ConfigService { get()... }")
279
- Object.assign(inst, snapshot)
280
- ImageService classSource → eval("class ImageService {...}")
281
- new ImageService(configInst)
282
- this.configService.get() ✓
246
+ MAIN THREAD WORKER THREAD
247
+ ───────────────────────────────────── ──────────────────────────────────────
248
+ serializeForWorker()
249
+ ConfigService filePath + snapshot → vm.runInContext(config.service.js)
250
+ Object.create(ConfigService.prototype)
251
+ Object.assign(inst, snapshot)
252
+ ImageService filePath vm.runInContext(image.service.js)
253
+ Object.create(ImageService.prototype)
254
+ inst.configService = configInst
255
+ this.configService.get()
283
256
  ```
284
257
 
285
- ### What deps can be passed to workers
258
+ ### What deps can be used
286
259
 
287
- ✅ Services holding plain config data (`Record`, `Map`, arrays, primitives)
288
- ✅ Services whose methods only read from their own properties
260
+ ✅ Services holding plain config data (`object`, `Map`, arrays, primitives)
261
+ ✅ Services whose methods only read from their own snapshotted properties
289
262
  ❌ Services that hold DB connections, HTTP clients, or open streams
290
- ❌ Services with `Socket`, `Stream`, or non-cloneable properties
263
+ ❌ Services with `Socket`, `Stream`, or other non-cloneable properties
291
264
 
292
265
  ---
293
266
 
@@ -1,4 +1,4 @@
1
- import { OnModuleDestroy } from '@nestjs/common';
1
+ import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
2
2
  import { WorkerDiscoveryService } from '../discovery/discovery.service';
3
3
  import type { TaskPriority, WorkerModuleOptions } from './worker.interfaces';
4
4
  /**
@@ -35,12 +35,13 @@ import type { TaskPriority, WorkerModuleOptions } from './worker.interfaces';
35
35
  * );
36
36
  * ```
37
37
  */
38
- export declare class WorkerService implements OnModuleDestroy {
38
+ export declare class WorkerService implements OnModuleInit, OnModuleDestroy {
39
39
  private readonly discovery;
40
40
  private readonly options;
41
41
  private pool;
42
42
  private readonly taskOptions;
43
43
  constructor(discovery: WorkerDiscoveryService, options: WorkerModuleOptions);
44
+ onModuleInit(): void;
44
45
  private initPool;
45
46
  /**
46
47
  * Executes a worker task.
@@ -60,6 +60,9 @@ let WorkerService = class WorkerService {
60
60
  this.discovery = discovery;
61
61
  this.options = options;
62
62
  }
63
+ onModuleInit() {
64
+ this.initPool();
65
+ }
63
66
  initPool() {
64
67
  if (this.pool)
65
68
  return;
@@ -102,7 +105,6 @@ let WorkerService = class WorkerService {
102
105
  * ```
103
106
  */
104
107
  run(serviceName, methodName, args = [], overrides = {}) {
105
- this.initPool();
106
108
  const key = `${serviceName}.${methodName}`;
107
109
  const defaults = this.taskOptions.get(key) ??
108
110
  { priority: 'NORMAL' };
@@ -1 +1 @@
1
- {"version":3,"file":"worker.service.js","sourceRoot":"","sources":["../../src/core/worker.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmE;AACnE,+CAAyC;AACzC,sEAAsE;AACtE,uDAAuD;AAGvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAa;IAWL;IAEA;IAZX,IAAI,GAAsB,IAAI,CAAC;IACtB,WAAW,GAAG,IAAI,GAAG,EAMnC,CAAC;IAEJ,YACmB,SAAiC,EAEjC,OAA4B;QAF5B,cAAS,GAAT,SAAS,CAAwB;QAEjC,YAAO,GAAP,OAAO,CAAqB;IAE/C,CAAC;IAEO,QAAQ;QACd,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QAEtB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAEpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,CAAC,GAAG,CAClB,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,UAAU,EAAE,EACxC,EAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAC,CACjD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,kCAAkB,EAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,GAAG,IAAI,wBAAU,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,GAAG,CACD,WAAmB,EACnB,UAAkB,EAClB,OAAkB,EAAE,EACpB,YAA2D,EAAE;QAE7D,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEhB,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,UAAU,EAAE,CAAC;QAE3C,MAAM,QAAQ,GACZ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YACzB,EAAC,QAAQ,EAAE,QAAwB,EAAC,CAAC;QAEvC,OAAO,IAAI,CAAC,IAAK,CAAC,OAAO,CAAI;YAC3B,WAAW;YACX,UAAU;YACV,IAAI;YACJ,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;YACjD,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO;SAC/C,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IAC7B,CAAC;CACF,CAAA;AAjGY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAaR,WAAA,IAAA,eAAM,EAAC,gBAAgB,CAAC,CAAA;qCADG,0CAAsB;GAXzC,aAAa,CAiGzB"}
1
+ {"version":3,"file":"worker.service.js","sourceRoot":"","sources":["../../src/core/worker.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmF;AACnF,+CAAyC;AACzC,sEAAsE;AACtE,uDAAuD;AAGvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAa;IAWL;IAEA;IAZX,IAAI,GAAsB,IAAI,CAAC;IACtB,WAAW,GAAG,IAAI,GAAG,EAMnC,CAAC;IAEJ,YACmB,SAAiC,EAEjC,OAA4B;QAF5B,cAAS,GAAT,SAAS,CAAwB;QAEjC,YAAO,GAAP,OAAO,CAAqB;IAE/C,CAAC;IAED,YAAY;QACV,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAEO,QAAQ;QACd,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QAEtB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAEpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,CAAC,GAAG,CAClB,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,UAAU,EAAE,EACxC,EAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAC,CACjD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,kCAAkB,EAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,GAAG,IAAI,wBAAU,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,GAAG,CACD,WAAmB,EACnB,UAAkB,EAClB,OAAkB,EAAE,EACpB,YAA2D,EAAE;QAE7D,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,UAAU,EAAE,CAAC;QAE3C,MAAM,QAAQ,GACZ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YACzB,EAAC,QAAQ,EAAE,QAAwB,EAAC,CAAC;QAEvC,OAAO,IAAI,CAAC,IAAK,CAAC,OAAO,CAAI;YAC3B,WAAW;YACX,UAAU;YACV,IAAI;YACJ,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;YACjD,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO;SAC/C,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IAC7B,CAAC;CACF,CAAA;AAnGY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAaR,WAAA,IAAA,eAAM,EAAC,gBAAgB,CAAC,CAAA;qCADG,0CAAsB;GAXzC,aAAa,CAmGzB"}
@@ -4,15 +4,16 @@ import type { SerializedService } from './worker-container';
4
4
  * serializeForWorker – converts the live NestJS service graph into a
5
5
  * structured-clone-safe SerializedService[] payload for workerData.
6
6
  *
7
- * KEY DESIGN DECISION: class source extraction instead of file paths.
7
+ * KEY DESIGN DECISION: file paths instead of class source strings.
8
8
  *
9
- * We cannot pass filePaths to workers because require(filePath) inside a
10
- * worker thread re-executes the compiled .ts output which imports @nestjs/common
11
- * at the top level crashing the isolated worker context.
9
+ * The previous approach extracted class source via Class.toString() and
10
+ * eval()'d it inside the worker. This broke on any import that TS compiled
11
+ * to a file-scoped alias (crypto_1, node_os_1, …) because those aliases
12
+ * don't exist inside a bare new Function() scope.
12
13
  *
13
- * Instead we extract each class's constructor and prototype methods as plain JS
14
- * source strings on the main thread (where NestJS is fully loaded), then send
15
- * those strings via workerData. WorkerContainer eval()s them in the worker
16
- * no require(), no NestJS imports, no crash.
14
+ * The new approach sends the absolute path to each compiled .js file.
15
+ * WorkerContainer runs each file in a vm context with a custom require()
16
+ * that stubs NestJS packages (so decorator calls at file-eval time are
17
+ * silent no-ops) while letting all other imports resolve normally.
17
18
  */
18
19
  export declare function serializeForWorker(tasks: DiscoveredTask[]): SerializedService[];
@@ -6,16 +6,17 @@ const worker_task_decorator_1 = require("../decorators/worker-task.decorator");
6
6
  * serializeForWorker – converts the live NestJS service graph into a
7
7
  * structured-clone-safe SerializedService[] payload for workerData.
8
8
  *
9
- * KEY DESIGN DECISION: class source extraction instead of file paths.
9
+ * KEY DESIGN DECISION: file paths instead of class source strings.
10
10
  *
11
- * We cannot pass filePaths to workers because require(filePath) inside a
12
- * worker thread re-executes the compiled .ts output which imports @nestjs/common
13
- * at the top level crashing the isolated worker context.
11
+ * The previous approach extracted class source via Class.toString() and
12
+ * eval()'d it inside the worker. This broke on any import that TS compiled
13
+ * to a file-scoped alias (crypto_1, node_os_1, …) because those aliases
14
+ * don't exist inside a bare new Function() scope.
14
15
  *
15
- * Instead we extract each class's constructor and prototype methods as plain JS
16
- * source strings on the main thread (where NestJS is fully loaded), then send
17
- * those strings via workerData. WorkerContainer eval()s them in the worker
18
- * no require(), no NestJS imports, no crash.
16
+ * The new approach sends the absolute path to each compiled .js file.
17
+ * WorkerContainer runs each file in a vm context with a custom require()
18
+ * that stubs NestJS packages (so decorator calls at file-eval time are
19
+ * silent no-ops) while letting all other imports resolve normally.
19
20
  */
20
21
  function serializeForWorker(tasks) {
21
22
  const byService = new Map();
@@ -31,21 +32,32 @@ function serializeForWorker(tasks) {
31
32
  }
32
33
  const result = [];
33
34
  for (const [serviceName, { representative, methods }] of byService) {
34
- const { metatype, instance, deps } = representative;
35
+ const { metatype, instance } = representative;
35
36
  const depTypes = Reflect.getMetadata(worker_task_decorator_1.WORKER_DEPS_META, metatype) ?? [];
36
- const serializedDeps = depTypes.map((DepType, i) => {
37
- const depInstance = deps[i];
38
- const propertyKey = findDepPropertyKey(instance, depInstance) ?? camelCase(DepType.name);
37
+ const serializedDeps = depTypes.map((DepType) => {
38
+ // Derive the property key from the class name first as a candidate,
39
+ // then verify by looking at the live instance's own properties.
40
+ // We read the dep instance DIRECTLY from the service instance's property
41
+ // rather than from moduleRef.get() — this avoids the NestJS Proxy
42
+ // mismatch where moduleRef returns the real instance but the service
43
+ // holds a lazy Proxy wrapper (different references, same underlying object).
44
+ const candidateKey = camelCase(DepType.name);
45
+ const propertyKey = findDepPropertyKey(instance, DepType) ?? candidateKey;
46
+ // Always read the dep from the live service instance by property key —
47
+ // this gives us the exact object the service will use at runtime,
48
+ // including any NestJS Proxy wrapper, so snapshot captures real state.
49
+ const depInstance = instance[propertyKey] ??
50
+ instance[candidateKey];
39
51
  return {
40
52
  name: DepType.name,
41
- classSource: extractClassSource(DepType),
53
+ filePath: findFilePath(DepType),
42
54
  snapshot: snapshotInstance(depInstance),
43
- propertyKey,
55
+ propertyKey: propertyKey ?? candidateKey,
44
56
  };
45
57
  });
46
58
  result.push({
47
59
  name: serviceName,
48
- classSource: extractClassSource(metatype),
60
+ filePath: findFilePath(metatype),
49
61
  methods,
50
62
  deps: serializedDeps,
51
63
  });
@@ -53,38 +65,43 @@ function serializeForWorker(tasks) {
53
65
  return result;
54
66
  }
55
67
  /**
56
- * Extract a plain, self-contained class source string from a constructor.
57
- *
58
- * In TypeScript compiled output, Function.prototype.toString() on a class
59
- * returns the full class body including all methods — but WITHOUT the
60
- * import statements or decorator calls at the top of the file.
61
- *
62
- * Example output:
63
- * "class ConfigService {
64
- * constructor() { this.config = { MULTIPLIER: '3' }; }
65
- * get(k) { return this.config[k]; }
66
- * getNumber(k) { return Number(this.config[k]); }
67
- * }"
68
- *
69
- * This is eval()-safe and has no NestJS dependencies.
68
+ * Locate the compiled .js file for this constructor by scanning require.cache.
69
+ * NestJS loads all providers via require() so every user-defined class will
70
+ * be present in the cache at the time serializeForWorker() is called.
70
71
  */
71
- function extractClassSource(metatype) {
72
- const src = metatype.toString();
73
- // Compiled TS classes always start with "class ClassName"
74
- // Strip any leading helper assignments TypeScript sometimes emits
75
- const classStart = src.indexOf('class ');
76
- if (classStart === -1) {
77
- throw new Error(`Could not extract class source for "${metatype.name}". ` +
78
- `Ensure the project is compiled with "target": "ES2022" or higher ` +
79
- `so classes are emitted as native class declarations, not functions.`);
72
+ function findFilePath(ctor) {
73
+ for (const [filePath, mod] of Object.entries(require.cache)) {
74
+ if (!mod?.exports || typeof mod.exports !== 'object')
75
+ continue;
76
+ // Object.values() triggers getters on prototype-based exports (e.g. Express
77
+ // IncomingMessage.protocol accesses this.socket which is undefined at scan
78
+ // time). Iterate keys manually and guard each access with try/catch.
79
+ for (const key of Object.keys(mod.exports)) {
80
+ // Skip getters entirely accessing them may trigger deprecation warnings
81
+ // (e.g. Express req.host) or throw (e.g. IncomingMessage.protocol).
82
+ // Constructors are always plain value exports, never getters.
83
+ const desc = Object.getOwnPropertyDescriptor(mod.exports, key);
84
+ if (!desc || typeof desc.get === 'function')
85
+ continue;
86
+ if (desc.value === ctor)
87
+ return filePath;
88
+ }
80
89
  }
81
- return src.slice(classStart);
90
+ throw new Error(`nestworker: could not find compiled file for "${ctor.name}" in require.cache. ` +
91
+ `Ensure the class is exported from its module file and the project is ` +
92
+ `compiled (not running via ts-node) before starting.`);
82
93
  }
83
- function findDepPropertyKey(serviceInstance, depInstance) {
94
+ function findDepPropertyKey(serviceInstance, DepType) {
84
95
  if (!serviceInstance || typeof serviceInstance !== 'object')
85
96
  return undefined;
86
- for (const [key, value] of Object.entries(serviceInstance)) {
87
- if (value === depInstance)
97
+ // private readonly fields are non-enumerable — must use getOwnPropertyNames().
98
+ // We match by constructor type rather than reference equality to correctly
99
+ // handle NestJS Proxy wrappers: the service may hold a Proxy of the dep
100
+ // while moduleRef.get() returns the unwrapped instance — different refs,
101
+ // same underlying class. instanceof sees through Proxy transparently.
102
+ for (const key of Object.getOwnPropertyNames(serviceInstance)) {
103
+ const val = serviceInstance[key];
104
+ if (val instanceof DepType)
88
105
  return key;
89
106
  }
90
107
  return undefined;
@@ -93,14 +110,20 @@ function snapshotInstance(instance) {
93
110
  if (!instance || typeof instance !== 'object')
94
111
  return {};
95
112
  const out = {};
96
- for (const [k, v] of Object.entries(instance)) {
113
+ // private readonly fields are non-enumerable — must use getOwnPropertyNames()
114
+ for (const k of Object.getOwnPropertyNames(instance)) {
115
+ const v = instance[k];
97
116
  if (typeof v === 'function' || typeof v === 'symbol')
98
117
  continue;
99
118
  try {
100
- structuredClone(v);
101
- out[k] = v;
119
+ // Store the CLONED value, not the original reference.
120
+ // structuredClone succeeds for plain outer objects even when they
121
+ // contain non-cloneable internal slots nested deeply — in that case
122
+ // storing `v` would pass a live socket/stream reference into workerData,
123
+ // producing broken objects with missing internal state in the worker.
124
+ out[k] = structuredClone(v);
102
125
  }
103
- catch { /* skip non-cloneable */ }
126
+ catch { /* skip non-cloneable values entirely */ }
104
127
  }
105
128
  return out;
106
129
  }
@@ -1 +1 @@
1
- {"version":3,"file":"di-serializer.js","sourceRoot":"","sources":["../../src/di/di-serializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"di-serializer.js","sourceRoot":"","sources":["../../src/di/di-serializer.ts"],"names":[],"mappings":"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"}
@@ -1,33 +1,24 @@
1
1
  /**
2
2
  * WorkerContainer – minimal DI container for worker threads.
3
3
  *
4
- * WHY NOT require(filePath)?
5
- * Compiled NestJS files import @nestjs/common at the top — requiring them
6
- * inside a worker triggers the full NestJS bootstrap chain which throws.
4
+ * APPROACH: vm.runInNewContext() with a shared module cache.
7
5
  *
8
- * THE FIX: extract each class as a plain JS string on the main thread via
9
- * Class.toString() (no imports, no decorators), send through workerData,
10
- * and eval() back into a constructor inside the worker.
6
+ * Each compiled .js file is executed inside a vm context that has:
7
+ * - A custom require() that blocks NestJS bootstrap imports (returning
8
+ * transparent Proxy stubs so decorator calls at file-eval time are no-ops)
9
+ * - Full access to Node built-ins and third-party packages
10
+ * - Correct __filename / __dirname so relative requires resolve properly
11
11
  *
12
- * WHY HELPERS ARE INJECTED:
13
- * new Function() runs in the global scope. TypeScript compiles dynamic
14
- * imports using file-level helpers:
15
- *
16
- * await import('node:os')
17
- * → Promise.resolve().then(() => __importStar(require('node:os')))
18
- *
19
- * These helpers are defined as `(this && this.__importStar)` at the top of
20
- * each compiled file — `this` being the module. Inside new Function(),
21
- * `this` is the global object so all helpers resolve to undefined, causing:
22
- * Fatal: Error: __importStar is not defined
23
- *
24
- * We define the helpers here (Node 16+ always has Object.create, no ternary
25
- * needed) and inject them alongside require as explicit parameters so both
26
- * `await import()` and `require()` work correctly inside task methods.
12
+ * This avoids every problem of the new Function() approach:
13
+ * - No alias injection (crypto_1, node_os_1, …)
14
+ * - No TS helper injection (__importStar, __importDefault, …)
15
+ * - No class-body-only extraction — the full compiled file runs as-is
16
+ * - Dynamic import() and require() both work natively
27
17
  */
28
18
  export interface SerializedDep {
29
19
  name: string;
30
- classSource: string;
20
+ /** Absolute path to the compiled .js file that exports this class */
21
+ filePath: string;
31
22
  snapshot: Record<string, unknown>;
32
23
  propertyKey: string;
33
24
  }
@@ -38,21 +29,32 @@ export interface SerializedMethod {
38
29
  }
39
30
  export interface SerializedService {
40
31
  name: string;
41
- classSource: string;
32
+ /** Absolute path to the compiled .js file that exports this class */
33
+ filePath: string;
42
34
  methods: SerializedMethod[];
43
35
  deps: SerializedDep[];
44
36
  }
45
37
  export declare class WorkerContainer {
46
38
  private readonly instances;
39
+ /**
40
+ * Module export cache — keyed by absolute file path.
41
+ * Avoids re-executing the same file multiple times when several services
42
+ * live in the same compiled output (monorepo barrel files, etc.).
43
+ */
44
+ private readonly fileCache;
47
45
  load(services: SerializedService[]): void;
48
46
  get<T>(name: string): T;
49
- private reconstructFromSource;
47
+ private reconstructFromFile;
48
+ /**
49
+ * Load a named export from a compiled .js file by running it in a vm
50
+ * context. The context's require() stubs NestJS packages so decorators
51
+ * at file-eval time are silent no-ops, while all other imports resolve
52
+ * normally through the real Node module system.
53
+ */
54
+ private loadClass;
50
55
  /**
51
- * eval() a plain class declaration and return the constructor.
52
- *
53
- * require + all four TypeScript CJS helpers are injected as explicit
54
- * parameters so that compiled dynamic imports (`await import(...)`) and
55
- * inline require() calls inside task methods work correctly.
56
+ * Execute a compiled .js file in an isolated vm context and return its
57
+ * module.exports. Results are cached by file path.
56
58
  */
57
- private evalClass;
59
+ private runFile;
58
60
  }
@@ -2,77 +2,92 @@
2
2
  /**
3
3
  * WorkerContainer – minimal DI container for worker threads.
4
4
  *
5
- * WHY NOT require(filePath)?
6
- * Compiled NestJS files import @nestjs/common at the top — requiring them
7
- * inside a worker triggers the full NestJS bootstrap chain which throws.
5
+ * APPROACH: vm.runInNewContext() with a shared module cache.
8
6
  *
9
- * THE FIX: extract each class as a plain JS string on the main thread via
10
- * Class.toString() (no imports, no decorators), send through workerData,
11
- * and eval() back into a constructor inside the worker.
7
+ * Each compiled .js file is executed inside a vm context that has:
8
+ * - A custom require() that blocks NestJS bootstrap imports (returning
9
+ * transparent Proxy stubs so decorator calls at file-eval time are no-ops)
10
+ * - Full access to Node built-ins and third-party packages
11
+ * - Correct __filename / __dirname so relative requires resolve properly
12
12
  *
13
- * WHY HELPERS ARE INJECTED:
14
- * new Function() runs in the global scope. TypeScript compiles dynamic
15
- * imports using file-level helpers:
13
+ * This avoids every problem of the new Function() approach:
14
+ * - No alias injection (crypto_1, node_os_1, …)
15
+ * - No TS helper injection (__importStar, __importDefault, …)
16
+ * - No class-body-only extraction — the full compiled file runs as-is
17
+ * - Dynamic import() and require() both work natively
18
+ */
19
+ var __importDefault = (this && this.__importDefault) || function (mod) {
20
+ return (mod && mod.__esModule) ? mod : { "default": mod };
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.WorkerContainer = void 0;
24
+ const node_vm_1 = __importDefault(require("node:vm"));
25
+ const node_path_1 = __importDefault(require("node:path"));
26
+ const node_module_1 = __importDefault(require("node:module"));
27
+ const node_fs_1 = __importDefault(require("node:fs"));
28
+ /**
29
+ * NestJS packages that must never be required inside a worker.
30
+ * Requiring them triggers the full NestJS bootstrap chain which crashes
31
+ * in an isolated vm context. We stub them with a transparent Proxy so
32
+ * decorator calls (@Injectable, @Controller, etc.) at file-eval time
33
+ * become silent no-ops.
34
+ */
35
+ const NESTJS_STUB_PACKAGES = new Set([
36
+ '@nestjs/common',
37
+ '@nestjs/core',
38
+ '@nestjs/microservices',
39
+ '@nestjs/platform-express',
40
+ '@nestjs/platform-fastify',
41
+ 'reflect-metadata',
42
+ ]);
43
+ /**
44
+ * A Proxy that silently absorbs NestJS decorator calls at file-eval time.
16
45
  *
17
- * await import('node:os')
18
- * Promise.resolve().then(() => __importStar(require('node:os')))
46
+ * The apply trap passes through its first argument when it is a function —
47
+ * this preserves the class through decorator factory patterns emitted by TS:
19
48
  *
20
- * These helpers are defined as `(this && this.__importStar)` at the top of
21
- * each compiled file `this` being the module. Inside new Function(),
22
- * `this` is the global object so all helpers resolve to undefined, causing:
23
- * Fatal: Error: __importStar is not defined
49
+ * MyClass = Injectable()(MyClass) ?? MyClass
50
+ * └─ NOOP_STUB() ──┘└─ apply(MyClass) MyClass ─┘
24
51
  *
25
- * We define the helpers here (Node 16+ always has Object.create, no ternary
26
- * needed) and inject them alongside require as explicit parameters so both
27
- * `await import()` and `require()` work correctly inside task methods.
52
+ * Without this, NOOP_STUB would replace the class, breaking all exports.
28
53
  */
29
- Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.WorkerContainer = void 0;
31
- // ── TypeScript CJS helpers ────────────────────────────────────────────────
32
- // Node 16+ always has Object.create — no legacy ternary branch needed.
33
- function __createBinding(o, m, k, k2) {
34
- if (k2 === undefined)
35
- k2 = k;
36
- const desc = Object.getOwnPropertyDescriptor(m, k);
37
- if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
38
- Object.defineProperty(o, k2, { enumerable: true, get: () => m[k] });
39
- }
40
- else {
41
- o[k2] = m[k];
42
- }
43
- }
44
- function __setModuleDefault(o, v) {
45
- Object.defineProperty(o, 'default', { enumerable: true, value: v });
46
- }
47
- function __importStar(mod) {
48
- if (mod && mod.__esModule)
49
- return mod;
50
- const result = {};
51
- if (mod != null) {
52
- for (const k of Object.getOwnPropertyNames(mod)) {
53
- if (k !== 'default')
54
- __createBinding(result, mod, k);
55
- }
56
- }
57
- __setModuleDefault(result, mod);
58
- return result;
59
- }
60
- function __importDefault(mod) {
61
- return mod && mod.__esModule ? mod : { default: mod };
62
- }
54
+ const NOOP_STUB = new Proxy(
55
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
56
+ function () { }, {
57
+ get: (_t, _k) => NOOP_STUB,
58
+ apply: (_t, _this, args) => {
59
+ // If called with a class/function as the first arg (decorator pattern),
60
+ // return it unchanged so the assignment keeps the real class.
61
+ const first = args[0];
62
+ return typeof first === 'function' ? first : NOOP_STUB;
63
+ },
64
+ construct: () => Object.create(null),
65
+ });
63
66
  // ── WorkerContainer ───────────────────────────────────────────────────────
64
67
  class WorkerContainer {
65
68
  instances = new Map();
69
+ /**
70
+ * Module export cache — keyed by absolute file path.
71
+ * Avoids re-executing the same file multiple times when several services
72
+ * live in the same compiled output (monorepo barrel files, etc.).
73
+ */
74
+ fileCache = new Map();
66
75
  load(services) {
67
76
  for (const svc of services) {
68
- const depInstances = [];
77
+ // Reconstruct each dep from its compiled file + snapshot
78
+ const depsByKey = new Map();
69
79
  for (const dep of svc.deps) {
70
- const inst = this.reconstructFromSource(dep.classSource, dep.name, dep.snapshot);
80
+ const inst = this.reconstructFromFile(dep.filePath, dep.name, dep.snapshot);
71
81
  this.instances.set(dep.name, inst);
72
- depInstances.push(inst);
82
+ depsByKey.set(dep.propertyKey, inst);
83
+ }
84
+ // Allocate the service without calling its constructor — deps are
85
+ // assigned by property key so constructor slot order never matters.
86
+ const ServiceClass = this.loadClass(svc.filePath, svc.name);
87
+ const serviceInstance = Object.create(ServiceClass.prototype);
88
+ for (const [key, inst] of depsByKey) {
89
+ serviceInstance[key] = inst;
73
90
  }
74
- const ServiceClass = this.evalClass(svc.classSource, svc.name);
75
- const serviceInstance = new ServiceClass(...depInstances);
76
91
  this.instances.set(svc.name, serviceInstance);
77
92
  }
78
93
  }
@@ -82,29 +97,74 @@ class WorkerContainer {
82
97
  throw new Error(`WorkerContainer: "${name}" not found`);
83
98
  return inst;
84
99
  }
85
- reconstructFromSource(classSource, className, snapshot) {
86
- const DepClass = this.evalClass(classSource, className);
100
+ reconstructFromFile(filePath, className, snapshot) {
101
+ const DepClass = this.loadClass(filePath, className);
87
102
  const instance = Object.create(DepClass.prototype);
88
103
  Object.assign(instance, snapshot);
89
104
  return instance;
90
105
  }
91
106
  /**
92
- * eval() a plain class declaration and return the constructor.
93
- *
94
- * require + all four TypeScript CJS helpers are injected as explicit
95
- * parameters so that compiled dynamic imports (`await import(...)`) and
96
- * inline require() calls inside task methods work correctly.
107
+ * Load a named export from a compiled .js file by running it in a vm
108
+ * context. The context's require() stubs NestJS packages so decorators
109
+ * at file-eval time are silent no-ops, while all other imports resolve
110
+ * normally through the real Node module system.
97
111
  */
98
- evalClass(classSource, className) {
99
- // eslint-disable-next-line no-new-func
100
- const factory = new Function('require', '__importStar', '__importDefault', '__createBinding', '__setModuleDefault', `return (${classSource})`);
101
- // eslint-disable-next-line @typescript-eslint/no-require-imports
102
- const cls = factory(require, __importStar, __importDefault, __createBinding, __setModuleDefault);
112
+ loadClass(filePath, className) {
113
+ const exports = this.runFile(filePath);
114
+ const cls = exports[className];
103
115
  if (typeof cls !== 'function') {
104
- throw new Error(`WorkerContainer: eval of "${className}" did not return a constructor`);
116
+ throw new Error(`WorkerContainer: "${className}" not found in "${filePath}". ` +
117
+ `Available exports: ${Object.keys(exports).join(', ')}`);
105
118
  }
106
119
  return cls;
107
120
  }
121
+ /**
122
+ * Execute a compiled .js file in an isolated vm context and return its
123
+ * module.exports. Results are cached by file path.
124
+ */
125
+ runFile(filePath) {
126
+ const cached = this.fileCache.get(filePath);
127
+ if (cached)
128
+ return cached;
129
+ const source = node_fs_1.default.readFileSync(filePath, 'utf8');
130
+ const mod = { exports: {} };
131
+ const customRequire = node_module_1.default.createRequire(filePath);
132
+ const sandboxRequire = (id) => {
133
+ if (NESTJS_STUB_PACKAGES.has(id))
134
+ return NOOP_STUB;
135
+ return customRequire(id);
136
+ };
137
+ const context = node_vm_1.default.createContext({
138
+ require: sandboxRequire,
139
+ module: mod,
140
+ exports: mod.exports,
141
+ __filename: filePath,
142
+ __dirname: node_path_1.default.dirname(filePath),
143
+ // Standard globals the compiled output may reference
144
+ console,
145
+ process,
146
+ Buffer,
147
+ URL,
148
+ URLSearchParams,
149
+ fetch,
150
+ setTimeout,
151
+ clearTimeout,
152
+ setInterval,
153
+ clearInterval,
154
+ setImmediate,
155
+ clearImmediate,
156
+ Promise,
157
+ // Make the context's global === the context itself so that
158
+ // `(this && this.__importStar)` patterns resolve to the context global
159
+ // rather than to undefined (as they would in new Function()).
160
+ global: undefined, // set below after createContext
161
+ });
162
+ // Wire global → context so self-referential global patterns work
163
+ context.global = context;
164
+ node_vm_1.default.runInContext(source, context, { filename: filePath });
165
+ this.fileCache.set(filePath, mod.exports);
166
+ return mod.exports;
167
+ }
108
168
  }
109
169
  exports.WorkerContainer = WorkerContainer;
110
170
  //# sourceMappingURL=worker-container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-container.js","sourceRoot":"","sources":["../../src/di/worker-container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker-container.js","sourceRoot":"","sources":["../../src/di/worker-container.ts"],"names":[],"mappings":"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"}
@@ -6,4 +6,8 @@ export declare class ImageService {
6
6
  generateThumbnail(width: number, height: number): string;
7
7
  moduleImport(): Promise<string>;
8
8
  moduleRequire(): Promise<string>;
9
+ outlineModule(): Promise<{
10
+ p: number;
11
+ f: number;
12
+ }>;
9
13
  }
@@ -41,11 +41,15 @@ var __importStar = (this && this.__importStar) || (function () {
41
41
  var __metadata = (this && this.__metadata) || function (k, v) {
42
42
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
43
  };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
44
47
  Object.defineProperty(exports, "__esModule", { value: true });
45
48
  exports.ImageService = void 0;
46
49
  const common_1 = require("@nestjs/common");
47
50
  const worker_task_decorator_1 = require("../decorators/worker-task.decorator");
48
51
  const config_service_1 = require("./config.service");
52
+ const promises_1 = __importDefault(require("fs/promises"));
49
53
  let ImageService = class ImageService {
50
54
  configService;
51
55
  constructor(configService) {
@@ -74,10 +78,15 @@ let ImageService = class ImageService {
74
78
  const os = require('node:os');
75
79
  return `Require os size ${os.cpus().length}`;
76
80
  }
81
+ async outlineModule() {
82
+ const p = await promises_1.default.readFile('./package.json', 'utf-8');
83
+ const f = (await fetch('https://api.github.com')).status;
84
+ return { p: p.length, f };
85
+ }
77
86
  };
78
87
  exports.ImageService = ImageService;
79
88
  __decorate([
80
- (0, worker_task_decorator_1.WorkerTask)(),
89
+ (0, worker_task_decorator_1.WorkerTask)({ priority: 'HIGH' }),
81
90
  __metadata("design:type", Function),
82
91
  __metadata("design:paramtypes", [Number]),
83
92
  __metadata("design:returntype", Number)
@@ -100,6 +109,12 @@ __decorate([
100
109
  __metadata("design:paramtypes", []),
101
110
  __metadata("design:returntype", Promise)
102
111
  ], ImageService.prototype, "moduleRequire", null);
112
+ __decorate([
113
+ (0, worker_task_decorator_1.WorkerTask)(),
114
+ __metadata("design:type", Function),
115
+ __metadata("design:paramtypes", []),
116
+ __metadata("design:returntype", Promise)
117
+ ], ImageService.prototype, "outlineModule", null);
103
118
  exports.ImageService = ImageService = __decorate([
104
119
  (0, common_1.Injectable)(),
105
120
  (0, worker_task_decorator_1.WorkerClass)({ deps: [config_service_1.ConfigService] }),
@@ -1 +1 @@
1
- {"version":3,"file":"image.service.js","sourceRoot":"","sources":["../../src/example/image.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA0C;AAC1C,+EAA4E;AAC5E,qDAA+C;AAIxC,IAAM,YAAY,GAAlB,MAAM,YAAY;IACM;IAA7B,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IACzD,CAAC;IAGD,WAAW,CAAC,KAAa;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,KAAK,GAAG,UAAU,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,iBAAiB,CAAC,KAAa,EAAE,MAAc;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,IAAI,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1E,OAAO,SAAS,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,MAAM,OAAO,CAAC;IAC9D,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY;QAChB,MAAM,EAAE,GAAG,wDAAa,SAAS,GAAC,CAAC;QACnC,OAAO,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAA;IAC7C,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa;QACjB,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9B,OAAO,mBAAmB,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAA;IAC9C,CAAC;CACF,CAAA;AAhCY,oCAAY;AAKvB;IADC,IAAA,kCAAU,GAAE;;;;+CAOZ;AAGD;IADC,IAAA,kCAAU,GAAE;;;;qDAMZ;AAGK;IADL,IAAA,kCAAU,GAAE;;;;gDAIZ;AAGK;IADL,IAAA,kCAAU,GAAE;;;;iDAIZ;uBA/BU,YAAY;IAFxB,IAAA,mBAAU,GAAE;IACZ,IAAA,mCAAW,EAAC,EAAC,IAAI,EAAE,CAAC,8BAAa,CAAC,EAAC,CAAC;qCAES,8BAAa;GAD9C,YAAY,CAgCxB"}
1
+ {"version":3,"file":"image.service.js","sourceRoot":"","sources":["../../src/example/image.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+EAA8E;AAC9E,qDAAiD;AACjD,2DAA6B;AAItB,IAAM,YAAY,GAAlB,MAAM,YAAY;IACM;IAA7B,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IACzD,CAAC;IAGD,WAAW,CAAC,KAAa;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,KAAK,GAAG,UAAU,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,iBAAiB,CAAC,KAAa,EAAE,MAAc;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,IAAI,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1E,OAAO,SAAS,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,MAAM,OAAO,CAAC;IAC9D,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY;QAChB,MAAM,EAAE,GAAG,wDAAa,SAAS,GAAC,CAAC;QACnC,OAAO,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;IAC9C,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa;QACjB,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9B,OAAO,mBAAmB,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa;QACjB,MAAM,CAAC,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAAC;QACzD,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IAC5B,CAAC;CACF,CAAA;AAvCY,oCAAY;AAKvB;IADC,IAAA,kCAAU,EAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;;;;+CAOhC;AAGD;IADC,IAAA,kCAAU,GAAE;;;;qDAMZ;AAGK;IADL,IAAA,kCAAU,GAAE;;;;gDAIZ;AAGK;IADL,IAAA,kCAAU,GAAE;;;;iDAIZ;AAGK;IADL,IAAA,kCAAU,GAAE;;;;iDAKZ;uBAtCU,YAAY;IAFxB,IAAA,mBAAU,GAAE;IACZ,IAAA,mCAAW,EAAC,EAAE,IAAI,EAAE,CAAC,8BAAa,CAAC,EAAE,CAAC;qCAEO,8BAAa;GAD9C,YAAY,CAuCxB"}
@@ -17,7 +17,7 @@ let AppModule = class AppModule {
17
17
  };
18
18
  AppModule = __decorate([
19
19
  (0, common_1.Module)({
20
- imports: [worker_module_1.WorkerModule.forRoot({ poolSize: 4 })],
20
+ imports: [worker_module_1.WorkerModule.forRoot({ poolSize: 8 })],
21
21
  providers: [config_service_1.ConfigService, image_service_1.ImageService],
22
22
  })
23
23
  ], AppModule);
@@ -47,6 +47,7 @@ async function bootstrap() {
47
47
  workerService.run('ImageService', 'generateThumbnail', [640, 480], { priority: 'HIGH' }),
48
48
  workerService.run('ImageService', 'moduleImport'),
49
49
  workerService.run('ImageService', 'moduleRequire'),
50
+ workerService.run('ImageService', 'outlineModule'),
50
51
  ]);
51
52
  console.timeEnd('concurrent');
52
53
  console.log(' results:', results);
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/example/main.ts"],"names":[],"mappings":";;;;;;;;AAAA,4BAA0B;AAC1B,uCAAyC;AACzC,2CAAsC;AACtC,yDAAmD;AACnD,2DAAqD;AACrD,qDAA+C;AAC/C,mDAA6C;AAM7C,IAAM,SAAS,GAAf,MAAM,SAAS;CACd,CAAA;AADK,SAAS;IAJd,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,CAAC,EAAC,CAAC,CAAC;QAC9C,SAAS,EAAE,CAAC,8BAAa,EAAE,4BAAY,CAAC;KACzC,CAAC;GACI,SAAS,CACd;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,wBAAwB,CAAC,SAAS,EAAE;QAChE,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,8BAAa,CAAC,CAAC;IAE7C,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,GAAG,CACrC,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CACnC,CAAC;IACF,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAElC,6EAA6E;IAC7E,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CACnC,cAAc,EAAE,mBAAmB,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAC,CACrE,CAAC;IACF,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAEhC,8EAA8E;IAC9E,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACvC,aAAa,CAAC,GAAG,CAAS,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC;QAChF,aAAa,CAAC,GAAG,CAAS,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAC,CAAC;QAC9F,aAAa,CAAC,GAAG,CAAS,cAAc,EAAE,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAC,QAAQ,EAAE,MAAM,EAAC,CAAC;QAC9F,aAAa,CAAC,GAAG,CAAS,cAAc,EAAE,cAAc,CAAC;QACzD,aAAa,CAAC,GAAG,CAAS,cAAc,EAAE,eAAe,CAAC;KAC3D,CAAC,CAAC;IACH,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAEnC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;AACpB,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/example/main.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestworker",
3
- "version": "2.0.4",
3
+ "version": "2.0.8",
4
4
  "description": "Enterprise-grade worker thread module for NestJS — priority pool, auto-discovery, DI in workers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",