nestworker 2.0.8 → 2.1.0
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 +343 -117
- package/dist/core/worker.interfaces.d.ts +89 -10
- package/dist/core/worker.module.d.ts +21 -11
- package/dist/core/worker.module.js +38 -10
- package/dist/core/worker.module.js.map +1 -1
- package/dist/core/worker.pool.d.ts +26 -6
- package/dist/core/worker.pool.js +246 -101
- package/dist/core/worker.pool.js.map +1 -1
- package/dist/core/worker.service.d.ts +26 -74
- package/dist/core/worker.service.js +105 -79
- package/dist/core/worker.service.js.map +1 -1
- package/dist/decorators/worker-task.decorator.d.ts +7 -25
- package/dist/decorators/worker-task.decorator.js +5 -26
- package/dist/decorators/worker-task.decorator.js.map +1 -1
- package/dist/discovery/discovery.service.d.ts +2 -9
- package/dist/discovery/discovery.service.js +86 -21
- package/dist/discovery/discovery.service.js.map +1 -1
- package/dist/example/main.js +14 -2
- package/dist/example/main.js.map +1 -1
- package/dist/health/worker.health.d.ts +46 -0
- package/dist/health/worker.health.js +77 -0
- package/dist/health/worker.health.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/worker.metrics.d.ts +65 -0
- package/dist/metrics/worker.metrics.js +122 -0
- package/dist/metrics/worker.metrics.js.map +1 -0
- package/dist/worker/worker-runtime.js +124 -27
- package/dist/worker/worker-runtime.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { WorkerService } from '../core/worker.service';
|
|
2
|
+
export interface WorkerHealthResult {
|
|
3
|
+
status: 'up' | 'down';
|
|
4
|
+
details: {
|
|
5
|
+
poolSize: number;
|
|
6
|
+
idle: number;
|
|
7
|
+
busy: number;
|
|
8
|
+
queued: number;
|
|
9
|
+
warmingUp: number;
|
|
10
|
+
};
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* WorkerHealthIndicator — plugs into NestJS Terminus.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // health.controller.ts
|
|
18
|
+
* import { HealthCheck, HealthCheckService } from '@nestjs/terminus';
|
|
19
|
+
* import { WorkerHealthIndicator } from 'nestworker';
|
|
20
|
+
*
|
|
21
|
+
* @Controller('health')
|
|
22
|
+
* export class HealthController {
|
|
23
|
+
* constructor(
|
|
24
|
+
* private health: HealthCheckService,
|
|
25
|
+
* private workerHealth: WorkerHealthIndicator,
|
|
26
|
+
* ) {}
|
|
27
|
+
*
|
|
28
|
+
* @Get()
|
|
29
|
+
* @HealthCheck()
|
|
30
|
+
* check() {
|
|
31
|
+
* return this.health.check([
|
|
32
|
+
* () => this.workerHealth.check('workers'),
|
|
33
|
+
* ]);
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
*/
|
|
37
|
+
export declare class WorkerHealthIndicator {
|
|
38
|
+
private readonly workerService;
|
|
39
|
+
constructor(workerService: WorkerService);
|
|
40
|
+
/**
|
|
41
|
+
* Returns a Terminus-compatible health indicator result.
|
|
42
|
+
* Reports 'down' when warmingUp > 0 (pool not fully ready) or when
|
|
43
|
+
* queued jobs exceed the pool size (backpressure signal).
|
|
44
|
+
*/
|
|
45
|
+
check(key: string): Record<string, WorkerHealthResult>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.WorkerHealthIndicator = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const worker_service_1 = require("../core/worker.service");
|
|
15
|
+
/**
|
|
16
|
+
* WorkerHealthIndicator — plugs into NestJS Terminus.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // health.controller.ts
|
|
20
|
+
* import { HealthCheck, HealthCheckService } from '@nestjs/terminus';
|
|
21
|
+
* import { WorkerHealthIndicator } from 'nestworker';
|
|
22
|
+
*
|
|
23
|
+
* @Controller('health')
|
|
24
|
+
* export class HealthController {
|
|
25
|
+
* constructor(
|
|
26
|
+
* private health: HealthCheckService,
|
|
27
|
+
* private workerHealth: WorkerHealthIndicator,
|
|
28
|
+
* ) {}
|
|
29
|
+
*
|
|
30
|
+
* @Get()
|
|
31
|
+
* @HealthCheck()
|
|
32
|
+
* check() {
|
|
33
|
+
* return this.health.check([
|
|
34
|
+
* () => this.workerHealth.check('workers'),
|
|
35
|
+
* ]);
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
let WorkerHealthIndicator = class WorkerHealthIndicator {
|
|
40
|
+
workerService;
|
|
41
|
+
constructor(workerService) {
|
|
42
|
+
this.workerService = workerService;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a Terminus-compatible health indicator result.
|
|
46
|
+
* Reports 'down' when warmingUp > 0 (pool not fully ready) or when
|
|
47
|
+
* queued jobs exceed the pool size (backpressure signal).
|
|
48
|
+
*/
|
|
49
|
+
check(key) {
|
|
50
|
+
const stats = this.workerService.stats();
|
|
51
|
+
const isDown = stats.warmingUp > 0 ||
|
|
52
|
+
stats.queued > stats.poolSize;
|
|
53
|
+
const result = {
|
|
54
|
+
status: isDown ? 'down' : 'up',
|
|
55
|
+
details: stats,
|
|
56
|
+
...(isDown && stats.warmingUp > 0
|
|
57
|
+
? { error: `${stats.warmingUp} worker(s) still warming up` }
|
|
58
|
+
: {}),
|
|
59
|
+
...(isDown && stats.queued > stats.poolSize
|
|
60
|
+
? { error: `Queue depth (${stats.queued}) exceeds pool size (${stats.poolSize})` }
|
|
61
|
+
: {}),
|
|
62
|
+
};
|
|
63
|
+
if (isDown) {
|
|
64
|
+
throw Object.assign(new Error(`Worker pool unhealthy`), {
|
|
65
|
+
[key]: result,
|
|
66
|
+
causes: [result.error],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return { [key]: result };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
exports.WorkerHealthIndicator = WorkerHealthIndicator;
|
|
73
|
+
exports.WorkerHealthIndicator = WorkerHealthIndicator = __decorate([
|
|
74
|
+
(0, common_1.Injectable)(),
|
|
75
|
+
__metadata("design:paramtypes", [worker_service_1.WorkerService])
|
|
76
|
+
], WorkerHealthIndicator);
|
|
77
|
+
//# sourceMappingURL=worker.health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.health.js","sourceRoot":"","sources":["../../src/health/worker.health.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2DAAuD;AAcvD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACH;IAA7B,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAE7D;;;;OAIG;IACH,KAAK,CAAC,GAAW;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,MAAM,GACV,KAAK,CAAC,SAAS,GAAG,CAAC;YACnB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;QAEhC,MAAM,MAAM,GAAuB;YACjC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;YAC9B,OAAO,EAAE,KAAK;YACd,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,CAAC;gBAC/B,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,SAAS,6BAA6B,EAAE;gBAC5D,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ;gBACzC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,KAAK,CAAC,MAAM,wBAAwB,KAAK,CAAC,QAAQ,GAAG,EAAE;gBAClF,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,EAAE;gBACtD,CAAC,GAAG,CAAC,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;aACvB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AAlCY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAEiC,8BAAa;GAD9C,qBAAqB,CAkCjC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { WorkerModule } from './core/worker.module';
|
|
2
2
|
export { WorkerService } from './core/worker.service';
|
|
3
|
+
export type { RunOptions } from './core/worker.service';
|
|
3
4
|
export { WorkerClass, WorkerTask } from './decorators/worker-task.decorator';
|
|
4
|
-
export type { WorkerModuleOptions, TaskPriority } from './core/worker.interfaces';
|
|
5
5
|
export type { WorkerTaskOptions } from './decorators/worker-task.decorator';
|
|
6
|
+
export { WorkerHealthIndicator } from './health/worker.health';
|
|
7
|
+
export type { WorkerHealthResult } from './health/worker.health';
|
|
8
|
+
export { WorkerMetricsService } from './metrics/worker.metrics';
|
|
9
|
+
export type { WorkerMetricsSnapshot } from './metrics/worker.metrics';
|
|
10
|
+
export type { WorkerJob, WorkerModuleOptions, WorkerModuleAsyncOptions, TaskPriority, DeadLetterEvent, PoolStats, SerializedError, } from './core/worker.interfaces';
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WorkerTask = exports.WorkerClass = exports.WorkerService = exports.WorkerModule = void 0;
|
|
3
|
+
exports.WorkerMetricsService = exports.WorkerHealthIndicator = exports.WorkerTask = exports.WorkerClass = exports.WorkerService = exports.WorkerModule = void 0;
|
|
4
|
+
// Module
|
|
4
5
|
var worker_module_1 = require("./core/worker.module");
|
|
5
6
|
Object.defineProperty(exports, "WorkerModule", { enumerable: true, get: function () { return worker_module_1.WorkerModule; } });
|
|
7
|
+
// Services
|
|
6
8
|
var worker_service_1 = require("./core/worker.service");
|
|
7
9
|
Object.defineProperty(exports, "WorkerService", { enumerable: true, get: function () { return worker_service_1.WorkerService; } });
|
|
10
|
+
// Decorators
|
|
8
11
|
var worker_task_decorator_1 = require("./decorators/worker-task.decorator");
|
|
9
12
|
Object.defineProperty(exports, "WorkerClass", { enumerable: true, get: function () { return worker_task_decorator_1.WorkerClass; } });
|
|
10
13
|
Object.defineProperty(exports, "WorkerTask", { enumerable: true, get: function () { return worker_task_decorator_1.WorkerTask; } });
|
|
14
|
+
// Health
|
|
15
|
+
var worker_health_1 = require("./health/worker.health");
|
|
16
|
+
Object.defineProperty(exports, "WorkerHealthIndicator", { enumerable: true, get: function () { return worker_health_1.WorkerHealthIndicator; } });
|
|
17
|
+
// Metrics
|
|
18
|
+
var worker_metrics_1 = require("./metrics/worker.metrics");
|
|
19
|
+
Object.defineProperty(exports, "WorkerMetricsService", { enumerable: true, get: function () { return worker_metrics_1.WorkerMetricsService; } });
|
|
11
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,sDAAsD;AAA7C,6GAAA,YAAY,OAAA;AAErB,WAAW;AACX,wDAAuD;AAA9C,+GAAA,aAAa,OAAA;AAGtB,aAAa;AACb,4EAA6E;AAApE,oHAAA,WAAW,OAAA;AAAE,mHAAA,UAAU,OAAA;AAGhC,SAAS;AACT,wDAA+D;AAAtD,sHAAA,qBAAqB,OAAA;AAG9B,UAAU;AACV,2DAAiE;AAAxD,sHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import { WorkerService } from '../core/worker.service';
|
|
3
|
+
export interface WorkerMetricsSnapshot {
|
|
4
|
+
/** Total jobs dispatched since startup */
|
|
5
|
+
jobsTotal: number;
|
|
6
|
+
/** Jobs that completed successfully */
|
|
7
|
+
jobsSuccess: number;
|
|
8
|
+
/** Jobs that failed (after all retries) */
|
|
9
|
+
jobsFailed: number;
|
|
10
|
+
/** Jobs that timed out */
|
|
11
|
+
jobsTimeout: number;
|
|
12
|
+
/** Jobs sent to dead letter queue */
|
|
13
|
+
jobsDead: number;
|
|
14
|
+
/** Current queue depth */
|
|
15
|
+
queueDepth: number;
|
|
16
|
+
/** Current idle worker count */
|
|
17
|
+
idleWorkers: number;
|
|
18
|
+
/** Current busy worker count */
|
|
19
|
+
busyWorkers: number;
|
|
20
|
+
/** Per-task duration histogram (p50, p95, p99) in ms */
|
|
21
|
+
durations: Record<string, {
|
|
22
|
+
p50: number;
|
|
23
|
+
p95: number;
|
|
24
|
+
p99: number;
|
|
25
|
+
count: number;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* WorkerMetricsService — collects runtime metrics from the worker pool.
|
|
30
|
+
*
|
|
31
|
+
* Designed to be framework-agnostic: read the snapshot and push to
|
|
32
|
+
* Prometheus, Datadog, CloudWatch, or any other metrics provider.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Prometheus integration
|
|
36
|
+
* @Get('metrics')
|
|
37
|
+
* async metrics() {
|
|
38
|
+
* const snap = this.workerMetrics.snapshot();
|
|
39
|
+
* return [
|
|
40
|
+
* `nestworker_jobs_total ${snap.jobsTotal}`,
|
|
41
|
+
* `nestworker_jobs_success ${snap.jobsSuccess}`,
|
|
42
|
+
* `nestworker_queue_depth ${snap.queueDepth}`,
|
|
43
|
+
* ].join('\n');
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
export declare class WorkerMetricsService implements OnModuleInit, OnModuleDestroy {
|
|
47
|
+
private readonly workerService;
|
|
48
|
+
private jobsTotal;
|
|
49
|
+
private jobsSuccess;
|
|
50
|
+
private jobsFailed;
|
|
51
|
+
private jobsTimeout;
|
|
52
|
+
private jobsDead;
|
|
53
|
+
/** Raw duration samples per task key — capped at 1000 samples */
|
|
54
|
+
private readonly durationSamples;
|
|
55
|
+
/** Interval handle for periodic pool-stats polling */
|
|
56
|
+
private statsInterval?;
|
|
57
|
+
constructor(workerService: WorkerService);
|
|
58
|
+
onModuleInit(): void;
|
|
59
|
+
onModuleDestroy(): void;
|
|
60
|
+
/** Returns a point-in-time snapshot of all metrics */
|
|
61
|
+
snapshot(): WorkerMetricsSnapshot;
|
|
62
|
+
/** Reset all counters (useful in tests) */
|
|
63
|
+
reset(): void;
|
|
64
|
+
private pushDuration;
|
|
65
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.WorkerMetricsService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const worker_service_1 = require("../core/worker.service");
|
|
15
|
+
/**
|
|
16
|
+
* WorkerMetricsService — collects runtime metrics from the worker pool.
|
|
17
|
+
*
|
|
18
|
+
* Designed to be framework-agnostic: read the snapshot and push to
|
|
19
|
+
* Prometheus, Datadog, CloudWatch, or any other metrics provider.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Prometheus integration
|
|
23
|
+
* @Get('metrics')
|
|
24
|
+
* async metrics() {
|
|
25
|
+
* const snap = this.workerMetrics.snapshot();
|
|
26
|
+
* return [
|
|
27
|
+
* `nestworker_jobs_total ${snap.jobsTotal}`,
|
|
28
|
+
* `nestworker_jobs_success ${snap.jobsSuccess}`,
|
|
29
|
+
* `nestworker_queue_depth ${snap.queueDepth}`,
|
|
30
|
+
* ].join('\n');
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
let WorkerMetricsService = class WorkerMetricsService {
|
|
34
|
+
workerService;
|
|
35
|
+
jobsTotal = 0;
|
|
36
|
+
jobsSuccess = 0;
|
|
37
|
+
jobsFailed = 0;
|
|
38
|
+
jobsTimeout = 0;
|
|
39
|
+
jobsDead = 0;
|
|
40
|
+
/** Raw duration samples per task key — capped at 1000 samples */
|
|
41
|
+
durationSamples = new Map();
|
|
42
|
+
/** Interval handle for periodic pool-stats polling */
|
|
43
|
+
statsInterval;
|
|
44
|
+
constructor(workerService) {
|
|
45
|
+
this.workerService = workerService;
|
|
46
|
+
}
|
|
47
|
+
onModuleInit() {
|
|
48
|
+
// Task start
|
|
49
|
+
this.workerService.onTaskStart((job) => {
|
|
50
|
+
this.jobsTotal++;
|
|
51
|
+
});
|
|
52
|
+
// Task end: record duration + success
|
|
53
|
+
this.workerService.onTaskEnd((job, durationMs) => {
|
|
54
|
+
const key = `${job.serviceName}.${job.methodName}`;
|
|
55
|
+
this.jobsSuccess++;
|
|
56
|
+
this.pushDuration(key, durationMs);
|
|
57
|
+
});
|
|
58
|
+
// Task error: record failure
|
|
59
|
+
this.workerService.onTaskError((job, error) => {
|
|
60
|
+
this.jobsFailed++;
|
|
61
|
+
if (error.name === 'TimeoutError')
|
|
62
|
+
this.jobsTimeout++;
|
|
63
|
+
});
|
|
64
|
+
// Dead letter: separate counter
|
|
65
|
+
this.workerService.onDead(() => {
|
|
66
|
+
this.jobsDead++;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
onModuleDestroy() {
|
|
70
|
+
if (this.statsInterval)
|
|
71
|
+
clearInterval(this.statsInterval);
|
|
72
|
+
}
|
|
73
|
+
/** Returns a point-in-time snapshot of all metrics */
|
|
74
|
+
snapshot() {
|
|
75
|
+
const stats = this.workerService.stats();
|
|
76
|
+
const durations = {};
|
|
77
|
+
for (const [key, samples] of this.durationSamples) {
|
|
78
|
+
durations[key] = computePercentiles(samples);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
jobsTotal: this.jobsTotal,
|
|
82
|
+
jobsSuccess: this.jobsSuccess,
|
|
83
|
+
jobsFailed: this.jobsFailed,
|
|
84
|
+
jobsTimeout: this.jobsTimeout,
|
|
85
|
+
jobsDead: this.jobsDead,
|
|
86
|
+
queueDepth: stats.queued,
|
|
87
|
+
idleWorkers: stats.idle,
|
|
88
|
+
busyWorkers: stats.busy,
|
|
89
|
+
durations,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Reset all counters (useful in tests) */
|
|
93
|
+
reset() {
|
|
94
|
+
this.jobsTotal = this.jobsSuccess = this.jobsFailed =
|
|
95
|
+
this.jobsTimeout = this.jobsDead = 0;
|
|
96
|
+
this.durationSamples.clear();
|
|
97
|
+
}
|
|
98
|
+
pushDuration(key, ms) {
|
|
99
|
+
if (!this.durationSamples.has(key))
|
|
100
|
+
this.durationSamples.set(key, []);
|
|
101
|
+
const samples = this.durationSamples.get(key);
|
|
102
|
+
samples.push(ms);
|
|
103
|
+
// Keep memory bounded — reservoir sampling after 1000 entries
|
|
104
|
+
if (samples.length > 1000) {
|
|
105
|
+
const idx = Math.floor(Math.random() * samples.length);
|
|
106
|
+
samples.splice(idx, 1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
exports.WorkerMetricsService = WorkerMetricsService;
|
|
111
|
+
exports.WorkerMetricsService = WorkerMetricsService = __decorate([
|
|
112
|
+
(0, common_1.Injectable)(),
|
|
113
|
+
__metadata("design:paramtypes", [worker_service_1.WorkerService])
|
|
114
|
+
], WorkerMetricsService);
|
|
115
|
+
function computePercentiles(samples) {
|
|
116
|
+
if (samples.length === 0)
|
|
117
|
+
return { p50: 0, p95: 0, p99: 0, count: 0 };
|
|
118
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
119
|
+
const p = (pct) => sorted[Math.ceil((pct / 100) * sorted.length) - 1] ?? 0;
|
|
120
|
+
return { p50: p(50), p95: p(95), p99: p(99), count: samples.length };
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=worker.metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.metrics.js","sourceRoot":"","sources":["../../src/metrics/worker.metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +1,73 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
7
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
8
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
4
9
|
const worker_container_1 = require("../di/worker-container");
|
|
5
|
-
/**
|
|
6
|
-
* Worker Runtime – entry point for every worker thread.
|
|
7
|
-
*
|
|
8
|
-
* Receives SerializedService[] via workerData and boots a WorkerContainer
|
|
9
|
-
* which eval()s the stripped class sources and reconstructs the full
|
|
10
|
-
* service graph (deps injected via constructor) without any require() calls
|
|
11
|
-
* into NestJS-annotated files.
|
|
12
|
-
*
|
|
13
|
-
* Jobs are processed serially via a queue — one postMessage() reply per job,
|
|
14
|
-
* which is exactly what the pool's worker.once('message') expects.
|
|
15
|
-
*/
|
|
16
10
|
const services = node_worker_threads_1.workerData?.services ?? [];
|
|
17
11
|
const container = new worker_container_1.WorkerContainer();
|
|
18
12
|
container.load(services);
|
|
19
|
-
|
|
20
|
-
const tasks = {};
|
|
13
|
+
const instances = new Map();
|
|
21
14
|
for (const svc of services) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
instances.set(svc.name, container.get(svc.name));
|
|
16
|
+
}
|
|
17
|
+
node_worker_threads_1.parentPort?.postMessage({ type: 'worker:ready' });
|
|
18
|
+
// ── Pending IPC calls ─────────────────────────────────────────────────────
|
|
19
|
+
const pendingIpc = new Map();
|
|
20
|
+
// ── Pending AbortControllers (keyed by abortSignalId) ────────────────────
|
|
21
|
+
const pendingAborts = new Map();
|
|
22
|
+
// ── Internal ALS for context propagation ─────────────────────────────────
|
|
23
|
+
// One ALS instance per context key — we use a single generic ALS that holds
|
|
24
|
+
// the full context map, then the user's ALS instances read from it via
|
|
25
|
+
// the context restoration path in WorkerService.
|
|
26
|
+
const workerAls = new node_async_hooks_1.AsyncLocalStorage();
|
|
27
|
+
node_worker_threads_1.parentPort?.on('message', (msg) => {
|
|
28
|
+
const message = msg;
|
|
29
|
+
// IPC result from main thread
|
|
30
|
+
if (message.type === 'ipc:result') {
|
|
31
|
+
const res = message;
|
|
32
|
+
const pending = pendingIpc.get(res.callId);
|
|
33
|
+
if (!pending)
|
|
34
|
+
return;
|
|
35
|
+
pendingIpc.delete(res.callId);
|
|
36
|
+
res.ok ? pending.resolve(res.data) : pending.reject(new Error(res.error ?? 'IPC failed'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Abort signal from main thread
|
|
40
|
+
if (message.type === 'abort') {
|
|
41
|
+
const abort = message;
|
|
42
|
+
pendingAborts.get(abort.abortSignalId)?.abort();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Normal job
|
|
46
|
+
queue.push(message);
|
|
47
|
+
runNext();
|
|
48
|
+
});
|
|
49
|
+
function buildProxy(descriptor) {
|
|
50
|
+
const proxy = {};
|
|
51
|
+
for (const methodName of descriptor.methodNames) {
|
|
52
|
+
proxy[methodName] = (...args) => new Promise((resolve, reject) => {
|
|
53
|
+
const callId = node_crypto_1.default.randomUUID();
|
|
54
|
+
pendingIpc.set(callId, { resolve, reject });
|
|
55
|
+
const request = {
|
|
56
|
+
type: 'ipc:invoke', callId,
|
|
57
|
+
propertyKey: descriptor.propertyKey,
|
|
58
|
+
methodName, args,
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
node_worker_threads_1.parentPort?.postMessage(request);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
pendingIpc.delete(callId);
|
|
65
|
+
reject(new Error(`IPC proxy "${descriptor.propertyKey}.${methodName}" could not serialise args: ` +
|
|
66
|
+
`${err.message}`));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
25
69
|
}
|
|
70
|
+
return proxy;
|
|
26
71
|
}
|
|
27
72
|
const queue = [];
|
|
28
73
|
let busy = false;
|
|
@@ -30,26 +75,78 @@ async function runNext() {
|
|
|
30
75
|
if (busy || queue.length === 0)
|
|
31
76
|
return;
|
|
32
77
|
busy = true;
|
|
33
|
-
const
|
|
34
|
-
|
|
78
|
+
const job = queue.shift();
|
|
79
|
+
// Set up AbortController for this job
|
|
80
|
+
const abortController = new AbortController();
|
|
81
|
+
if (job.abortSignalId) {
|
|
82
|
+
pendingAborts.set(job.abortSignalId, abortController);
|
|
83
|
+
}
|
|
84
|
+
// Inject proxy stubs
|
|
85
|
+
if (job.proxyServices?.length) {
|
|
86
|
+
const inst = instances.get(job.serviceName);
|
|
87
|
+
if (inst) {
|
|
88
|
+
for (const descriptor of job.proxyServices) {
|
|
89
|
+
inst[descriptor.propertyKey] = buildProxy(descriptor);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Restore ALS context and run the task inside it
|
|
94
|
+
const alsContext = job.alsContext ?? {};
|
|
95
|
+
const run = async () => {
|
|
96
|
+
const inst = instances.get(job.serviceName);
|
|
97
|
+
if (!inst)
|
|
98
|
+
throw new Error(`Service "${job.serviceName}" is not registered`);
|
|
99
|
+
const fn = inst[job.methodName];
|
|
100
|
+
if (typeof fn !== 'function') {
|
|
101
|
+
throw new Error(`Task "${job.serviceName}.${job.methodName}" is not registered`);
|
|
102
|
+
}
|
|
103
|
+
// Inject AbortSignal as a last argument if the job has an abortSignalId.
|
|
104
|
+
// Call via inst.method() — not as a detached fn() — so `this` is preserved.
|
|
105
|
+
const args = job.abortSignalId
|
|
106
|
+
? [...job.args, abortController.signal]
|
|
107
|
+
: job.args;
|
|
108
|
+
return inst[job.methodName](...args);
|
|
109
|
+
};
|
|
35
110
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const data = await fn(...payload.args);
|
|
111
|
+
// Run the task inside the ALS context so any nested ALS.getStore() calls
|
|
112
|
+
// inside the task body see the propagated main-thread context.
|
|
113
|
+
const data = await workerAls.run(alsContext, run);
|
|
40
114
|
node_worker_threads_1.parentPort?.postMessage({ ok: true, data });
|
|
41
115
|
}
|
|
42
116
|
catch (error) {
|
|
43
117
|
const e = error;
|
|
44
|
-
|
|
118
|
+
const serialized = {
|
|
119
|
+
name: e.name ?? 'Error',
|
|
120
|
+
message: e.message,
|
|
121
|
+
stack: e.stack,
|
|
122
|
+
code: e.code,
|
|
123
|
+
// Capture any extra own enumerable properties (e.g. HttpException.status)
|
|
124
|
+
extra: serializeExtraProps(e),
|
|
125
|
+
};
|
|
126
|
+
node_worker_threads_1.parentPort?.postMessage({ ok: false, error: serialized });
|
|
45
127
|
}
|
|
46
128
|
finally {
|
|
129
|
+
if (job.abortSignalId) {
|
|
130
|
+
pendingAborts.delete(job.abortSignalId);
|
|
131
|
+
}
|
|
47
132
|
busy = false;
|
|
48
133
|
runNext();
|
|
49
134
|
}
|
|
50
135
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
136
|
+
function serializeExtraProps(err) {
|
|
137
|
+
const skip = new Set(['name', 'message', 'stack', 'code']);
|
|
138
|
+
const extra = {};
|
|
139
|
+
let hasExtra = false;
|
|
140
|
+
for (const key of Object.keys(err)) {
|
|
141
|
+
if (skip.has(key))
|
|
142
|
+
continue;
|
|
143
|
+
try {
|
|
144
|
+
structuredClone(err[key]);
|
|
145
|
+
extra[key] = err[key];
|
|
146
|
+
hasExtra = true;
|
|
147
|
+
}
|
|
148
|
+
catch { /* skip non-cloneable */ }
|
|
149
|
+
}
|
|
150
|
+
return hasExtra ? extra : undefined;
|
|
151
|
+
}
|
|
55
152
|
//# sourceMappingURL=worker-runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-runtime.js","sourceRoot":"","sources":["../../src/worker/worker-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worker-runtime.js","sourceRoot":"","sources":["../../src/worker/worker-runtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED