Skip to content

Commit a9a2e56

Browse files
committed
Added useIsConnected() hook to keep track of DataSync connection state
1 parent 70ec375 commit a9a2e56

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

lib/IHP/DataSync/ihp-datasync.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,17 @@ class DataSyncController {
3434
this.eventListeners = {
3535
message: [],
3636
close: [],
37-
reconnect: []
37+
reconnect: [],
38+
open: []
3839
};
3940

4041
// We store messages here that cannot be send because the connection is not available
4142
this.outbox = [];
4243
this.reconnectTimeout = null;
44+
45+
// Every message from the client expects a reply from the server
46+
// If that doesn't arrive in time, we can expect the connection to be broken
47+
this.pendingRequestTimeout = null;
4348

4449
this.dataSubscriptions = [];
4550

@@ -63,12 +68,16 @@ class DataSyncController {
6368
const connect = () => new Promise((resolve, reject) => {
6469
const socket = new WebSocket(DataSyncController.getWSUrl())
6570

66-
socket.onopen = () => {
71+
socket.onopen = event => {
6772
// These handlers should only be installed once the connection is established
6873
socket.onclose = this.onClose.bind(this);
6974
socket.onmessage = this.onMessage.bind(this);
7075

7176
resolve(socket);
77+
78+
for (const listener of this.eventListeners.open) {
79+
listener(event);
80+
}
7281
}
7382

7483
socket.onerror = (event) => reject(event);
@@ -115,6 +124,11 @@ class DataSyncController {
115124

116125
this.receivedFirstResponse = true;
117126

127+
if (this.pendingRequestTimeout) {
128+
clearTimeout(this.pendingRequestTimeout);
129+
this.pendingRequestTimeout = null;
130+
}
131+
118132
if (request) {
119133
const { resolve, reject } = request;
120134

@@ -156,6 +170,10 @@ class DataSyncController {
156170
}
157171
} else {
158172
this.connection.send(JSON.stringify(payload));
173+
174+
if (!this.pendingRequestTimeout) {
175+
this.pendingRequestTimeout = setTimeout(this.onPendingRequestTimeout.bind(this), 5000);
176+
}
159177
}
160178
});
161179
}
@@ -198,6 +216,14 @@ class DataSyncController {
198216
}
199217
}
200218
}
219+
220+
onPendingRequestTimeout() {
221+
if (this.connection) {
222+
console.log('Pending request timed out, closing WebSocket');
223+
this.connection.close();
224+
this.onClose(null);
225+
}
226+
}
201227
}
202228

203229
const APPEND_NEW_RECORD = 0;

lib/IHP/DataSync/react.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,26 @@ export function useQuery(queryBuilder) {
6767
export function useQuerySingleResult(queryBuilder) {
6868
const result = useQuery(queryBuilder.limit(1));
6969
return result === null ? null : result[0];
70+
}
71+
72+
export function useIsConnected() {
73+
const dataSyncController = DataSyncController.getInstance();
74+
const isConnectedDefault = dataSyncController.connection !== null;
75+
76+
const [isConnected, setConnected] = useState(isConnectedDefault);
77+
78+
useEffect(() => {
79+
const setConnectedTrue = () => setConnected(true);
80+
const setConnectedFalse = () => setConnected(false);
81+
82+
dataSyncController.addEventListener('open', setConnectedTrue);
83+
dataSyncController.addEventListener('close', setConnectedFalse);
84+
85+
return () => {
86+
dataSyncController.removeEventListener('open', setConnectedTrue);
87+
dataSyncController.removeEventListener('close', setConnectedFalse);
88+
}
89+
}, [ setConnected ]);
90+
91+
return isConnected;
7092
}

0 commit comments

Comments
 (0)