Fix change counter check in fts optimization

This commit is contained in:
Fedor Indutny 2023-01-25 13:22:13 -08:00 committed by GitHub
parent f751687af3
commit 78a33f28c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 34 deletions

View file

@ -361,7 +361,6 @@ export type GetAllStoriesResultType = ReadonlyArray<
>; >;
export type FTSOptimizationStateType = Readonly<{ export type FTSOptimizationStateType = Readonly<{
changes: number;
steps: number; steps: number;
done?: boolean; done?: boolean;
}>; }>;

View file

@ -364,7 +364,8 @@ const statementCache = new WeakMap<Database, DatabaseQueryCache>();
function prepare<T extends Array<unknown> | Record<string, unknown>>( function prepare<T extends Array<unknown> | Record<string, unknown>>(
db: Database, db: Database,
query: string query: string,
{ pluck = false }: { pluck?: boolean } = {}
): Statement<T> { ): Statement<T> {
let dbCache = statementCache.get(db); let dbCache = statementCache.get(db);
if (!dbCache) { if (!dbCache) {
@ -372,10 +373,14 @@ function prepare<T extends Array<unknown> | Record<string, unknown>>(
statementCache.set(db, dbCache); statementCache.set(db, dbCache);
} }
let result = dbCache.get(query) as Statement<T>; const cacheKey = `${pluck}:${query}`;
let result = dbCache.get(cacheKey) as Statement<T>;
if (!result) { if (!result) {
result = db.prepare<T>(query); result = db.prepare<T>(query);
dbCache.set(query, result); if (pluck === true) {
result.pluck();
}
dbCache.set(cacheKey, result);
} }
return result; return result;
@ -1077,10 +1082,9 @@ async function deleteSentProtoRecipient(
` `
SELECT count(1) FROM sendLogRecipients SELECT count(1) FROM sendLogRecipients
WHERE payloadId = $id AND recipientUuid = $recipientUuid; WHERE payloadId = $id AND recipientUuid = $recipientUuid;
` `,
) { pluck: true }
.pluck(true) ).get({ id, recipientUuid });
.get({ id, recipientUuid });
// 4. If there are no remaining devices for this recipient and we included // 4. If there are no remaining devices for this recipient and we included
// the pni signature in the proto - return the recipient to the caller. // the pni signature in the proto - return the recipient to the caller.
@ -1101,10 +1105,9 @@ async function deleteSentProtoRecipient(
// 5. See how many more recipients there were for this payload. // 5. See how many more recipients there were for this payload.
const remainingTotal = prepare( const remainingTotal = prepare(
db, db,
'SELECT count(1) FROM sendLogRecipients WHERE payloadId = $id;' 'SELECT count(1) FROM sendLogRecipients WHERE payloadId = $id;',
) { pluck: true }
.pluck(true) ).get({ id });
.get({ id });
strictAssert( strictAssert(
isNumber(remainingTotal), isNumber(remainingTotal),
@ -5408,9 +5411,7 @@ async function removeKnownDraftAttachments(
return Object.keys(lookup); return Object.keys(lookup);
} }
// Default value of 'automerge'. const OPTIMIZE_FTS_PAGE_COUNT = 64;
// See: https://www.sqlite.org/fts5.html#the_automerge_configuration_option
const OPTIMIZE_FTS_PAGE_COUNT = 4;
// This query is incremental. It gets the `state` from the return value of // This query is incremental. It gets the `state` from the return value of
// previous `optimizeFTS` call. When `state.done` is `true` - optimization is // previous `optimizeFTS` call. When `state.done` is `true` - optimization is
@ -5423,30 +5424,33 @@ async function optimizeFTS(
if (state === undefined) { if (state === undefined) {
pageCount = -pageCount; pageCount = -pageCount;
} }
const db = getInstance(); const db = getInstance();
const { changes } = prepare( const getChanges = prepare(db, 'SELECT total_changes() as changes;', {
db, pluck: true,
` });
INSERT INTO messages_fts(messages_fts, rank) VALUES ('merge', $pageCount);
`
).run({ pageCount });
if (state === undefined) { const changeDifference = db.transaction(() => {
return { const before: number = getChanges.get({});
changes,
steps: 1,
};
}
const { changes: prevChanges, steps } = state; prepare(
db,
`
INSERT INTO messages_fts(messages_fts, rank) VALUES ('merge', $pageCount);
`
).run({ pageCount });
if (Math.abs(changes - prevChanges) < 2) { const after: number = getChanges.get({});
return { changes, steps, done: true };
}
// More work is needed. return after - before;
return { changes, steps: steps + 1 }; })();
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>> { async function getJobsInQueue(queueType: string): Promise<Array<StoredJob>> {