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)
}
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)
}
}

Loading…
Cancel
Save