From 5c8e2b40444e6f9897844f0de044c1bad20b8714 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 21 Apr 2022 14:04:11 +1000 Subject: [PATCH] cleanup swarm unused after removing unused convos --- ts/components/SessionPasswordPrompt.tsx | 3 + ts/models/conversation.ts | 18 +++--- ts/models/message.ts | 18 +++--- ts/node/sql.ts | 61 ++++++++++++++++--- .../conversations/ConversationController.ts | 2 +- 5 files changed, 78 insertions(+), 24 deletions(-) diff --git a/ts/components/SessionPasswordPrompt.tsx b/ts/components/SessionPasswordPrompt.tsx index 1764c5d0f..afc14e383 100644 --- a/ts/components/SessionPasswordPrompt.tsx +++ b/ts/components/SessionPasswordPrompt.tsx @@ -130,6 +130,9 @@ class SessionPasswordPromptInner extends React.PureComponent<{}, State> { }); this.setState({ error }); + global.setTimeout(() => { + document.getElementById('password-prompt-input')?.focus(); + }, 50); } this.setState({ loading: false, diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index dcf5cf02e..d50597ca8 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1741,14 +1741,18 @@ export class ConversationModel extends Backbone.Model { } } -const trotthledAllConversationsDispatch = _.debounce(() => { - if (updatesToDispatch.size === 0) { - return; - } - window.inboxStore?.dispatch(conversationsChanged([...updatesToDispatch.values()])); +const trotthledAllConversationsDispatch = _.debounce( + () => { + if (updatesToDispatch.size === 0) { + return; + } + window.inboxStore?.dispatch(conversationsChanged([...updatesToDispatch.values()])); - updatesToDispatch.clear(); -}, 2000); + updatesToDispatch.clear(); + }, + 2000, + { maxWait: 5000, trailing: true } +); const updatesToDispatch: Map = new Map(); diff --git a/ts/models/message.ts b/ts/models/message.ts index 886d54166..f6332ccf2 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1313,13 +1313,17 @@ export class MessageModel extends Backbone.Model { } } -const trotthledAllMessagesDispatch = _.debounce(() => { - if (updatesToDispatch.size === 0) { - return; - } - window.inboxStore?.dispatch(messagesChanged([...updatesToDispatch.values()])); - updatesToDispatch.clear(); -}, 2000); +const trotthledAllMessagesDispatch = _.debounce( + () => { + if (updatesToDispatch.size === 0) { + return; + } + window.inboxStore?.dispatch(messagesChanged([...updatesToDispatch.values()])); + updatesToDispatch.clear(); + }, + 2000, + { trailing: true, maxWait: 5000 } +); const updatesToDispatch: Map = new Map(); export class MessageCollection extends Backbone.Collection {} diff --git a/ts/node/sql.ts b/ts/node/sql.ts index d6ab5126a..9a434b633 100644 --- a/ts/node/sql.ts +++ b/ts/node/sql.ts @@ -6,6 +6,7 @@ import { app, clipboard, dialog, Notification } from 'electron'; import { chunk, + difference, flattenDeep, forEach, fromPairs, @@ -214,12 +215,10 @@ function vacuumDatabase(db: BetterSqlite3.Database) { if (!db) { throw new Error('vacuum: db is not initialized'); } - console.time('vaccumming db'); const start = Date.now(); console.info('Vacuuming DB. This might take a while.'); db.exec('VACUUM;'); console.info(`Vacuuming DB Finished in ${Date.now() - start}ms.`); - console.timeEnd('vaccumming db'); } function updateToSchemaVersion1(currentVersion: number, db: BetterSqlite3.Database) { @@ -1401,6 +1400,7 @@ function assertGlobalInstanceOrInstance( let databaseFilePath: string | undefined; +// tslint:disable-next-line: function-name function _initializePaths(configDir: string) { const dbDir = path.join(configDir, 'sql'); fs.mkdirSync(dbDir, { recursive: true }); @@ -1473,6 +1473,7 @@ async function initializeSql({ console.info('total message count before cleaning: ', getMessageCount()); console.info('total conversation count before cleaning: ', getConversationCount()); cleanUpOldOpengroups(); + cleanUpUnusedNodeForKeyEntries(); printDbStats(); console.info('total message count after cleaning: ', getMessageCount()); @@ -3360,18 +3361,19 @@ function removeV2OpenGroupRoom(conversationId: string) { }); } -function printDbStats() { - // const tables = assertGlobalInstance() - // .prepare(`SELECT distinct * from sqlite_master order by 1`) - // .all(); - - function getCount(tbl: string) { +function getEntriesCountInTable(tbl: string) { + try { const row = assertGlobalInstance() .prepare(`SELECT count(*) from ${tbl};`) .get(); return row['count(*)']; + } catch (e) { + console.warn(e); + return 0; } +} +function printDbStats() { [ 'attachment_downloads', 'conversations', @@ -3396,10 +3398,50 @@ function printDbStats() { 'sqlite_stat4', 'unprocessed', ].forEach(i => { - console.warn(`${i} count`, getCount(i)); + console.log(`${i} count`, getEntriesCountInTable(i)); }); } +/** + * Remove all the unused entries in the snodes for pubkey table. + * This table is used to know which snodes we should contact to send a message to a recipient + */ +function cleanUpUnusedNodeForKeyEntries() { + // we have to allow private and closed group entries + const allIdsToKeep = + assertGlobalInstance() + .prepare( + `SELECT id FROM ${CONVERSATIONS_TABLE} WHERE id NOT LIKE 'publicChat:1@%' + ` + ) + .all() + .map(m => m.id) || []; + + const allEntriesInSnodeForPubkey = + assertGlobalInstance() + .prepare(`SELECT pubkey FROM ${NODES_FOR_PUBKEY_TABLE};`) + .all() + .map(m => m.pubkey) || []; + + const swarmUnused = difference(allEntriesInSnodeForPubkey, allIdsToKeep); + + console.log('swarmStored but unused ', swarmUnused.length); + if (swarmUnused.length) { + const start = Date.now(); + + const chunks = chunk(swarmUnused, 500); + chunks.forEach(ch => { + assertGlobalInstance() + .prepare( + `DELETE FROM ${NODES_FOR_PUBKEY_TABLE} WHERE pubkey IN (${ch.map(() => '?').join(',')});` + ) + .run(ch); + }); + + console.log(`Removing of ${swarmUnused.length} unused swarms took ${Date.now() - start}ms`); + } +} + function cleanUpOldOpengroups() { const v2Convos = getAllOpenGroupV2Conversations(); @@ -3491,6 +3533,7 @@ function cleanUpOldOpengroups() { } completely inactive convos done in ${Date.now() - start}ms` ); } + rebuildFtsTable(assertGlobalInstance()); } diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index df0876080..b0a0b4c67 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -119,7 +119,7 @@ export class ConversationController { }) ); } - if (!conversation.isPublic()) { + if (!conversation.isPublic() && conversation.isActive()) { // NOTE: we request snodes updating the cache, but ignore the result void getSwarmFor(id);