nostrdb: add profiles to nostrdb
This adds profiles to nostrdb - Remove in-memory Profiles caches, nostrdb is as fast as an in-memory cache - Remove ProfileDatabase and just use nostrdb directly Changelog-Changed: Use nostrdb for profiles
This commit is contained in:
@@ -15,72 +15,52 @@ class ValidationModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
class ProfileDataModel: ObservableObject {
|
||||
@Published var profile: TimestampedProfile?
|
||||
|
||||
init() {
|
||||
self.profile = nil
|
||||
}
|
||||
}
|
||||
|
||||
class ProfileData {
|
||||
var status: UserStatusModel
|
||||
var profile_model: ProfileDataModel
|
||||
var validation_model: ValidationModel
|
||||
var zapper: Pubkey?
|
||||
|
||||
init() {
|
||||
status = .init()
|
||||
profile_model = .init()
|
||||
validation_model = .init()
|
||||
zapper = nil
|
||||
}
|
||||
}
|
||||
|
||||
class Profiles {
|
||||
|
||||
static let db_freshness_threshold: TimeInterval = 24 * 60 * 60
|
||||
|
||||
/// This queue is used to synchronize access to the profiles dictionary, which
|
||||
/// prevents data races from crashing the app.
|
||||
private var profiles_queue = DispatchQueue(label: "io.damus.profiles",
|
||||
qos: .userInteractive,
|
||||
attributes: .concurrent)
|
||||
private var ndb: Ndb
|
||||
|
||||
private var validated_queue = DispatchQueue(label: "io.damus.profiles.validated",
|
||||
qos: .userInteractive,
|
||||
attributes: .concurrent)
|
||||
|
||||
static let db_freshness_threshold: TimeInterval = 24 * 60 * 60
|
||||
|
||||
@MainActor
|
||||
private var profiles: [Pubkey: ProfileData] = [:]
|
||||
|
||||
@MainActor
|
||||
var nip05_pubkey: [String: Pubkey] = [:]
|
||||
|
||||
private let database = ProfileDatabase()
|
||||
|
||||
let user_search_cache: UserSearchCache
|
||||
|
||||
init(user_search_cache: UserSearchCache) {
|
||||
init(user_search_cache: UserSearchCache, ndb: Ndb) {
|
||||
self.user_search_cache = user_search_cache
|
||||
self.ndb = ndb
|
||||
}
|
||||
|
||||
|
||||
@MainActor
|
||||
func is_validated(_ pk: Pubkey) -> NIP05? {
|
||||
validated_queue.sync {
|
||||
self.profile_data(pk).validation_model.validated
|
||||
}
|
||||
self.profile_data(pk).validation_model.validated
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func invalidate_nip05(_ pk: Pubkey) {
|
||||
validated_queue.async(flags: .barrier) {
|
||||
self.profile_data(pk).validation_model.validated = nil
|
||||
}
|
||||
self.profile_data(pk).validation_model.validated = nil
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func set_validated(_ pk: Pubkey, nip05: NIP05?) {
|
||||
validated_queue.async(flags: .barrier) {
|
||||
self.profile_data(pk).validation_model.validated = nip05
|
||||
}
|
||||
self.profile_data(pk).validation_model.validated = nip05
|
||||
}
|
||||
|
||||
|
||||
@MainActor
|
||||
func profile_data(_ pubkey: Pubkey) -> ProfileData {
|
||||
guard let data = profiles[pubkey] else {
|
||||
let data = ProfileData()
|
||||
@@ -91,60 +71,28 @@ class Profiles {
|
||||
return data
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func lookup_zapper(pubkey: Pubkey) -> Pubkey? {
|
||||
profile_data(pubkey).zapper
|
||||
}
|
||||
|
||||
func add(id: Pubkey, profile: TimestampedProfile) {
|
||||
profiles_queue.async(flags: .barrier) {
|
||||
let old_timestamped_profile = self.profile_data(id).profile_model.profile
|
||||
self.profile_data(id).profile_model.profile = profile
|
||||
self.user_search_cache.updateProfile(id: id, profiles: self, oldProfile: old_timestamped_profile?.profile, newProfile: profile.profile)
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
try await database.upsert(id: id, profile: profile.profile, last_update: Date(timeIntervalSince1970: TimeInterval(profile.timestamp)))
|
||||
} catch {
|
||||
print("⚠️ Warning: Profiles failed to save a profile: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func lookup_with_timestamp(_ pubkey: Pubkey) -> ProfileRecord? {
|
||||
return ndb.lookup_profile(pubkey)
|
||||
}
|
||||
|
||||
|
||||
func lookup(id: Pubkey) -> Profile? {
|
||||
var profile: Profile?
|
||||
profiles_queue.sync {
|
||||
profile = self.profile_data(id).profile_model.profile?.profile
|
||||
}
|
||||
return profile ?? database.get(id: id)
|
||||
return ndb.lookup_profile(id)?.profile
|
||||
}
|
||||
|
||||
func lookup_with_timestamp(id: Pubkey) -> TimestampedProfile? {
|
||||
profiles_queue.sync {
|
||||
return self.profile_data(id).profile_model.profile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func has_fresh_profile(id: Pubkey) -> Bool {
|
||||
var profile: Profile?
|
||||
profiles_queue.sync {
|
||||
profile = self.profile_data(id).profile_model.profile?.profile
|
||||
}
|
||||
if profile != nil {
|
||||
return true
|
||||
}
|
||||
// check memory first
|
||||
return false
|
||||
|
||||
// then disk
|
||||
guard let pull_date = database.get_network_pull_date(id: id) else {
|
||||
return false
|
||||
}
|
||||
return Date.now.timeIntervalSince(pull_date) < Profiles.db_freshness_threshold
|
||||
guard let profile = lookup_with_timestamp(id) else { return false }
|
||||
return Date.now.timeIntervalSince(Date(timeIntervalSince1970: Double(profile.receivedAt))) < Profiles.db_freshness_threshold
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@MainActor
|
||||
func invalidate_zapper_cache(pubkey: Pubkey, profiles: Profiles, lnurl: LNUrls) {
|
||||
profiles.profile_data(pubkey).zapper = nil
|
||||
lnurl.endpoints.removeValue(forKey: pubkey)
|
||||
|
||||
Reference in New Issue
Block a user