Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: supports serialization of options #97

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 12 additions & 11 deletions README.md
Expand Up @@ -50,17 +50,18 @@ startCluster(options, () => {

## Options

| Param | Type | Description |
| ------------ | --------- | ---------------------------------------- |
| baseDir | `String` | directory of application |
| framework | `String` | specify framework that can be absolute path or npm package |
| plugins | `Object` | plugins for unittest |
| workers | `Number` | numbers of app workers |
| sticky | `Boolean` | sticky mode server |
| port | `Number` | port |
| https | `Object` | start a https server, note: `key` / `cert` / `ca` should be full path to file |
| require | `Array\|String` | will inject into worker/agent process |
| pidFile | `String` | will save master pid to this file |
| Param | Type | Description |
| ------------- | --------------- | ----------------------------------------------------------------------------- |
| baseDir | `String` | directory of application |
| framework | `String` | specify framework that can be absolute path or npm package |
| plugins | `Object` | plugins for unittest |
| workers | `Number` | numbers of app workers |
| sticky | `Boolean` | sticky mode server |
| port | `Number` | port |
| https | `Object` | start a https server, note: `key` / `cert` / `ca` should be full path to file |
| require | `Array\|String` | will inject into worker/agent process |
| pidFile | `String` | will save master pid to this file |
| serialization | `json|advanced` | default: 'json'. 'advanced' requires Node.js >= 12.16.0 or >= 13.2.0 |

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是 12.16.0 吧?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另,是否需要在 debug 模式时默认设置为 advanced 值?
或者当 >= 12.16.0 时全部默认 'advanced'?

我看了下下面的相关讨论:nodejs/node#30162 (comment), 看起来 advanced 并不是所有场景下都是最优解,所以这里确实应该 follow 上游的设置,默认为 'json',但是在框架里在适当的版本暴露可配置选项。

我也是如此考虑:随着版本更新性能提升及可靠性得到进一步验证,可能在未来某个版本默认改为 advanced。
所以跟随 node.js 默认设置(json),代码里面不做默认值设置,让有需要的用户自行决定传入参数控制。

## Env

Expand Down
13 changes: 13 additions & 0 deletions lib/master.js
Expand Up @@ -38,6 +38,8 @@ class Master extends EventEmitter {
* - {Object} [https] https options, { key, cert, ca }, full path
* - {Array|String} [require] will inject into worker/agent process
* - {String} [pidFile] will save master pid to this file
* - {json|advanced} [serialization] Advanced serialization for IPC need Node.js >= v12.16.0 or >= v13.2.0,
* see: https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V12.md#advanced-serialization-for-ipc
*/
constructor(options) {
super();
Expand Down Expand Up @@ -248,6 +250,17 @@ class Master extends EventEmitter {
const debugPort = process.env.EGG_AGENT_DEBUG_PORT || 5800;
if (this.options.isDebug) opt.execArgv = process.execArgv.concat([ `--${semver.gte(process.version, '8.0.0') ? 'inspect' : 'debug'}-port=${debugPort}` ]);

/* istanbul ignore next */

if ((semver.gte(process.version, '12.16.0') && semver.lt(process.version, '13.0.0'))
|| semver.gte(process.version, '13.2.0')
) {
/* istanbul ignore next */
if (this.options.serialization) {
opt.serialization = this.options.serialization;
}
}

const agentWorker = childprocess.fork(this.getAgentWorkerFile(), args, opt);
agentWorker.status = 'starting';
agentWorker.id = ++this.agentWorkerIndex;
Expand Down
17 changes: 17 additions & 0 deletions lib/utils/options.js
Expand Up @@ -7,6 +7,7 @@ const assert = require('assert');
const utils = require('egg-utils');
const is = require('is-type-of');
const deprecate = require('depd')('egg');
const semver = require('semver');

module.exports = function(options) {
const defaults = {
Expand Down Expand Up @@ -64,6 +65,22 @@ module.exports = function(options) {
const isDebug = process.execArgv.some(argv => argv.includes('--debug') || argv.includes('--inspect'));
if (isDebug) options.isDebug = isDebug;

if ((semver.gte(process.version, '12.16.0') && semver.lt(process.version, '13.0.0'))
|| semver.gte(process.version, '13.2.0')
) {
/* istanbul ignore else */
if (typeof options.serialization !== 'undefined'
&& options.serialization !== 'json'
&& options.serialization !== 'advanced') {
throw new Error(`[egg-cluster] options.serialization must be "json" or "advanced", value is ${options.serialization}`);
}
} else {
/* istanbul ignore else */
if (options.serialization) {
throw new Error('[egg-cluster] options.serialization requires Node.js >= v12.16.0 or >= v13.2.0');
}
}

return options;
};

Expand Down
68 changes: 68 additions & 0 deletions test/options.test.js
Expand Up @@ -4,6 +4,7 @@ const path = require('path');
const assert = require('assert');
const os = require('os');
const mm = require('egg-mock');
const semver = require('semver');
const parseOptions = require('../lib/utils/options');
const utils = require('./utils');

Expand Down Expand Up @@ -202,4 +203,71 @@ describe('test/options.test.js', () => {
}
});
});

describe('should options.serialization', () => {
let isSupportSerialization = false;
if ((semver.gte(process.version, '12.16.0') && semver.lt(process.version, '13.0.0'))
|| semver.gte(process.version, '13.2.0')
) {
isSupportSerialization = true;
}

it('should with "json" value when Node.js supports serialization', () => {
if (isSupportSerialization) {
const options = parseOptions({
serialization: 'json',
});
assert(options.serialization === 'json');
}
});

it('should with "advanced" value when Node.js supports serialization', () => {
if (isSupportSerialization) {
const options = parseOptions({
serialization: 'advanced',
});
assert(options.serialization === 'advanced');
}
});

it('should error with invalid value when Node.js supports serialization', () => {
if (isSupportSerialization) {
try {
parseOptions({
serialization: 'fake',
});
assert(false);
} catch (ex) {
assert(ex.message.includes('must be "json" or "advanced"'));
}
}
});

it('should error with empty value when Node.js supports serialization', () => {
if (isSupportSerialization) {
try {
parseOptions({
serialization: '',
});
assert(false);
} catch (ex) {
assert(ex.message.includes('must be "json" or "advanced"'));
}
}
});

it('should error with value when Node.js not supports serialization', () => {
if (!isSupportSerialization) {
try {
parseOptions({
serialization: 'json',
});
assert(false);
} catch (ex) {
assert(ex.message.includes('requires Node.js >= v12.16.0'));
}
}
});
});

});