From 20bbc56bbe41827448e8e4e8b529bdd2c0317ee7 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Wed, 22 Feb 2023 02:47:29 +0200 Subject: [PATCH] experiment with "signal" rpc that does not send the data returned by the method --- frontend/src/gateway.js | 11 ++++++----- frontend/src/request.js | 15 +++++++++++---- frontend/src/stores.js | 10 ++++------ src/gateway/gatewaypayloadtype.ts | 1 + src/gateway/index.ts | 7 +++---- src/rpc/rpc.ts | 10 ++++++++-- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/frontend/src/gateway.js b/frontend/src/gateway.js index 920ffb1..18a01d7 100644 --- a/frontend/src/gateway.js +++ b/frontend/src/gateway.js @@ -15,11 +15,12 @@ export const GatewayErrors = { export const GatewayPayloadType = { Hello: 0, - Authenticate: 1, + Authenticate: 1, // client Ready: 2, - Ping: 3, + Ping: 3, // client RPCRequest: 4, // client - RPCResponse: 5, + RPCSignal: 5, // client + RPCResponse: 6, ChannelCreate: 110, ChannelUpdate: 111, @@ -194,11 +195,11 @@ export default { this.handlers.delete(event); } }, - sendRPCRequest(calls) { + sendRPCRequest(calls, isSignal) { return new Promise((resolve, _reject) => { this.waitingSerials.set(this.serial, resolve); this.send({ - t: GatewayPayloadType.RPCRequest, + t: isSignal ? GatewayPayloadType.RPCSignal : GatewayPayloadType.RPCRequest, d: calls, s: this.serial }); diff --git a/frontend/src/request.js b/frontend/src/request.js index 7ec7bf5..08912f4 100644 --- a/frontend/src/request.js +++ b/frontend/src/request.js @@ -94,11 +94,11 @@ export default function doRequest(method, endpoint, auth=true, body=null) { }); } -export async function remoteCall({methodId, requiresAuthentication, cacheable}, ...args) { +export async function remoteCall({methodId, requiresAuthentication, cacheable, _isSignal=false}, ...args) { const calls = [[methodId, ...args]]; if (requiresAuthentication && gateway.authenticated && !cacheable) { - const replies = await gateway.sendRPCRequest(calls); - const ok = Array.isArray(replies) && replies[0] && !replies[0].code; + const replies = await gateway.sendRPCRequest(calls, _isSignal); + const ok = Array.isArray(replies) && !(replies[0] && replies[0].code); return { json: ok ? replies[0] : null, ok @@ -111,7 +111,14 @@ export async function remoteCall({methodId, requiresAuthentication, cacheable}, } else { response = await doRequest("POST", apiRoute("rpc"), requiresAuthentication, calls); } - response.ok = response.ok && Array.isArray(response.json) && response.json[0] && !response.json[0].code; + response.ok = response.ok && Array.isArray(response.json) && !(response.json[0] && response.json[0].code); response.json = response.ok ? response.json[0] : null; return response; } + +export async function remoteSignal(method, ...args) { + return await remoteCall({ + ...method, + _isSignal: true + }, ...args); +} diff --git a/frontend/src/stores.js b/frontend/src/stores.js index 06a6529..ff38751 100644 --- a/frontend/src/stores.js +++ b/frontend/src/stores.js @@ -1,6 +1,6 @@ import gateway, { GatewayEventType, GatewayPayloadType, GatewayPresenceStatus } from "./gateway"; import logger from "./logging"; -import { methods, remoteCall } from "./request"; +import { methods, remoteCall, remoteSignal } from "./request"; import { getItem, setItem } from "./storage"; const storeLog = logger("Store"); @@ -539,7 +539,7 @@ class TypingStore extends Store { this.startedTyping(userInfoStore.value, selectedChannel.value.id, 6500); if (this.ownNeedsUpdate) { this.ownNeedsUpdate = false; - await remoteCall(methods.putChannelTyping, selectedChannel.value.id); + await remoteSignal(methods.putChannelTyping, selectedChannel.value.id); } } } @@ -695,11 +695,9 @@ export const sendMessageAction = createAction("sendMessageAction", async ({chann const messagesStoreForChannel = messagesStoreProvider.getStore(channelId); messagesStoreForChannel.addMessage(optimisticMessage); - const res = await remoteCall(methods.createChannelMessage, channelId, content, optimisticMessageId, null); + const res = await remoteSignal(methods.createChannelMessage, channelId, content, optimisticMessageId, null); - if (res.ok) { - messagesStoreForChannel.setMessage(optimisticMessageId, res.json); - } else { + if (!res.ok) { messagesStoreForChannel.deleteMessage({ id: optimisticMessageId }); diff --git a/src/gateway/gatewaypayloadtype.ts b/src/gateway/gatewaypayloadtype.ts index fc92fe3..f64e3e9 100644 --- a/src/gateway/gatewaypayloadtype.ts +++ b/src/gateway/gatewaypayloadtype.ts @@ -4,6 +4,7 @@ export enum GatewayPayloadType { Ready, Ping, // client RPCRequest, // client + RPCSignal, // client RPCResponse, ChannelCreate = 110, diff --git a/src/gateway/index.ts b/src/gateway/index.ts index 3c9f4a9..f33944b 100644 --- a/src/gateway/index.ts +++ b/src/gateway/index.ts @@ -409,20 +409,19 @@ export default function(server: Server) { ws.state.alive = true; break; } + case GatewayPayloadType.RPCSignal: /* through */ case GatewayPayloadType.RPCRequest: { if (!ws.state.ready || !ws.state.user) { return closeWithError(ws, gatewayErrors.NOT_AUTHENTICATED); } - processMethodBatch(ws.state.user, payload.d).then((results) => { + // RPCSignal is like RPCRequest however it does not send RPC method output unless there is an error + processMethodBatch(ws.state.user, payload.d, (payload.t === GatewayPayloadType.RPCSignal ? true : false)).then((results) => { sendPayload(ws, { t: GatewayPayloadType.RPCResponse, d: results, s: payload.s }); - }).catch(e => { - console.error("gateway: unexpected error while handling RPCRequest", e); - return closeWithError(ws, gatewayErrors.INTERNAL_ERROR); }); break; } diff --git a/src/rpc/rpc.ts b/src/rpc/rpc.ts index 53c0b6d..51cd46b 100644 --- a/src/rpc/rpc.ts +++ b/src/rpc/rpc.ts @@ -121,7 +121,7 @@ export const userInvokeMethod = async (user: User | null, methodId: number, args } }; -export const processMethodBatch = async (user: User | null, calls: any) => { +export const processMethodBatch = async (user: User | null, calls: any, ignoreNonErrors = false) => { if (!Array.isArray(calls) || !calls.length || calls.length > 5) { return { ...errors.BAD_REQUEST, @@ -141,7 +141,13 @@ export const processMethodBatch = async (user: User | null, calls: any) => { } const promise = userInvokeMethod(user, call[0], call.slice(1, call.length)); - promise.then(value => responses[index] = value); + promise.then(value => { + if (ignoreNonErrors && !value.code) { + responses[index] = null; + } else { + responses[index] = value; + } + }); promises[index] = promise; });