Only one system contacts fetch at a time.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 445045b801
commit 8c1dfe7ee6

@ -344,6 +344,8 @@ class SystemContactsFetcher: NSObject {
private var systemContactsHaveBeenRequestedAtLeastOnce = false private var systemContactsHaveBeenRequestedAtLeastOnce = false
private var hasSetupObservation = false private var hasSetupObservation = false
private var isFetchingContacts = false
private static let serialQueue = DispatchQueue(label: "org.whispersystems.system.contacts")
override init() { override init() {
self.contactStoreAdapter = ContactStoreAdapter() self.contactStoreAdapter = ContactStoreAdapter()
@ -432,20 +434,32 @@ class SystemContactsFetcher: NSObject {
systemContactsHaveBeenRequestedAtLeastOnce = true systemContactsHaveBeenRequestedAtLeastOnce = true
setupObservationIfNecessary() setupObservationIfNecessary()
DispatchQueue.global().async { SystemContactsFetcher.serialQueue.async { [weak self] _ in
guard let strongSelf = self else {
return
}
var fetchedContacts: [Contact]? var fetchedContacts: [Contact]?
switch self.contactStoreAdapter.fetchContacts() { guard !strongSelf.isFetchingContacts else {
Logger.info("\(strongSelf.TAG) ignoring redundant system contacts fetch.")
return
}
strongSelf.isFetchingContacts = true
switch strongSelf.contactStoreAdapter.fetchContacts() {
case .success(let result): case .success(let result):
fetchedContacts = result fetchedContacts = result
case .error(let error): case .error(let error):
completion?(error) completion?(error)
strongSelf.isFetchingContacts = false
return return
} }
strongSelf.isFetchingContacts = false
guard let contacts = fetchedContacts else { guard let contacts = fetchedContacts else {
owsFail("\(self.TAG) contacts was unexpectedly not set.") owsFail("\(strongSelf.TAG) contacts was unexpectedly not set.")
completion?(nil) completion?(nil)
} }
@ -454,43 +468,43 @@ class SystemContactsFetcher: NSObject {
DispatchQueue.main.async { DispatchQueue.main.async {
var shouldNotifyDelegate = false var shouldNotifyDelegate = false
if self.lastContactUpdateHash != contactsHash { if strongSelf.lastContactUpdateHash != contactsHash {
Logger.info("\(self.TAG) contact hash changed. new contactsHash: \(contactsHash)") Logger.info("\(strongSelf.TAG) contact hash changed. new contactsHash: \(contactsHash)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} else if ignoreDebounce { } else if ignoreDebounce {
Logger.info("\(self.TAG) ignoring debounce.") Logger.info("\(strongSelf.TAG) ignoring debounce.")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} else { } else {
// If nothing has changed, only notify delegate (to perform contact intersection) every N hours // If nothing has changed, only notify delegate (to perform contact intersection) every N hours
if let lastDelegateNotificationDate = self.lastDelegateNotificationDate { if let lastDelegateNotificationDate = strongSelf.lastDelegateNotificationDate {
let kDebounceInterval = TimeInterval(12 * 60 * 60) let kDebounceInterval = TimeInterval(12 * 60 * 60)
let expiresAtDate = Date(timeInterval: kDebounceInterval, since:lastDelegateNotificationDate) let expiresAtDate = Date(timeInterval: kDebounceInterval, since:lastDelegateNotificationDate)
if Date() > expiresAtDate { if Date() > expiresAtDate {
Logger.info("\(self.TAG) debounce interval expired at: \(expiresAtDate)") Logger.info("\(strongSelf.TAG) debounce interval expired at: \(expiresAtDate)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} else { } else {
Logger.info("\(self.TAG) ignoring since debounce interval hasn't expired") Logger.info("\(strongSelf.TAG) ignoring since debounce interval hasn't expired")
} }
} else { } else {
Logger.info("\(self.TAG) first contact fetch. contactsHash: \(contactsHash)") Logger.info("\(strongSelf.TAG) first contact fetch. contactsHash: \(contactsHash)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} }
} }
guard shouldNotifyDelegate else { guard shouldNotifyDelegate else {
Logger.info("\(self.TAG) no reason to notify delegate.") Logger.info("\(strongSelf.TAG) no reason to notify delegate.")
completion?(nil) completion?(nil)
return return
} }
self.lastDelegateNotificationDate = Date() strongSelf.lastDelegateNotificationDate = Date()
self.lastContactUpdateHash = contactsHash strongSelf.lastContactUpdateHash = contactsHash
self.delegate?.systemContactsFetcher(self, updatedContacts: contacts) strongSelf.delegate?.systemContactsFetcher(strongSelf, updatedContacts: contacts)
completion?(nil) completion?(nil)
} }
} }

Loading…
Cancel
Save