Skip to content

Commit 218c349

Browse files
authored
Implement WebSocketServer Adapter (#5866)
* Implement WebSocketServerAdapter * lint * clean up
1 parent 7c8e940 commit 218c349

File tree

10 files changed

+593
-544
lines changed

10 files changed

+593
-544
lines changed

spec/ParseWebSocket.spec.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ describe('ParseWebSocket', function() {
99
expect(parseWebSocket.ws).toBe(ws);
1010
});
1111

12-
it('can handle events defined in typeMap', function() {
12+
it('can handle disconnect event', function(done) {
1313
const ws = {
14-
on: jasmine.createSpy('on'),
14+
onclose: () => {},
1515
};
16-
const callback = {};
1716
const parseWebSocket = new ParseWebSocket(ws);
18-
parseWebSocket.on('disconnect', callback);
19-
20-
expect(parseWebSocket.ws.on).toHaveBeenCalledWith('close', callback);
17+
parseWebSocket.on('disconnect', () => {
18+
done();
19+
});
20+
ws.onclose();
2121
});
2222

23-
it('can handle events which are not defined in typeMap', function() {
23+
it('can handle message event', function(done) {
2424
const ws = {
25-
on: jasmine.createSpy('on'),
25+
onmessage: () => {},
2626
};
27-
const callback = {};
2827
const parseWebSocket = new ParseWebSocket(ws);
29-
parseWebSocket.on('open', callback);
30-
31-
expect(parseWebSocket.ws.on).toHaveBeenCalledWith('open', callback);
28+
parseWebSocket.on('message', () => {
29+
done();
30+
});
31+
ws.onmessage();
3232
});
3333

3434
it('can send a message', function() {

spec/ParseWebSocketServer.spec.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const ParseWebSocketServer = require('../lib/LiveQuery/ParseWebSocketServer')
2-
.ParseWebSocketServer;
1+
const { ParseWebSocketServer } = require('../lib/LiveQuery/ParseWebSocketServer');
32

43
describe('ParseWebSocketServer', function() {
54
beforeEach(function(done) {
@@ -19,14 +18,14 @@ describe('ParseWebSocketServer', function() {
1918
const parseWebSocketServer = new ParseWebSocketServer(
2019
server,
2120
onConnectCallback,
22-
5
21+
{ websocketTimeout: 5 }
2322
).server;
2423
const ws = {
2524
readyState: 0,
2625
OPEN: 0,
2726
ping: jasmine.createSpy('ping'),
2827
};
29-
parseWebSocketServer.emit('connection', ws);
28+
parseWebSocketServer.onConnection(ws);
3029

3130
// Make sure callback is called
3231
expect(onConnectCallback).toHaveBeenCalled();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*eslint no-unused-vars: "off"*/
2+
import { WSSAdapter } from './WSSAdapter';
3+
const WebSocketServer = require('ws').Server;
4+
5+
/**
6+
* Wrapper for ws node module
7+
*/
8+
export class WSAdapter extends WSSAdapter {
9+
constructor(options: any) {
10+
super(options);
11+
const wss = new WebSocketServer({ server: options.server });
12+
wss.on('listening', this.onListen);
13+
wss.on('connection', this.onConnection);
14+
}
15+
16+
onListen() {}
17+
onConnection(ws) {}
18+
start() {}
19+
close() {}
20+
}
21+
22+
export default WSAdapter;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*eslint no-unused-vars: "off"*/
2+
// WebSocketServer Adapter
3+
//
4+
// Adapter classes must implement the following functions:
5+
// * onListen()
6+
// * onConnection(ws)
7+
// * start()
8+
// * close()
9+
//
10+
// Default is WSAdapter. The above functions will be binded.
11+
12+
/**
13+
* @module Adapters
14+
*/
15+
/**
16+
* @interface WSSAdapter
17+
*/
18+
export class WSSAdapter {
19+
/**
20+
* @param {Object} options - {http.Server|https.Server} server
21+
*/
22+
constructor(options) {
23+
this.onListen = () => {}
24+
this.onConnection = () => {}
25+
}
26+
27+
// /**
28+
// * Emitted when the underlying server has been bound.
29+
// */
30+
// onListen() {}
31+
32+
// /**
33+
// * Emitted when the handshake is complete.
34+
// *
35+
// * @param {WebSocket} ws - RFC 6455 WebSocket.
36+
// */
37+
// onConnection(ws) {}
38+
39+
/**
40+
* Initialize Connection.
41+
*
42+
* @param {Object} options
43+
*/
44+
start(options) {}
45+
46+
/**
47+
* Closes server.
48+
*/
49+
close() {}
50+
}
51+
52+
export default WSSAdapter;

src/LiveQuery/ParseLiveQueryServer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ParseLiveQueryServer {
6161
this.parseWebSocketServer = new ParseWebSocketServer(
6262
server,
6363
parseWebsocket => this._onConnect(parseWebsocket),
64-
config.websocketTimeout
64+
config
6565
);
6666

6767
// Initialize subscriber

src/LiveQuery/ParseWebSocketServer.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1+
import { loadAdapter } from '../Adapters/AdapterLoader';
2+
import { WSAdapter } from '../Adapters/WebSocketServer/WSAdapter';
13
import logger from '../logger';
2-
3-
const typeMap = new Map([['disconnect', 'close']]);
4-
const getWS = function(){
5-
return require('ws');
6-
};
4+
import events from 'events';
75

86
export class ParseWebSocketServer {
97
server: Object;
108

119
constructor(
1210
server: any,
1311
onConnect: Function,
14-
websocketTimeout: number = 10 * 1000
12+
config
1513
) {
16-
const WebSocketServer = getWS().Server;
17-
const wss = new WebSocketServer({ server: server });
18-
wss.on('listening', () => {
14+
config.server = server;
15+
const wss = loadAdapter(
16+
config.wssAdapter,
17+
WSAdapter,
18+
config,
19+
);
20+
wss.onListen = () => {
1921
logger.info('Parse LiveQuery Server starts running');
20-
});
21-
wss.on('connection', ws => {
22+
};
23+
wss.onConnection = (ws) => {
2224
onConnect(new ParseWebSocket(ws));
2325
// Send ping to client periodically
2426
const pingIntervalId = setInterval(() => {
@@ -27,24 +29,29 @@ export class ParseWebSocketServer {
2729
} else {
2830
clearInterval(pingIntervalId);
2931
}
30-
}, websocketTimeout);
31-
});
32+
}, config.websocketTimeout || 10 * 1000);
33+
};
34+
wss.start();
3235
this.server = wss;
3336
}
37+
38+
close() {
39+
if (this.server && this.server.close) {
40+
this.server.close();
41+
}
42+
}
3443
}
3544

36-
export class ParseWebSocket {
45+
export class ParseWebSocket extends events.EventEmitter {
3746
ws: any;
3847

3948
constructor(ws: any) {
49+
super();
50+
ws.onmessage = (request) => this.emit('message', request);
51+
ws.onclose = () => this.emit('disconnect');
4052
this.ws = ws;
4153
}
4254

43-
on(type: string, callback): void {
44-
const wsType = typeMap.has(type) ? typeMap.get(type) : type;
45-
this.ws.on(wsType, callback);
46-
}
47-
4855
send(message: any): void {
4956
this.ws.send(message);
5057
}

0 commit comments

Comments
 (0)