mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-12 22:26:08 -04:00
feat(realtime): add disconnect reason
The frontend now doesn't try to reconnect, when the disconnection happened because of a lack of permissions Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
f6cfe74d8c
commit
723f3f611c
11 changed files with 111 additions and 46 deletions
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { FrontendWebsocketAdapter } from './frontend-websocket-adapter'
|
||||
import type { Message } from '@hedgedoc/commons'
|
||||
import { ConnectionState, MessageType } from '@hedgedoc/commons'
|
||||
import { ConnectionState, DisconnectReason, MessageType } from '@hedgedoc/commons'
|
||||
import { Mock } from 'ts-mockery'
|
||||
|
||||
describe('frontend websocket', () => {
|
||||
|
@ -34,11 +34,22 @@ describe('frontend websocket', () => {
|
|||
|
||||
it('can bind and unbind the close event', () => {
|
||||
mockSocket()
|
||||
const handler = jest.fn()
|
||||
const handler = jest.fn((reason?: DisconnectReason) => console.log(reason))
|
||||
|
||||
let modifiedHandler: (event: CloseEvent) => void = jest.fn()
|
||||
jest.spyOn(mockedSocket, 'addEventListener').mockImplementation((event, handler_) => {
|
||||
modifiedHandler = handler_
|
||||
})
|
||||
|
||||
const unbind = adapter.bindOnCloseEvent(handler)
|
||||
expect(addEventListenerSpy).toHaveBeenCalledWith('close', handler)
|
||||
|
||||
modifiedHandler(Mock.of<CloseEvent>({ code: DisconnectReason.USER_NOT_PERMITTED }))
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
expect(handler).toHaveBeenCalledWith(DisconnectReason.USER_NOT_PERMITTED)
|
||||
|
||||
unbind()
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith('close', handler)
|
||||
|
||||
expect(removeEventListenerSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('can bind and unbind the connect event', () => {
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { TransportAdapter } from '@hedgedoc/commons'
|
||||
import type { DisconnectReason, Message, MessageType, TransportAdapter } from '@hedgedoc/commons'
|
||||
import { ConnectionState } from '@hedgedoc/commons'
|
||||
import type { Message, MessageType } from '@hedgedoc/commons'
|
||||
|
||||
/**
|
||||
* Implements a transport adapter that communicates using a browser websocket.
|
||||
|
@ -13,10 +12,11 @@ import type { Message, MessageType } from '@hedgedoc/commons'
|
|||
export class FrontendWebsocketAdapter implements TransportAdapter {
|
||||
constructor(private socket: WebSocket) {}
|
||||
|
||||
bindOnCloseEvent(handler: () => void): () => void {
|
||||
this.socket.addEventListener('close', handler)
|
||||
bindOnCloseEvent(handler: (reason?: DisconnectReason) => void): () => void {
|
||||
const callback = (event: CloseEvent): void => handler(event.code)
|
||||
this.socket.addEventListener('close', callback)
|
||||
return () => {
|
||||
this.socket.removeEventListener('close', handler)
|
||||
this.socket.removeEventListener('close', callback)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ import { Logger } from '../../../../../utils/logger'
|
|||
import { isMockMode } from '../../../../../utils/test-modes'
|
||||
import { FrontendWebsocketAdapter } from './frontend-websocket-adapter'
|
||||
import { useWebsocketUrl } from './use-websocket-url'
|
||||
import { MessageTransporter, MockedBackendTransportAdapter } from '@hedgedoc/commons'
|
||||
import { DisconnectReason, MessageTransporter, MockedBackendTransportAdapter } from '@hedgedoc/commons'
|
||||
import type { Listener } from 'eventemitter2'
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
|
||||
|
@ -28,6 +28,7 @@ export const useRealtimeConnection = (): MessageTransporter => {
|
|||
const messageTransporter = useMemo(() => new MessageTransporter(), [])
|
||||
|
||||
const reconnectCount = useRef(0)
|
||||
const disconnectReason = useRef<DisconnectReason | undefined>(undefined)
|
||||
const establishWebsocketConnection = useCallback(() => {
|
||||
if (isMockMode) {
|
||||
logger.debug('Creating Loopback connection...')
|
||||
|
@ -57,7 +58,7 @@ export const useRealtimeConnection = (): MessageTransporter => {
|
|||
const isConnected = useApplicationState((state) => state.realtimeStatus.isConnected)
|
||||
|
||||
useEffect(() => {
|
||||
if (isConnected || reconnectCount.current > 0) {
|
||||
if (isConnected || reconnectCount.current > 0 || disconnectReason.current === DisconnectReason.USER_NOT_PERMITTED) {
|
||||
return
|
||||
}
|
||||
establishWebsocketConnection()
|
||||
|
@ -86,9 +87,16 @@ export const useRealtimeConnection = (): MessageTransporter => {
|
|||
|
||||
useEffect(() => {
|
||||
const connectedListener = messageTransporter.doAsSoonAsReady(() => setRealtimeConnectionState(true))
|
||||
const disconnectedListener = messageTransporter.on('disconnected', () => setRealtimeConnectionState(false), {
|
||||
objectify: true
|
||||
}) as Listener
|
||||
const disconnectedListener = messageTransporter.on(
|
||||
'disconnected',
|
||||
(reason?: DisconnectReason) => {
|
||||
disconnectReason.current = reason
|
||||
setRealtimeConnectionState(false)
|
||||
},
|
||||
{
|
||||
objectify: true
|
||||
}
|
||||
) as Listener
|
||||
|
||||
return () => {
|
||||
connectedListener.off()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue