Skip to content

Commit

Permalink
perf: Improvements on retrieving frozenContacts (#1281)
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinperignon authored Feb 14, 2024
2 parents 8edbbd8 + 0560580 commit b4dddc6
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
7 changes: 4 additions & 3 deletions MailCore/Cache/ContactManager/ContactManager+DB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public protocol ContactFetchable {
/// - string: input string to match against email and name
/// - fetchLimit: limit the query by default to limit memory footprint
/// - Returns: The collection of matching contacts.
func frozenContacts(matching string: String, fetchLimit: Int?) -> [MergedContact]
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MergedContact>
func getContact(for correspondent: any Correspondent, realm: Realm?) -> MergedContact?
func addressBook(with id: Int) -> AddressBook?
func addContact(recipient: Recipient) async throws
Expand All @@ -43,16 +43,17 @@ public extension ContactManager {
/// - string: input string to match against email and name
/// - fetchLimit: limit the query by default to limit memory footprint
/// - Returns: The collection of matching contacts. Frozen.
func frozenContacts(matching string: String, fetchLimit: Int?) -> [MergedContact] {
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MergedContact> {
let realm = getRealm()
let lazyResults = realm
.objects(MergedContact.self)
.filter(Self.searchContactInsensitivePredicate, string, string)
.freeze()

let fetchLimit = min(lazyResults.count, fetchLimit ?? Self.contactFetchLimit)

let limitedResults = lazyResults[0 ..< fetchLimit]
return limitedResults.map { $0.freezeIfNeeded() }
return limitedResults
}

func getContact(for correspondent: any Correspondent, realm: Realm? = nil) -> MergedContact? {
Expand Down
57 changes: 57 additions & 0 deletions MailTests/Contacts/UTContactManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Infomaniak Mail - iOS App
Copyright (C) 2024 Infomaniak Network SA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import MailCore
import XCTest

final class UTContactManager: XCTestCase {
let contactManager = ContactManager(userId: 0, apiFetcher: MailApiFetcher())

override func setUpWithError() throws {}

func generateFakeContacts(count: Int) {
let realm = contactManager.getRealm()
// swiftlint:disable:next force_try
try! realm.write {
realm.deleteAll()
}

// swiftlint:disable:next force_try
try! realm.write {
for i in 0 ..< count {
let contact = MergedContact()
contact.id = i
let randomName = UUID().uuidString
contact.name = "\(randomName)"
contact.email = "\(randomName)@somemail.com"
realm.add(contact)
}
}
}

func testGetContactsMatching() throws {
// GIVEN
generateFakeContacts(count: 100_000)
measure {
// WHEN
let matchingContacts = contactManager.frozenContacts(matching: "mail", fetchLimit: nil)
// THEN
XCTAssertEqual(matchingContacts.isEmpty, false)
}
}
}
2 changes: 1 addition & 1 deletion MailTests/Folders/ITFolderListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import InfomaniakLogin
import XCTest

struct MCKContactManageable_FolderListViewModel: ContactManageable {
func frozenContacts(matching string: String, fetchLimit: Int?) -> [MailCore.MergedContact] { [] }
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MailCore.MergedContact> { [] }

func getContact(for correspondent: any MailCore.Correspondent, realm: RealmSwift.Realm?) -> MailCore.MergedContact? { nil }

Expand Down
2 changes: 1 addition & 1 deletion MailTests/Search/ITSearchViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import XCTest

/// A ContactManageable used to test the SearchViewModel
struct MCKContactManageable_SearchViewModel: ContactManageable {
func frozenContacts(matching string: String, fetchLimit: Int?) -> [MailCore.MergedContact] { [] }
func frozenContacts(matching string: String, fetchLimit: Int?) -> any Collection<MailCore.MergedContact> { [] }

func getContact(for correspondent: any MailCore.Correspondent, realm: RealmSwift.Realm?) -> MailCore.MergedContact? { nil }

Expand Down

0 comments on commit b4dddc6

Please sign in to comment.