65 lines
2.1 KiB
Swift
65 lines
2.1 KiB
Swift
//
|
|
// Copyright 2023 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// A transaction-scoped, address-to-user-visible-name resolver.
|
|
///
|
|
/// This class is a cache for user-visible names. If you need to look up the
|
|
/// name associated with an address multiple times, you may see a
|
|
/// performance improvement from adopting this class.
|
|
///
|
|
/// An instance of this class is only valid within the context of a single
|
|
/// transaction. If your transaction ends, the names might change before the
|
|
/// next transaction starts, so you need to throw away the cached state and
|
|
/// re-fetch it from disk. In debug builds, this class will ensure that it's
|
|
/// always used with the same transaction object.
|
|
public protocol NameResolver {
|
|
func displayName(for address: SignalServiceAddress, tx: DBReadTransaction) -> DisplayName
|
|
}
|
|
|
|
public class NameResolverImpl: NameResolver {
|
|
private let contactsManager: any ContactManager
|
|
|
|
private var displayNameCache = [SignalServiceAddress: DisplayName]()
|
|
|
|
public init(contactsManager: any ContactManager) {
|
|
self.contactsManager = contactsManager
|
|
}
|
|
|
|
private func cachedValue(
|
|
for address: SignalServiceAddress,
|
|
orValue value: @autoclosure () -> DisplayName
|
|
) -> DisplayName {
|
|
if let cachedResult = displayNameCache[address] {
|
|
return cachedResult
|
|
}
|
|
let result = value()
|
|
displayNameCache[address] = result
|
|
return result
|
|
}
|
|
|
|
public func displayName(for address: SignalServiceAddress, tx: DBReadTransaction) -> DisplayName {
|
|
let tx = SDSDB.shimOnlyBridge(tx)
|
|
checkTransaction(transaction: tx)
|
|
return cachedValue(
|
|
for: address,
|
|
orValue: contactsManager.displayName(for: address, tx: tx)
|
|
)
|
|
}
|
|
|
|
#if DEBUG
|
|
private weak var expectedTransaction: SDSAnyReadTransaction?
|
|
#endif
|
|
|
|
private func checkTransaction(transaction: SDSAnyReadTransaction) {
|
|
#if DEBUG
|
|
if expectedTransaction == nil {
|
|
expectedTransaction = transaction
|
|
}
|
|
assert(expectedTransaction == transaction)
|
|
#endif
|
|
}
|
|
}
|