egg 3.29.0 → 4.0.0-beta.10
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 +2 -1
- package/README.zh-CN.md +7 -5
- package/dist/commonjs/agent.d.ts +4 -0
- package/dist/commonjs/agent.js +10 -0
- package/dist/commonjs/app/extend/context.d.ts +154 -0
- package/dist/commonjs/app/extend/context.js +261 -0
- package/dist/commonjs/app/extend/context.types.d.ts +16 -0
- package/dist/commonjs/app/extend/context.types.js +3 -0
- package/dist/commonjs/app/extend/helper.d.ts +37 -0
- package/dist/commonjs/app/extend/helper.js +49 -0
- package/dist/commonjs/app/extend/request.d.ts +128 -0
- package/dist/commonjs/app/extend/request.js +270 -0
- package/dist/commonjs/app/extend/response.d.ts +25 -0
- package/dist/commonjs/app/extend/response.js +37 -0
- package/dist/commonjs/app/middleware/body_parser.d.ts +2 -0
- package/dist/commonjs/app/middleware/body_parser.js +8 -0
- package/dist/commonjs/app/middleware/meta.d.ts +10 -0
- package/dist/commonjs/app/middleware/meta.js +22 -0
- package/dist/commonjs/app/middleware/notfound.d.ts +7 -0
- package/dist/commonjs/app/middleware/notfound.js +31 -0
- package/dist/commonjs/app/middleware/override_method.d.ts +2 -0
- package/dist/commonjs/app/middleware/override_method.js +8 -0
- package/dist/commonjs/app/middleware/site_file.d.ts +9 -0
- package/dist/commonjs/app/middleware/site_file.js +58 -0
- package/dist/commonjs/config/config.default.d.ts +9 -0
- package/dist/commonjs/config/config.default.js +379 -0
- package/dist/commonjs/config/config.local.d.ts +8 -0
- package/dist/commonjs/config/config.local.js +12 -0
- package/dist/commonjs/config/config.unittest.d.ts +7 -0
- package/dist/commonjs/config/config.unittest.js +11 -0
- package/dist/commonjs/config/plugin.d.ts +122 -0
- package/dist/commonjs/config/plugin.js +125 -0
- package/dist/commonjs/index.d.ts +63 -0
- package/dist/commonjs/index.js +91 -0
- package/dist/commonjs/lib/agent.d.ts +19 -0
- package/dist/commonjs/lib/agent.js +58 -0
- package/dist/commonjs/lib/application.d.ts +59 -0
- package/dist/commonjs/lib/application.js +270 -0
- package/dist/commonjs/lib/core/base_context_class.d.ts +14 -0
- package/dist/commonjs/lib/core/base_context_class.js +22 -0
- package/dist/commonjs/lib/core/base_context_logger.d.ts +36 -0
- package/dist/commonjs/lib/core/base_context_logger.js +64 -0
- package/dist/commonjs/lib/core/base_hook_class.d.ts +11 -0
- package/dist/commonjs/lib/core/base_hook_class.js +30 -0
- package/dist/commonjs/lib/core/context_httpclient.d.ts +16 -0
- package/dist/commonjs/lib/core/context_httpclient.js +30 -0
- package/dist/commonjs/lib/core/httpclient.d.ts +13 -0
- package/dist/commonjs/lib/core/httpclient.js +37 -0
- package/dist/commonjs/lib/core/logger.d.ts +3 -0
- package/dist/commonjs/lib/core/logger.js +40 -0
- package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +50 -0
- package/dist/commonjs/lib/core/messenger/IMessenger.js +3 -0
- package/dist/commonjs/lib/core/messenger/index.d.ts +7 -0
- package/dist/commonjs/lib/core/messenger/index.js +14 -0
- package/dist/commonjs/lib/core/messenger/ipc.d.ts +59 -0
- package/dist/commonjs/lib/core/messenger/ipc.js +137 -0
- package/dist/commonjs/lib/core/messenger/local.d.ts +61 -0
- package/dist/commonjs/lib/core/messenger/local.js +137 -0
- package/dist/commonjs/lib/core/singleton.d.ts +23 -0
- package/dist/commonjs/lib/core/singleton.js +120 -0
- package/dist/commonjs/lib/core/utils.d.ts +2 -0
- package/dist/commonjs/lib/core/utils.js +77 -0
- package/dist/commonjs/lib/egg.d.ts +276 -0
- package/dist/commonjs/lib/egg.js +617 -0
- package/dist/commonjs/lib/egg.types.d.ts +6 -0
- package/dist/commonjs/lib/egg.types.js +3 -0
- package/dist/commonjs/lib/loader/AgentWorkerLoader.d.ts +12 -0
- package/dist/commonjs/lib/loader/AgentWorkerLoader.js +24 -0
- package/dist/commonjs/lib/loader/AppWorkerLoader.d.ts +17 -0
- package/dist/commonjs/lib/loader/AppWorkerLoader.js +43 -0
- package/dist/commonjs/lib/loader/EggApplicationLoader.d.ts +4 -0
- package/dist/commonjs/lib/loader/EggApplicationLoader.js +8 -0
- package/dist/commonjs/lib/loader/index.d.ts +3 -0
- package/dist/commonjs/lib/loader/index.js +22 -0
- package/dist/commonjs/lib/start.d.ts +15 -0
- package/dist/commonjs/lib/start.js +49 -0
- package/dist/commonjs/lib/type.d.ts +293 -0
- package/dist/commonjs/lib/type.js +3 -0
- package/dist/commonjs/lib/utils.d.ts +2 -0
- package/dist/commonjs/lib/utils.js +21 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/esm/agent.d.ts +4 -0
- package/dist/esm/agent.js +7 -0
- package/dist/esm/app/extend/context.d.ts +154 -0
- package/dist/esm/app/extend/context.js +255 -0
- package/dist/esm/app/extend/context.types.d.ts +16 -0
- package/dist/esm/app/extend/context.types.js +2 -0
- package/dist/esm/app/extend/helper.d.ts +37 -0
- package/dist/esm/app/extend/helper.js +43 -0
- package/dist/esm/app/extend/request.d.ts +128 -0
- package/dist/esm/app/extend/request.js +264 -0
- package/dist/esm/app/extend/response.d.ts +25 -0
- package/dist/esm/app/extend/response.js +34 -0
- package/dist/esm/app/middleware/body_parser.d.ts +2 -0
- package/dist/esm/app/middleware/body_parser.js +3 -0
- package/dist/esm/app/middleware/meta.d.ts +10 -0
- package/dist/esm/app/middleware/meta.js +20 -0
- package/dist/esm/app/middleware/notfound.d.ts +7 -0
- package/dist/esm/app/middleware/notfound.js +29 -0
- package/dist/esm/app/middleware/override_method.d.ts +2 -0
- package/dist/esm/app/middleware/override_method.js +3 -0
- package/dist/esm/app/middleware/site_file.d.ts +9 -0
- package/dist/esm/app/middleware/site_file.js +53 -0
- package/dist/esm/config/config.default.d.ts +9 -0
- package/dist/esm/config/config.default.js +374 -0
- package/dist/esm/config/config.local.d.ts +8 -0
- package/dist/esm/config/config.local.js +10 -0
- package/dist/esm/config/config.unittest.d.ts +7 -0
- package/dist/esm/config/config.unittest.js +9 -0
- package/dist/esm/config/favicon.png +0 -0
- package/dist/esm/config/plugin.d.ts +122 -0
- package/dist/esm/config/plugin.js +123 -0
- package/dist/esm/index.d.ts +63 -0
- package/dist/esm/index.js +66 -0
- package/dist/esm/lib/agent.d.ts +19 -0
- package/dist/esm/lib/agent.js +54 -0
- package/dist/esm/lib/application.d.ts +59 -0
- package/dist/esm/lib/application.js +263 -0
- package/dist/esm/lib/core/base_context_class.d.ts +14 -0
- package/dist/esm/lib/core/base_context_class.js +18 -0
- package/dist/esm/lib/core/base_context_logger.d.ts +36 -0
- package/dist/esm/lib/core/base_context_logger.js +60 -0
- package/dist/esm/lib/core/base_hook_class.d.ts +11 -0
- package/dist/esm/lib/core/base_hook_class.js +23 -0
- package/dist/esm/lib/core/context_httpclient.d.ts +16 -0
- package/dist/esm/lib/core/context_httpclient.js +26 -0
- package/dist/esm/lib/core/httpclient.d.ts +13 -0
- package/dist/esm/lib/core/httpclient.js +33 -0
- package/dist/esm/lib/core/logger.d.ts +3 -0
- package/dist/esm/lib/core/logger.js +37 -0
- package/dist/esm/lib/core/messenger/IMessenger.d.ts +50 -0
- package/dist/esm/lib/core/messenger/IMessenger.js +2 -0
- package/dist/esm/lib/core/messenger/index.d.ts +7 -0
- package/dist/esm/lib/core/messenger/index.js +11 -0
- package/dist/esm/lib/core/messenger/ipc.d.ts +59 -0
- package/dist/esm/lib/core/messenger/ipc.js +130 -0
- package/dist/esm/lib/core/messenger/local.d.ts +61 -0
- package/dist/esm/lib/core/messenger/local.js +130 -0
- package/dist/esm/lib/core/singleton.d.ts +23 -0
- package/dist/esm/lib/core/singleton.js +113 -0
- package/dist/esm/lib/core/utils.d.ts +2 -0
- package/dist/esm/lib/core/utils.js +70 -0
- package/dist/esm/lib/egg.d.ts +276 -0
- package/dist/esm/lib/egg.js +574 -0
- package/dist/esm/lib/egg.types.d.ts +6 -0
- package/dist/esm/lib/egg.types.js +2 -0
- package/dist/esm/lib/loader/AgentWorkerLoader.d.ts +12 -0
- package/dist/esm/lib/loader/AgentWorkerLoader.js +20 -0
- package/dist/esm/lib/loader/AppWorkerLoader.d.ts +17 -0
- package/dist/esm/lib/loader/AppWorkerLoader.js +39 -0
- package/dist/esm/lib/loader/EggApplicationLoader.d.ts +4 -0
- package/dist/esm/lib/loader/EggApplicationLoader.js +4 -0
- package/dist/esm/lib/loader/index.d.ts +3 -0
- package/dist/esm/lib/loader/index.js +4 -0
- package/dist/esm/lib/start.d.ts +15 -0
- package/dist/esm/lib/start.js +43 -0
- package/dist/esm/lib/type.d.ts +293 -0
- package/dist/esm/lib/type.js +2 -0
- package/dist/esm/lib/utils.d.ts +2 -0
- package/dist/esm/lib/utils.js +14 -0
- package/dist/esm/package.json +3 -0
- package/dist/package.json +4 -0
- package/package.json +97 -79
- package/src/agent.ts +7 -0
- package/src/app/extend/context.ts +303 -0
- package/src/app/extend/context.types.ts +24 -0
- package/{app/extend/helper.js → src/app/extend/helper.ts} +14 -13
- package/{app/extend/request.js → src/app/extend/request.ts} +81 -79
- package/src/app/extend/response.ts +36 -0
- package/src/app/middleware/body_parser.ts +3 -0
- package/{app/middleware/meta.js → src/app/middleware/meta.ts} +11 -4
- package/{app/middleware/notfound.js → src/app/middleware/notfound.ts} +8 -3
- package/src/app/middleware/override_method.ts +3 -0
- package/src/app/middleware/site_file.ts +68 -0
- package/{config/config.default.js → src/config/config.default.ts} +25 -45
- package/src/config/config.local.ts +11 -0
- package/src/config/config.unittest.ts +10 -0
- package/src/config/favicon.png +0 -0
- package/{config/plugin.js → src/config/plugin.ts} +3 -5
- package/src/index.ts +80 -0
- package/src/lib/agent.ts +66 -0
- package/{lib/application.js → src/lib/application.ts} +76 -124
- package/src/lib/core/base_context_class.ts +21 -0
- package/src/lib/core/base_context_logger.ts +67 -0
- package/src/lib/core/base_hook_class.ts +30 -0
- package/src/lib/core/context_httpclient.ts +33 -0
- package/src/lib/core/httpclient.ts +51 -0
- package/src/lib/core/logger.ts +42 -0
- package/src/lib/core/messenger/IMessenger.ts +58 -0
- package/src/lib/core/messenger/index.ts +15 -0
- package/src/lib/core/messenger/ipc.ts +148 -0
- package/{lib/core/messenger/local.js → src/lib/core/messenger/local.ts} +36 -28
- package/{lib/core/singleton.js → src/lib/core/singleton.ts} +56 -33
- package/src/lib/core/utils.ts +77 -0
- package/{lib/egg.js → src/lib/egg.ts} +287 -221
- package/src/lib/egg.types.ts +6 -0
- package/src/lib/loader/AgentWorkerLoader.ts +21 -0
- package/src/lib/loader/AppWorkerLoader.ts +42 -0
- package/src/lib/loader/EggApplicationLoader.ts +5 -0
- package/src/lib/loader/index.ts +3 -0
- package/src/lib/start.ts +56 -0
- package/src/lib/type.ts +329 -0
- package/src/lib/utils.ts +16 -0
- package/CHANGELOG.md +0 -2395
- package/History.md +0 -52
- package/agent.js +0 -11
- package/app/extend/context.js +0 -285
- package/app/extend/response.js +0 -101
- package/app/middleware/body_parser.js +0 -3
- package/app/middleware/override_method.js +0 -3
- package/app/middleware/site_file.js +0 -31
- package/config/config.local.js +0 -7
- package/config/config.unittest.js +0 -8
- package/index.d.ts +0 -1288
- package/index.js +0 -68
- package/lib/agent.js +0 -95
- package/lib/core/base_context_class.js +0 -20
- package/lib/core/base_context_logger.js +0 -64
- package/lib/core/base_hook_class.js +0 -31
- package/lib/core/context_httpclient.js +0 -26
- package/lib/core/dnscache_httpclient.js +0 -93
- package/lib/core/httpclient.js +0 -119
- package/lib/core/httpclient_next.js +0 -80
- package/lib/core/logger.js +0 -35
- package/lib/core/messenger/index.js +0 -14
- package/lib/core/messenger/ipc.js +0 -141
- package/lib/core/utils.js +0 -73
- package/lib/loader/agent_worker_loader.js +0 -27
- package/lib/loader/app_worker_loader.js +0 -48
- package/lib/loader/index.js +0 -5
- package/lib/start.js +0 -39
- /package/{config → dist/commonjs/config}/favicon.png +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HttpClient as RawHttpClient,
|
|
3
|
+
RequestURL as HttpClientRequestURL,
|
|
4
|
+
RequestOptions,
|
|
5
|
+
} from 'urllib';
|
|
6
|
+
import { ms } from 'humanize-ms';
|
|
7
|
+
import type { EggApplicationCore, ContextDelegation } from '../egg.js';
|
|
8
|
+
|
|
9
|
+
export type {
|
|
10
|
+
HttpClientResponse,
|
|
11
|
+
RequestURL as HttpClientRequestURL,
|
|
12
|
+
} from 'urllib';
|
|
13
|
+
|
|
14
|
+
export interface HttpClientRequestOptions extends RequestOptions {
|
|
15
|
+
ctx?: ContextDelegation;
|
|
16
|
+
tracer?: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class HttpClient extends RawHttpClient {
|
|
20
|
+
readonly #app: EggApplicationCore & { tracer?: unknown };
|
|
21
|
+
|
|
22
|
+
constructor(app: EggApplicationCore) {
|
|
23
|
+
normalizeConfig(app);
|
|
24
|
+
const config = app.config.httpclient;
|
|
25
|
+
super({
|
|
26
|
+
defaultArgs: config.request,
|
|
27
|
+
});
|
|
28
|
+
this.#app = app;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async request<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
|
|
32
|
+
options = options ?? {};
|
|
33
|
+
if (options.ctx?.tracer) {
|
|
34
|
+
options.tracer = options.ctx.tracer;
|
|
35
|
+
} else {
|
|
36
|
+
options.tracer = options.tracer ?? this.#app.tracer;
|
|
37
|
+
}
|
|
38
|
+
return await super.request<T>(url, options);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async curl<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
|
|
42
|
+
return await this.request<T>(url, options);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeConfig(app: EggApplicationCore) {
|
|
47
|
+
const config = app.config.httpclient;
|
|
48
|
+
if (typeof config.request?.timeout === 'string') {
|
|
49
|
+
config.request.timeout = ms(config.request.timeout);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EggLoggers, EggLoggersOptions } from 'egg-logger';
|
|
2
|
+
import { setCustomLogger } from 'onelogger';
|
|
3
|
+
import type { EggApplicationCore } from '../egg.js';
|
|
4
|
+
|
|
5
|
+
export function createLoggers(app: EggApplicationCore) {
|
|
6
|
+
const loggerOptions = {
|
|
7
|
+
...app.config.logger,
|
|
8
|
+
type: app.type,
|
|
9
|
+
localStorage: app.ctxStorage,
|
|
10
|
+
} as EggLoggersOptions;
|
|
11
|
+
|
|
12
|
+
// set DEBUG level into INFO on prod env
|
|
13
|
+
if (app.config.env === 'prod' && loggerOptions.level === 'DEBUG' && !app.config.logger.allowDebugAtProd) {
|
|
14
|
+
loggerOptions.level = 'INFO';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const loggers = new EggLoggers({
|
|
18
|
+
logger: loggerOptions,
|
|
19
|
+
customLogger: app.config.customLogger,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// won't print to console after started, except for local and unittest
|
|
23
|
+
app.ready(() => {
|
|
24
|
+
if (app.config.logger.disableConsoleAfterReady) {
|
|
25
|
+
loggers.disableConsole();
|
|
26
|
+
loggers.coreLogger.info('[egg:lib:core:logger] disable console log after app ready');
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// set global logger
|
|
31
|
+
for (const loggerName of Object.keys(loggers)) {
|
|
32
|
+
setCustomLogger(loggerName, loggers[loggerName]);
|
|
33
|
+
}
|
|
34
|
+
// reset global logger on beforeClose hook
|
|
35
|
+
app.lifecycle.registerBeforeClose(() => {
|
|
36
|
+
for (const loggerName of Object.keys(loggers)) {
|
|
37
|
+
setCustomLogger(loggerName, undefined);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
loggers.coreLogger.info('[egg:lib:core:logger] init all loggers with options: %j', loggerOptions);
|
|
41
|
+
return loggers;
|
|
42
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
export interface IMessenger extends EventEmitter {
|
|
4
|
+
/**
|
|
5
|
+
* Send message to all agent and app
|
|
6
|
+
* @param {String} action - message key
|
|
7
|
+
* @param {Object} data - message value
|
|
8
|
+
* @return {Messenger} this
|
|
9
|
+
*/
|
|
10
|
+
broadcast(action: string, data?: unknown): IMessenger;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* send message to the specified process
|
|
14
|
+
* @param {String} workerId - the workerId of the receiver
|
|
15
|
+
* @param {String} action - message key
|
|
16
|
+
* @param {Object} data - message value
|
|
17
|
+
* @return {Messenger} this
|
|
18
|
+
*/
|
|
19
|
+
sendTo(workerId: string, action: string, data?: unknown): IMessenger;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* send message to one app worker by random
|
|
23
|
+
* - if it's running in agent, it will send to one of app workers
|
|
24
|
+
* - if it's running in app, it will send to agent
|
|
25
|
+
* @param {String} action - message key
|
|
26
|
+
* @param {Object} data - message value
|
|
27
|
+
* @return {Messenger} this
|
|
28
|
+
*/
|
|
29
|
+
sendRandom(action: string, data?: unknown): IMessenger;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* send message to app
|
|
33
|
+
* @param {String} action - message key
|
|
34
|
+
* @param {Object} data - message value
|
|
35
|
+
* @return {Messenger} this
|
|
36
|
+
*/
|
|
37
|
+
sendToApp(action: string, data?: unknown): IMessenger;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* send message to agent
|
|
41
|
+
* @param {String} action - message key
|
|
42
|
+
* @param {Object} data - message value
|
|
43
|
+
* @return {Messenger} this
|
|
44
|
+
*/
|
|
45
|
+
sendToAgent(action: string, data?: unknown): IMessenger;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {String} action - message key
|
|
49
|
+
* @param {Object} data - message value
|
|
50
|
+
* @param {String} to - let master know how to send message
|
|
51
|
+
* @return {Messenger} this
|
|
52
|
+
*/
|
|
53
|
+
send(action: string, data: unknown | undefined, to?: string): IMessenger;
|
|
54
|
+
|
|
55
|
+
close(): void;
|
|
56
|
+
|
|
57
|
+
onMessage(message: any): void;
|
|
58
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Messenger as LocalMessenger } from './local.js';
|
|
2
|
+
import { Messenger as IPCMessenger } from './ipc.js';
|
|
3
|
+
import type { IMessenger } from './IMessenger.js';
|
|
4
|
+
import type { EggApplicationCore } from '../../egg.js';
|
|
5
|
+
|
|
6
|
+
export type { IMessenger } from './IMessenger.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @class Messenger
|
|
10
|
+
*/
|
|
11
|
+
export function create(egg: EggApplicationCore): IMessenger {
|
|
12
|
+
return egg.options.mode === 'single'
|
|
13
|
+
? new LocalMessenger(egg)
|
|
14
|
+
: new IPCMessenger(egg);
|
|
15
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { debuglog } from 'node:util';
|
|
3
|
+
import workerThreads from 'node:worker_threads';
|
|
4
|
+
import { sendmessage } from 'sendmessage';
|
|
5
|
+
import type { IMessenger } from './IMessenger.js';
|
|
6
|
+
import type { EggApplicationCore } from '../../egg.js';
|
|
7
|
+
|
|
8
|
+
const debug = debuglog('egg/lib/core/messenger/ipc');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Communication between app worker and agent worker by IPC channel
|
|
12
|
+
*/
|
|
13
|
+
export class Messenger extends EventEmitter implements IMessenger {
|
|
14
|
+
readonly pid: string;
|
|
15
|
+
readonly egg: EggApplicationCore;
|
|
16
|
+
opids: string[] = [];
|
|
17
|
+
|
|
18
|
+
constructor(egg: EggApplicationCore) {
|
|
19
|
+
super();
|
|
20
|
+
this.pid = String(process.pid);
|
|
21
|
+
this.egg = egg;
|
|
22
|
+
// pids of agent or app managed by master
|
|
23
|
+
// - retrieve app worker pids when it's an agent worker
|
|
24
|
+
// - retrieve agent worker pids when it's an app worker
|
|
25
|
+
this.on('egg-pids', workerIds => {
|
|
26
|
+
debug('[%s:%s] got egg-pids %j', this.egg.type, this.pid, workerIds);
|
|
27
|
+
this.opids = workerIds.map((workerId: number) => String(workerId));
|
|
28
|
+
});
|
|
29
|
+
this.onMessage = this.onMessage.bind(this);
|
|
30
|
+
process.on('message', this.onMessage);
|
|
31
|
+
if (!workerThreads.isMainThread) {
|
|
32
|
+
workerThreads.parentPort!.on('message', this.onMessage);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Send message to all agent and app
|
|
38
|
+
* @param {String} action - message key
|
|
39
|
+
* @param {Object} data - message value
|
|
40
|
+
* @return {Messenger} this
|
|
41
|
+
*/
|
|
42
|
+
broadcast(action: string, data?: unknown): Messenger {
|
|
43
|
+
debug('[%s:%s] broadcast %s with %j', this.egg.type, this.pid, action, data);
|
|
44
|
+
this.send(action, data, 'app');
|
|
45
|
+
this.send(action, data, 'agent');
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* send message to the specified process
|
|
51
|
+
* @param {String} workerId - the workerId of the receiver
|
|
52
|
+
* @param {String} action - message key
|
|
53
|
+
* @param {Object} data - message value
|
|
54
|
+
* @return {Messenger} this
|
|
55
|
+
*/
|
|
56
|
+
sendTo(workerId: string, action: string, data?: unknown): Messenger {
|
|
57
|
+
debug('[%s:%s] send %s with %j to workerId:%s', this.egg.type, this.pid, action, data, workerId);
|
|
58
|
+
sendmessage(process, {
|
|
59
|
+
action,
|
|
60
|
+
data,
|
|
61
|
+
/**
|
|
62
|
+
* @deprecated Keep compatible, please use receiverWorkerId instead
|
|
63
|
+
*/
|
|
64
|
+
receiverPid: String(workerId),
|
|
65
|
+
receiverWorkerId: String(workerId),
|
|
66
|
+
});
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* send message to one app worker by random
|
|
72
|
+
* - if it's running in agent, it will send to one of app workers
|
|
73
|
+
* - if it's running in app, it will send to agent
|
|
74
|
+
* @param {String} action - message key
|
|
75
|
+
* @param {Object} data - message value
|
|
76
|
+
* @return {Messenger} this
|
|
77
|
+
*/
|
|
78
|
+
sendRandom(action: string, data?: unknown): Messenger {
|
|
79
|
+
if (this.opids.length === 0) {
|
|
80
|
+
debug('[%s:%s] no pids, ignore sendRandom %s with %j', this.egg.type, this.pid, action, data);
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
const index = Math.floor(Math.random() * this.opids.length);
|
|
84
|
+
const workerId = this.opids[index];
|
|
85
|
+
this.sendTo(workerId, action, data);
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* send message to app
|
|
91
|
+
* @param {String} action - message key
|
|
92
|
+
* @param {Object} data - message value
|
|
93
|
+
* @return {Messenger} this
|
|
94
|
+
*/
|
|
95
|
+
sendToApp(action: string, data?: unknown): Messenger {
|
|
96
|
+
debug('[%s:%s] send %s with %j to all app', this.egg.type, this.pid, action, data);
|
|
97
|
+
this.send(action, data, 'app');
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* send message to agent
|
|
103
|
+
* @param {String} action - message key
|
|
104
|
+
* @param {Object} data - message value
|
|
105
|
+
* @return {Messenger} this
|
|
106
|
+
*/
|
|
107
|
+
sendToAgent(action: string, data?: unknown): Messenger {
|
|
108
|
+
debug('[%s:%s] send %s with %j to all agent', this.egg.type, this.pid, action, data);
|
|
109
|
+
this.send(action, data, 'agent');
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {String} action - message key
|
|
115
|
+
* @param {Object} data - message value
|
|
116
|
+
* @param {String} to - let master know how to send message
|
|
117
|
+
* @return {Messenger} this
|
|
118
|
+
*/
|
|
119
|
+
send(action: string, data: unknown | undefined, to?: string): Messenger {
|
|
120
|
+
sendmessage(process, {
|
|
121
|
+
action,
|
|
122
|
+
data,
|
|
123
|
+
to,
|
|
124
|
+
});
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
onMessage(message: any) {
|
|
129
|
+
if (typeof message?.action === 'string') {
|
|
130
|
+
debug('[%s:%s] got message %s with %j, receiverWorkerId: %s',
|
|
131
|
+
this.egg.type, this.pid, message.action, message.data, message.receiverWorkerId ?? message.receiverPid);
|
|
132
|
+
this.emit(message.action, message.data);
|
|
133
|
+
} else {
|
|
134
|
+
debug('[%s:%s] got an invalid message %j', this.egg.type, this.pid, message);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
close() {
|
|
139
|
+
process.removeListener('message', this.onMessage);
|
|
140
|
+
this.removeAllListeners();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @function Messenger#on
|
|
145
|
+
* @param {String} action - message key
|
|
146
|
+
* @param {Object} data - message value
|
|
147
|
+
*/
|
|
148
|
+
}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
import EventEmitter from 'node:events';
|
|
3
|
+
import type { IMessenger } from './IMessenger.js';
|
|
4
|
+
import type { EggApplicationCore } from '../../egg.js';
|
|
2
5
|
|
|
3
|
-
const debug =
|
|
4
|
-
const is = require('is-type-of');
|
|
5
|
-
const EventEmitter = require('events');
|
|
6
|
+
const debug = debuglog('egg/lib/core/messenger/local');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Communication between app worker and agent worker with EventEmitter
|
|
9
10
|
*/
|
|
10
|
-
class Messenger extends EventEmitter {
|
|
11
|
+
export class Messenger extends EventEmitter implements IMessenger {
|
|
12
|
+
readonly pid: string;
|
|
13
|
+
readonly egg: EggApplicationCore;
|
|
11
14
|
|
|
12
|
-
constructor(egg) {
|
|
15
|
+
constructor(egg: EggApplicationCore) {
|
|
13
16
|
super();
|
|
14
17
|
this.egg = egg;
|
|
18
|
+
this.pid = String(process.pid);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
/**
|
|
@@ -20,8 +24,8 @@ class Messenger extends EventEmitter {
|
|
|
20
24
|
* @param {Object} data - message value
|
|
21
25
|
* @return {Messenger} this
|
|
22
26
|
*/
|
|
23
|
-
broadcast(action, data) {
|
|
24
|
-
debug('[%s] broadcast %s with %j', this.pid, action, data);
|
|
27
|
+
broadcast(action: string, data?: unknown): Messenger {
|
|
28
|
+
debug('[%s:%s] broadcast %s with %j', this.egg.type, this.pid, action, data);
|
|
25
29
|
this.send(action, data, 'both');
|
|
26
30
|
return this;
|
|
27
31
|
}
|
|
@@ -30,14 +34,16 @@ class Messenger extends EventEmitter {
|
|
|
30
34
|
* send message to the specified process
|
|
31
35
|
* Notice: in single process mode, it only can send to self process,
|
|
32
36
|
* and it will send to both agent and app's messengers.
|
|
33
|
-
* @param {String}
|
|
37
|
+
* @param {String} workerId - the workerId of the receiver
|
|
34
38
|
* @param {String} action - message key
|
|
35
39
|
* @param {Object} data - message value
|
|
36
40
|
* @return {Messenger} this
|
|
37
41
|
*/
|
|
38
|
-
sendTo(
|
|
39
|
-
debug('[%s] send %s with %j to %s', this.pid, action, data,
|
|
40
|
-
if (
|
|
42
|
+
sendTo(workerId: string, action: string, data?: unknown): Messenger {
|
|
43
|
+
debug('[%s:%s] send %s with %j to %s', this.egg.type, this.pid, action, data, workerId);
|
|
44
|
+
if (String(workerId) !== this.pid) {
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
41
47
|
this.send(action, data, 'both');
|
|
42
48
|
return this;
|
|
43
49
|
}
|
|
@@ -51,8 +57,8 @@ class Messenger extends EventEmitter {
|
|
|
51
57
|
* @param {Object} data - message value
|
|
52
58
|
* @return {Messenger} this
|
|
53
59
|
*/
|
|
54
|
-
sendRandom(action, data) {
|
|
55
|
-
debug('[%s] send %s with %j to opposite', this.pid, action, data);
|
|
60
|
+
sendRandom(action: string, data?: unknown): Messenger {
|
|
61
|
+
debug('[%s:%s] send %s with %j to opposite', this.egg.type, this.pid, action, data);
|
|
56
62
|
this.send(action, data, 'opposite');
|
|
57
63
|
return this;
|
|
58
64
|
}
|
|
@@ -63,8 +69,8 @@ class Messenger extends EventEmitter {
|
|
|
63
69
|
* @param {Object} data - message value
|
|
64
70
|
* @return {Messenger} this
|
|
65
71
|
*/
|
|
66
|
-
sendToApp(action, data) {
|
|
67
|
-
debug('[%s] send %s with %j to all app', this.pid, action, data);
|
|
72
|
+
sendToApp(action: string, data?: unknown): Messenger {
|
|
73
|
+
debug('[%s:%s] send %s with %j to all app', this.egg.type, this.pid, action, data);
|
|
68
74
|
this.send(action, data, 'application');
|
|
69
75
|
return this;
|
|
70
76
|
}
|
|
@@ -75,8 +81,8 @@ class Messenger extends EventEmitter {
|
|
|
75
81
|
* @param {Object} data - message value
|
|
76
82
|
* @return {Messenger} this
|
|
77
83
|
*/
|
|
78
|
-
sendToAgent(action, data) {
|
|
79
|
-
debug('[%s] send %s with %j to all agent', this.pid, action, data);
|
|
84
|
+
sendToAgent(action: string, data?: unknown): Messenger {
|
|
85
|
+
debug('[%s:%s] send %s with %j to all agent', this.egg.type, this.pid, action, data);
|
|
80
86
|
this.send(action, data, 'agent');
|
|
81
87
|
return this;
|
|
82
88
|
}
|
|
@@ -87,7 +93,7 @@ class Messenger extends EventEmitter {
|
|
|
87
93
|
* @param {String} to - let master know how to send message
|
|
88
94
|
* @return {Messenger} this
|
|
89
95
|
*/
|
|
90
|
-
send(action, data, to) {
|
|
96
|
+
send(action: string, data: unknown | undefined, to?: string): Messenger {
|
|
91
97
|
// use nextTick to keep it async as IPC messenger
|
|
92
98
|
process.nextTick(() => {
|
|
93
99
|
const { egg } = this;
|
|
@@ -104,26 +110,30 @@ class Messenger extends EventEmitter {
|
|
|
104
110
|
application = egg.application;
|
|
105
111
|
opposite = application;
|
|
106
112
|
}
|
|
107
|
-
if (!to)
|
|
113
|
+
if (!to) {
|
|
114
|
+
to = egg.type === 'application' ? 'agent' : 'application';
|
|
115
|
+
}
|
|
108
116
|
|
|
109
117
|
if (application && application.messenger && (to === 'application' || to === 'both')) {
|
|
110
|
-
application.messenger.
|
|
118
|
+
application.messenger.onMessage({ action, data });
|
|
111
119
|
}
|
|
112
120
|
if (agent && agent.messenger && (to === 'agent' || to === 'both')) {
|
|
113
|
-
agent.messenger.
|
|
121
|
+
agent.messenger.onMessage({ action, data });
|
|
114
122
|
}
|
|
115
123
|
if (opposite && opposite.messenger && to === 'opposite') {
|
|
116
|
-
opposite.messenger.
|
|
124
|
+
opposite.messenger.onMessage({ action, data });
|
|
117
125
|
}
|
|
118
126
|
});
|
|
119
127
|
|
|
120
128
|
return this;
|
|
121
129
|
}
|
|
122
130
|
|
|
123
|
-
|
|
124
|
-
if (message
|
|
125
|
-
debug('[%s] got message %s with %j', this.pid, message.action, message.data);
|
|
131
|
+
onMessage(message: any) {
|
|
132
|
+
if (typeof message?.action === 'string') {
|
|
133
|
+
debug('[%s:%s] got message %s with %j', this.egg.type, this.pid, message.action, message.data);
|
|
126
134
|
this.emit(message.action, message.data);
|
|
135
|
+
} else {
|
|
136
|
+
debug('[%s:%s] got an invalid message %j', this.egg.type, this.pid, message);
|
|
127
137
|
}
|
|
128
138
|
}
|
|
129
139
|
|
|
@@ -137,5 +147,3 @@ class Messenger extends EventEmitter {
|
|
|
137
147
|
* @param {Object} data - message value
|
|
138
148
|
*/
|
|
139
149
|
}
|
|
140
|
-
|
|
141
|
-
module.exports = Messenger;
|
|
@@ -1,36 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { isAsyncFunction } from 'is-type-of';
|
|
3
|
+
import type { EggApplicationCore } from '../egg.js';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
export type SingletonCreateMethod =
|
|
6
|
+
(config: Record<string, any>, app: EggApplicationCore, clientName: string) => unknown | Promise<unknown>;
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
export interface SingletonOptions {
|
|
9
|
+
name: string;
|
|
10
|
+
app: EggApplicationCore;
|
|
11
|
+
create: SingletonCreateMethod;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Singleton {
|
|
15
|
+
readonly clients = new Map<string, any>();
|
|
16
|
+
readonly app: EggApplicationCore;
|
|
17
|
+
readonly create: SingletonCreateMethod;
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly options: Record<string, any>;
|
|
20
|
+
|
|
21
|
+
constructor(options: SingletonOptions) {
|
|
8
22
|
assert(options.name, '[egg:singleton] Singleton#constructor options.name is required');
|
|
9
23
|
assert(options.app, '[egg:singleton] Singleton#constructor options.app is required');
|
|
10
24
|
assert(options.create, '[egg:singleton] Singleton#constructor options.create is required');
|
|
11
|
-
assert(!options.
|
|
12
|
-
this.clients = new Map();
|
|
25
|
+
assert(!(options.name in options.app), `[egg:singleton] ${options.name} is already exists in app`);
|
|
13
26
|
this.app = options.app;
|
|
14
27
|
this.name = options.name;
|
|
15
28
|
this.create = options.create;
|
|
16
|
-
|
|
17
|
-
this.options = options.app.config[this.name] || {};
|
|
29
|
+
this.options = options.app.config[this.name] ?? {};
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
init() {
|
|
21
|
-
return
|
|
33
|
+
return isAsyncFunction(this.create) ? this.initAsync() : this.initSync();
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
initSync() {
|
|
25
37
|
const options = this.options;
|
|
26
38
|
assert(!(options.client && options.clients),
|
|
27
|
-
`egg:singleton ${this.name} can not set options.client and options.clients both`);
|
|
39
|
+
`[egg:singleton] ${this.name} can not set options.client and options.clients both`);
|
|
28
40
|
|
|
29
41
|
// alias app[name] as client, but still support createInstance method
|
|
30
42
|
if (options.client) {
|
|
31
43
|
const client = this.createInstance(options.client, options.name);
|
|
32
|
-
this
|
|
33
|
-
this
|
|
44
|
+
this.#setClientToApp(client);
|
|
45
|
+
this.#extendDynamicMethods(client);
|
|
34
46
|
return;
|
|
35
47
|
}
|
|
36
48
|
|
|
@@ -40,66 +52,76 @@ class Singleton {
|
|
|
40
52
|
const client = this.createInstance(options.clients[id], id);
|
|
41
53
|
this.clients.set(id, client);
|
|
42
54
|
});
|
|
43
|
-
this
|
|
55
|
+
this.#setClientToApp(this);
|
|
44
56
|
return;
|
|
45
57
|
}
|
|
46
58
|
|
|
47
59
|
// no config.clients and config.client
|
|
48
|
-
this
|
|
60
|
+
this.#setClientToApp(this);
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
async initAsync() {
|
|
52
64
|
const options = this.options;
|
|
53
65
|
assert(!(options.client && options.clients),
|
|
54
|
-
`egg:singleton ${this.name} can not set options.client and options.clients both`);
|
|
66
|
+
`[egg:singleton] ${this.name} can not set options.client and options.clients both`);
|
|
55
67
|
|
|
56
68
|
// alias app[name] as client, but still support createInstance method
|
|
57
69
|
if (options.client) {
|
|
58
70
|
const client = await this.createInstanceAsync(options.client, options.name);
|
|
59
|
-
this
|
|
60
|
-
this
|
|
71
|
+
this.#setClientToApp(client);
|
|
72
|
+
this.#extendDynamicMethods(client);
|
|
61
73
|
return;
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
// multi client, use app[name].getInstance(id)
|
|
65
77
|
if (options.clients) {
|
|
66
|
-
await Promise.all(Object.keys(options.clients).map(id => {
|
|
78
|
+
await Promise.all(Object.keys(options.clients).map((id: string) => {
|
|
67
79
|
return this.createInstanceAsync(options.clients[id], id)
|
|
68
80
|
.then(client => this.clients.set(id, client));
|
|
69
81
|
}));
|
|
70
|
-
this
|
|
82
|
+
this.#setClientToApp(this);
|
|
71
83
|
return;
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
// no config.clients and config.client
|
|
75
|
-
this
|
|
87
|
+
this.#setClientToApp(this);
|
|
76
88
|
}
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
#setClientToApp(client: unknown) {
|
|
91
|
+
Reflect.set(this.app, this.name, client);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get(id: string) {
|
|
79
95
|
return this.clients.get(id);
|
|
80
96
|
}
|
|
81
97
|
|
|
82
98
|
// alias to `get(id)`
|
|
83
|
-
getSingletonInstance(id) {
|
|
99
|
+
getSingletonInstance(id: string) {
|
|
84
100
|
return this.clients.get(id);
|
|
85
101
|
}
|
|
86
102
|
|
|
87
|
-
createInstance(config, clientName) {
|
|
103
|
+
createInstance(config: Record<string, any>, clientName: string) {
|
|
88
104
|
// async creator only support createInstanceAsync
|
|
89
|
-
assert(!
|
|
105
|
+
assert(!isAsyncFunction(this.create),
|
|
90
106
|
`egg:singleton ${this.name} only support create asynchronous, please use createInstanceAsync`);
|
|
91
107
|
// options.default will be merge in to options.clients[id]
|
|
92
|
-
config =
|
|
93
|
-
|
|
108
|
+
config = {
|
|
109
|
+
...this.options.default,
|
|
110
|
+
...config,
|
|
111
|
+
};
|
|
112
|
+
return (this.create as SingletonCreateMethod)(config, this.app, clientName);
|
|
94
113
|
}
|
|
95
114
|
|
|
96
|
-
async createInstanceAsync(config, clientName) {
|
|
115
|
+
async createInstanceAsync(config: Record<string, any>, clientName: string) {
|
|
97
116
|
// options.default will be merge in to options.clients[id]
|
|
98
|
-
config =
|
|
117
|
+
config = {
|
|
118
|
+
...this.options.default,
|
|
119
|
+
...config,
|
|
120
|
+
};
|
|
99
121
|
return await this.create(config, this.app, clientName);
|
|
100
122
|
}
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
#extendDynamicMethods(client: any) {
|
|
103
125
|
assert(!client.createInstance, 'singleton instance should not have createInstance method');
|
|
104
126
|
assert(!client.createInstanceAsync, 'singleton instance should not have createInstanceAsync method');
|
|
105
127
|
|
|
@@ -113,9 +135,10 @@ class Singleton {
|
|
|
113
135
|
extendable.createInstance = this.createInstance.bind(this);
|
|
114
136
|
extendable.createInstanceAsync = this.createInstanceAsync.bind(this);
|
|
115
137
|
} catch (err) {
|
|
116
|
-
this.app.
|
|
138
|
+
this.app.coreLogger.warn(
|
|
139
|
+
'[egg:singleton] %s dynamic create is disabled because of client is un-extendable',
|
|
140
|
+
this.name);
|
|
141
|
+
this.app.coreLogger.warn(err);
|
|
117
142
|
}
|
|
118
143
|
}
|
|
119
144
|
}
|
|
120
|
-
|
|
121
|
-
module.exports = Singleton;
|