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

Fixed EADDRINUSE issue for tests running in parallel #3068

Merged
merged 1 commit into from
Jul 11, 2018

Conversation

sergei-startsev
Copy link
Contributor

Fixed #3065 by passing handle that has already been bound to a port, see server.listen.

@googlebot
Copy link

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. I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

@googlebot
Copy link

CLAs look good, thanks!

Copy link
Contributor

@lusarz lusarz left a 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.

return new Promise((resolve, reject) => {
const server = net.createServer()
getAvailablePort (port, listenAddress) {
function listen (port, listenAddress) {
Copy link
Contributor

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) => {
Copy link
Contributor

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]) => { ... } ).

Copy link

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I see.

isPortAvailable (port, listenAddress) {
return new Promise((resolve, reject) => {
const server = net.createServer()
getAvailablePort (port, listenAddress) {
Copy link
Contributor

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 ?

Copy link

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()

server.listen(port, listenAddress, () => {
server.close(() => resolve(true))
server.listen(port, listenAddress, () => {
resolve([port, server])
Copy link

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.

Copy link
Contributor

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 ?

server.on('error', (err) => {
server.close()
if (err.code === 'EADDRINUSE' || err.code === 'EACCES') {
server.listen(++port, listenAddress)
Copy link

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?

@sergei-startsev sergei-startsev force-pushed the addr-in-use-fix branch 2 times, most recently from dc25020 to 0f78818 Compare July 1, 2018 21:07
@sergei-startsev
Copy link
Contributor Author

Folks, I've updated PR, could you take a look one more time?

reject(err)
}
})
.on('listening', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Really nice 👍

Copy link
Contributor

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 ?

Copy link
Contributor Author

@sergei-startsev sergei-startsev Jul 3, 2018

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.

}
})
.on('listening', () => {
resolve(server)
Copy link
Contributor Author

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

sinon
.stub(server._injector, 'get')
.withArgs('webServer')
.returns(mockWebServer)
Copy link

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()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

NP

sinon
.stub(server, 'get')
.withArgs('config')
.returns(config)
Copy link

Choose a reason for hiding this comment

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

same here

@sergei-startsev
Copy link
Contributor Author

Is there a chance to merge the PR?

@lusarz
Copy link
Contributor

lusarz commented Jul 11, 2018

Yes, I approved it. You should be able to merge it yourself.

@sergei-startsev
Copy link
Contributor Author

@lusarz I see Only those with write access to this repository can merge pull requests.

@lusarz lusarz merged commit 850a90b into karma-runner:master Jul 11, 2018
@lusarz
Copy link
Contributor

lusarz commented Jul 11, 2018

@sergei-startsev Ok, I thought that it works in another way - merged :)

@sergei-startsev
Copy link
Contributor Author

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants