-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Fixed EADDRINUSE
issue for tests running in parallel
#3068
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here (e.g. What to do if you already signed the CLAIndividual signers
Corporate signers
|
b12a496
to
6cb6d12
Compare
CLAs look good, thanks! |
6cb6d12
to
1777152
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, I did a quick test, and it seems to works as expected now.
Just a few small things to consider, please either fix or add comment, then I'll approve.
lib/utils/net-utils.js
Outdated
return new Promise((resolve, reject) => { | ||
const server = net.createServer() | ||
getAvailablePort (port, listenAddress) { | ||
function listen (port, listenAddress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we need to create listen function, and invoke it right after ? Can we return new Promise directly in getAvailablePort
method ?
lib/server.js
Outdated
@@ -117,8 +117,11 @@ class Server extends KarmaEventEmitter { | |||
BundleUtils.bundleResourceIfNotExist('context/main.js', 'static/context.js') | |||
]) | |||
.then(() => NetUtils.getAvailablePort(config.port, config.listenAddress)) | |||
.then((port) => { | |||
.then((bound) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider using array decomposition: then(([port, server]) => { ... } )
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Node 4 doesn't support destructuring: https://node.green/#ES2015-syntax-destructuring--parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see.
lib/utils/net-utils.js
Outdated
isPortAvailable (port, listenAddress) { | ||
return new Promise((resolve, reject) => { | ||
const server = net.createServer() | ||
getAvailablePort (port, listenAddress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about changing name of this function ? Now it works a bit different, so it would be nice to change name of function to be more descriptive. Maybe one of boundPort
, takePort
, findAndBoundAvailablePort
- what do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bind is the correct verb - findAndBindAvailablePort()
lib/utils/net-utils.js
Outdated
server.listen(port, listenAddress, () => { | ||
server.close(() => resolve(true)) | ||
server.listen(port, listenAddress, () => { | ||
resolve([port, server]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you can get the port as server.address().port
: https://nodejs.org/api/net.html#net_server_address
So maybe no need to pass it as a param.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sergei-startsev What do you think about that ?
lib/utils/net-utils.js
Outdated
server.on('error', (err) => { | ||
server.close() | ||
if (err.code === 'EADDRINUSE' || err.code === 'EACCES') { | ||
server.listen(++port, listenAddress) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're not passing the callback here - does the one below get invoked?
dc25020
to
0f78818
Compare
Folks, I've updated PR, could you take a look one more time? |
reject(err) | ||
} | ||
}) | ||
.on('listening', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be sure - did you tested if #3011 don't occurs ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there're no clear repro steps, I've tried to test it on a project with thousands tests running in parallel - I haven't seen any issues.
0f78818
to
acdb61c
Compare
} | ||
}) | ||
.on('listening', () => { | ||
resolve(server) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API has been changed a bit - now it returns only a bound server
test/unit/server.spec.js
Outdated
sinon | ||
.stub(server._injector, 'get') | ||
.withArgs('webServer') | ||
.returns(mockWebServer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: I would put returns()
on the same line as the corresponding withArgs()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP
test/unit/server.spec.js
Outdated
sinon | ||
.stub(server, 'get') | ||
.withArgs('config') | ||
.returns(config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
acdb61c
to
2b3a32c
Compare
Is there a chance to merge the PR? |
Yes, I approved it. You should be able to merge it yourself. |
@lusarz I see |
@sergei-startsev Ok, I thought that it works in another way - merged :) |
thanks! |
Fixed #3065 by passing
handle
that has already been bound to a port, see server.listen.