From 3c380d35fdb9d7184f9070d4681af1a681273ff1 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 1 May 2024 16:23:59 -0400 Subject: [PATCH] Attempt to reduce impact of thread updates. --- .../conversation/drafts/DraftViewModel.kt | 32 ++++---- .../securesms/database/MessageTable.kt | 73 +------------------ .../securesms/database/MmsSmsDatabaseTest.kt | 1 + 3 files changed, 21 insertions(+), 85 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt index 5e558dee8f..fb73761799 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt @@ -38,7 +38,7 @@ class DraftViewModel @JvmOverloads constructor( fun saveEphemeralVoiceNoteDraft(draft: Draft) { store.update { draftState -> - saveDrafts(draftState.copy(voiceNoteDraft = draft)) + saveDraftsIfChanged(draftState, draftState.copy(voiceNoteDraft = draft)) } } @@ -49,7 +49,7 @@ class DraftViewModel @JvmOverloads constructor( fun deleteVoiceNoteDraft() { store.update { repository.deleteVoiceNoteDraftData(it.voiceNoteDraft) - saveDrafts(it.copy(voiceNoteDraft = null)) + saveDraftsIfChanged(it, it.copy(voiceNoteDraft = null)) } } @@ -65,13 +65,13 @@ class DraftViewModel @JvmOverloads constructor( styleBodyRanges.newBuilder().apply { ranges += mentionRanges.ranges }.build() } - saveDrafts(it.copy(textDraft = text.toTextDraft(), bodyRangesDraft = bodyRanges?.toDraft(), messageEditDraft = Draft(Draft.MESSAGE_EDIT, messageId.serialize()))) + saveDraftsIfChanged(it, it.copy(textDraft = text.toTextDraft(), bodyRangesDraft = bodyRanges?.toDraft(), messageEditDraft = Draft(Draft.MESSAGE_EDIT, messageId.serialize()))) } } fun deleteMessageEditDraft() { store.update { - saveDrafts(it.copy(textDraft = null, bodyRangesDraft = null, messageEditDraft = null)) + saveDraftsIfChanged(it, it.copy(textDraft = null, bodyRangesDraft = null, messageEditDraft = null)) } } @@ -87,49 +87,53 @@ class DraftViewModel @JvmOverloads constructor( styleBodyRanges.newBuilder().apply { ranges += mentionRanges.ranges }.build() } - saveDrafts(it.copy(textDraft = text.toTextDraft(), bodyRangesDraft = bodyRanges?.toDraft())) + saveDraftsIfChanged(it, it.copy(textDraft = text.toTextDraft(), bodyRangesDraft = bodyRanges?.toDraft())) } } fun setLocationDraft(place: SignalPlace) { store.update { - saveDrafts(it.copy(locationDraft = Draft(Draft.LOCATION, place.serialize() ?: ""))) + saveDraftsIfChanged(it, it.copy(locationDraft = Draft(Draft.LOCATION, place.serialize() ?: ""))) } } fun clearLocationDraft() { store.update { - saveDrafts(it.copy(locationDraft = null)) + saveDraftsIfChanged(it, it.copy(locationDraft = null)) } } fun setQuoteDraft(id: Long, author: RecipientId) { store.update { - saveDrafts(it.copy(quoteDraft = Draft(Draft.QUOTE, QuoteId(id, author).serialize()))) + saveDraftsIfChanged(it, it.copy(quoteDraft = Draft(Draft.QUOTE, QuoteId(id, author).serialize()))) } } fun clearQuoteDraft() { store.update { - saveDrafts(it.copy(quoteDraft = null)) + saveDraftsIfChanged(it, it.copy(quoteDraft = null)) } } fun onSendComplete(threadId: Long = store.state.threadId) { repository.deleteVoiceNoteDraftData(store.state.voiceNoteDraft) - store.update { saveDrafts(it.copyAndClearDrafts(threadId)) } + store.update { saveDraftsIfChanged(it, it.copyAndClearDrafts(threadId)) } } - private fun saveDrafts(state: DraftState): DraftState { - repository.saveDrafts(state.threadId, state.toDrafts()) - return state + private fun saveDraftsIfChanged(oldState: DraftState, newState: DraftState): DraftState { + if (oldState == newState) { + return oldState + } + + repository.saveDrafts(newState.threadId, newState.toDrafts()) + return newState } fun loadShareOrDraftData(lastShareDataTimestamp: Long): Maybe { return repository.getShareOrDraftData(lastShareDataTimestamp) .doOnSuccess { (_, drafts) -> if (drafts != null) { - store.update { saveDrafts(it.copyAndSetDrafts(drafts = drafts)) } + store.update { saveDraftsIfChanged(it, it.copyAndSetDrafts(drafts = drafts)) } } } .flatMap { (data, _) -> diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index 97f088fbe8..895469d33e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -29,7 +29,6 @@ import org.json.JSONObject import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil -import org.signal.core.util.SqlUtil.appendArg import org.signal.core.util.SqlUtil.buildArgs import org.signal.core.util.SqlUtil.buildCustomCollectionQuery import org.signal.core.util.SqlUtil.buildSingleCollectionQuery @@ -395,7 +394,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat $TYPE, $DATE_RECEIVED FROM - $TABLE_NAME + $TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID WHERE $THREAD_ID = ? AND $TYPE & ${MessageTypes.GROUP_V2_LEAVE_BITS} != ${MessageTypes.GROUP_V2_LEAVE_BITS} AND @@ -1849,14 +1848,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } private fun rawQueryWithAttachments(where: String, arguments: Array?, reverse: Boolean = false, limit: Long = 0): Cursor { - return rawQueryWithAttachments(MMS_PROJECTION_WITH_ATTACHMENTS, where, arguments, reverse, limit) - } - - private fun rawQueryWithAttachments(projection: Array, where: String, arguments: Array?, reverse: Boolean, limit: Long): Cursor { val database = databaseHelper.signalReadableDatabase var rawQueryString = """ SELECT - ${Util.join(projection, ",")} + ${Util.join(MMS_PROJECTION_WITH_ATTACHMENTS, ",")} FROM $TABLE_NAME LEFT OUTER JOIN ${AttachmentTable.TABLE_NAME} ON ($TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID}) WHERE @@ -1947,17 +1942,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } } - fun markAsOutbox(messageId: Long) { - val threadId = getThreadIdForMessage(messageId) - updateMailboxBitmask(messageId, MessageTypes.BASE_TYPE_MASK, MessageTypes.BASE_OUTBOX_TYPE, Optional.of(threadId)) - } - - fun markAsForcedSms(messageId: Long) { - val threadId = getThreadIdForMessage(messageId) - updateMailboxBitmask(messageId, MessageTypes.PUSH_MESSAGE_BIT, MessageTypes.MESSAGE_FORCE_SMS_BIT, Optional.of(threadId)) - ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(MessageId(messageId)) - } - fun markAsRateLimited(messageId: Long) { val threadId = getThreadIdForMessage(messageId) updateMailboxBitmask(messageId, 0, MessageTypes.MESSAGE_RATE_LIMITED_BIT, Optional.of(threadId)) @@ -3384,59 +3368,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat return ids } - fun getUnexportedInsecureMessages(limit: Int): Cursor { - return rawQueryWithAttachments( - projection = appendArg(MMS_PROJECTION_WITH_ATTACHMENTS, EXPORT_STATE), - where = "${getInsecureMessageClause()} AND NOT $EXPORTED", - arguments = null, - reverse = false, - limit = limit.toLong() - ) - } - - fun getUnexportedInsecureMessagesEstimatedSize(): Long { - val bodyTextSize: Long = readableDatabase - .select("SUM(LENGTH($BODY))") - .from(TABLE_NAME) - .where("${getInsecureMessageClause()} AND $EXPORTED < ?", MessageExportStatus.EXPORTED) - .run() - .readToSingleLong() - - val fileSize: Long = readableDatabase.rawQuery( - """ - SELECT - SUM(${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_SIZE}) AS s - FROM - $TABLE_NAME INNER JOIN ${AttachmentTable.TABLE_NAME} ON $TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID} - WHERE - ${getInsecureMessageClause()} AND $EXPORTED < ${MessageExportStatus.EXPORTED.serialize()} - """, - null - ).readToSingleLong() - - return bodyTextSize + fileSize - } - - fun deleteExportedMessages() { - writableDatabase.withinTransaction { db -> - val threadsToUpdate: List = db - .query(TABLE_NAME, arrayOf(THREAD_ID), "$EXPORTED = ?", buildArgs(MessageExportStatus.EXPORTED), THREAD_ID, null, null, null) - .readToList { it.requireLong(THREAD_ID) } - - db.delete(TABLE_NAME) - .where("$EXPORTED = ?", MessageExportStatus.EXPORTED) - .run() - - for (threadId in threadsToUpdate) { - threads.update(threadId, false) - } - - attachments.deleteAbandonedAttachmentFiles() - } - - OptimizeMessageSearchIndexJob.enqueue() - } - private fun deleteThreads(threadIds: Set) { Log.d(TAG, "deleteThreads(count: ${threadIds.size})") diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/MmsSmsDatabaseTest.kt b/app/src/test/java/org/thoughtcrime/securesms/database/MmsSmsDatabaseTest.kt index df71f2c9d1..6a027bedfb 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/MmsSmsDatabaseTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/MmsSmsDatabaseTest.kt @@ -24,6 +24,7 @@ class MmsSmsDatabaseTest { fun setup() { val sqlCipher = TestDatabaseUtil.inMemoryDatabase { execSQL(MessageTable.CREATE_TABLE) + MessageTable.CREATE_INDEXS.forEach { execSQL(it) } } db = sqlCipher.writableDatabase