From 3d6e22f2fe052119bff557b5dec7531185660342 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 12 Feb 2024 11:44:45 +1100 Subject: [PATCH] fix: cleanup DaR unread messages after 14d --- ts/node/migration/sessionMigrations.ts | 21 +++++++++++++++++++++ ts/node/sql.ts | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ts/node/migration/sessionMigrations.ts b/ts/node/migration/sessionMigrations.ts index 1c949d7b0..e000ed1b8 100644 --- a/ts/node/migration/sessionMigrations.ts +++ b/ts/node/migration/sessionMigrations.ts @@ -104,6 +104,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToSessionSchemaVersion33, updateToSessionSchemaVersion34, updateToSessionSchemaVersion35, + updateToSessionSchemaVersion36, ]; function updateToSessionSchemaVersion1(currentVersion: number, db: BetterSqlite3.Database) { @@ -1928,6 +1929,26 @@ function updateToSessionSchemaVersion35(currentVersion: number, db: BetterSqlite console.log(`updateToSessionSchemaVersion${targetVersion}: success!`); } +function updateToSessionSchemaVersion36(currentVersion: number, db: BetterSqlite3.Database) { + const targetVersion = 36; + if (currentVersion >= targetVersion) { + return; + } + + console.log(`updateToSessionSchemaVersion${targetVersion}: starting...`); + + db.transaction(() => { + db.exec(`CREATE INDEX messages_DaR_unread_sent_at ON ${MESSAGES_TABLE} ( + expirationType, + unread, + sent_at + );`); + writeSessionSchemaVersion(targetVersion, db); + })(); + + console.log(`updateToSessionSchemaVersion${targetVersion}: success!`); +} + export function printTableColumns(table: string, db: BetterSqlite3.Database) { console.info(db.pragma(`table_info('${table}');`)); } diff --git a/ts/node/sql.ts b/ts/node/sql.ts index 3f0cc08c3..52a12d6e0 100644 --- a/ts/node/sql.ts +++ b/ts/node/sql.ts @@ -64,6 +64,7 @@ import { KNOWN_BLINDED_KEYS_ITEM, SettingsKey } from '../data/settings-key'; import { MessageAttributes } from '../models/messageType'; import { SignalService } from '../protobuf'; import { Quote } from '../receiver/types'; +import { DURATION } from '../session/constants'; import { getSQLCipherIntegrityCheck, openAndMigrateDatabase, @@ -192,6 +193,7 @@ async function initializeSql({ console.info('total conversation count before cleaning: ', getConversationCount()); cleanUpOldOpengroupsOnStart(); cleanUpUnusedNodeForKeyEntriesOnStart(); + cleanUpUnreadExpiredDaRMessages(); printDbStats(); console.info('total message count after cleaning: ', getMessageCount()); @@ -1614,6 +1616,28 @@ function getExpiredMessages() { return map(rows, row => jsonToObject(row.json)); } +function cleanUpUnreadExpiredDaRMessages() { + // we cannot rely on network offset here, so we need to trust the user clock + const t14daysEarlier = Date.now() - 14 * DURATION.DAYS; + const start = Date.now(); + const deleted = assertGlobalInstance() + .prepare( + `DELETE FROM ${MESSAGES_TABLE} WHERE + expirationType = 'deleteAfterRead' AND + unread = $unread AND + sent_at <= $t14daysEarlier;` + ) + .run({ + unread: toSqliteBoolean(true), + t14daysEarlier, + }); + console.info( + `cleanUpUnreadExpiredDaRMessages: deleted ${ + deleted.changes + } message(s) which were DaR and sent before ${t14daysEarlier} in ${Date.now() - start}ms` + ); +} + function getOutgoingWithoutExpiresAt() { const rows = assertGlobalInstance() .prepare(