From 4b6c308ae98adbe4189d7884c6423c1a88b64d40 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 6 Jul 2023 17:00:41 -0400 Subject: [PATCH] Stop HEAD requests for possibly-unlisted contacts during CDS refresh. --- .../sync/ContactDiscoveryRefreshV2.kt | 51 +++++-------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt index 78e280c7ca..fa2b6ad982 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt @@ -4,7 +4,6 @@ import android.content.Context import androidx.annotation.WorkerThread import org.signal.contacts.SystemContactsRepository import org.signal.core.util.Stopwatch -import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BuildConfig import org.thoughtcrime.securesms.contacts.sync.FuzzyPhoneNumberHelper.InputResult @@ -12,7 +11,6 @@ import org.thoughtcrime.securesms.contacts.sync.FuzzyPhoneNumberHelper.OutputRes import org.thoughtcrime.securesms.database.RecipientTable.CdsV2Result import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.thoughtcrime.securesms.jobs.RetrieveProfileJob import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter import org.thoughtcrime.securesms.recipients.Recipient @@ -24,8 +22,6 @@ import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhauste import org.whispersystems.signalservice.api.services.CdsiV2Service import java.io.IOException import java.util.Optional -import java.util.concurrent.Callable -import java.util.concurrent.Future import kotlin.math.roundToInt import kotlin.time.Duration.Companion.seconds @@ -190,7 +186,7 @@ object ContactDiscoveryRefreshV2 { val existingIds: Set = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values) stopwatch.split("get-ids") - val inactiveIds: Set = (existingIds - registeredIds).removeRegisteredButUnlisted() + val inactiveIds: Set = (existingIds - registeredIds).removePossiblyRegisteredButUnlisted() stopwatch.split("registered-but-unlisted") SignalDatabase.recipients.bulkUpdatedRegisteredStatus(aciMap, inactiveIds) @@ -213,7 +209,7 @@ object ContactDiscoveryRefreshV2 { val existingIds: Set = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values) stopwatch.split("get-ids") - val inactiveIds: Set = (existingIds - registeredIds).removeRegisteredButUnlisted() + val inactiveIds: Set = (existingIds - registeredIds).removePossiblyRegisteredButUnlisted() stopwatch.split("registered-but-unlisted") SignalDatabase.recipients.bulkUpdatedRegisteredStatusV2(registeredIds, inactiveIds) @@ -230,42 +226,19 @@ object ContactDiscoveryRefreshV2 { return SignalDatabase.threads.hasThread(recipient.id) || (recipient.hasServiceId() && SignalDatabase.sessions.hasSessionFor(localAci, recipient.requireServiceId().toString())) } + /** + * If an account is unlisted, it won't come back in the CDS response. So just because we're missing a entry doesn't mean they've become unregistered. + * This function removes people from the list that both have a serviceId and some history of communication. We consider this a good hueristic for + * "maybe this person just removed themselves from CDS". We'll rely on profile fetches that occur during chat opens to check registered status and clear + * actually-unregistered users out. + */ @WorkerThread - private fun Set.removeRegisteredButUnlisted(): Set { - val futures: List>> = Recipient.resolvedList(this) + private fun Set.removePossiblyRegisteredButUnlisted(): Set { + return this - Recipient.resolvedList(this) .filter { it.hasServiceId() } .filter { hasCommunicatedWith(it) } - .map { - SignalExecutors.UNBOUNDED.submit( - Callable { - try { - it.id to ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(it.requireServiceId()) - } catch (e: IOException) { - it.id to null - } - } - ) - } - - val registeredIds: MutableSet = mutableSetOf() - val retryIds: MutableSet = mutableSetOf() - - for (future in futures) { - val (id, registered) = future.get() - if (registered == null) { - retryIds += id - registeredIds += id - } else if (registered) { - registeredIds += id - } - } - - if (retryIds.isNotEmpty()) { - Log.w(TAG, "Failed to determine registered status of ${retryIds.size} recipients. Assuming registered, but enqueuing profile jobs to check later.") - RetrieveProfileJob.enqueue(retryIds) - } - - return this - registeredIds + .map { it.id } + .toSet() } private fun Set.toE164s(context: Context): Set {