Improve story DOE flow

This commit is contained in:
Fedor Indutny 2022-11-28 18:07:26 -08:00 committed by GitHub
parent 5e9744d62a
commit 37d383f344
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 630 additions and 245 deletions

View file

@ -8,10 +8,7 @@ import * as log from '../logging/log';
import { Deletes } from '../messageModifiers/Deletes';
import { SendStatus } from '../messages/MessageSendState';
import { deleteForEveryone } from './deleteForEveryone';
import {
getConversationIdForLogging,
getMessageIdForLogging,
} from './idForLogging';
import { getConversationIdForLogging } from './idForLogging';
import { isStory } from '../state/selectors/message';
import { normalizeUuid } from './normalizeUuid';
import { queueUpdateMessage } from './messageBatcher';
@ -25,8 +22,10 @@ export async function onStoryRecipientUpdate(
const conversation = window.ConversationController.get(destinationUuid);
const logId = `onStoryRecipientUpdate(${destinationUuid}, ${timestamp})`;
if (!conversation) {
log.info(`onStoryRecipientUpdate no conversation for ${destinationUuid}`);
log.info(`${logId}: no conversation`);
return;
}
@ -37,20 +36,16 @@ export async function onStoryRecipientUpdate(
);
if (!targetConversation) {
log.info('onStoryRecipientUpdate !targetConversation', {
destinationUuid,
timestamp,
});
log.info(`${logId}: no targetConversation`);
return;
}
targetConversation.queueJob('onStoryRecipientUpdate', async () => {
log.info('onStoryRecipientUpdate updating', timestamp);
targetConversation.queueJob(logId, async () => {
log.info(`${logId}: updating`);
// Build up some maps for fast/easy lookups
const isAllowedToReply = new Map<string, boolean>();
const conversationIdToDistributionListIds = new Map<string, Set<string>>();
const distributionListIdToConversationIds = new Map<string, Set<string>>();
data.storyMessageRecipients.forEach(item => {
const convo = window.ConversationController.get(item.destinationUuid);
@ -58,14 +53,16 @@ export async function onStoryRecipientUpdate(
return;
}
conversationIdToDistributionListIds.set(
convo.id,
new Set(
item.distributionListIds.map(uuid =>
normalizeUuid(uuid, 'onStoryRecipientUpdate.distributionListId')
)
)
);
for (const rawUuid of item.distributionListIds) {
const uuid = normalizeUuid(rawUuid, `${logId}.distributionListId`);
const existing = distributionListIdToConversationIds.get(uuid);
if (existing === undefined) {
distributionListIdToConversationIds.set(uuid, new Set([convo.id]));
} else {
existing.add(convo.id);
}
}
isAllowedToReply.set(convo.id, item.isAllowedToReply !== false);
});
@ -87,55 +84,60 @@ export async function onStoryRecipientUpdate(
return false;
}
const newConversationIds =
distributionListIdToConversationIds.get(storyDistributionListId) ??
new Set();
const nextSendStateByConversationId = {
...sendStateByConversationId,
};
conversationIdToDistributionListIds.forEach(
(distributionListIds, conversationId) => {
const hasDistributionListId = distributionListIds.has(
storyDistributionListId
);
// Find conversation ids present in the local send state, but missing
// in the remote state, and remove them from the local state.
for (const oldId of Object.keys(sendStateByConversationId)) {
if (!newConversationIds.has(oldId)) {
const recipient = window.ConversationController.get(oldId);
const recipient = window.ConversationController.get(conversationId);
const conversationIdForLogging = recipient
const recipientLogId = recipient
? getConversationIdForLogging(recipient.attributes)
: conversationId;
: oldId;
if (
hasDistributionListId &&
!sendStateByConversationId[conversationId]
) {
log.info('onStoryRecipientUpdate adding', {
conversationId: conversationIdForLogging,
messageId: getMessageIdForLogging(item),
storyDistributionListId,
});
nextSendStateByConversationId[conversationId] = {
isAllowedToReplyToStory: Boolean(
isAllowedToReply.get(conversationId)
),
status: SendStatus.Sent,
updatedAt: now,
};
} else if (
sendStateByConversationId[conversationId] &&
!hasDistributionListId
) {
log.info('onStoryRecipientUpdate removing', {
conversationId: conversationIdForLogging,
messageId: getMessageIdForLogging(item),
storyDistributionListId,
});
delete nextSendStateByConversationId[conversationId];
}
log.info(`${logId}: removing`, {
recipient: recipientLogId,
messageId: item.id,
storyDistributionListId,
});
delete nextSendStateByConversationId[oldId];
}
);
}
// Find conversation ids present in the remote send state, but missing in
// the local send state, and add them to the local state.
for (const newId of newConversationIds) {
if (sendStateByConversationId[newId] === undefined) {
const recipient = window.ConversationController.get(newId);
const recipientLogId = recipient
? getConversationIdForLogging(recipient.attributes)
: newId;
log.info(`${logId}: adding`, {
recipient: recipientLogId,
messageId: item.id,
storyDistributionListId,
});
nextSendStateByConversationId[newId] = {
isAllowedToReplyToStory: Boolean(isAllowedToReply.get(newId)),
status: SendStatus.Sent,
updatedAt: now,
};
}
}
if (isEqual(sendStateByConversationId, nextSendStateByConversationId)) {
log.info(
'onStoryRecipientUpdate: sendStateByConversationId does not need update'
);
log.info(`${logId}: sendStateByConversationId does not need update`, {
messageId: item.id,
});
return true;
}
@ -150,8 +152,8 @@ export async function onStoryRecipientUpdate(
(sendStateConversationIds.size === 1 &&
sendStateConversationIds.has(ourConversationId))
) {
log.info('onStoryRecipientUpdate DOE', {
messageId: getMessageIdForLogging(item),
log.info(`${logId} DOE`, {
messageId: item.id,
storyDistributionListId,
});
const delAttributes: DeleteAttributesType = {