Reenable FTS optimization

This commit is contained in:
Fedor Indutny 2023-09-03 01:03:19 +02:00 committed by Fedor Indutnyy
parent 372d9c2198
commit b6ed789197
10 changed files with 195 additions and 8 deletions

View file

@ -93,6 +93,7 @@ import type {
DeleteSentProtoRecipientResultType,
EditedMessageType,
EmojiType,
FTSOptimizationStateType,
GetAllStoriesResultType,
GetConversationRangeCenteredOnMessageResultType,
GetKnownMessageAttachmentsResultType,
@ -402,6 +403,8 @@ const dataInterface: ServerInterface = {
getStatisticsForLogging,
optimizeFTS,
// Server-only
initialize,
@ -2219,6 +2222,7 @@ async function _removeAllMessages(): Promise<void> {
const db = getInstance();
db.exec(`
DELETE FROM messages;
INSERT INTO messages_fts(messages_fts) VALUES('optimize');
`);
}
@ -5544,6 +5548,8 @@ async function removeAll(): Promise<void> {
DELETE FROM unprocessed;
DELETE FROM uninstalled_sticker_packs;
INSERT INTO messages_fts(messages_fts) VALUES('optimize');
--- Re-create the messages delete trigger
--- See migration 45
CREATE TRIGGER messages_on_delete AFTER DELETE ON messages BEGIN
@ -6127,6 +6133,48 @@ async function removeKnownDraftAttachments(
return Object.keys(lookup);
}
const OPTIMIZE_FTS_PAGE_COUNT = 64;
// This query is incremental. It gets the `state` from the return value of
// previous `optimizeFTS` call. When `state.done` is `true` - optimization is
// complete.
async function optimizeFTS(
state?: FTSOptimizationStateType
): Promise<FTSOptimizationStateType | undefined> {
// See https://www.sqlite.org/fts5.html#the_merge_command
let pageCount = OPTIMIZE_FTS_PAGE_COUNT;
if (state === undefined) {
pageCount = -pageCount;
}
const db = getInstance();
const getChanges = prepare(db, 'SELECT total_changes() as changes;', {
pluck: true,
});
const changeDifference = db.transaction(() => {
const before: number = getChanges.get({});
prepare(
db,
`
INSERT INTO messages_fts(messages_fts, rank) VALUES ('merge', $pageCount);
`
).run({ pageCount });
const after: number = getChanges.get({});
return after - before;
})();
const nextSteps = (state?.steps ?? 0) + 1;
// From documentation:
// "If the difference is less than 2, then the 'merge' command was a no-op"
const done = changeDifference < 2;
return { steps: nextSteps, done };
}
async function getJobsInQueue(queueType: string): Promise<Array<StoredJob>> {
const db = getInstance();
return getJobsInQueueSync(db, queueType);