diff --git a/damus/Nostr/ProfileDatabase.swift b/damus/Nostr/ProfileDatabase.swift index 31a4fb43..9fbd2c9b 100644 --- a/damus/Nostr/ProfileDatabase.swift +++ b/damus/Nostr/ProfileDatabase.swift @@ -99,33 +99,31 @@ final class ProfileDatabase { /// - id: Profile id (pubkey) /// - profile: Profile object to be stored /// - last_update: Date that the Profile was updated - func upsert(id: String, profile: Profile, last_update: Date) throws { + func upsert(id: String, profile: Profile, last_update: Date) async throws { guard let context = background_context else { throw ProfileDatabaseError.missing_context } - Task { - try await context.perform { - var persisted_profile: PersistedProfile? - if let profile = self.get_persisted(id: id, context: context) { - if let existing_last_update = profile.last_update, last_update < existing_last_update { - throw ProfileDatabaseError.outdated_input - } else { - persisted_profile = profile - } + try await context.perform { + var persisted_profile: PersistedProfile? + if let profile = self.get_persisted(id: id, context: context) { + if let existing_last_update = profile.last_update, last_update < existing_last_update { + throw ProfileDatabaseError.outdated_input } else { - persisted_profile = NSEntityDescription.insertNewObject(forEntityName: self.entity_name, into: context) as? PersistedProfile - persisted_profile?.id = id + persisted_profile = profile } - persisted_profile?.copyValues(from: profile) - persisted_profile?.last_update = last_update - - let pull_date = Date.now - persisted_profile?.network_pull_date = pull_date - self.network_pull_date_cache[id] = pull_date - - try context.save() + } else { + persisted_profile = NSEntityDescription.insertNewObject(forEntityName: self.entity_name, into: context) as? PersistedProfile + persisted_profile?.id = id } + persisted_profile?.copyValues(from: profile) + persisted_profile?.last_update = last_update + + let pull_date = Date.now + persisted_profile?.network_pull_date = pull_date + self.network_pull_date_cache[id] = pull_date + + try context.save() } } diff --git a/damus/Nostr/Profiles.swift b/damus/Nostr/Profiles.swift index f0aec4bb..05f914db 100644 --- a/damus/Nostr/Profiles.swift +++ b/damus/Nostr/Profiles.swift @@ -37,10 +37,12 @@ class Profiles { self.profiles[id] = profile } - do { - try database.upsert(id: id, profile: profile.profile, last_update: Date(timeIntervalSince1970: TimeInterval(profile.timestamp))) - } catch { - print("⚠️ Warning: Profiles failed to save a profile: \(error)") + 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)") + } } } diff --git a/damusTests/ProfileDatabaseTests.swift b/damusTests/ProfileDatabaseTests.swift index 31fe4b1b..89a2c189 100644 --- a/damusTests/ProfileDatabaseTests.swift +++ b/damusTests/ProfileDatabaseTests.swift @@ -30,7 +30,7 @@ class ProfileDatabaseTests: XCTestCase { nip05: "test-nip05") } - func testStoreAndRetrieveProfile() throws { + func testStoreAndRetrieveProfile() async throws { let id = "test-id" let profile = test_profile @@ -39,7 +39,7 @@ class ProfileDatabaseTests: XCTestCase { XCTAssertNil(database.get(id: id)) // store the profile - try database.upsert(id: id, profile: profile, last_update: .now) + try await database.upsert(id: id, profile: profile, last_update: .now) // read the profile out of the database let retrievedProfile = try XCTUnwrap(database.get(id: id)) @@ -55,50 +55,55 @@ class ProfileDatabaseTests: XCTestCase { XCTAssertEqual(profile.nip05, retrievedProfile.nip05) } - func testRejectOutdatedProfile() throws { + func testRejectOutdatedProfile() async throws { let id = "test-id" // store a profile let profile = test_profile let profile_last_updated = Date.now - try database.upsert(id: id, profile: profile, last_update: profile_last_updated) + try await database.upsert(id: id, profile: profile, last_update: profile_last_updated) // try to store a profile with the same id but the last_update date is older than the previously stored profile let outdatedProfile = test_profile let outdated_last_updated = profile_last_updated.addingTimeInterval(-60) - XCTAssertThrowsError(try database.upsert(id: id, profile: outdatedProfile, last_update: outdated_last_updated)) { error in - XCTAssertEqual(error as? ProfileDatabaseError, ProfileDatabaseError.outdated_input) + do { + try await database.upsert(id: id, profile: outdatedProfile, last_update: outdated_last_updated) + XCTFail("expected to throw error") + } catch let error as ProfileDatabaseError { + XCTAssertEqual(error, ProfileDatabaseError.outdated_input) + } catch { + XCTFail("not the expected error") } } - func testUpdateExistingProfile() throws { + func testUpdateExistingProfile() async throws { let id = "test-id" // store a profile let profile = test_profile let profile_last_update = Date.now - try database.upsert(id: id, profile: profile, last_update: profile_last_update) + try await database.upsert(id: id, profile: profile, last_update: profile_last_update) // update the same profile let updated_profile = test_profile updated_profile.nip05 = "updated-nip05" let updated_profile_last_update = profile_last_update.addingTimeInterval(60) - try database.upsert(id: id, profile: updated_profile, last_update: updated_profile_last_update) + try await database.upsert(id: id, profile: updated_profile, last_update: updated_profile_last_update) // retrieve the profile and make sure it was updated let retrieved_profile = database.get(id: id) XCTAssertEqual(retrieved_profile?.nip05, "updated-nip05") } - func testStoreMultipleAndRemoveAllProfiles() throws { + func testStoreMultipleAndRemoveAllProfiles() async throws { XCTAssertEqual(database.count, 0) // store a profile let id = "test-id" let profile = test_profile let profile_last_update = Date.now - try database.upsert(id: id, profile: profile, last_update: profile_last_update) + try await database.upsert(id: id, profile: profile, last_update: profile_last_update) XCTAssertEqual(database.count, 1) @@ -106,7 +111,7 @@ class ProfileDatabaseTests: XCTestCase { let id2 = "test-id-2" let profile2 = test_profile let profile_last_update2 = Date.now - try database.upsert(id: id2, profile: profile2, last_update: profile_last_update2) + try await database.upsert(id: id2, profile: profile2, last_update: profile_last_update2) XCTAssertEqual(database.count, 2)