From 878fd3d8425cdfa2591bb333180678976dee6e23 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Oct 2017 15:50:44 -0400 Subject: [PATCH] Only one system contacts fetch at a time. // FREEBIE --- .../src/contact/SystemContactsFetcher.swift | 59 +++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/Signal/src/contact/SystemContactsFetcher.swift b/Signal/src/contact/SystemContactsFetcher.swift index 9d6a4b343..9b80df975 100644 --- a/Signal/src/contact/SystemContactsFetcher.swift +++ b/Signal/src/contact/SystemContactsFetcher.swift @@ -428,38 +428,51 @@ class SystemContactsFetcher: NSObject { updateContacts(completion: nil, ignoreDebounce:ignoreDebounce) } + private func tryToAcquireContactFetchLock() -> Bool { + var didAcquireLock = false + SystemContactsFetcher.serialQueue.sync { + guard !self.isFetchingContacts else { + return + } + self.isFetchingContacts = true + didAcquireLock = true + } + return didAcquireLock + } + + private func releaseContactFetchLock() { + SystemContactsFetcher.serialQueue.sync { + self.isFetchingContacts = false + } + } + private func updateContacts(completion: ((Error?) -> Void)?, ignoreDebounce: Bool = false) { AssertIsOnMainThread() systemContactsHaveBeenRequestedAtLeastOnce = true setupObservationIfNecessary() - SystemContactsFetcher.serialQueue.async { [weak self] _ in - guard let strongSelf = self else { - return - } + DispatchQueue.global().async { var fetchedContacts: [Contact]? - guard !strongSelf.isFetchingContacts else { - Logger.info("\(strongSelf.TAG) ignoring redundant system contacts fetch.") + guard self.tryToAcquireContactFetchLock() else { + Logger.info("\(self.TAG) ignoring redundant system contacts fetch.") return } - strongSelf.isFetchingContacts = true - switch strongSelf.contactStoreAdapter.fetchContacts() { + switch self.contactStoreAdapter.fetchContacts() { case .success(let result): fetchedContacts = result case .error(let error): completion?(error) - strongSelf.isFetchingContacts = false + self.releaseContactFetchLock() return } - - strongSelf.isFetchingContacts = false + self.releaseContactFetchLock() guard let contacts = fetchedContacts else { - owsFail("\(strongSelf.TAG) contacts was unexpectedly not set.") + owsFail("\(self.TAG) contacts was unexpectedly not set.") completion?(nil) } @@ -468,43 +481,43 @@ class SystemContactsFetcher: NSObject { DispatchQueue.main.async { var shouldNotifyDelegate = false - if strongSelf.lastContactUpdateHash != contactsHash { - Logger.info("\(strongSelf.TAG) contact hash changed. new contactsHash: \(contactsHash)") + if self.lastContactUpdateHash != contactsHash { + Logger.info("\(self.TAG) contact hash changed. new contactsHash: \(contactsHash)") shouldNotifyDelegate = true } else if ignoreDebounce { - Logger.info("\(strongSelf.TAG) ignoring debounce.") + Logger.info("\(self.TAG) ignoring debounce.") shouldNotifyDelegate = true } else { // If nothing has changed, only notify delegate (to perform contact intersection) every N hours - if let lastDelegateNotificationDate = strongSelf.lastDelegateNotificationDate { + if let lastDelegateNotificationDate = self.lastDelegateNotificationDate { let kDebounceInterval = TimeInterval(12 * 60 * 60) let expiresAtDate = Date(timeInterval: kDebounceInterval, since:lastDelegateNotificationDate) if Date() > expiresAtDate { - Logger.info("\(strongSelf.TAG) debounce interval expired at: \(expiresAtDate)") + Logger.info("\(self.TAG) debounce interval expired at: \(expiresAtDate)") shouldNotifyDelegate = true } else { - Logger.info("\(strongSelf.TAG) ignoring since debounce interval hasn't expired") + Logger.info("\(self.TAG) ignoring since debounce interval hasn't expired") } } else { - Logger.info("\(strongSelf.TAG) first contact fetch. contactsHash: \(contactsHash)") + Logger.info("\(self.TAG) first contact fetch. contactsHash: \(contactsHash)") shouldNotifyDelegate = true } } guard shouldNotifyDelegate else { - Logger.info("\(strongSelf.TAG) no reason to notify delegate.") + Logger.info("\(self.TAG) no reason to notify delegate.") completion?(nil) return } - strongSelf.lastDelegateNotificationDate = Date() - strongSelf.lastContactUpdateHash = contactsHash + self.lastDelegateNotificationDate = Date() + self.lastContactUpdateHash = contactsHash - strongSelf.delegate?.systemContactsFetcher(strongSelf, updatedContacts: contacts) + self.delegate?.systemContactsFetcher(self, updatedContacts: contacts) completion?(nil) } }