From cf65a5cd932ff89148ed4524bc377ee0cf4c6efa Mon Sep 17 00:00:00 2001 From: liuyi Date: Fri, 24 Nov 2023 07:26:39 +0000 Subject: [PATCH] fix(server): never throw in websocket gateways (#5050) --- .../src/modules/sync/events/events.gateway.ts | 66 ++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/packages/backend/server/src/modules/sync/events/events.gateway.ts b/packages/backend/server/src/modules/sync/events/events.gateway.ts index 2649b526f7fcc..6471c91afe56d 100644 --- a/packages/backend/server/src/modules/sync/events/events.gateway.ts +++ b/packages/backend/server/src/modules/sync/events/events.gateway.ts @@ -28,8 +28,46 @@ import { WorkspaceNotFoundError, } from './error'; +export const GatewayErrorWrapper = (): MethodDecorator => { + // @ts-expect-error allow + return ( + _target, + _key, + desc: TypedPropertyDescriptor<(...args: any[]) => any> + ) => { + const originalMethod = desc.value; + if (!originalMethod) { + return desc; + } + + desc.value = function (...args: any[]) { + let result: any; + try { + result = originalMethod.apply(this, args); + } catch (e) { + return { + error: new InternalError(e as Error), + }; + } + + if (result instanceof Promise) { + return result.catch(e => { + return { + error: new InternalError(e), + }; + }); + } else { + return result; + } + }; + + return desc; + }; +}; + const SubscribeMessage = (event: string) => applyDecorators( + GatewayErrorWrapper(), CallCounter('socket_io_counter', { event }), CallTimer('socket_io_timer', { event }), RawSubscribeMessage(event) @@ -233,25 +271,19 @@ export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect { }; } - try { - const docId = new DocID(guid, workspaceId); - client - .to(docId.workspace) - .emit('server-updates', { workspaceId, guid, updates }); + const docId = new DocID(guid, workspaceId); + client + .to(docId.workspace) + .emit('server-updates', { workspaceId, guid, updates }); - const buffers = updates.map(update => Buffer.from(update, 'base64')); + const buffers = updates.map(update => Buffer.from(update, 'base64')); - await this.docManager.batchPush(docId.workspace, docId.guid, buffers); - return { - data: { - accepted: true, - }, - }; - } catch (e) { - return { - error: new InternalError(e as Error), - }; - } + await this.docManager.batchPush(docId.workspace, docId.guid, buffers); + return { + data: { + accepted: true, + }, + }; } @Auth()