Skip to content

Commit

Permalink
fix: port in use handling
Browse files Browse the repository at this point in the history
  • Loading branch information
arlac77 committed Nov 6, 2019
1 parent 5a85faf commit 8c9123a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 93 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"test": "ava"
},
"dependencies": {
"@kronos-integration/service": "^5.6.0",
"@kronos-integration/service": "^5.6.1",
"koa": "^2.11.0",
"koa-jwt": "^3.6.0",
"model-attributes": "^4.1.0",
Expand Down
128 changes: 40 additions & 88 deletions src/service-koa.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,11 @@ export class ServiceKOA extends Service {
description: "server listen definition",

attributes: {
retryTimeout: {
description:
"how long should we retry binding to the address (EADDRINUSE)",
default: 10,
type: "duration"
},
address: {
description: "hostname/ip-address of the http(s) server",
needsRestart: true,
type: "hostname"
},
fromPort: {
description: "start port range of the http(s) server",
type: "ip-port"
},
toPort: {
description: "end port range of the http(s) server",
type: "ip-port"
},
socket: {
description: "listening port|socket of the http(s) server",
needsRestart: true,
Expand Down Expand Up @@ -194,6 +180,9 @@ export class ServiceKOA extends Service {
? https.createServer(this.serverOptions, this.koa.callback())
: http.createServer(this.koa.callback());

const server = this.server;


/*
this.wss = new WebSocketServer({
server: this.server
Expand Down Expand Up @@ -222,80 +211,42 @@ export class ServiceKOA extends Service {
*/

if (this.timeout !== undefined) {
this.server.setTimeout(this.timeout * 1000);
server.setTimeout(this.timeout * 1000);
}


return new Promise((resolve, reject) => {
this.trace(severity => `starting ${this.url}`);

const service = this;
const server = this.server;

if (service.listen.fromPort !== undefined) {
service.listen.socket = service.listen.fromPort;
}

function listen() {
const handler = err => {
process.removeListener("uncaughtException", addressInUseHandler);
if (err) {
delete service.server;
service.error(err);
reject(err);
} else {
service.trace(severity => `listening on ${service.url}`);
resolve();
}
};

try {
if (service.listen.address === undefined) {
server.listen(service.listen.socket, handler);
} else {
server.listen(
service.listen.socket,
service.listen.address,
handler
);
}
} catch (err) {
delete service.server;
service.error(err);
const handler = err => {
if (err) {
delete this.server;
this.error(err);
reject(err);
} else {
this.trace(severity => `listening on ${this.url}`);
resolve();
}
}

function addressInUseHandler(e) {
if (e.code === "EADDRINUSE") {
//console.log(`addressInUseHandler: ${e.code}`);

service.trace(
severity => `Address in use ${service.url} retrying...`
};

server.on('error', handler);

try {
if (this.listen.address === undefined) {
server.listen(this.listen.socket, handler);
} else {
server.listen(
this.listen.socket,
this.listen.address,
handler
);

// try different strategies
// 1. retry later
// 2. use other port / interface

if (
service.listen.fromPort &&
service.listen.socket < service.listen.toPort
) {
service.listen.socket++;
listen();
return;
}

setTimeout(() => {
server.close();
listen();
}, 10000);
}
} catch (err) {
delete this.server;
this.error(err);
reject(err);
}

process.on("uncaughtException", addressInUseHandler);
//server.on('error', addressInUseHandler);
listen();
});
} catch (e) {
delete this.server;
Expand All @@ -304,18 +255,19 @@ export class ServiceKOA extends Service {
}

_stop() {
return new Promise((resolve, reject) => {
this.trace(severity => `stopping ${this.url}`);

this.server.close(err => {
if (err) {
reject(err);
} else {
this.server = undefined;
resolve();
}
if (this.server) {
return new Promise((resolve, reject) => {
this.trace(severity => `stopping ${this.url}`);
this.server.close(err => {
if (err) {
reject(err);
} else {
this.server = undefined;
resolve();
}
});
});
});
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions tests/failure-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ServiceProvider extends ServiceProviderMixin(Service) {}

const sp = new ServiceProvider();

test.skip("service-koa failures with already in use port", async t => {
test("service-koa failures with already in use port", async t => {
const port = 1235;

const ks1 = new ServiceKOA(
Expand All @@ -32,10 +32,12 @@ test.skip("service-koa failures with already in use port", async t => {
await ks1.start();
t.is(ks1.state, "running");

await ks2.start();
await t.throwsAsync(() => ks2.start(), Error, 'listen EADDRINUSE: address already in use :::1235');

t.is(ks2.state, "failed");
// await ks2.start();

//t.is(ks2.state, "failed");

await ks1.stop();
await ks2.stop();
//await ks2.stop();
});

0 comments on commit 8c9123a

Please sign in to comment.