94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
|
// Copyright 2024 Signal Messenger, LLC
|
||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||
|
|
||
|
import assert from 'assert';
|
||
|
import { v7 as uuid } from 'uuid';
|
||
|
import { migrateMessageData } from '../../messages/migrateMessageData';
|
||
|
import type { MessageAttributesType } from '../../model-types';
|
||
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||
|
import { generateAci } from '../../types/ServiceId';
|
||
|
|
||
|
function composeMessage(timestamp: number): MessageAttributesType {
|
||
|
return {
|
||
|
schemaVersion: 1,
|
||
|
conversationId: uuid(),
|
||
|
id: uuid(),
|
||
|
type: 'incoming',
|
||
|
received_at: timestamp,
|
||
|
received_at_ms: timestamp,
|
||
|
sent_at: timestamp,
|
||
|
timestamp,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
describe('utils/migrateMessageData', async () => {
|
||
|
before(async () => {
|
||
|
await DataWriter.removeAll();
|
||
|
await window.storage.put('uuid_id', generateAci());
|
||
|
});
|
||
|
after(async () => {
|
||
|
await DataWriter.removeAll();
|
||
|
});
|
||
|
it('increments attempts for messages which fail to save', async () => {
|
||
|
const messages = new Array(5)
|
||
|
.fill(null)
|
||
|
.map((_, idx) => composeMessage(idx + 1));
|
||
|
|
||
|
const CANNOT_UPGRADE_MESSAGE_ID = messages[1].id;
|
||
|
const CANNOT_SAVE_MESSAGE_ID = messages[2].id;
|
||
|
await DataWriter.saveMessages(messages, {
|
||
|
forceSave: true,
|
||
|
ourAci: generateAci(),
|
||
|
});
|
||
|
|
||
|
const result = await migrateMessageData({
|
||
|
numMessagesPerBatch: 10_000,
|
||
|
upgradeMessageSchema: async (message, ...rest) => {
|
||
|
if (message.id === CANNOT_UPGRADE_MESSAGE_ID) {
|
||
|
throw new Error('upgrade failed');
|
||
|
}
|
||
|
return window.Signal.Migrations.upgradeMessageSchema(message, ...rest);
|
||
|
},
|
||
|
getMessagesNeedingUpgrade: async (...args) => {
|
||
|
const messagesToUpgrade = await DataReader.getMessagesNeedingUpgrade(
|
||
|
...args
|
||
|
);
|
||
|
|
||
|
return messagesToUpgrade.map(message => {
|
||
|
if (message.id === CANNOT_SAVE_MESSAGE_ID) {
|
||
|
return {
|
||
|
...message,
|
||
|
// mimic bad data in DB
|
||
|
sent_at: { low: 0, high: 0 } as unknown as number,
|
||
|
};
|
||
|
}
|
||
|
return message;
|
||
|
});
|
||
|
},
|
||
|
saveMessagesIndividually: DataWriter.saveMessagesIndividually,
|
||
|
incrementMessagesMigrationAttempts:
|
||
|
DataWriter.incrementMessagesMigrationAttempts,
|
||
|
});
|
||
|
|
||
|
assert.equal(result.done, true);
|
||
|
assert.equal(result.numProcessed, 5);
|
||
|
assert.equal(result.numSucceeded, 3);
|
||
|
assert.equal(result.numFailedSave, 1);
|
||
|
assert.equal(result.numFailedUpgrade, 1);
|
||
|
|
||
|
const upgradedMessages = await DataReader._getAllMessages();
|
||
|
for (const message of upgradedMessages) {
|
||
|
if (
|
||
|
message.id === CANNOT_SAVE_MESSAGE_ID ||
|
||
|
message.id === CANNOT_UPGRADE_MESSAGE_ID
|
||
|
) {
|
||
|
assert.equal(message.schemaMigrationAttempts, 1);
|
||
|
assert.equal(message.schemaVersion, 1);
|
||
|
} else {
|
||
|
assert.equal(message.schemaMigrationAttempts ?? 0, 0);
|
||
|
assert.equal((message.schemaVersion ?? 0) > 1, true);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|