Add read through cache for thread id.

This commit is contained in:
Clark
2023-05-08 20:17:57 -04:00
committed by Cody Henthorne
parent 054a1e4017
commit 77751c1d28

View File

@@ -17,7 +17,6 @@ import org.signal.core.util.exists
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.signal.core.util.or import org.signal.core.util.or
import org.signal.core.util.readToList import org.signal.core.util.readToList
import org.signal.core.util.readToSingleLong
import org.signal.core.util.requireBoolean import org.signal.core.util.requireBoolean
import org.signal.core.util.requireInt import org.signal.core.util.requireInt
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
@@ -60,6 +59,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.util.ConversationUtil import org.thoughtcrime.securesms.util.ConversationUtil
import org.thoughtcrime.securesms.util.JsonUtils import org.thoughtcrime.securesms.util.JsonUtils
import org.thoughtcrime.securesms.util.JsonUtils.SaneJSONObject import org.thoughtcrime.securesms.util.JsonUtils.SaneJSONObject
import org.thoughtcrime.securesms.util.LRUCache
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.isScheduled import org.thoughtcrime.securesms.util.isScheduled
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId
@@ -107,6 +107,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
const val PINNED = "pinned" const val PINNED = "pinned"
const val UNREAD_SELF_MENTION_COUNT = "unread_self_mention_count" const val UNREAD_SELF_MENTION_COUNT = "unread_self_mention_count"
const val MAX_CACHE_SIZE = 1000
@JvmField @JvmField
val CREATE_TABLE = """ val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME ( CREATE TABLE $TABLE_NAME (
@@ -179,6 +181,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
const val NO_TRIM_MESSAGE_COUNT_SET = Int.MAX_VALUE const val NO_TRIM_MESSAGE_COUNT_SET = Int.MAX_VALUE
} }
private val threadIdCache = LRUCache<RecipientId, Long>(MAX_CACHE_SIZE)
private fun createThreadForRecipient(recipientId: RecipientId, group: Boolean, distributionType: Int): Long { private fun createThreadForRecipient(recipientId: RecipientId, group: Boolean, distributionType: Int): Long {
if (recipientId.isUnknown) { if (recipientId.isUnknown) {
throw AssertionError("Cannot create a thread for an unknown recipient!") throw AssertionError("Cannot create a thread for an unknown recipient!")
@@ -1057,6 +1061,9 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
db.delete(TABLE_NAME) db.delete(TABLE_NAME)
.where("$ID = ?", threadId) .where("$ID = ?", threadId)
.run() .run()
synchronized(threadIdCache) {
threadIdCache.remove(recipientIdForThreadId)
}
} }
notifyConversationListListeners() notifyConversationListListeners()
@@ -1080,6 +1087,11 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
mentions.deleteAbandonedMentions() mentions.deleteAbandonedMentions()
drafts.clearDrafts(selectedConversations) drafts.clearDrafts(selectedConversations)
attachments.deleteAbandonedAttachmentFiles() attachments.deleteAbandonedAttachmentFiles()
synchronized(threadIdCache) {
for (recipientId in recipientIds) {
threadIdCache.remove(recipientId)
}
}
} }
notifyConversationListListeners() notifyConversationListListeners()
@@ -1096,6 +1108,9 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
drafts.clearAllDrafts() drafts.clearAllDrafts()
db.delete(TABLE_NAME, null, null) db.delete(TABLE_NAME, null, null)
calls.deleteAllCalls() calls.deleteAllCalls()
synchronized(threadIdCache) {
threadIdCache.clear()
}
} }
notifyConversationListListeners() notifyConversationListListeners()
@@ -1103,12 +1118,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
} }
fun getThreadIdIfExistsFor(recipientId: RecipientId): Long { fun getThreadIdIfExistsFor(recipientId: RecipientId): Long {
return readableDatabase return getThreadIdFor(recipientId) ?: -1
.select(ID)
.from(TABLE_NAME)
.where("$RECIPIENT_ID = ?", recipientId)
.run()
.readToSingleLong(-1)
} }
fun getOrCreateValidThreadId(recipient: Recipient, candidateId: Long): Long { fun getOrCreateValidThreadId(recipient: Recipient, candidateId: Long): Long {
@@ -1150,18 +1160,29 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
} }
fun getThreadIdFor(recipientId: RecipientId): Long? { fun getThreadIdFor(recipientId: RecipientId): Long? {
return readableDatabase var threadId: Long? = synchronized(threadIdCache) {
.select(ID) threadIdCache[recipientId]
.from(TABLE_NAME) }
.where("$RECIPIENT_ID = ?", recipientId) if (threadId == null) {
.run() threadId = readableDatabase
.use { cursor -> .select(ID)
if (cursor.moveToFirst()) { .from(TABLE_NAME)
cursor.requireLong(ID) .where("$RECIPIENT_ID = ?", recipientId)
} else { .run()
null .use { cursor ->
if (cursor.moveToFirst()) {
cursor.requireLong(ID)
} else {
null
}
}
if (threadId != null) {
synchronized(threadIdCache) {
threadIdCache[recipientId] = threadId
} }
} }
}
return threadId
} }
fun getRecipientIdForThreadId(threadId: Long): RecipientId? { fun getRecipientIdForThreadId(threadId: Long): RecipientId? {
@@ -1500,6 +1521,9 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
.values(RECIPIENT_ID to primaryRecipientId.serialize()) .values(RECIPIENT_ID to primaryRecipientId.serialize())
.where("$ID = ?", secondary.threadId) .where("$ID = ?", secondary.threadId)
.run() .run()
synchronized(threadIdCache) {
threadIdCache.remove(secondaryRecipientId)
}
MergeResult(threadId = secondary.threadId, previousThreadId = -1, neededMerge = false) MergeResult(threadId = secondary.threadId, previousThreadId = -1, neededMerge = false)
} else if (primary == null && secondary == null) { } else if (primary == null && secondary == null) {
Log.w(TAG, "[merge] No thread for either.") Log.w(TAG, "[merge] No thread for either.")
@@ -1518,6 +1542,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
.where("$ID = ?", secondary.threadId) .where("$ID = ?", secondary.threadId)
.run() .run()
synchronized(threadIdCache) {
threadIdCache.remove(secondaryRecipientId)
}
if (primary.expiresIn != secondary.expiresIn) { if (primary.expiresIn != secondary.expiresIn) {
val values = ContentValues() val values = ContentValues()
if (primary.expiresIn == 0L) { if (primary.expiresIn == 0L) {