Stop HEAD requests for possibly-unlisted contacts during CDS refresh.
This commit is contained in:
parent
002279f6a7
commit
4b6c308ae9
1 changed files with 12 additions and 39 deletions
|
@ -4,7 +4,6 @@ import android.content.Context
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import org.signal.contacts.SystemContactsRepository
|
import org.signal.contacts.SystemContactsRepository
|
||||||
import org.signal.core.util.Stopwatch
|
import org.signal.core.util.Stopwatch
|
||||||
import org.signal.core.util.concurrent.SignalExecutors
|
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.BuildConfig
|
import org.thoughtcrime.securesms.BuildConfig
|
||||||
import org.thoughtcrime.securesms.contacts.sync.FuzzyPhoneNumberHelper.InputResult
|
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.RecipientTable.CdsV2Result
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
|
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
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 org.whispersystems.signalservice.api.services.CdsiV2Service
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import java.util.concurrent.Callable
|
|
||||||
import java.util.concurrent.Future
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
|
@ -190,7 +186,7 @@ object ContactDiscoveryRefreshV2 {
|
||||||
val existingIds: Set<RecipientId> = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values)
|
val existingIds: Set<RecipientId> = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values)
|
||||||
stopwatch.split("get-ids")
|
stopwatch.split("get-ids")
|
||||||
|
|
||||||
val inactiveIds: Set<RecipientId> = (existingIds - registeredIds).removeRegisteredButUnlisted()
|
val inactiveIds: Set<RecipientId> = (existingIds - registeredIds).removePossiblyRegisteredButUnlisted()
|
||||||
stopwatch.split("registered-but-unlisted")
|
stopwatch.split("registered-but-unlisted")
|
||||||
|
|
||||||
SignalDatabase.recipients.bulkUpdatedRegisteredStatus(aciMap, inactiveIds)
|
SignalDatabase.recipients.bulkUpdatedRegisteredStatus(aciMap, inactiveIds)
|
||||||
|
@ -213,7 +209,7 @@ object ContactDiscoveryRefreshV2 {
|
||||||
val existingIds: Set<RecipientId> = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values)
|
val existingIds: Set<RecipientId> = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values)
|
||||||
stopwatch.split("get-ids")
|
stopwatch.split("get-ids")
|
||||||
|
|
||||||
val inactiveIds: Set<RecipientId> = (existingIds - registeredIds).removeRegisteredButUnlisted()
|
val inactiveIds: Set<RecipientId> = (existingIds - registeredIds).removePossiblyRegisteredButUnlisted()
|
||||||
stopwatch.split("registered-but-unlisted")
|
stopwatch.split("registered-but-unlisted")
|
||||||
|
|
||||||
SignalDatabase.recipients.bulkUpdatedRegisteredStatusV2(registeredIds, inactiveIds)
|
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()))
|
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
|
@WorkerThread
|
||||||
private fun Set<RecipientId>.removeRegisteredButUnlisted(): Set<RecipientId> {
|
private fun Set<RecipientId>.removePossiblyRegisteredButUnlisted(): Set<RecipientId> {
|
||||||
val futures: List<Future<Pair<RecipientId, Boolean?>>> = Recipient.resolvedList(this)
|
return this - Recipient.resolvedList(this)
|
||||||
.filter { it.hasServiceId() }
|
.filter { it.hasServiceId() }
|
||||||
.filter { hasCommunicatedWith(it) }
|
.filter { hasCommunicatedWith(it) }
|
||||||
.map {
|
.map { it.id }
|
||||||
SignalExecutors.UNBOUNDED.submit(
|
.toSet()
|
||||||
Callable {
|
|
||||||
try {
|
|
||||||
it.id to ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(it.requireServiceId())
|
|
||||||
} catch (e: IOException) {
|
|
||||||
it.id to null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val registeredIds: MutableSet<RecipientId> = mutableSetOf()
|
|
||||||
val retryIds: MutableSet<RecipientId> = 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Set<String>.toE164s(context: Context): Set<String> {
|
private fun Set<String>.toE164s(context: Context): Set<String> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue