1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
import { observable, reaction } from 'mobx';
import WebSocket from 'ws';
import ms from 'ms';
import Store from '../../stores/lib/Store';
import { WS_API } from '../../environment';
const debug = require('debug')('Franz:feature:settingsWS:store');
export class SettingsWSStore extends Store {
ws = null;
@observable connected = false;
pingTimeout = null;
reconnectTimeout = null;
constructor(stores, api, actions, state) {
super(stores, api, actions);
this.state = state;
}
setup() {
reaction(() => this.stores.user.data.id, this.connect.bind(this), {
fireImmediately: true,
});
reaction(() => !this.connected, this.reconnect.bind(this));
}
connect() {
try {
const wsURL = `${WS_API}/ws/${this.stores.user.data.id}`;
debug('Setting up WebSocket to', wsURL);
this.ws = new WebSocket(wsURL);
this.ws.on('open', () => {
debug('Opened WebSocket');
this.send({
action: 'authorize',
token: this.stores.user.authToken,
});
this.connected = true;
this.heartbeat();
});
this.ws.on('message', (data) => {
const resp = JSON.parse(data);
debug('Received message', resp);
if (resp.id) {
this.stores.user.getUserInfoRequest.patch((result) => {
if (!result) return;
debug('Patching user object with new values');
Object.assign(result, resp);
});
}
});
this.ws.on('ping', this.heartbeat.bind(this));
} catch (err) {
console.err(err);
}
}
heartbeat() {
debug('Heartbeat');
clearTimeout(this.pingTimeout);
this.pingTimeout = setTimeout(() => {
debug('Terminating connection reconnecting in 35');
this.ws.terminate();
this.connected = false;
}, ms('35s'));
}
send(data) {
if (this.ws) {
this.ws.send(JSON.stringify(data));
debug('Sending data', data);
} else {
debug('WebSocket is not initialized');
}
}
reconnect() {
if (!this.connected) {
debug('Trying to reconnect in 30s');
this.reconnectTimeout = setInterval(() => {
debug('Trying to reconnect');
this.connect();
}, ms('30s'));
} else {
debug('Clearing reconnect interval');
clearInterval(this.reconnectTimeout);
}
}
}
export default SettingsWSStore;
|