diff --git a/ts/messageModifiers/MessageReceipts.ts b/ts/messageModifiers/MessageReceipts.ts index 797fdc2d628..5bb05b1582b 100644 --- a/ts/messageModifiers/MessageReceipts.ts +++ b/ts/messageModifiers/MessageReceipts.ts @@ -35,7 +35,8 @@ import { drop } from '../util/drop'; import { getMessageById } from '../messages/getMessageById'; import { MessageModel } from '../models/messages'; -const { deleteSentProtoRecipient, removeSyncTaskById } = DataWriter; +const { deleteSentProtoRecipient, removeSyncTasks, removeSyncTaskById } = + DataWriter; export const messageReceiptTypeSchema = z.enum(['Delivery', 'Read', 'View']); @@ -197,9 +198,21 @@ async function processReceiptsForMessage( ); } - const { validReceipts } = await updateMessageWithReceipts(message, receipts); + const { droppedReceipts, validReceipts } = await updateMessageWithReceipts( + message, + receipts + ); - await window.MessageCache.saveMessage(message.attributes); + await Promise.all([ + window.MessageCache.saveMessage(message.attributes), + removeSyncTasks( + droppedReceipts.map(item => { + const { syncTaskId } = item; + cachedReceipts.delete(syncTaskId); + return syncTaskId; + }) + ), + ]); // Confirm/remove receipts, and delete sent protos for (const receipt of validReceipts) { @@ -219,6 +232,7 @@ async function updateMessageWithReceipts( message: MessageModel, receipts: Array ): Promise<{ + droppedReceipts: Array; validReceipts: Array; }> { const logId = `updateMessageWithReceipts(timestamp=${message.get('timestamp')})`; @@ -244,7 +258,8 @@ async function updateMessageWithReceipts( log.info( `${logId}: batch processing ${receipts.length}` + - ` receipt${receipts.length === 1 ? '' : 's'}` + ` receipt${receipts.length === 1 ? '' : 's'}` + + `, dropped count: ${droppedReceipts.length}` ); // Generate the updated message synchronously @@ -257,7 +272,7 @@ async function updateMessageWithReceipts( } message.set(attributes); - return { validReceipts: receiptsToProcess }; + return { droppedReceipts, validReceipts: receiptsToProcess }; } const deleteSentProtoBatcher = createWaitBatcher({ diff --git a/ts/sql/Interface.ts b/ts/sql/Interface.ts index 0acb43578ea..d136e21d0ba 100644 --- a/ts/sql/Interface.ts +++ b/ts/sql/Interface.ts @@ -902,6 +902,7 @@ type WritableInterface = { ) => void; removeSyncTaskById: (id: string) => void; + removeSyncTasks: (ids: ReadonlyArray) => void; saveSyncTasks: (tasks: Array) => void; incrementAllSyncTaskAttempts: () => void; diff --git a/ts/sql/Server.ts b/ts/sql/Server.ts index 66c20f7b487..acb308db865 100644 --- a/ts/sql/Server.ts +++ b/ts/sql/Server.ts @@ -520,6 +520,7 @@ export const DataWriter: ServerWritableInterface = { incrementMessagesMigrationAttempts, removeSyncTaskById, + removeSyncTasks, saveSyncTasks, incrementAllSyncTaskAttempts, dequeueOldestSyncTasks, @@ -2147,6 +2148,19 @@ export function removeSyncTaskById(db: WritableDB, id: string): void { db.prepare(query).run(parameters); } +function removeSyncTaskBatch(db: WritableDB, ids: ReadonlyArray): void { + db.prepare( + ` + DELETE FROM syncTasks + WHERE id IN ( ${ids.map(() => '?').join(', ')} ); + ` + ).run(ids); +} + +function removeSyncTasks(db: WritableDB, ids: ReadonlyArray): void { + batchMultiVarQuery(db, ids, batch => removeSyncTaskBatch(db, batch)); +} + export function saveSyncTasks( db: WritableDB, tasks: Array