Flush last conversation message save on shutdown

This commit is contained in:
Fedor Indutny 2022-04-12 11:16:58 -07:00 committed by GitHub
parent 0ccbf5e4bd
commit 42108c9ca9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 8 deletions

View file

@ -658,6 +658,17 @@ export async function startApp(): Promise<void> {
await window.waitForAllBatchers();
}
log.info('background/shutdown: flushing conversations');
// Flush debounced updates for conversations
await Promise.all(
window.ConversationController.getAll().map(convo =>
convo.flushDebouncedUpdates()
)
);
log.info('background/shutdown: waiting for all batchers');
// A number of still-to-queue database queries might be waiting inside batchers.
// We wait for these to empty first, and then shut down the data interface.
await Promise.all([
@ -665,6 +676,8 @@ export async function startApp(): Promise<void> {
window.waitForAllWaitBatchers(),
]);
log.info('background/shutdown: closing the database');
// Shut down the data interface cleanly
await window.Signal.Data.shutdown();
},

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable camelcase */
import { compact, isNumber } from 'lodash';
import { compact, isNumber, throttle, debounce } from 'lodash';
import { batch as batchDispatch } from 'react-redux';
import PQueue from 'p-queue';
@ -178,7 +178,7 @@ export class ConversationModel extends window.Backbone
contactCollection?: Backbone.Collection<ConversationModel>;
debouncedUpdateLastMessage?: () => void;
debouncedUpdateLastMessage?: (() => void) & { flush(): void };
initialPromise?: Promise<unknown>;
@ -293,14 +293,14 @@ export class ConversationModel extends window.Backbone
// our first save to the database. Or first fetch from the database.
this.initialPromise = Promise.resolve();
this.throttledBumpTyping = window._.throttle(this.bumpTyping, 300);
this.debouncedUpdateLastMessage = window._.debounce(
this.throttledBumpTyping = throttle(this.bumpTyping, 300);
this.debouncedUpdateLastMessage = debounce(
this.updateLastMessage.bind(this),
200
);
this.throttledUpdateSharedGroups =
this.throttledUpdateSharedGroups ||
window._.throttle(this.updateSharedGroups.bind(this), FIVE_MINUTES);
throttle(this.updateSharedGroups.bind(this), FIVE_MINUTES);
this.contactCollection = this.getContactCollection();
this.contactCollection.on(
@ -362,11 +362,11 @@ export class ConversationModel extends window.Backbone
// conversation for the first time.
this.isFetchingUUID = this.isSMSOnly();
this.throttledFetchSMSOnlyUUID = window._.throttle(
this.throttledFetchSMSOnlyUUID = throttle(
this.fetchSMSOnlyUUID.bind(this),
FIVE_MINUTES
);
this.throttledMaybeMigrateV1Group = window._.throttle(
this.throttledMaybeMigrateV1Group = throttle(
this.maybeMigrateV1Group.bind(this),
FIVE_MINUTES
);
@ -5465,6 +5465,18 @@ export class ConversationModel extends window.Backbone
log.info(`conversation ${this.idForLogging()} open took ${delta}ms`);
window.CI?.handleEvent('conversation:open', { delta });
}
async flushDebouncedUpdates(): Promise<void> {
try {
await this.debouncedUpdateLastMessage?.flush();
} catch (error) {
const logId = this.idForLogging();
log.error(
`flushDebouncedUpdates(${logId}): got error`,
Errors.toLogFormat(error)
);
}
}
}
window.Whisper.Conversation = ConversationModel;

View file

@ -3133,8 +3133,10 @@ function removeUnprocessedSync(id: string | Array<string>): void {
return;
}
// This can happen normally due to flushing of `cacheRemoveBatcher` in
// MessageReceiver.
if (!id.length) {
throw new Error('removeUnprocessedSync: No ids to delete!');
return;
}
assertSync(batchMultiVarQuery(db, id, removeUnprocessedsSync));