mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-02-14 23:18:54 +00:00
Avoid race when downloading group avatars post-import
This commit is contained in:
@@ -11,6 +11,8 @@ import type { JOB_STATUS } from './JobQueue.std.js';
|
||||
import { JobQueue } from './JobQueue.std.js';
|
||||
import { jobQueueDatabaseStore } from './JobQueueDatabaseStore.preload.js';
|
||||
import { parseUnknown } from '../util/schemas.std.js';
|
||||
import { waitForOnline } from '../util/waitForOnline.dom.js';
|
||||
import { isOnline } from '../textsecure/WebAPI.preload.js';
|
||||
|
||||
const groupAvatarJobDataSchema = z.object({
|
||||
conversationId: z.string(),
|
||||
@@ -29,6 +31,8 @@ export class GroupAvatarJobQueue extends JobQueue<GroupAvatarJobData> {
|
||||
{ attempt, log }: Readonly<{ attempt: number; log: LoggerType }>
|
||||
): Promise<typeof JOB_STATUS.NEEDS_RETRY | undefined> {
|
||||
const { conversationId, newAvatarUrl } = data;
|
||||
await waitForOnline({ server: { isOnline } });
|
||||
|
||||
const logId = `groupAvatarJobQueue(${conversationId}, attempt=${attempt})`;
|
||||
|
||||
const convo = window.ConversationController.get(conversationId);
|
||||
@@ -43,15 +47,21 @@ export class GroupAvatarJobQueue extends JobQueue<GroupAvatarJobData> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Generate correct attributes patch
|
||||
const patch = await applyNewAvatar({
|
||||
newAvatarUrl,
|
||||
attributes,
|
||||
logId,
|
||||
});
|
||||
await convo.queueJob('GroupAvatarJobQueue', async () => {
|
||||
if (convo.attributes.remoteAvatarUrl !== newAvatarUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
convo.set(patch);
|
||||
await DataWriter.updateConversation(convo.attributes);
|
||||
// Generate correct attributes patch
|
||||
const patch = await applyNewAvatar({
|
||||
newAvatarUrl,
|
||||
attributes,
|
||||
logId,
|
||||
});
|
||||
|
||||
convo.set(patch);
|
||||
await DataWriter.updateConversation(convo.attributes);
|
||||
});
|
||||
|
||||
return undefined;
|
||||
}
|
||||
@@ -60,5 +70,5 @@ export class GroupAvatarJobQueue extends JobQueue<GroupAvatarJobData> {
|
||||
export const groupAvatarJobQueue = new GroupAvatarJobQueue({
|
||||
store: jobQueueDatabaseStore,
|
||||
queueType: 'groupAvatar',
|
||||
maxAttempts: 25,
|
||||
maxAttempts: 5,
|
||||
});
|
||||
|
||||
@@ -279,7 +279,6 @@ export class BackupImportStream extends Writable {
|
||||
#customColorById = new Map<number, CustomColorDataType>();
|
||||
#releaseNotesRecipientId: Long | undefined;
|
||||
#releaseNotesChatId: Long | undefined;
|
||||
#pendingGroupAvatars = new Map<string, string>();
|
||||
#pinnedMessages: Array<PinnedMessageParams> = [];
|
||||
#frameErrorCount: number = 0;
|
||||
#backupTier: BackupLevel | undefined;
|
||||
@@ -422,7 +421,19 @@ export class BackupImportStream extends Writable {
|
||||
// conversation's last message, which uses redux selectors)
|
||||
await loadAllAndReinitializeRedux();
|
||||
|
||||
const allConversations = window.ConversationController.getAll();
|
||||
const allConversations = window.ConversationController.getAll().sort(
|
||||
(convoA, convoB) => {
|
||||
if (convoA.get('isPinned')) {
|
||||
return -1;
|
||||
}
|
||||
if (convoB.get('isPinned')) {
|
||||
return 1;
|
||||
}
|
||||
return (
|
||||
(convoB.get('active_at') ?? 0) - (convoA.get('active_at') ?? 0)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Update last message in every active conversation now that we have
|
||||
// them loaded into memory.
|
||||
@@ -445,12 +456,21 @@ export class BackupImportStream extends Writable {
|
||||
|
||||
// Schedule group avatar download.
|
||||
await pMap(
|
||||
[...this.#pendingGroupAvatars.entries()],
|
||||
async ([conversationId, newAvatarUrl]) => {
|
||||
allConversations,
|
||||
async conversation => {
|
||||
if (this.options.type === 'cross-client-integration-test') {
|
||||
return;
|
||||
}
|
||||
await groupAvatarJobQueue.add({ conversationId, newAvatarUrl });
|
||||
if (
|
||||
!isGroup(conversation.attributes) ||
|
||||
!conversation.get('remoteAvatarUrl')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await groupAvatarJobQueue.add({
|
||||
conversationId: conversation.get('id'),
|
||||
newAvatarUrl: conversation.get('remoteAvatarUrl'),
|
||||
});
|
||||
},
|
||||
{ concurrency: MAX_CONCURRENCY }
|
||||
);
|
||||
@@ -1218,6 +1238,7 @@ export class BackupImportStream extends Writable {
|
||||
url: avatarUrl,
|
||||
}
|
||||
: undefined,
|
||||
remoteAvatarUrl: dropNull(avatarUrl),
|
||||
color: fromAvatarColor(group.avatarColor),
|
||||
colorFromPrimary: dropNull(group.avatarColor),
|
||||
|
||||
@@ -1319,9 +1340,7 @@ export class BackupImportStream extends Writable {
|
||||
: undefined,
|
||||
announcementsOnly: dropNull(announcementsOnly),
|
||||
};
|
||||
if (avatarUrl) {
|
||||
this.#pendingGroupAvatars.set(attrs.id, avatarUrl);
|
||||
}
|
||||
|
||||
if (group.blocked) {
|
||||
await itemStorage.blocked.addBlockedGroup(groupId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user