Only one system contacts fetch at a time.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 8c1dfe7ee6
commit 878fd3d842

@ -428,38 +428,51 @@ class SystemContactsFetcher: NSObject {
updateContacts(completion: nil, ignoreDebounce:ignoreDebounce) 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) { private func updateContacts(completion: ((Error?) -> Void)?, ignoreDebounce: Bool = false) {
AssertIsOnMainThread() AssertIsOnMainThread()
systemContactsHaveBeenRequestedAtLeastOnce = true systemContactsHaveBeenRequestedAtLeastOnce = true
setupObservationIfNecessary() setupObservationIfNecessary()
SystemContactsFetcher.serialQueue.async { [weak self] _ in DispatchQueue.global().async {
guard let strongSelf = self else {
return
}
var fetchedContacts: [Contact]? var fetchedContacts: [Contact]?
guard !strongSelf.isFetchingContacts else { guard self.tryToAcquireContactFetchLock() else {
Logger.info("\(strongSelf.TAG) ignoring redundant system contacts fetch.") Logger.info("\(self.TAG) ignoring redundant system contacts fetch.")
return return
} }
strongSelf.isFetchingContacts = true
switch strongSelf.contactStoreAdapter.fetchContacts() { switch self.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 self.releaseContactFetchLock()
return return
} }
self.releaseContactFetchLock()
strongSelf.isFetchingContacts = false
guard let contacts = fetchedContacts else { guard let contacts = fetchedContacts else {
owsFail("\(strongSelf.TAG) contacts was unexpectedly not set.") owsFail("\(self.TAG) contacts was unexpectedly not set.")
completion?(nil) completion?(nil)
} }
@ -468,43 +481,43 @@ class SystemContactsFetcher: NSObject {
DispatchQueue.main.async { DispatchQueue.main.async {
var shouldNotifyDelegate = false var shouldNotifyDelegate = false
if strongSelf.lastContactUpdateHash != contactsHash { if self.lastContactUpdateHash != contactsHash {
Logger.info("\(strongSelf.TAG) contact hash changed. new contactsHash: \(contactsHash)") Logger.info("\(self.TAG) contact hash changed. new contactsHash: \(contactsHash)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} else if ignoreDebounce { } else if ignoreDebounce {
Logger.info("\(strongSelf.TAG) ignoring debounce.") Logger.info("\(self.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 = strongSelf.lastDelegateNotificationDate { if let lastDelegateNotificationDate = self.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("\(strongSelf.TAG) debounce interval expired at: \(expiresAtDate)") Logger.info("\(self.TAG) debounce interval expired at: \(expiresAtDate)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} else { } else {
Logger.info("\(strongSelf.TAG) ignoring since debounce interval hasn't expired") Logger.info("\(self.TAG) ignoring since debounce interval hasn't expired")
} }
} else { } else {
Logger.info("\(strongSelf.TAG) first contact fetch. contactsHash: \(contactsHash)") Logger.info("\(self.TAG) first contact fetch. contactsHash: \(contactsHash)")
shouldNotifyDelegate = true shouldNotifyDelegate = true
} }
} }
guard shouldNotifyDelegate else { guard shouldNotifyDelegate else {
Logger.info("\(strongSelf.TAG) no reason to notify delegate.") Logger.info("\(self.TAG) no reason to notify delegate.")
completion?(nil) completion?(nil)
return return
} }
strongSelf.lastDelegateNotificationDate = Date() self.lastDelegateNotificationDate = Date()
strongSelf.lastContactUpdateHash = contactsHash self.lastContactUpdateHash = contactsHash
strongSelf.delegate?.systemContactsFetcher(strongSelf, updatedContacts: contacts) self.delegate?.systemContactsFetcher(self, updatedContacts: contacts)
completion?(nil) completion?(nil)
} }
} }

Loading…
Cancel
Save