From 9677601155e28d2d2f85016171a434dcdc3e3842 Mon Sep 17 00:00:00 2001 From: automated-signal <37887102+automated-signal@users.noreply.github.com> Date: Wed, 8 Jan 2025 12:12:32 -0600 Subject: [PATCH] De-asyncify receipt handling logic Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> --- ts/messageModifiers/MessageReceipts.ts | 38 ++++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/ts/messageModifiers/MessageReceipts.ts b/ts/messageModifiers/MessageReceipts.ts index 9542ff787..9db7b26d1 100644 --- a/ts/messageModifiers/MessageReceipts.ts +++ b/ts/messageModifiers/MessageReceipts.ts @@ -193,17 +193,20 @@ async function processReceiptsForMessage( messageId ); - const { updatedMessage, validReceipts } = await updateMessageWithReceipts( - message, - receipts - ); + // Note: it is important to have no `await` in between `resolveAttributes` and + // `setAttributes` since it might overwrite other updates otherwise. + const { updatedMessage, validReceipts, droppedReceipts } = + updateMessageWithReceipts(message, receipts); - // Save it to cache & to DB - await window.MessageCache.setAttributes({ - messageId, - messageAttributes: updatedMessage, - skipSaveToDatabase: false, - }); + // Save it to cache & to DB, and remove dropped receipts + await Promise.all([ + window.MessageCache.setAttributes({ + messageId, + messageAttributes: updatedMessage, + skipSaveToDatabase: false, + }), + Promise.all(droppedReceipts.map(remove)), + ]); // Confirm/remove receipts, and delete sent protos for (const receipt of validReceipts) { @@ -219,23 +222,24 @@ async function processReceiptsForMessage( conversation?.debouncedUpdateLastMessage?.(); } -async function updateMessageWithReceipts( +function updateMessageWithReceipts( message: MessageAttributesType, receipts: Array -): Promise<{ +): { updatedMessage: MessageAttributesType; validReceipts: Array; -}> { + droppedReceipts: Array; +} { const logId = `updateMessageWithReceipts(timestamp=${message.timestamp})`; - const toRemove: Array = []; + const droppedReceipts: Array = []; const receiptsToProcess = receipts.filter(receipt => { if (shouldDropReceipt(receipt, message)) { const { receiptSync } = receipt; log.info( `${logId}: Dropping a receipt ${receiptSync.type} for sentAt=${receiptSync.messageSentAt}` ); - toRemove.push(receipt); + droppedReceipts.push(receipt); return false; } @@ -247,8 +251,6 @@ async function updateMessageWithReceipts( return true; }); - await Promise.all(toRemove.map(remove)); - log.info( `${logId}: batch processing ${receipts.length}` + ` receipt${receipts.length === 1 ? '' : 's'}` @@ -262,7 +264,7 @@ async function updateMessageWithReceipts( ...updateMessageSendStateWithReceipt(updatedMessage, receipt), }; } - return { updatedMessage, validReceipts: receiptsToProcess }; + return { updatedMessage, validReceipts: receiptsToProcess, droppedReceipts }; } const deleteSentProtoBatcher = createWaitBatcher({