@midwayjs/piscina 4.0.0-beta.1
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 +3 -0
- package/dist/configuration.d.ts +6 -0
- package/dist/configuration.js +41 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +5 -0
- package/dist/decorator.d.ts +16 -0
- package/dist/decorator.js +29 -0
- package/dist/framework.d.ts +23 -0
- package/dist/framework.js +64 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +26 -0
- package/dist/interface.d.ts +27 -0
- package/dist/interface.js +3 -0
- package/dist/manager.d.ts +34 -0
- package/dist/manager.js +132 -0
- package/dist/worker-bootstrap.d.ts +3 -0
- package/dist/worker-bootstrap.js +128 -0
- package/index.d.ts +8 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ILifeCycle, IMidwayContainer } from '@midwayjs/core';
|
|
2
|
+
export declare class PiscinaConfiguration implements ILifeCycle {
|
|
3
|
+
onReady(container: IMidwayContainer): Promise<void>;
|
|
4
|
+
onStop(container: IMidwayContainer): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=configuration.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PiscinaConfiguration = void 0;
|
|
10
|
+
const core_1 = require("@midwayjs/core");
|
|
11
|
+
const manager_1 = require("./manager");
|
|
12
|
+
let PiscinaConfiguration = class PiscinaConfiguration {
|
|
13
|
+
async onReady(container) {
|
|
14
|
+
await container.getAsync(manager_1.PiscinaServiceFactory);
|
|
15
|
+
}
|
|
16
|
+
async onStop(container) {
|
|
17
|
+
const factory = await container.getAsync(manager_1.PiscinaServiceFactory);
|
|
18
|
+
await factory.stop();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
exports.PiscinaConfiguration = PiscinaConfiguration;
|
|
22
|
+
exports.PiscinaConfiguration = PiscinaConfiguration = __decorate([
|
|
23
|
+
(0, core_1.Configuration)({
|
|
24
|
+
namespace: 'piscina',
|
|
25
|
+
importConfigs: [
|
|
26
|
+
{
|
|
27
|
+
default: {
|
|
28
|
+
piscina: {},
|
|
29
|
+
midwayLogger: {
|
|
30
|
+
clients: {
|
|
31
|
+
piscinaWorkerLogger: {
|
|
32
|
+
fileLogName: 'midway-piscina-worker.log',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
], PiscinaConfiguration);
|
|
41
|
+
//# sourceMappingURL=configuration.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Piscina Task 装饰器
|
|
3
|
+
* 用于标记 Worker 中的任务类
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* @PiscinaTask('calculate')
|
|
8
|
+
* export class CalculateTask {
|
|
9
|
+
* async execute(payload: any) {
|
|
10
|
+
* return payload.a + payload.b;
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function PiscinaTask(handler: string): ClassDecorator;
|
|
16
|
+
//# sourceMappingURL=decorator.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PiscinaTask = PiscinaTask;
|
|
4
|
+
const core_1 = require("@midwayjs/core");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
/**
|
|
7
|
+
* Piscina Task 装饰器
|
|
8
|
+
* 用于标记 Worker 中的任务类
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* @PiscinaTask('calculate')
|
|
13
|
+
* export class CalculateTask {
|
|
14
|
+
* async execute(payload: any) {
|
|
15
|
+
* return payload.a + payload.b;
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function PiscinaTask(handler) {
|
|
21
|
+
return (target) => {
|
|
22
|
+
core_1.DecoratorManager.saveModule(constants_1.PISCINA_TASK_KEY, target);
|
|
23
|
+
// 保存 handler 名称到元数据
|
|
24
|
+
core_1.MetadataManager.defineMetadata(constants_1.PISCINA_TASK_KEY, { handler }, target);
|
|
25
|
+
(0, core_1.Provide)()(target);
|
|
26
|
+
(0, core_1.Scope)(core_1.ScopeEnum.Request)(target);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=decorator.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseFramework, IMidwayBootstrapOptions } from '@midwayjs/core';
|
|
2
|
+
import { Application, Context } from './interface';
|
|
3
|
+
/**
|
|
4
|
+
* Piscina Worker Framework
|
|
5
|
+
* 用于在 Worker 线程中启动 Midway 应用
|
|
6
|
+
*/
|
|
7
|
+
export declare class PiscinaWorkerFramework extends BaseFramework<Application, Context, any> {
|
|
8
|
+
protected frameworkLoggerName: string;
|
|
9
|
+
private taskHandlers;
|
|
10
|
+
applicationInitialize(options: IMidwayBootstrapOptions): Promise<void>;
|
|
11
|
+
configure(): {};
|
|
12
|
+
getFrameworkName(): string;
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* 根据 handler 名称执行任务
|
|
16
|
+
*/
|
|
17
|
+
executeTask<T = any, R = any>(handler: string, payload?: T): Promise<R>;
|
|
18
|
+
/**
|
|
19
|
+
* 获取所有已注册的 handler
|
|
20
|
+
*/
|
|
21
|
+
getTaskHandlers(): string[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=framework.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PiscinaWorkerFramework = void 0;
|
|
10
|
+
const core_1 = require("@midwayjs/core");
|
|
11
|
+
const constants_1 = require("./constants");
|
|
12
|
+
/**
|
|
13
|
+
* Piscina Worker Framework
|
|
14
|
+
* 用于在 Worker 线程中启动 Midway 应用
|
|
15
|
+
*/
|
|
16
|
+
let PiscinaWorkerFramework = class PiscinaWorkerFramework extends core_1.BaseFramework {
|
|
17
|
+
frameworkLoggerName = 'piscinaWorkerLogger';
|
|
18
|
+
taskHandlers = new Map();
|
|
19
|
+
async applicationInitialize(options) {
|
|
20
|
+
this.app = {};
|
|
21
|
+
}
|
|
22
|
+
configure() {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
getFrameworkName() {
|
|
26
|
+
return 'piscinaWorker';
|
|
27
|
+
}
|
|
28
|
+
async run() {
|
|
29
|
+
// 加载所有标记了 @PiscinaTask 的任务类
|
|
30
|
+
const taskModules = core_1.DecoratorManager.listModule(constants_1.PISCINA_TASK_KEY);
|
|
31
|
+
for (const module of taskModules) {
|
|
32
|
+
const metadata = core_1.MetadataManager.getMetadata(constants_1.PISCINA_TASK_KEY, module);
|
|
33
|
+
if (metadata && metadata.handler) {
|
|
34
|
+
this.taskHandlers.set(metadata.handler, module);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 根据 handler 名称执行任务
|
|
40
|
+
*/
|
|
41
|
+
async executeTask(handler, payload) {
|
|
42
|
+
const TaskClass = this.taskHandlers.get(handler);
|
|
43
|
+
if (!TaskClass) {
|
|
44
|
+
throw new core_1.MidwayCommonError(`Task handler "${handler}" not found. Did you forget to use @PiscinaTask('${handler}') decorator?`);
|
|
45
|
+
}
|
|
46
|
+
const ctx = this.app.createAnonymousContext();
|
|
47
|
+
const taskInstance = await ctx.requestContext.getAsync(TaskClass);
|
|
48
|
+
if (!taskInstance || typeof taskInstance.execute !== 'function') {
|
|
49
|
+
throw new core_1.MidwayCommonError(`Task "${handler}" must implement execute method`);
|
|
50
|
+
}
|
|
51
|
+
return await taskInstance.execute(payload);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 获取所有已注册的 handler
|
|
55
|
+
*/
|
|
56
|
+
getTaskHandlers() {
|
|
57
|
+
return Array.from(this.taskHandlers.keys());
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.PiscinaWorkerFramework = PiscinaWorkerFramework;
|
|
61
|
+
exports.PiscinaWorkerFramework = PiscinaWorkerFramework = __decorate([
|
|
62
|
+
(0, core_1.Framework)()
|
|
63
|
+
], PiscinaWorkerFramework);
|
|
64
|
+
//# sourceMappingURL=framework.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { PiscinaConfiguration as Configuration } from './configuration';
|
|
2
|
+
export { PiscinaWorkerFramework as framework } from './framework';
|
|
3
|
+
export * from './manager';
|
|
4
|
+
export * from './decorator';
|
|
5
|
+
export * from './constants';
|
|
6
|
+
export * from './interface';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.framework = exports.Configuration = void 0;
|
|
18
|
+
var configuration_1 = require("./configuration");
|
|
19
|
+
Object.defineProperty(exports, "Configuration", { enumerable: true, get: function () { return configuration_1.PiscinaConfiguration; } });
|
|
20
|
+
var framework_1 = require("./framework");
|
|
21
|
+
Object.defineProperty(exports, "framework", { enumerable: true, get: function () { return framework_1.PiscinaWorkerFramework; } });
|
|
22
|
+
__exportStar(require("./manager"), exports);
|
|
23
|
+
__exportStar(require("./decorator"), exports);
|
|
24
|
+
__exportStar(require("./constants"), exports);
|
|
25
|
+
__exportStar(require("./interface"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IMidwayApplication, IMidwayContext, ServiceFactoryConfigOption } from '@midwayjs/core';
|
|
2
|
+
import type { Piscina } from 'piscina';
|
|
3
|
+
/**
|
|
4
|
+
* Piscina 构造函数选项类型
|
|
5
|
+
*/
|
|
6
|
+
export type PiscinaOptions = Omit<NonNullable<ConstructorParameters<typeof Piscina>[0]>, 'filename'>;
|
|
7
|
+
/**
|
|
8
|
+
* 单个线程池配置
|
|
9
|
+
*/
|
|
10
|
+
export interface PiscinaPoolConfig extends PiscinaOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Worker 文件路径(相对于 baseDir 或绝对路径)
|
|
13
|
+
*/
|
|
14
|
+
workerFile: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Piscina 组件配置
|
|
18
|
+
*/
|
|
19
|
+
export type PiscinaConfig = ServiceFactoryConfigOption<PiscinaPoolConfig>;
|
|
20
|
+
export interface Application extends IMidwayApplication<IMidwayContext> {
|
|
21
|
+
}
|
|
22
|
+
export interface Context extends IMidwayContext {
|
|
23
|
+
}
|
|
24
|
+
export interface IPiscinaTask<P = unknown, R = unknown> {
|
|
25
|
+
execute(payload: P): Promise<R>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ServiceFactory, ILogger, MidwayEnvironmentService } from '@midwayjs/core';
|
|
2
|
+
import { Piscina } from 'piscina';
|
|
3
|
+
import { PiscinaConfig, PiscinaPoolConfig } from './interface';
|
|
4
|
+
/**
|
|
5
|
+
* Midway 扩展的 Piscina 类
|
|
6
|
+
* 继承了原生 Piscina 的所有功能,并添加了 Midway 容器相关方法
|
|
7
|
+
*/
|
|
8
|
+
export declare class MidwayPiscina extends Piscina {
|
|
9
|
+
/**
|
|
10
|
+
* 在 Worker 中的 Midway 容器中执行 @PiscinaTask 装饰器任务
|
|
11
|
+
* @param handler 任务的 handler 名称(对应 @PiscinaTask 装饰器参数)
|
|
12
|
+
* @param payload 传递给任务的参数
|
|
13
|
+
* @param options Piscina 运行选项(transferList, signal 等)
|
|
14
|
+
*/
|
|
15
|
+
runInContainer<T = any, R = any>(handler: string, payload?: T, options?: Parameters<Piscina['run']>[1]): Promise<R>;
|
|
16
|
+
}
|
|
17
|
+
export declare class PiscinaServiceFactory extends ServiceFactory<MidwayPiscina> {
|
|
18
|
+
protected config: PiscinaConfig;
|
|
19
|
+
protected logger: ILogger;
|
|
20
|
+
protected appDir: any;
|
|
21
|
+
protected environmentService: MidwayEnvironmentService;
|
|
22
|
+
protected init(): Promise<void>;
|
|
23
|
+
protected createClient(config: PiscinaPoolConfig, name: string): Promise<MidwayPiscina>;
|
|
24
|
+
getName(): string;
|
|
25
|
+
protected destroyClient(pool: MidwayPiscina, name: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare class PiscinaService implements MidwayPiscina {
|
|
28
|
+
private serviceFactory;
|
|
29
|
+
private instance;
|
|
30
|
+
init(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export interface PiscinaService extends MidwayPiscina {
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=manager.d.ts.map
|
package/dist/manager.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
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.PiscinaService = exports.PiscinaServiceFactory = exports.MidwayPiscina = void 0;
|
|
13
|
+
const core_1 = require("@midwayjs/core");
|
|
14
|
+
const piscina_1 = require("piscina");
|
|
15
|
+
const path_1 = require("path");
|
|
16
|
+
/**
|
|
17
|
+
* Midway 扩展的 Piscina 类
|
|
18
|
+
* 继承了原生 Piscina 的所有功能,并添加了 Midway 容器相关方法
|
|
19
|
+
*/
|
|
20
|
+
class MidwayPiscina extends piscina_1.Piscina {
|
|
21
|
+
/**
|
|
22
|
+
* 在 Worker 中的 Midway 容器中执行 @PiscinaTask 装饰器任务
|
|
23
|
+
* @param handler 任务的 handler 名称(对应 @PiscinaTask 装饰器参数)
|
|
24
|
+
* @param payload 传递给任务的参数
|
|
25
|
+
* @param options Piscina 运行选项(transferList, signal 等)
|
|
26
|
+
*/
|
|
27
|
+
runInContainer(handler, payload, options) {
|
|
28
|
+
return this.run({
|
|
29
|
+
handler: 'defineConfiguration',
|
|
30
|
+
payload: {
|
|
31
|
+
handler,
|
|
32
|
+
data: payload,
|
|
33
|
+
},
|
|
34
|
+
}, options);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.MidwayPiscina = MidwayPiscina;
|
|
38
|
+
let PiscinaServiceFactory = class PiscinaServiceFactory extends core_1.ServiceFactory {
|
|
39
|
+
config;
|
|
40
|
+
logger;
|
|
41
|
+
appDir;
|
|
42
|
+
environmentService;
|
|
43
|
+
async init() {
|
|
44
|
+
await this.initClients(this.config, {
|
|
45
|
+
concurrent: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async createClient(config, name) {
|
|
49
|
+
const { workerFile, ...piscinaOptions } = config;
|
|
50
|
+
if (!workerFile) {
|
|
51
|
+
throw new core_1.MidwayCommonError(`[midway:piscina] client(${name}) 'workerFile' is required`);
|
|
52
|
+
}
|
|
53
|
+
const pool = new MidwayPiscina({
|
|
54
|
+
...piscinaOptions,
|
|
55
|
+
filename: (0, path_1.join)(__dirname, 'worker-bootstrap.js'),
|
|
56
|
+
workerData: {
|
|
57
|
+
_fullPath: workerFile,
|
|
58
|
+
_mainAppDir: this.appDir,
|
|
59
|
+
_isDevelopmentEnvironment: this.environmentService.isDevelopmentEnvironment(),
|
|
60
|
+
...piscinaOptions.workerData,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
this.logger.info(`[midway:piscina] pool(${name}) created with worker: ${workerFile}`);
|
|
64
|
+
return pool;
|
|
65
|
+
}
|
|
66
|
+
getName() {
|
|
67
|
+
return 'piscina';
|
|
68
|
+
}
|
|
69
|
+
async destroyClient(pool, name) {
|
|
70
|
+
try {
|
|
71
|
+
if (pool) {
|
|
72
|
+
await pool.destroy();
|
|
73
|
+
this.logger.info(`[midway:piscina] pool(${name}) destroyed`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.logger.error(`[midway:piscina] pool(${name}) destroy failed.`, error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
exports.PiscinaServiceFactory = PiscinaServiceFactory;
|
|
82
|
+
__decorate([
|
|
83
|
+
(0, core_1.Config)('piscina'),
|
|
84
|
+
__metadata("design:type", Object)
|
|
85
|
+
], PiscinaServiceFactory.prototype, "config", void 0);
|
|
86
|
+
__decorate([
|
|
87
|
+
(0, core_1.Logger)('coreLogger'),
|
|
88
|
+
__metadata("design:type", Object)
|
|
89
|
+
], PiscinaServiceFactory.prototype, "logger", void 0);
|
|
90
|
+
__decorate([
|
|
91
|
+
(0, core_1.Inject)('appDir'),
|
|
92
|
+
__metadata("design:type", Object)
|
|
93
|
+
], PiscinaServiceFactory.prototype, "appDir", void 0);
|
|
94
|
+
__decorate([
|
|
95
|
+
(0, core_1.Inject)(),
|
|
96
|
+
__metadata("design:type", core_1.MidwayEnvironmentService)
|
|
97
|
+
], PiscinaServiceFactory.prototype, "environmentService", void 0);
|
|
98
|
+
__decorate([
|
|
99
|
+
(0, core_1.Init)(),
|
|
100
|
+
__metadata("design:type", Function),
|
|
101
|
+
__metadata("design:paramtypes", []),
|
|
102
|
+
__metadata("design:returntype", Promise)
|
|
103
|
+
], PiscinaServiceFactory.prototype, "init", null);
|
|
104
|
+
exports.PiscinaServiceFactory = PiscinaServiceFactory = __decorate([
|
|
105
|
+
(0, core_1.Singleton)()
|
|
106
|
+
], PiscinaServiceFactory);
|
|
107
|
+
let PiscinaService = class PiscinaService {
|
|
108
|
+
serviceFactory;
|
|
109
|
+
instance;
|
|
110
|
+
async init() {
|
|
111
|
+
this.instance = this.serviceFactory.get(this.serviceFactory.getDefaultClientName?.() || 'default');
|
|
112
|
+
if (!this.instance) {
|
|
113
|
+
throw new core_1.MidwayCommonError('piscina default instance not found.');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
exports.PiscinaService = PiscinaService;
|
|
118
|
+
__decorate([
|
|
119
|
+
(0, core_1.Inject)(),
|
|
120
|
+
__metadata("design:type", PiscinaServiceFactory)
|
|
121
|
+
], PiscinaService.prototype, "serviceFactory", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
(0, core_1.Init)(),
|
|
124
|
+
__metadata("design:type", Function),
|
|
125
|
+
__metadata("design:paramtypes", []),
|
|
126
|
+
__metadata("design:returntype", Promise)
|
|
127
|
+
], PiscinaService.prototype, "init", null);
|
|
128
|
+
exports.PiscinaService = PiscinaService = __decorate([
|
|
129
|
+
(0, core_1.Singleton)()
|
|
130
|
+
], PiscinaService);
|
|
131
|
+
(0, core_1.delegateTargetAllPrototypeMethod)(PiscinaService, MidwayPiscina);
|
|
132
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { workerData, threadId } = require('worker_threads');
|
|
5
|
+
const { FunctionalConfiguration } = require('@midwayjs/core/functional');
|
|
6
|
+
const { initializeGlobalApplicationContext, MidwayFrameworkService, } = require('@midwayjs/core');
|
|
7
|
+
const { loggers } = require('@midwayjs/logger');
|
|
8
|
+
/**
|
|
9
|
+
* 解析 worker 文件路径
|
|
10
|
+
* 支持 .ts 和 .js,自动查找存在的文件
|
|
11
|
+
*/
|
|
12
|
+
function resolveWorkerFile(workerFile) {
|
|
13
|
+
// 如果路径已经有扩展名且文件存在,直接返回
|
|
14
|
+
if (fs.existsSync(workerFile)) {
|
|
15
|
+
return workerFile;
|
|
16
|
+
}
|
|
17
|
+
const ext = path.extname(workerFile);
|
|
18
|
+
const basePath = ext ? workerFile.slice(0, -ext.length) : workerFile;
|
|
19
|
+
// 尝试的扩展名顺序:.js -> .ts -> .mjs -> .cjs
|
|
20
|
+
const extensions = ['.js', '.ts', '.mjs', '.cjs'];
|
|
21
|
+
for (const tryExt of extensions) {
|
|
22
|
+
const tryPath = basePath + tryExt;
|
|
23
|
+
if (fs.existsSync(tryPath)) {
|
|
24
|
+
return tryPath;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// 都找不到,返回原路径,让 require 报错
|
|
28
|
+
return workerFile;
|
|
29
|
+
}
|
|
30
|
+
// 从 workerData 获取 fullpath 并加载模块
|
|
31
|
+
const { _fullPath: fullpath, _mainAppDir: mainAppDir, _isDevelopmentEnvironment: isDevelopmentEnvironment, } = workerData || {};
|
|
32
|
+
let workerModule = null;
|
|
33
|
+
let resolvedFile = null;
|
|
34
|
+
let baseDir = null;
|
|
35
|
+
if (isDevelopmentEnvironment) {
|
|
36
|
+
process.env['MIDWAY_LOGGER_WRITEABLE_DIR'] =
|
|
37
|
+
process.env['MIDWAY_LOGGER_WRITEABLE_DIR'] ?? mainAppDir;
|
|
38
|
+
}
|
|
39
|
+
if (fullpath) {
|
|
40
|
+
resolvedFile = resolveWorkerFile(fullpath);
|
|
41
|
+
baseDir = path.dirname(resolvedFile);
|
|
42
|
+
// 如果是 .ts 文件,注册 ts-node 以支持 TypeScript
|
|
43
|
+
if (resolvedFile.endsWith('.ts')) {
|
|
44
|
+
try {
|
|
45
|
+
// 查找 worker 目录中的 tsconfig.json
|
|
46
|
+
const workerTsConfig = path.join(baseDir, 'tsconfig.json');
|
|
47
|
+
const hasWorkerTsConfig = fs.existsSync(workerTsConfig);
|
|
48
|
+
/* eslint-disable-next-line node/no-extraneous-require */
|
|
49
|
+
require('ts-node').register(hasWorkerTsConfig
|
|
50
|
+
? { project: workerTsConfig }
|
|
51
|
+
: {
|
|
52
|
+
transpileOnly: true,
|
|
53
|
+
compilerOptions: {
|
|
54
|
+
module: 'commonjs',
|
|
55
|
+
moduleResolution: 'node',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
// ts-node 可能不存在(生产环境),忽略错误
|
|
61
|
+
// 如果真的需要 ts-node 但没安装,后续 require 会失败并报错
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
workerModule = require(resolvedFile);
|
|
65
|
+
}
|
|
66
|
+
let applicationContext = null;
|
|
67
|
+
let framework = null;
|
|
68
|
+
/**
|
|
69
|
+
* Worker Thread 启动入口
|
|
70
|
+
*/
|
|
71
|
+
module.exports = async function workerEntry(message) {
|
|
72
|
+
const { handler, payload } = message;
|
|
73
|
+
if (!workerModule) {
|
|
74
|
+
throw new Error('workerData.fullpath is required');
|
|
75
|
+
}
|
|
76
|
+
// 支持 FunctionalConfiguration 的情况
|
|
77
|
+
if (applicationContext ||
|
|
78
|
+
workerModule.default instanceof FunctionalConfiguration) {
|
|
79
|
+
if (!applicationContext) {
|
|
80
|
+
applicationContext = await initializeGlobalApplicationContext({
|
|
81
|
+
baseDir,
|
|
82
|
+
loggerFactory: loggers,
|
|
83
|
+
});
|
|
84
|
+
// 获取 PiscinaWorkerFramework
|
|
85
|
+
const midwayFrameworkService = await applicationContext.getAsync(MidwayFrameworkService);
|
|
86
|
+
framework = midwayFrameworkService.getMainFramework();
|
|
87
|
+
if (!framework) {
|
|
88
|
+
throw new Error('Framework instance not found in application context');
|
|
89
|
+
}
|
|
90
|
+
framework
|
|
91
|
+
.getLogger()
|
|
92
|
+
.info(`[piscina:worker:${threadId}]: ApplicationContext initialized in worker`);
|
|
93
|
+
}
|
|
94
|
+
framework
|
|
95
|
+
.getLogger()
|
|
96
|
+
.info(`[piscina:worker:${threadId}]: Executing task handler "${payload.handler}" with payload`, payload.data);
|
|
97
|
+
// 执行容器中的任务
|
|
98
|
+
return await framework.executeTask(payload.handler, payload.data);
|
|
99
|
+
}
|
|
100
|
+
// 获取处理函数
|
|
101
|
+
let fn;
|
|
102
|
+
// 1. 如果指定了 handler,先查找具名导出
|
|
103
|
+
if (handler && workerModule[handler]) {
|
|
104
|
+
fn = workerModule[handler];
|
|
105
|
+
}
|
|
106
|
+
// 2. 如果没找到,尝试 default export
|
|
107
|
+
else if (typeof workerModule.default === 'function') {
|
|
108
|
+
fn = workerModule.default;
|
|
109
|
+
}
|
|
110
|
+
// 3. 如果 workerModule 本身是函数(CommonJS)
|
|
111
|
+
else if (typeof workerModule === 'function') {
|
|
112
|
+
fn = workerModule;
|
|
113
|
+
}
|
|
114
|
+
// 4. 都找不到,报错
|
|
115
|
+
else {
|
|
116
|
+
if (handler) {
|
|
117
|
+
throw new Error(`Handler "${handler}" not found and no default function in "${resolvedFile}"`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
throw new Error(`No handler specified and no default function found in "${resolvedFile}"`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (typeof fn !== 'function') {
|
|
124
|
+
throw new Error(`Handler is not a function in "${resolvedFile}"`);
|
|
125
|
+
}
|
|
126
|
+
return await fn(payload);
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=worker-bootstrap.js.map
|
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@midwayjs/piscina",
|
|
3
|
+
"version": "4.0.0-beta.1",
|
|
4
|
+
"description": "Midway Component for Piscina worker thread pool",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"typings": "index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "node -r ts-node/register ../../node_modules/jest/bin/jest.js --runInBand",
|
|
10
|
+
"cov": "node -r ts-node/register ../../node_modules/jest/bin/jest.js --runInBand --coverage --forceExit",
|
|
11
|
+
"ci": "npm run test"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"midway",
|
|
15
|
+
"component",
|
|
16
|
+
"piscina",
|
|
17
|
+
"worker",
|
|
18
|
+
"thread"
|
|
19
|
+
],
|
|
20
|
+
"author": "Harry Chen <czy88840616@gmail.com>",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist/**/*.js",
|
|
23
|
+
"dist/**/*.d.ts",
|
|
24
|
+
"index.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@midwayjs/core": "workspace:^",
|
|
32
|
+
"@midwayjs/logger": "^4.0.0",
|
|
33
|
+
"@midwayjs/mock": "workspace:^"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"piscina": "5.1.4"
|
|
37
|
+
}
|
|
38
|
+
}
|