mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-08 08:58:38 +01:00
Introduce new conversationJobQueue
This commit is contained in:
@@ -425,7 +425,7 @@ describe('LeftPaneInboxHelper', () => {
|
||||
});
|
||||
|
||||
describe('getConversationAndMessageAtIndex', () => {
|
||||
it('returns pinned converastions, then non-pinned conversations', () => {
|
||||
it('returns pinned conversations, then non-pinned conversations', () => {
|
||||
const conversations = [
|
||||
getDefaultConversation(),
|
||||
getDefaultConversation(),
|
||||
|
||||
@@ -4,10 +4,34 @@
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { noop, omit } from 'lodash';
|
||||
import { HTTPError } from '../../../textsecure/Errors';
|
||||
import { HTTPError, SendMessageProtoError } from '../../../textsecure/Errors';
|
||||
import { SECOND } from '../../../util/durations';
|
||||
|
||||
import { handleMultipleSendErrors } from '../../../jobs/helpers/handleMultipleSendErrors';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
} from '../../../jobs/helpers/handleMultipleSendErrors';
|
||||
|
||||
describe('maybeExpandErrors', () => {
|
||||
// This returns a readonly array, but Chai wants a mutable one.
|
||||
const expand = (input: unknown) => maybeExpandErrors(input) as Array<unknown>;
|
||||
|
||||
it("wraps the provided value if it's not a SendMessageProtoError with errors", () => {
|
||||
const input = { foo: 123 };
|
||||
assert.sameMembers(expand(input), [input]);
|
||||
});
|
||||
|
||||
it('wraps the provided value if a SendMessageProtoError with no errors', () => {
|
||||
const input = new SendMessageProtoError({});
|
||||
assert.sameMembers(expand(input), [input]);
|
||||
});
|
||||
|
||||
it("uses a SendMessageProtoError's errors", () => {
|
||||
const errors = [new Error('one'), new Error('two')];
|
||||
const input = new SendMessageProtoError({ errors });
|
||||
assert.strictEqual(expand(input), errors);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleMultipleSendErrors', () => {
|
||||
const make413 = (retryAfter: number): HTTPError =>
|
||||
@@ -43,8 +67,9 @@ describe('handleMultipleSendErrors', () => {
|
||||
handleMultipleSendErrors({
|
||||
...defaultOptions,
|
||||
errors: [new Error('first'), new Error('second')],
|
||||
toThrow: new Error('to throw'),
|
||||
}),
|
||||
'first'
|
||||
'to throw'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -57,6 +82,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
errors: [new Error('uh oh')],
|
||||
markFailed,
|
||||
isFinalAttempt: true,
|
||||
toThrow: new Error('to throw'),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -69,8 +95,9 @@ describe('handleMultipleSendErrors', () => {
|
||||
...omit(defaultOptions, 'markFailed'),
|
||||
errors: [new Error('Test message')],
|
||||
isFinalAttempt: true,
|
||||
toThrow: new Error('to throw'),
|
||||
}),
|
||||
'Test message'
|
||||
'to throw'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -89,6 +116,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
make413(20),
|
||||
],
|
||||
timeRemaining: 99999999,
|
||||
toThrow: new Error('to throw'),
|
||||
});
|
||||
} catch (err) {
|
||||
// No-op
|
||||
@@ -112,6 +140,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
...defaultOptions,
|
||||
errors: [make413(9999)],
|
||||
timeRemaining: 99,
|
||||
toThrow: new Error('to throw'),
|
||||
});
|
||||
} catch (err) {
|
||||
// No-op
|
||||
@@ -130,6 +159,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
...defaultOptions,
|
||||
errors: [new Error('uh oh')],
|
||||
isFinalAttempt: true,
|
||||
toThrow: new Error('to throw'),
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -142,6 +172,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
...defaultOptions,
|
||||
errors: [new Error('uh oh'), { code: 508 }, make413(99999)],
|
||||
markFailed: noop,
|
||||
toThrow: new Error('to throw'),
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -153,6 +184,7 @@ describe('handleMultipleSendErrors', () => {
|
||||
...defaultOptions,
|
||||
errors: [{ code: 508 }],
|
||||
markFailed,
|
||||
toThrow: new Error('to throw'),
|
||||
});
|
||||
|
||||
sinon.assert.calledOnceWithExactly(markFailed);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// Copyright 2021-2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
@@ -8,6 +8,7 @@ import { v4 as generateGuid } from 'uuid';
|
||||
|
||||
import { SCHEMA_VERSIONS } from '../sql/migrations';
|
||||
import { consoleLogger } from '../util/consoleLogger';
|
||||
import { getJobsInQueueSync, insertJobSync } from '../sql/Server';
|
||||
|
||||
const OUR_UUID = generateGuid();
|
||||
|
||||
@@ -1325,7 +1326,7 @@ describe('SQL migrations test', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateToSchemaVersion49', () => {
|
||||
describe('updateToSchemaVersion50', () => {
|
||||
it('creates usable index for messages_unread', () => {
|
||||
updateToVersion(50);
|
||||
|
||||
@@ -1351,4 +1352,252 @@ describe('SQL migrations test', () => {
|
||||
assert.notInclude(details, 'SCAN');
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateToSchemaVersion51', () => {
|
||||
it('moves reactions/normal send jobs over to conversation queue', () => {
|
||||
updateToVersion(50);
|
||||
|
||||
const MESSAGE_ID_1 = generateGuid();
|
||||
const CONVERSATION_ID_1 = generateGuid();
|
||||
|
||||
db.exec(
|
||||
`
|
||||
INSERT INTO messages
|
||||
(id, json)
|
||||
VALUES ('${MESSAGE_ID_1}', '${JSON.stringify({
|
||||
conversationId: CONVERSATION_ID_1,
|
||||
})}')
|
||||
`
|
||||
);
|
||||
|
||||
db.exec(
|
||||
`
|
||||
INSERT INTO jobs
|
||||
(id, timestamp, queueType, data)
|
||||
VALUES
|
||||
('id-1', 1, 'random job', '{}'),
|
||||
('id-2', 2, 'normal send', '{}'),
|
||||
('id-3', 3, 'reactions', '{"messageId":"${MESSAGE_ID_1}"}'),
|
||||
('id-4', 4, 'conversation', '{}');
|
||||
`
|
||||
);
|
||||
|
||||
const totalJobs = db.prepare('SELECT COUNT(*) FROM jobs;').pluck();
|
||||
const normalSendJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'normal send';")
|
||||
.pluck();
|
||||
const conversationJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'conversation';")
|
||||
.pluck();
|
||||
const reactionJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'reactions';")
|
||||
.pluck();
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 4, 'before total');
|
||||
assert.strictEqual(normalSendJobs.get(), 1, 'before normal');
|
||||
assert.strictEqual(conversationJobs.get(), 1, 'before conversation');
|
||||
assert.strictEqual(reactionJobs.get(), 1, 'before reaction');
|
||||
|
||||
updateToVersion(51);
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 4, 'after total');
|
||||
assert.strictEqual(normalSendJobs.get(), 0, 'after normal');
|
||||
assert.strictEqual(conversationJobs.get(), 3, 'after conversation');
|
||||
assert.strictEqual(reactionJobs.get(), 0, 'after reaction');
|
||||
});
|
||||
|
||||
it('updates reactions jobs with their conversationId', () => {
|
||||
updateToVersion(50);
|
||||
|
||||
const MESSAGE_ID_1 = generateGuid();
|
||||
const MESSAGE_ID_2 = generateGuid();
|
||||
const MESSAGE_ID_3 = generateGuid();
|
||||
|
||||
const CONVERSATION_ID_1 = generateGuid();
|
||||
const CONVERSATION_ID_2 = generateGuid();
|
||||
|
||||
insertJobSync(db, {
|
||||
id: 'id-1',
|
||||
timestamp: 1,
|
||||
queueType: 'reactions',
|
||||
data: {
|
||||
messageId: MESSAGE_ID_1,
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-2',
|
||||
timestamp: 2,
|
||||
queueType: 'reactions',
|
||||
data: {
|
||||
messageId: MESSAGE_ID_2,
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-3-missing-data',
|
||||
timestamp: 3,
|
||||
queueType: 'reactions',
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-4-non-string-messageId',
|
||||
timestamp: 1,
|
||||
queueType: 'reactions',
|
||||
data: {
|
||||
messageId: 4,
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-5-missing-message',
|
||||
timestamp: 5,
|
||||
queueType: 'reactions',
|
||||
data: {
|
||||
messageId: 'missing',
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-6-missing-conversation',
|
||||
timestamp: 6,
|
||||
queueType: 'reactions',
|
||||
data: {
|
||||
messageId: MESSAGE_ID_3,
|
||||
},
|
||||
});
|
||||
|
||||
const messageJson1 = JSON.stringify({
|
||||
conversationId: CONVERSATION_ID_1,
|
||||
});
|
||||
const messageJson2 = JSON.stringify({
|
||||
conversationId: CONVERSATION_ID_2,
|
||||
});
|
||||
db.exec(
|
||||
`
|
||||
INSERT INTO messages
|
||||
(id, conversationId, json)
|
||||
VALUES
|
||||
('${MESSAGE_ID_1}', '${CONVERSATION_ID_1}', '${messageJson1}'),
|
||||
('${MESSAGE_ID_2}', '${CONVERSATION_ID_2}', '${messageJson2}'),
|
||||
('${MESSAGE_ID_3}', null, '{}');
|
||||
`
|
||||
);
|
||||
|
||||
const totalJobs = db.prepare('SELECT COUNT(*) FROM jobs;').pluck();
|
||||
const reactionJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'reactions';")
|
||||
.pluck();
|
||||
const conversationJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'conversation';")
|
||||
.pluck();
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 6, 'total jobs before');
|
||||
assert.strictEqual(reactionJobs.get(), 6, 'reaction jobs before');
|
||||
assert.strictEqual(conversationJobs.get(), 0, 'conversation jobs before');
|
||||
|
||||
updateToVersion(51);
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 2, 'total jobs after');
|
||||
assert.strictEqual(reactionJobs.get(), 0, 'reaction jobs after');
|
||||
assert.strictEqual(conversationJobs.get(), 2, 'conversation jobs after');
|
||||
|
||||
const jobs = getJobsInQueueSync(db, 'conversation');
|
||||
|
||||
assert.deepEqual(jobs, [
|
||||
{
|
||||
id: 'id-1',
|
||||
timestamp: 1,
|
||||
queueType: 'conversation',
|
||||
data: {
|
||||
type: 'Reaction',
|
||||
conversationId: CONVERSATION_ID_1,
|
||||
messageId: MESSAGE_ID_1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'id-2',
|
||||
timestamp: 2,
|
||||
queueType: 'conversation',
|
||||
data: {
|
||||
type: 'Reaction',
|
||||
conversationId: CONVERSATION_ID_2,
|
||||
messageId: MESSAGE_ID_2,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('updates normal send jobs with their conversationId', () => {
|
||||
updateToVersion(50);
|
||||
|
||||
const MESSAGE_ID_1 = generateGuid();
|
||||
const MESSAGE_ID_2 = generateGuid();
|
||||
|
||||
const CONVERSATION_ID_1 = generateGuid();
|
||||
const CONVERSATION_ID_2 = generateGuid();
|
||||
|
||||
insertJobSync(db, {
|
||||
id: 'id-1',
|
||||
timestamp: 1,
|
||||
queueType: 'normal send',
|
||||
data: {
|
||||
conversationId: CONVERSATION_ID_1,
|
||||
messageId: MESSAGE_ID_1,
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-2',
|
||||
timestamp: 2,
|
||||
queueType: 'normal send',
|
||||
data: {
|
||||
conversationId: CONVERSATION_ID_2,
|
||||
messageId: MESSAGE_ID_2,
|
||||
},
|
||||
});
|
||||
insertJobSync(db, {
|
||||
id: 'id-3-missing-data',
|
||||
timestamp: 3,
|
||||
queueType: 'normal send',
|
||||
});
|
||||
|
||||
const totalJobs = db.prepare('SELECT COUNT(*) FROM jobs;').pluck();
|
||||
const normalSend = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'normal send';")
|
||||
.pluck();
|
||||
const conversationJobs = db
|
||||
.prepare("SELECT COUNT(*) FROM jobs WHERE queueType = 'conversation';")
|
||||
.pluck();
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 3, 'total jobs before');
|
||||
assert.strictEqual(normalSend.get(), 3, 'normal send jobs before');
|
||||
assert.strictEqual(conversationJobs.get(), 0, 'conversation jobs before');
|
||||
|
||||
updateToVersion(51);
|
||||
|
||||
assert.strictEqual(totalJobs.get(), 2, 'total jobs after');
|
||||
assert.strictEqual(normalSend.get(), 0, 'normal send jobs after');
|
||||
assert.strictEqual(conversationJobs.get(), 2, 'conversation jobs after');
|
||||
|
||||
const jobs = getJobsInQueueSync(db, 'conversation');
|
||||
|
||||
assert.deepEqual(jobs, [
|
||||
{
|
||||
id: 'id-1',
|
||||
timestamp: 1,
|
||||
queueType: 'conversation',
|
||||
data: {
|
||||
type: 'NormalMessage',
|
||||
conversationId: CONVERSATION_ID_1,
|
||||
messageId: MESSAGE_ID_1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'id-2',
|
||||
timestamp: 2,
|
||||
queueType: 'conversation',
|
||||
data: {
|
||||
type: 'NormalMessage',
|
||||
conversationId: CONVERSATION_ID_2,
|
||||
messageId: MESSAGE_ID_2,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user