From e52d31444d20e51e32a2e8309c590eb59db4be11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Fern=C3=A1ndez?= Date: Fri, 19 Jan 2024 11:10:04 +0100 Subject: [PATCH] fix: lost socket reactivity (#2214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fernando Fernández --- frontend/src/composables/apis.ts | 6 +-- frontend/src/plugins/remote/socket/index.ts | 47 ++++++++++++--------- frontend/src/store/api.ts | 6 +-- frontend/src/store/taskManager.ts | 6 +-- frontend/src/utils/items.ts | 4 +- frontend/types/global/util.d.ts | 2 +- 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/frontend/src/composables/apis.ts b/frontend/src/composables/apis.ts index 8a8046b30f8..19b8aecf500 100644 --- a/frontend/src/composables/apis.ts +++ b/frontend/src/composables/apis.ts @@ -11,7 +11,7 @@ import { network } from '@/store'; import { apiStore } from '@/store/api'; import { isArray, isNil } from '@/utils/validation'; -/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */ type OmittedKeys = 'fields' | 'userId' | 'enableImages' | 'enableTotalRecordCount' | 'enableImageTypes'; type ParametersAsGetters any> = T extends (...args: infer P) => any ? { [K in keyof P]: () => BetterOmit, OmittedKeys> } @@ -274,7 +274,7 @@ function _sharedInternalLogic any>, K ex await runNormally(); } }); - watch(() => remote.socket.isConnected, runWithRetry); + watch(remote.socket.isConnected, runWithRetry); watch(network.isOnline, runWithRetry); isRef(api) && watch(api, runNormally); isRef(methodName) && watch(methodName, runNormally); @@ -448,4 +448,4 @@ export function methodsAsObject any>, K }; } -/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access */ +/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */ diff --git a/frontend/src/plugins/remote/socket/index.ts b/frontend/src/plugins/remote/socket/index.ts index bcf74d578a0..19a8b24076c 100644 --- a/frontend/src/plugins/remote/socket/index.ts +++ b/frontend/src/plugins/remote/socket/index.ts @@ -7,7 +7,9 @@ import type { WebSocketMessage } from './types'; import { isNil } from '@/utils/validation'; class RemotePluginSocket { - private _internalMessage: WebSocketMessage | undefined = undefined; + /** + * == STATE == + */ private readonly _socketUrl = computed(() => { if ( auth.currentUserToken && @@ -26,9 +28,30 @@ class RemotePluginSocket { } }); private readonly _keepAliveMessage = 'KeepAlive'; + private readonly _forceKeepAliveMessage = 'ForceKeepAlive'; /** * Formats the message to be sent to the socket */ + private readonly _webSocket = useWebSocket(this._socketUrl, { + heartbeat: false, + autoReconnect: { retries: () => true }, + immediate: true, + autoClose: false + }); + private readonly _parsedmsg = computed(() => destr(this._webSocket.data.value)); + public readonly message = computed((previous) => { + if (this._parsedmsg.value?.MessageType === this._keepAliveMessage || + this._parsedmsg.value?.MessageType === this._forceKeepAliveMessage) { + return previous; + } + + return this._parsedmsg.value; + }); + public readonly isConnected = computed(() => this._webSocket.status.value === 'OPEN'); + + /** + * == METHODS == + */ private readonly _formatSocketMessage = ( name: string, data?: WebSocketMessage['Data'] @@ -41,20 +64,6 @@ class RemotePluginSocket { return JSON.stringify(message); }; - private readonly _webSocket = useWebSocket(this._socketUrl, { - heartbeat: false, - autoReconnect: { retries: () => true }, - immediate: true, - autoClose: false - }); - - public get isConnected(): boolean { - return this._webSocket.status.value === 'OPEN'; - } - - public get message(): WebSocketMessage | undefined { - return this._internalMessage; - } /** * Send message to socket @@ -72,13 +81,9 @@ class RemotePluginSocket { * Sending updates through this watcher to avoid sending KeepAlive messages to consumers of * of this plugin */ - watch(this._webSocket.data, () => { - const message = destr(this._webSocket.data.value); - - if (message?.MessageType === 'ForceKeepAlive') { + watch(this._parsedmsg, () => { + if (this._parsedmsg.value?.MessageType === this._forceKeepAliveMessage) { this.sendToSocket(this._keepAliveMessage); - } else if (message?.MessageType !== this._keepAliveMessage) { - this._internalMessage = message; } }, { flush: 'sync' } ); diff --git a/frontend/src/store/api.ts b/frontend/src/store/api.ts index 6cf807bbc6e..3319a08b218 100644 --- a/frontend/src/store/api.ts +++ b/frontend/src/store/api.ts @@ -161,13 +161,13 @@ class ApiStore { public constructor() { watch( - () => remote.socket.message, + remote.socket.message, async () => { - if (!remote.socket.message) { + if (!remote.socket.message.value) { return; } - const { MessageType, Data } = remote.socket.message; + const { MessageType, Data } = remote.socket.message.value; if (!Data || !isObj(Data)) { return; diff --git a/frontend/src/store/taskManager.ts b/frontend/src/store/taskManager.ts index 248e2287002..ac1587338a1 100644 --- a/frontend/src/store/taskManager.ts +++ b/frontend/src/store/taskManager.ts @@ -181,13 +181,13 @@ class TaskManagerStore { }; watch( - () => remote.socket.message, + remote.socket.message, () => { - if (!remote.socket.message) { + if (!remote.socket.message.value) { return; } - const { MessageType, Data } = remote.socket.message; + const { MessageType, Data } = remote.socket.message.value; if (!Data || !isObj(Data)) { return; diff --git a/frontend/src/utils/items.ts b/frontend/src/utils/items.ts index f0d96871a3f..12b3ed4032c 100644 --- a/frontend/src/utils/items.ts +++ b/frontend/src/utils/items.ts @@ -582,8 +582,8 @@ export async function ensureWebSocket(): Promise { await new Promise((resolve) => { scope.run(() => { - watch(() => remote.socket.isConnected, () => { - if (remote.socket.isConnected) { + watch(remote.socket.isConnected, () => { + if (remote.socket.isConnected.value) { resolve(); } }, { immediate: true, flush: 'sync' }); diff --git a/frontend/types/global/util.d.ts b/frontend/types/global/util.d.ts index 1361c529359..1472409d1f4 100644 --- a/frontend/types/global/util.d.ts +++ b/frontend/types/global/util.d.ts @@ -2,7 +2,7 @@ * BetterOmit still provides IntelliSense fedback, unlike the built-in Omit type. * See https://github.com/microsoft/TypeScript/issues/56135 */ -type BetterOmit = T extends Record +type BetterOmit = T extends Record ? { [P in keyof T as P extends K ? never : P]: T[P] }