aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/settingsWS/store.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/settingsWS/store.js')
-rwxr-xr-xsrc/features/settingsWS/store.js107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/features/settingsWS/store.js b/src/features/settingsWS/store.js
new file mode 100755
index 000000000..21fd3440e
--- /dev/null
+++ b/src/features/settingsWS/store.js
@@ -0,0 +1,107 @@
1import { observable, reaction } from 'mobx';
2import WebSocket from 'ws';
3import ms from 'ms';
4
5import Store from '../../stores/lib/Store';
6import { WS_API } from '../../environment';
7
8const debug = require('debug')('Franz:feature:settingsWS:store');
9
10export class SettingsWSStore extends Store {
11 ws = null;
12
13 @observable connected = false;
14
15 pingTimeout = null;
16
17 reconnectTimeout = null;
18
19 constructor(stores, api, actions, state) {
20 super(stores, api, actions);
21 this.state = state;
22 }
23
24 setup() {
25 this.connect();
26
27 reaction(() => !this.connected, this.reconnect.bind(this));
28 }
29
30 connect() {
31 try {
32 const wsURL = `${WS_API}/ws/${this.stores.user.data.id}`;
33 debug('Setting up WebSocket to', wsURL);
34
35 this.ws = new WebSocket(wsURL);
36
37 this.ws.on('open', () => {
38 debug('Opened WebSocket');
39 this.send({
40 action: 'authorize',
41 token: this.stores.user.authToken,
42 });
43
44 this.connected = true;
45
46 this.heartbeat();
47 });
48
49 this.ws.on('message', (data) => {
50 const resp = JSON.parse(data);
51 debug('Received message', resp);
52
53 if (resp.id) {
54 this.stores.user.getUserInfoRequest.patch((result) => {
55 if (!result) return;
56
57 debug('Patching user object with new values');
58 Object.assign(result, resp);
59 });
60 }
61 });
62
63 this.ws.on('ping', this.heartbeat.bind(this));
64 } catch (err) {
65 console.err(err);
66 }
67 }
68
69 heartbeat() {
70 debug('Heartbeat');
71 clearTimeout(this.pingTimeout);
72
73 // Use `WebSocket#terminate()` and not `WebSocket#close()`. Delay should be
74 // equal to the interval at which your server sends out pings plus a
75 // conservative assumption of the latency.
76 this.pingTimeout = setTimeout(() => {
77 debug('Terminating connection reconnecting in 35');
78 this.ws.terminate();
79
80 this.connected = false;
81 }, ms('35s'));
82 }
83
84 send(data) {
85 if (this.ws) {
86 this.ws.send(JSON.stringify(data));
87 debug('Sending data', data);
88 } else {
89 debug('WebSocket is not initialized');
90 }
91 }
92
93 reconnect() {
94 if (!this.connected) {
95 debug('Trying to reconnect in 30s');
96 this.reconnectTimeout = setInterval(() => {
97 debug('Trying to reconnect');
98 this.connect();
99 }, ms('30s'));
100 } else {
101 debug('Clearing reconnect interval');
102 clearInterval(this.reconnectTimeout);
103 }
104 }
105}
106
107export default SettingsWSStore;