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

cluster: refactor module into multiple files #10746

Merged
merged 1 commit into from
Jan 13, 2017

Conversation

cjihrig
Copy link
Contributor

@cjihrig cjihrig commented Jan 11, 2017

I've always found the cluster code unpleasant to deal with. Currently, one large file contains the Worker, SharedHandle, and RoundRobinHandle structures. The same file also contains the cluster master and worker implementations, each of which modifies Worker. This makes the code tricky, because when you jump around in the code, you need to determine what context you're working in. I'm hoping to make it more readable/maintainable.

This commit splits the existing cluster module into several internal modules. More specifically, the cluster master and worker implementations are separated, and the various data structures are separated.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

cluster

@nodejs-github-bot nodejs-github-bot added build Issues and PRs related to build files or the CI. dont-land-on-v7.x cluster Issues and PRs related to the cluster subsystem. labels Jan 11, 2017
@mscdex
Copy link
Contributor

mscdex commented Jan 11, 2017

I think the triple newlines could be changed to just double newlines (one empty line between function definitions, etc. instead of two).

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

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

Generally LGTM. Couple comments tho (consider to be optional)

this.handle.onconnection = (err, handle) => this.distribute(err, handle);
this.server._handle = null;
this.server = null;
});
Copy link
Member

Choose a reason for hiding this comment

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

While we're at it, perhaps consider eliminating the closure by moving these handlers into top level functions. Doing so should result in at least some performance improvement overall.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it was a function, how would it get access to this? Wouldn't it have to be bound, which has perf negatives?

'worker.suicide is deprecated. Please use worker.exitedAfterDisconnect.'),
set: internalUtil.deprecate(
(val) => { this.exitedAfterDisconnect = val; },
'worker.suicide is deprecated. Please use worker.exitedAfterDisconnect.'),
Copy link
Member

Choose a reason for hiding this comment

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

The deprecation message could be made into a const and reused.

};


function onmessage(message, handle) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: While we're refactoring all this code, maybe remove handle as an argument here? It's not used in the function.

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 12, 2017

Switched from two blank lines to one blank line between functions.

@mscdex I have two questions for you:

  1. Are we in the clear to use bind() for things like cluster: refactor module into multiple files #10746 (comment)? If so, it might be good to move to a separate commit, so it doesn't get backported.
  2. Is there a performance hit for removing functions arguments that may be provided by the caller, but not used, such as in cluster: refactor module into multiple files #10746 (comment).

@mscdex
Copy link
Contributor

mscdex commented Jan 12, 2017

@cjihrig

  1. I believe so, but I would do it as a separate commit/PR for easier backporting of this PR.
  2. I haven't tested that, so I don't know offhand. I'd probably err on the side caution and leave it the way it was until we know for sure.

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 12, 2017

OK, thanks! That's what I was thinking on both points, but wanted to check.

CI: https://ci.nodejs.org/job/node-test-pull-request/5824/

Copy link
Contributor

@sam-github sam-github left a comment

Choose a reason for hiding this comment

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

Couple small suggestions, and I don't think we should be using mixed case filenames, but basically LGTM.

this.handle.onconnection = (err, handle) => this.distribute(err, handle);
this.server._handle = null;
this.server = null;
});
Copy link
Contributor

Choose a reason for hiding this comment

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

If it was a function, how would it get access to this? Wouldn't it have to be bound, which has perf negatives?

if (getOwnPropertyNames(this.all).length !== 0)
return false;

for (var handle; handle = this.handles.shift(); handle.close());
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this kindof for construction hard to read, could you put the empty statement, the ;, on the next line?

@@ -0,0 +1,113 @@
'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

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

file-naming convention in lib/ is is snake_case.js, AFAICT.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used https://github.com/nodejs/node/blob/master/lib/internal/streams/BufferList.js as a reference for naming files that hold a single data type.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that BufferList is an unfortunate outlier. lib/internal/streams/lazy_transform.js is a better model to follow.

'use strict';
const assert = require('assert');
const net = require('net');
const { sendHelper } = require('internal/cluster/utils');
Copy link
Contributor

Choose a reason for hiding this comment

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

sort requires?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm all for sorting requires. Do we sort by the variable name on the left hand side, or the string inside of require()? What about internal modules? Should they be grouped differently?

Copy link
Contributor

Choose a reason for hiding this comment

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

Lexical sort (in ASCII order/posix "C" locale) on the statements (which ends up being by name of variable, but variable name usually maps 1:1 to the require name, es6 requires aside) (:sort in vim, pipe block through !sort, whatever your editor likes). No grouping, too complicated to document and reproduce.

}

RoundRobinHandle.prototype.add = function(worker, send) {
assert(worker.id in this.all === false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use ! operator instead of comparison against false? As is done in

+  if (!(this instanceof Worker))
 +    return new Worker(options);

@@ -0,0 +1,224 @@
'use strict';
const assert = require('assert');
Copy link
Contributor

Choose a reason for hiding this comment

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

sort requires?


cluster.settings = settings;

if (initialized === true)
Copy link
Contributor

Choose a reason for hiding this comment

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

if (initialized) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think a strict comparison against a boolean is faster. This was also the existing code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Some of the asserts don't do direct comparisons. but its existing, so NBD. I more noticed the inconsistent usage, sometimes direct comparisons, sometimes not. But again, pre-existing, so its OK.

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 13, 2017

New CI: https://ci.nodejs.org/job/node-test-pull-request/5848/

Looks like an unrelated failure, so trying again: https://ci.nodejs.org/job/node-test-pull-request/5850/

This commit splits the existing cluster module into several
internal modules. More specifically, the cluster master and
worker implementations are separated, and the various data
structures are separated.

PR-URL: nodejs#10746
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Sam Roberts <[email protected]>
@cjihrig cjihrig merged commit 2f885e7 into nodejs:master Jan 13, 2017
@cjihrig cjihrig deleted the cluster_refactor branch January 13, 2017 22:08
italoacasas pushed a commit to italoacasas/node that referenced this pull request Jan 18, 2017
This commit splits the existing cluster module into several
internal modules. More specifically, the cluster master and
worker implementations are separated, and the various data
structures are separated.

PR-URL: nodejs#10746
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Sam Roberts <[email protected]>
targos pushed a commit that referenced this pull request Jan 28, 2017
This commit splits the existing cluster module into several
internal modules. More specifically, the cluster master and
worker implementations are separated, and the various data
structures are separated.

PR-URL: #10746
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Sam Roberts <[email protected]>
@italoacasas italoacasas mentioned this pull request Jan 29, 2017
italoacasas pushed a commit to italoacasas/node that referenced this pull request Jan 30, 2017
This commit splits the existing cluster module into several
internal modules. More specifically, the cluster master and
worker implementations are separated, and the various data
structures are separated.

PR-URL: nodejs#10746
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Sam Roberts <[email protected]>
italoacasas pushed a commit to italoacasas/node that referenced this pull request Jan 30, 2017
This commit splits the existing cluster module into several
internal modules. More specifically, the cluster master and
worker implementations are separated, and the various data
structures are separated.

PR-URL: nodejs#10746
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Sam Roberts <[email protected]>
@jasnell
Copy link
Member

jasnell commented Mar 8, 2017

@nodejs/lts @cjihrig ... trying to decide if we should backport this to v6 or not. Recommending that we skip backporting to v4

@jasnell
Copy link
Member

jasnell commented Mar 8, 2017

If we do backport to v6, a backport PR will be required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build Issues and PRs related to build files or the CI. cluster Issues and PRs related to the cluster subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants