1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-11 07:51:20 +00:00

Merge branch '345-implement-an-exponential-backoff-for-the-websocket-reconnecting' into 'develop'

Resolve "Implement an exponential backoff for the websocket reconnecting"

Closes 

See merge request 
This commit is contained in:
Bram Wiepjes 2021-03-08 14:08:41 +00:00
commit 179a2d4c34
4 changed files with 49 additions and 16 deletions
backend/src/baserow/ws
changelog.md
web-frontend/modules/core

View file

@ -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()

View file

@ -1,5 +1,9 @@
# Changelog
## Unreleased
* Prevent websocket reconnect loop when the authentication fails.
## Released (2021-03-01)
* Redesigned the left sidebar.

View file

@ -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) => {

View file

@ -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