diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index dbca8e883fa..3a40f590297 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -1433,6 +1433,11 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { node: BinaryNode } + /** Yields control to the event loop to prevent blocking */ + const yieldToEventLoop = (): Promise => { + return new Promise(resolve => setImmediate(resolve)) + } + const makeOfflineNodeProcessor = () => { const nodeProcessorMap: Map Promise> = new Map([ ['message', handleMessage], @@ -1443,6 +1448,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const nodes: OfflineNode[] = [] let isProcessing = false + // Number of nodes to process before yielding to event loop + const BATCH_SIZE = 10 + const enqueue = (type: MessageType, node: BinaryNode) => { nodes.push({ type, node }) @@ -1453,6 +1461,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { isProcessing = true const promise = async () => { + let processedInBatch = 0 + while (nodes.length && ws.isOpen) { const { type, node } = nodes.shift()! @@ -1464,6 +1474,14 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } await nodeProcessor(node) + processedInBatch++ + + // Yield to event loop after processing a batch + // This prevents blocking the event loop for too long when there are many offline nodes + if (processedInBatch >= BATCH_SIZE) { + processedInBatch = 0 + await yieldToEventLoop() + } } isProcessing = false