Attempt to reduce impact of thread updates.

This commit is contained in:
Greyson Parrelli 2024-05-01 16:23:59 -04:00 committed by Alex Hart
parent 41935120e5
commit 3c380d35fd
3 changed files with 21 additions and 85 deletions

View file

@ -38,7 +38,7 @@ class DraftViewModel @JvmOverloads constructor(
fun saveEphemeralVoiceNoteDraft(draft: Draft) { fun saveEphemeralVoiceNoteDraft(draft: Draft) {
store.update { draftState -> store.update { draftState ->
saveDrafts(draftState.copy(voiceNoteDraft = draft)) saveDraftsIfChanged(draftState, draftState.copy(voiceNoteDraft = draft))
} }
} }
@ -49,7 +49,7 @@ class DraftViewModel @JvmOverloads constructor(
fun deleteVoiceNoteDraft() { fun deleteVoiceNoteDraft() {
store.update { store.update {
repository.deleteVoiceNoteDraftData(it.voiceNoteDraft) 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() 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() { fun deleteMessageEditDraft() {
store.update { 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() 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) { fun setLocationDraft(place: SignalPlace) {
store.update { store.update {
saveDrafts(it.copy(locationDraft = Draft(Draft.LOCATION, place.serialize() ?: ""))) saveDraftsIfChanged(it, it.copy(locationDraft = Draft(Draft.LOCATION, place.serialize() ?: "")))
} }
} }
fun clearLocationDraft() { fun clearLocationDraft() {
store.update { store.update {
saveDrafts(it.copy(locationDraft = null)) saveDraftsIfChanged(it, it.copy(locationDraft = null))
} }
} }
fun setQuoteDraft(id: Long, author: RecipientId) { fun setQuoteDraft(id: Long, author: RecipientId) {
store.update { 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() { fun clearQuoteDraft() {
store.update { store.update {
saveDrafts(it.copy(quoteDraft = null)) saveDraftsIfChanged(it, it.copy(quoteDraft = null))
} }
} }
fun onSendComplete(threadId: Long = store.state.threadId) { fun onSendComplete(threadId: Long = store.state.threadId) {
repository.deleteVoiceNoteDraftData(store.state.voiceNoteDraft) repository.deleteVoiceNoteDraftData(store.state.voiceNoteDraft)
store.update { saveDrafts(it.copyAndClearDrafts(threadId)) } store.update { saveDraftsIfChanged(it, it.copyAndClearDrafts(threadId)) }
} }
private fun saveDrafts(state: DraftState): DraftState { private fun saveDraftsIfChanged(oldState: DraftState, newState: DraftState): DraftState {
repository.saveDrafts(state.threadId, state.toDrafts()) if (oldState == newState) {
return state return oldState
}
repository.saveDrafts(newState.threadId, newState.toDrafts())
return newState
} }
fun loadShareOrDraftData(lastShareDataTimestamp: Long): Maybe<DraftRepository.ShareOrDraftData> { fun loadShareOrDraftData(lastShareDataTimestamp: Long): Maybe<DraftRepository.ShareOrDraftData> {
return repository.getShareOrDraftData(lastShareDataTimestamp) return repository.getShareOrDraftData(lastShareDataTimestamp)
.doOnSuccess { (_, drafts) -> .doOnSuccess { (_, drafts) ->
if (drafts != null) { if (drafts != null) {
store.update { saveDrafts(it.copyAndSetDrafts(drafts = drafts)) } store.update { saveDraftsIfChanged(it, it.copyAndSetDrafts(drafts = drafts)) }
} }
} }
.flatMap { (data, _) -> .flatMap { (data, _) ->

View file

@ -29,7 +29,6 @@ import org.json.JSONObject
import org.signal.core.util.Base64 import org.signal.core.util.Base64
import org.signal.core.util.CursorUtil import org.signal.core.util.CursorUtil
import org.signal.core.util.SqlUtil 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.buildArgs
import org.signal.core.util.SqlUtil.buildCustomCollectionQuery import org.signal.core.util.SqlUtil.buildCustomCollectionQuery
import org.signal.core.util.SqlUtil.buildSingleCollectionQuery import org.signal.core.util.SqlUtil.buildSingleCollectionQuery
@ -395,7 +394,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$TYPE, $TYPE,
$DATE_RECEIVED $DATE_RECEIVED
FROM FROM
$TABLE_NAME $TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID
WHERE WHERE
$THREAD_ID = ? AND $THREAD_ID = ? AND
$TYPE & ${MessageTypes.GROUP_V2_LEAVE_BITS} != ${MessageTypes.GROUP_V2_LEAVE_BITS} 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<String>?, reverse: Boolean = false, limit: Long = 0): Cursor { private fun rawQueryWithAttachments(where: String, arguments: Array<String>?, reverse: Boolean = false, limit: Long = 0): Cursor {
return rawQueryWithAttachments(MMS_PROJECTION_WITH_ATTACHMENTS, where, arguments, reverse, limit)
}
private fun rawQueryWithAttachments(projection: Array<String>, where: String, arguments: Array<String>?, reverse: Boolean, limit: Long): Cursor {
val database = databaseHelper.signalReadableDatabase val database = databaseHelper.signalReadableDatabase
var rawQueryString = """ var rawQueryString = """
SELECT SELECT
${Util.join(projection, ",")} ${Util.join(MMS_PROJECTION_WITH_ATTACHMENTS, ",")}
FROM FROM
$TABLE_NAME LEFT OUTER JOIN ${AttachmentTable.TABLE_NAME} ON ($TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID}) $TABLE_NAME LEFT OUTER JOIN ${AttachmentTable.TABLE_NAME} ON ($TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID})
WHERE 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) { fun markAsRateLimited(messageId: Long) {
val threadId = getThreadIdForMessage(messageId) val threadId = getThreadIdForMessage(messageId)
updateMailboxBitmask(messageId, 0, MessageTypes.MESSAGE_RATE_LIMITED_BIT, Optional.of(threadId)) 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 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<Long> = 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<Long>) { private fun deleteThreads(threadIds: Set<Long>) {
Log.d(TAG, "deleteThreads(count: ${threadIds.size})") Log.d(TAG, "deleteThreads(count: ${threadIds.size})")

View file

@ -24,6 +24,7 @@ class MmsSmsDatabaseTest {
fun setup() { fun setup() {
val sqlCipher = TestDatabaseUtil.inMemoryDatabase { val sqlCipher = TestDatabaseUtil.inMemoryDatabase {
execSQL(MessageTable.CREATE_TABLE) execSQL(MessageTable.CREATE_TABLE)
MessageTable.CREATE_INDEXS.forEach { execSQL(it) }
} }
db = sqlCipher.writableDatabase db = sqlCipher.writableDatabase