Keep messages in their own transaction in saveMessagesIndividually

This commit is contained in:
trevor-signal
2025-08-26 17:17:16 -04:00
committed by GitHub
parent b0bbf4189e
commit f4c1d9334f
2 changed files with 58 additions and 11 deletions

View File

@@ -2731,7 +2731,6 @@ function saveMessage(
_testOnlyAvoidNormalizingAttachments?: boolean;
}
): string {
// NB: `saveMessagesIndividually` relies on `saveMessage` being atomic
const { alreadyInTransaction, forceSave, jobToInsert, ourAci } = options;
if (!alreadyInTransaction) {
return db.transaction(() => {
@@ -2901,6 +2900,10 @@ function saveMessage(
} satisfies Omit<MessageTypeUnhydrated, 'json'>;
if (id && !forceSave) {
if (normalizeAttachmentData) {
saveMessageAttachments(db, message);
}
const result = db
.prepare(
// UPDATE queries that set the value of a primary key column can be very slow when
@@ -2919,16 +2922,12 @@ function saveMessage(
return id;
}
strictAssert(result.changes === 1, 'One row should have been changed');
if (normalizeAttachmentData) {
saveMessageAttachments(db, message);
}
if (jobToInsert) {
insertJob(db, jobToInsert);
}
strictAssert(result.changes === 1, 'One row should have been changed');
return id;
}
@@ -2991,10 +2990,7 @@ function saveMessagesIndividually(
const failedIndices: Array<number> = [];
arrayOfMessages.forEach((message, index) => {
try {
saveMessage(db, message, {
...options,
alreadyInTransaction: true,
});
saveMessage(db, message, options);
} catch (e) {
logger.error(
'saveMessagesIndividually: failed to save message',

View File

@@ -3,6 +3,7 @@
import { assert } from 'chai';
import { v4 as generateGuid } from 'uuid';
import { omit } from 'lodash';
import * as Bytes from '../Bytes';
import type {
@@ -637,4 +638,54 @@ describe('normalizes attachment references', () => {
incrementalMac: undefined,
});
});
it('is resilient when called from saveMessagesIndividually to incorrect data', async () => {
const attachment = {
...composeAttachment(),
key: {},
randomKey: 'random',
} as unknown as AttachmentType;
const attachments = [attachment];
const message = composeMessage(Date.now(), {
attachments,
});
await DataWriter.saveMessages([message], {
forceSave: true,
ourAci: generateAci(),
postSaveUpdates: () => Promise.resolve(),
_testOnlyAvoidNormalizingAttachments: true,
});
await DataWriter.saveMessagesIndividually([message], {
ourAci: generateAci(),
postSaveUpdates: () => Promise.resolve(),
});
let messageFromDB = await DataReader.getMessageById(message.id);
assert(messageFromDB, 'message was saved');
assert.deepEqual(messageFromDB.attachments?.[0], attachment);
const attachmentWithoutKey = { ...attachment, key: undefined };
await DataWriter.saveMessagesIndividually(
[
{
...message,
attachments: [attachmentWithoutKey],
},
],
{
ourAci: generateAci(),
postSaveUpdates: () => Promise.resolve(),
}
);
messageFromDB = await DataReader.getMessageById(message.id);
assert(messageFromDB, 'message was saved');
assert.deepEqual(
messageFromDB.attachments?.[0],
omit(attachmentWithoutKey, 'randomKey')
);
});
});