Promisify server starting

Summary:
We had a promise for initializing the servers, but it wasn't rejected when server startup failed.
Fixed by resolving / rejecting based on the listen / error events fired from the server.

Reviewed By: passy

Differential Revision: D13762580

fbshipit-source-id: a0d1a56473f84dc416e5ce2de91a53b21574f452
This commit is contained in:
John Knox
2019-01-23 05:15:56 -08:00
committed by Facebook Github Bot
parent 84a8b1acab
commit ecd6935d18
2 changed files with 53 additions and 39 deletions

View File

@@ -25,13 +25,13 @@ beforeAll(() => {
const logger = initLogger(mockStore); const logger = initLogger(mockStore);
server = new Server(logger, mockStore); server = new Server(logger, mockStore);
return server.init();
}); });
test('servers starting at ports', done => { test('servers starting at ports', done => {
const serversToBeStarted = new Set([SECURE_PORT, INSECURE_PORT]); const serversToBeStarted = new Set([SECURE_PORT, INSECURE_PORT]);
return new Promise((resolve, reject) => { // Resolve promise when we get a listen event for each port
const listenerPromise = new Promise((resolve, reject) => {
server.addListener('listening', port => { server.addListener('listening', port => {
if (!serversToBeStarted.has(port)) { if (!serversToBeStarted.has(port)) {
throw Error(`unknown server started at port ${port}`); throw Error(`unknown server started at port ${port}`);
@@ -44,6 +44,11 @@ test('servers starting at ports', done => {
} }
}); });
}); });
// Initialise server after the listeners have been setup
server.init();
return listenerPromise;
}); });
afterAll(() => { afterAll(() => {

View File

@@ -40,8 +40,8 @@ type ClientInfo = {|
export default class Server extends EventEmitter { export default class Server extends EventEmitter {
connections: Map<string, ClientInfo>; connections: Map<string, ClientInfo>;
secureServer: RSocketServer; secureServer: Promise<RSocketServer>;
insecureServer: RSocketServer; insecureServer: Promise<RSocketServer>;
certificateProvider: CertificateProvider; certificateProvider: CertificateProvider;
connectionTracker: ConnectionTracker; connectionTracker: ConnectionTracker;
logger: Logger; logger: Logger;
@@ -75,42 +75,49 @@ export default class Server extends EventEmitter {
return this.initialisePromise; return this.initialisePromise;
} }
startServer(port: number, sslConfig?: SecureServerConfig) { startServer(
port: number,
sslConfig?: SecureServerConfig,
): Promise<RSocketServer> {
const server = this; const server = this;
const serverFactory = onConnect => { return new Promise((resolve, reject) => {
const transportServer = sslConfig let rsServer;
? tls.createServer(sslConfig, socket => { const serverFactory = onConnect => {
onConnect(socket); const transportServer = sslConfig
? tls.createServer(sslConfig, socket => {
onConnect(socket);
})
: net.createServer(onConnect);
transportServer
.on('error', err => {
server.emit('error', err);
console.error(`Error opening server on port ${port}`, 'server');
reject(err);
}) })
: net.createServer(onConnect); .on('listening', () => {
transportServer console.debug(
.on('error', err => { `${
server.emit('error', err); sslConfig ? 'Secure' : 'Certificate'
console.error(`Error opening server on port ${port}`, 'server'); } server started on port ${port}`,
}) 'server',
.on('listening', () => { );
console.debug( server.emit('listening', port);
`${ resolve(rsServer);
sslConfig ? 'Secure' : 'Certificate' });
} server started on port ${port}`, return transportServer;
'server', };
);
server.emit('listening', port);
});
return transportServer;
};
const rsServer = new RSocketServer({
getRequestHandler: sslConfig
? this._trustedRequestHandler
: this._untrustedRequestHandler,
transport: new RSocketTCPServer({
port: port,
serverFactory: serverFactory,
}),
});
rsServer.start(); rsServer = new RSocketServer({
return rsServer; getRequestHandler: sslConfig
? this._trustedRequestHandler
: this._untrustedRequestHandler,
transport: new RSocketTCPServer({
port: port,
serverFactory: serverFactory,
}),
});
rsServer.start();
});
} }
_trustedRequestHandler = (conn: RSocket, connectRequest: {data: string}) => { _trustedRequestHandler = (conn: RSocket, connectRequest: {data: string}) => {
@@ -244,8 +251,10 @@ export default class Server extends EventEmitter {
close(): Promise<void> { close(): Promise<void> {
if (this.initialisePromise) { if (this.initialisePromise) {
return this.initialisePromise.then(_ => { return this.initialisePromise.then(_ => {
this.secureServer.stop(); return Promise.all([
this.insecureServer.stop(); this.secureServer.then(server => server.stop()),
this.insecureServer.then(server => server.stop()),
]).then(() => undefined);
}); });
} }
return Promise.resolve(); return Promise.resolve();