mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
fix(sync): wait for websocket full connection
Websocket has now a "connect" method, which is a promise, that yields "onconnect", so the engine can wait for it before proceding.
This commit is contained in:
parent
1ce491a70c
commit
414cc805c2
2 changed files with 51 additions and 46 deletions
|
@ -75,19 +75,20 @@ export class SyncEngine {
|
||||||
this.reconnect()
|
this.reconnect()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.start(response.token)
|
await this.start(response.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
start(authToken) {
|
async start(authToken) {
|
||||||
const path = this._umap.urls.get('ws_sync', { map_id: this._umap.id })
|
const path = this._umap.urls.get('ws_sync', { map_id: this._umap.id })
|
||||||
const protocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:'
|
const protocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:'
|
||||||
this.transport = new WebSocketTransport(
|
this.transport = new WebSocketTransport(this)
|
||||||
|
await this.transport.connect(
|
||||||
`${protocol}//${window.location.host}${path}`,
|
`${protocol}//${window.location.host}${path}`,
|
||||||
authToken,
|
authToken,
|
||||||
this,
|
|
||||||
this.peerId,
|
this.peerId,
|
||||||
this._umap.properties.user?.name
|
this._umap.properties.user?.name
|
||||||
)
|
)
|
||||||
|
this.onConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
|
@ -108,11 +109,11 @@ export class SyncEngine {
|
||||||
this.websocketConnected = false
|
this.websocketConnected = false
|
||||||
this.updaters.map.update({ key: 'numberOfConnectedPeers' })
|
this.updaters.map.update({ key: 'numberOfConnectedPeers' })
|
||||||
|
|
||||||
this._reconnectTimeout = setTimeout(() => {
|
this._reconnectTimeout = setTimeout(async () => {
|
||||||
if (this._reconnectDelay < MAX_RECONNECT_DELAY) {
|
if (this._reconnectDelay < MAX_RECONNECT_DELAY) {
|
||||||
this._reconnectDelay = this._reconnectDelay * RECONNECT_DELAY_FACTOR
|
this._reconnectDelay = this._reconnectDelay * RECONNECT_DELAY_FACTOR
|
||||||
}
|
}
|
||||||
this.authenticate()
|
await this.authenticate()
|
||||||
}, this._reconnectDelay)
|
}, this._reconnectDelay)
|
||||||
}
|
}
|
||||||
upsert(subject, metadata, value) {
|
upsert(subject, metadata, value) {
|
||||||
|
|
|
@ -3,53 +3,57 @@ const PING_INTERVAL = 30000
|
||||||
const FIRST_CONNECTION_TIMEOUT = 2000
|
const FIRST_CONNECTION_TIMEOUT = 2000
|
||||||
|
|
||||||
export class WebSocketTransport {
|
export class WebSocketTransport {
|
||||||
constructor(webSocketURI, authToken, messagesReceiver, peerId, username) {
|
constructor(messagesReceiver) {
|
||||||
this.receiver = messagesReceiver
|
this.receiver = messagesReceiver
|
||||||
|
}
|
||||||
|
|
||||||
this.websocket = new WebSocket(webSocketURI)
|
async connect(webSocketURI, authToken, peerId, username) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.websocket = new WebSocket(webSocketURI)
|
||||||
|
|
||||||
this.websocket.onopen = () => {
|
this.websocket.onopen = () => {
|
||||||
this.send('JoinRequest', { token: authToken, peer: peerId, username })
|
this.send('JoinRequest', { token: authToken, peer: peerId, username })
|
||||||
this.receiver.onConnection()
|
resolve(this.websocket)
|
||||||
}
|
|
||||||
this.websocket.addEventListener('message', this.onMessage.bind(this))
|
|
||||||
this.websocket.onclose = () => {
|
|
||||||
console.log('websocket closed')
|
|
||||||
if (!this.receiver.closeRequested) {
|
|
||||||
console.log('Not requested, reconnecting...')
|
|
||||||
this.receiver.reconnect()
|
|
||||||
}
|
}
|
||||||
}
|
this.websocket.addEventListener('message', this.onMessage.bind(this))
|
||||||
|
this.websocket.onclose = () => {
|
||||||
this.websocket.onerror = (error) => {
|
console.log('websocket closed')
|
||||||
console.log('WS ERROR', error)
|
if (!this.receiver.closeRequested) {
|
||||||
}
|
console.log('Not requested, reconnecting...')
|
||||||
|
this.receiver.reconnect()
|
||||||
this.ensureOpen = setInterval(() => {
|
}
|
||||||
if (this.websocket.readyState !== WebSocket.OPEN) {
|
|
||||||
this.websocket.close()
|
|
||||||
clearInterval(this.ensureOpen)
|
|
||||||
}
|
}
|
||||||
}, FIRST_CONNECTION_TIMEOUT)
|
|
||||||
|
|
||||||
// To ensure the connection is still alive, we send ping and expect pong back.
|
this.websocket.onerror = (error) => {
|
||||||
// Websocket provides a `ping` method to keep the connection alive, but it's
|
console.log('WS ERROR', error)
|
||||||
// unfortunately not possible to access it from the WebSocket object.
|
|
||||||
// See https://making.close.com/posts/reliable-websockets/ for more details.
|
|
||||||
this.pingInterval = setInterval(() => {
|
|
||||||
if (this.websocket.readyState === WebSocket.OPEN) {
|
|
||||||
console.log('sending ping')
|
|
||||||
this.websocket.send('ping')
|
|
||||||
this.pongReceived = false
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.pongReceived) {
|
|
||||||
console.warn('No pong received, reconnecting...')
|
|
||||||
this.websocket.close()
|
|
||||||
clearInterval(this.pingInterval)
|
|
||||||
}
|
|
||||||
}, PONG_TIMEOUT)
|
|
||||||
}
|
}
|
||||||
}, PING_INTERVAL)
|
|
||||||
|
this.ensureOpen = setInterval(() => {
|
||||||
|
if (this.websocket.readyState !== WebSocket.OPEN) {
|
||||||
|
this.websocket.close()
|
||||||
|
clearInterval(this.ensureOpen)
|
||||||
|
}
|
||||||
|
}, FIRST_CONNECTION_TIMEOUT)
|
||||||
|
|
||||||
|
// To ensure the connection is still alive, we send ping and expect pong back.
|
||||||
|
// Websocket provides a `ping` method to keep the connection alive, but it's
|
||||||
|
// unfortunately not possible to access it from the WebSocket object.
|
||||||
|
// See https://making.close.com/posts/reliable-websockets/ for more details.
|
||||||
|
this.pingInterval = setInterval(() => {
|
||||||
|
if (this.websocket.readyState === WebSocket.OPEN) {
|
||||||
|
console.log('sending ping')
|
||||||
|
this.websocket.send('ping')
|
||||||
|
this.pongReceived = false
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.pongReceived) {
|
||||||
|
console.warn('No pong received, reconnecting...')
|
||||||
|
this.websocket.close()
|
||||||
|
clearInterval(this.pingInterval)
|
||||||
|
}
|
||||||
|
}, PONG_TIMEOUT)
|
||||||
|
}
|
||||||
|
}, PING_INTERVAL)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMessage(wsMessage) {
|
onMessage(wsMessage) {
|
||||||
|
|
Loading…
Reference in a new issue