Simplify expireTimer change handling, queue for contact sync

This commit is contained in:
Scott Nonnenberg 2022-07-11 17:32:26 -07:00 committed by GitHub
parent 50222558bf
commit 14591358f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 94 deletions

View file

@ -317,7 +317,7 @@ export async function startApp(): Promise<void> {
); );
messageReceiver.addEventListener( messageReceiver.addEventListener(
'contact', 'contact',
queuedEventListener(onContactReceived) queuedEventListener(onContactReceived, false)
); );
messageReceiver.addEventListener( messageReceiver.addEventListener(
'contactSync', 'contactSync',
@ -2718,7 +2718,9 @@ export async function startApp(): Promise<void> {
window.Whisper.events.trigger('contactSync:complete'); window.Whisper.events.trigger('contactSync:complete');
} }
async function onContactReceived(ev: ContactEvent) { // Note: Like the handling for incoming/outgoing messages, this method is synchronous,
// deferring its async logic to the function passed to conversation.queueJob().
function onContactReceived(ev: ContactEvent) {
const details = ev.contactDetails; const details = ev.contactDetails;
const c = new window.Whisper.Conversation({ const c = new window.Whisper.Conversation({
@ -2735,7 +2737,6 @@ export async function startApp(): Promise<void> {
return; return;
} }
try {
const detailsId = window.ConversationController.ensureContactIds({ const detailsId = window.ConversationController.ensureContactIds({
e164: details.number, e164: details.number,
uuid: details.uuid, uuid: details.uuid,
@ -2745,6 +2746,11 @@ export async function startApp(): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const conversation = window.ConversationController.get(detailsId)!; const conversation = window.ConversationController.get(detailsId)!;
// It's important to use queueJob here because we might update the expiration timer
// and we don't want conflicts with incoming message processing happening on the
// conversation queue.
conversation.queueJob('onContactReceived', async () => {
try {
conversation.set({ conversation.set({
name: details.name, name: details.name,
inbox_position: details.inboxPosition, inbox_position: details.inboxPosition,
@ -2773,8 +2779,7 @@ export async function startApp(): Promise<void> {
window.Signal.Data.updateConversation(conversation.attributes); window.Signal.Data.updateConversation(conversation.attributes);
// expireTimer isn't stored in Storage Service so we have to rely on the // expireTimer isn't in Storage Service so we have to rely on contact sync.
// contact sync.
const { expireTimer } = details; const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number'; const isValidExpireTimer = typeof expireTimer === 'number';
if (isValidExpireTimer) { if (isValidExpireTimer) {
@ -2786,9 +2791,12 @@ export async function startApp(): Promise<void> {
reason: 'contact sync', reason: 'contact sync',
}); });
} }
window.Whisper.events.trigger('incrementProgress');
} catch (error) { } catch (error) {
log.error('onContactReceived error:', Errors.toLogFormat(error)); log.error('onContactReceived error:', Errors.toLogFormat(error));
} }
});
} }
async function onGroupSyncComplete() { async function onGroupSyncComplete() {

View file

@ -2045,7 +2045,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
const idLog = conversation.idForLogging(); const idLog = conversation.idForLogging();
await conversation.queueJob('handleDataMessage', async () => { await conversation.queueJob('handleDataMessage', async () => {
log.info( log.info(
`handleDataMessage/${idLog}: processsing message ${message.idForLogging()}` `handleDataMessage/${idLog}: processing message ${message.idForLogging()}`
); );
if ( if (
@ -2603,26 +2603,23 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
expireTimer: initialMessage.expireTimer, expireTimer: initialMessage.expireTimer,
}, },
}); });
conversation.set({ expireTimer: dataMessage.expireTimer });
}
// NOTE: Remove once the above calls this.model.updateExpirationTimer() if (conversation.get('expireTimer') !== dataMessage.expireTimer) {
const { expireTimer } = dataMessage; log.info('Incoming expirationTimerUpdate changed timer', {
const shouldLogExpireTimerChange =
isExpirationTimerUpdate(message.attributes) || expireTimer;
if (shouldLogExpireTimerChange) {
log.info("Update conversation 'expireTimer'", {
id: conversation.idForLogging(), id: conversation.idForLogging(),
expireTimer, expireTimer: dataMessage.expireTimer || 'disabled',
source: 'handleDataMessage', source: 'handleDataMessage/expirationTimerUpdate',
});
conversation.set({
expireTimer: dataMessage.expireTimer,
}); });
} }
}
if (!isEndSession(message.attributes)) { // Note: For incoming expire timer updates (not normal messages that come
// along with an expireTimer), the conversation will be updated by this
// point and these calls will return early.
if (dataMessage.expireTimer) { if (dataMessage.expireTimer) {
if (
dataMessage.expireTimer !== conversation.get('expireTimer')
) {
conversation.updateExpirationTimer(dataMessage.expireTimer, { conversation.updateExpirationTimer(dataMessage.expireTimer, {
source, source,
receivedAt: message.get('received_at'), receivedAt: message.get('received_at'),
@ -2631,11 +2628,10 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
fromGroupUpdate: isGroupUpdate(message.attributes), fromGroupUpdate: isGroupUpdate(message.attributes),
reason: `handleDataMessage(${this.idForLogging()})`, reason: `handleDataMessage(${this.idForLogging()})`,
}); });
}
} else if ( } else if (
conversation.get('expireTimer') && // We won't turn off timers for these kinds of messages:
// We only turn off timers if it's not a group update !isGroupUpdate(message.attributes) &&
!isGroupUpdate(message.attributes) !isEndSession(message.attributes)
) { ) {
conversation.updateExpirationTimer(undefined, { conversation.updateExpirationTimer(undefined, {
source, source,
@ -2646,7 +2642,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
}); });
} }
} }
}
if (initialMessage.profileKey) { if (initialMessage.profileKey) {
const { profileKey } = initialMessage; const { profileKey } = initialMessage;

View file

@ -2885,7 +2885,7 @@ export default class MessageReceiver
envelope: ProcessedEnvelope, envelope: ProcessedEnvelope,
contacts: Proto.SyncMessage.IContacts contacts: Proto.SyncMessage.IContacts
): Promise<void> { ): Promise<void> {
log.info('MessageReceiver: handleContacts'); log.info(`MessageReceiver: handleContacts ${getEnvelopeId(envelope)}`);
const { blob } = contacts; const { blob } = contacts;
if (!blob) { if (!blob) {
throw new Error('MessageReceiver.handleContacts: blob field was missing'); throw new Error('MessageReceiver.handleContacts: blob field was missing');
@ -2924,6 +2924,7 @@ export default class MessageReceiver
groups: Proto.SyncMessage.IGroups groups: Proto.SyncMessage.IGroups
): Promise<void> { ): Promise<void> {
log.info('group sync'); log.info('group sync');
log.info(`MessageReceiver: handleGroups ${getEnvelopeId(envelope)}`);
const { blob } = groups; const { blob } = groups;
this.removeFromCache(envelope); this.removeFromCache(envelope);