mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-10 23:50:12 +00:00
Resolve "Implement an exponential backoff for the websocket reconnecting"
This commit is contained in:
parent
fc126f4c08
commit
c8a9c1438e
4 changed files with 49 additions and 16 deletions
|
@ -42,6 +42,9 @@ class CoreConsumer(AsyncJsonWebsocketConsumer):
|
|||
user = self.scope['user']
|
||||
web_socket_id = self.scope['web_socket_id']
|
||||
|
||||
if not user:
|
||||
return
|
||||
|
||||
# If the user has already joined another page we need to discard that
|
||||
# page first before we can join a new one.
|
||||
await self.discard_current_page()
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Prevent websocket reconnect loop when the authentication fails.
|
||||
|
||||
## Released (2021-03-01)
|
||||
|
||||
* Redesigned the left sidebar.
|
||||
|
|
|
@ -12,6 +12,8 @@ export class RealTimeHandler {
|
|||
this.page = null
|
||||
this.pageParameters = {}
|
||||
this.subscribedToPage = true
|
||||
this.lastToken = null
|
||||
this.authenticationSuccess = true
|
||||
this.registerCoreEvents()
|
||||
}
|
||||
|
||||
|
@ -24,6 +26,16 @@ export class RealTimeHandler {
|
|||
|
||||
const token = this.context.store.getters['auth/token']
|
||||
|
||||
// Check if we already had a failed authentication response from the server before.
|
||||
// If so, and if the authentication token has not changed, we don't need to connect
|
||||
// because we already know it will fail.
|
||||
if (!this.authenticationSuccess && token === this.lastToken) {
|
||||
this.delayedReconnect()
|
||||
return
|
||||
}
|
||||
|
||||
this.lastToken = token
|
||||
|
||||
// The web socket url is the same as the PUBLIC_BACKEND_URL apart from the
|
||||
// protocol.
|
||||
const rawUrl = this.context.app.$env.PUBLIC_BACKEND_URL
|
||||
|
@ -76,22 +88,32 @@ export class RealTimeHandler {
|
|||
// page is already null we can mark it as subscribed.
|
||||
this.subscribedToPage = this.page === null
|
||||
|
||||
// Automatically reconnect if the socket closes.
|
||||
if (this.reconnect) {
|
||||
this.attempts++
|
||||
this.context.store.dispatch('notification/setConnecting', true)
|
||||
|
||||
this.reconnectTimeout = setTimeout(
|
||||
() => {
|
||||
this.connect(true)
|
||||
},
|
||||
// After the first try, we want to try again every 5 seconds.
|
||||
this.attempts > 0 ? 5000 : 0
|
||||
)
|
||||
}
|
||||
// Automatically reconnect after the given timeout.
|
||||
this.delayedReconnect()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If reconnecting is enabled then a timeout is created that will try to connect
|
||||
* to the backend one more time.
|
||||
*/
|
||||
delayedReconnect() {
|
||||
if (!this.reconnect) {
|
||||
return
|
||||
}
|
||||
|
||||
this.attempts++
|
||||
this.context.store.dispatch('notification/setConnecting', true)
|
||||
|
||||
this.reconnectTimeout = setTimeout(
|
||||
() => {
|
||||
this.connect(true)
|
||||
},
|
||||
// After the first try, we want to try again every 5 seconds.
|
||||
this.attempts > 1 ? 5000 : 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes the client to a given page. After subscribing the client will
|
||||
* receive updated related to that page. This is for example used when a user
|
||||
|
@ -155,6 +177,10 @@ export class RealTimeHandler {
|
|||
// because we already know about the change.
|
||||
this.registerEvent('authentication', ({ store }, data) => {
|
||||
store.dispatch('auth/setWebSocketId', data.web_socket_id)
|
||||
|
||||
// Store if the authentication was successful in order to prevent retries that
|
||||
// will fail.
|
||||
this.authenticationSuccess = data.success
|
||||
})
|
||||
|
||||
this.registerEvent('group_created', ({ store }, data) => {
|
||||
|
|
|
@ -109,12 +109,12 @@ export const actions = {
|
|||
clearTimeout(this.refreshTimeout)
|
||||
commit('SET_REFRESHING', true)
|
||||
|
||||
// The token expires within an hour. We have to calculate how many seconds are
|
||||
// left and 30 seconds before it expires we will refresh the token.
|
||||
// The token expires within a given time. When 80% of that time has expired we want
|
||||
// to fetch a new token.
|
||||
this.refreshTimeout = setTimeout(() => {
|
||||
dispatch('refresh', getters.token)
|
||||
commit('SET_REFRESHING', false)
|
||||
}, (getters.tokenExpireSeconds - 30) * 1000)
|
||||
}, Math.floor((getters.tokenExpireSeconds / 100) * 80) * 1000)
|
||||
},
|
||||
/**
|
||||
* The web socket id is generated by the backend when connecting to the real time
|
||||
|
|
Loading…
Add table
Reference in a new issue