1
0
mirror of git://jb55.com/damus synced 2024-09-18 19:23:49 +00:00

make database write async at the call site and update tests

This commit is contained in:
Bryan Montz 2023-05-25 09:09:50 -05:00
parent 7259641e26
commit 61ff7da2ae
3 changed files with 41 additions and 36 deletions

View File

@ -99,33 +99,31 @@ final class ProfileDatabase {
/// - id: Profile id (pubkey) /// - id: Profile id (pubkey)
/// - profile: Profile object to be stored /// - profile: Profile object to be stored
/// - last_update: Date that the Profile was updated /// - 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 { guard let context = background_context else {
throw ProfileDatabaseError.missing_context throw ProfileDatabaseError.missing_context
} }
Task { try await context.perform {
try await context.perform { var persisted_profile: PersistedProfile?
var persisted_profile: PersistedProfile? if let profile = self.get_persisted(id: id, context: context) {
if let profile = self.get_persisted(id: id, context: context) { if let existing_last_update = profile.last_update, last_update < existing_last_update {
if let existing_last_update = profile.last_update, last_update < existing_last_update { throw ProfileDatabaseError.outdated_input
throw ProfileDatabaseError.outdated_input
} else {
persisted_profile = profile
}
} else { } else {
persisted_profile = NSEntityDescription.insertNewObject(forEntityName: self.entity_name, into: context) as? PersistedProfile persisted_profile = profile
persisted_profile?.id = id
} }
persisted_profile?.copyValues(from: profile) } else {
persisted_profile?.last_update = last_update persisted_profile = NSEntityDescription.insertNewObject(forEntityName: self.entity_name, into: context) as? PersistedProfile
persisted_profile?.id = id
let pull_date = Date.now
persisted_profile?.network_pull_date = pull_date
self.network_pull_date_cache[id] = pull_date
try context.save()
} }
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()
} }
} }

View File

@ -37,10 +37,12 @@ class Profiles {
self.profiles[id] = profile self.profiles[id] = profile
} }
do { Task {
try database.upsert(id: id, profile: profile.profile, last_update: Date(timeIntervalSince1970: TimeInterval(profile.timestamp))) do {
} catch { try await database.upsert(id: id, profile: profile.profile, last_update: Date(timeIntervalSince1970: TimeInterval(profile.timestamp)))
print("⚠️ Warning: Profiles failed to save a profile: \(error)") } catch {
print("⚠️ Warning: Profiles failed to save a profile: \(error)")
}
} }
} }

View File

@ -30,7 +30,7 @@ class ProfileDatabaseTests: XCTestCase {
nip05: "test-nip05") nip05: "test-nip05")
} }
func testStoreAndRetrieveProfile() throws { func testStoreAndRetrieveProfile() async throws {
let id = "test-id" let id = "test-id"
let profile = test_profile let profile = test_profile
@ -39,7 +39,7 @@ class ProfileDatabaseTests: XCTestCase {
XCTAssertNil(database.get(id: id)) XCTAssertNil(database.get(id: id))
// store the profile // 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 // read the profile out of the database
let retrievedProfile = try XCTUnwrap(database.get(id: id)) let retrievedProfile = try XCTUnwrap(database.get(id: id))
@ -55,50 +55,55 @@ class ProfileDatabaseTests: XCTestCase {
XCTAssertEqual(profile.nip05, retrievedProfile.nip05) XCTAssertEqual(profile.nip05, retrievedProfile.nip05)
} }
func testRejectOutdatedProfile() throws { func testRejectOutdatedProfile() async throws {
let id = "test-id" let id = "test-id"
// store a profile // store a profile
let profile = test_profile let profile = test_profile
let profile_last_updated = Date.now 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 // 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 outdatedProfile = test_profile
let outdated_last_updated = profile_last_updated.addingTimeInterval(-60) let outdated_last_updated = profile_last_updated.addingTimeInterval(-60)
XCTAssertThrowsError(try database.upsert(id: id, profile: outdatedProfile, last_update: outdated_last_updated)) { error in do {
XCTAssertEqual(error as? ProfileDatabaseError, ProfileDatabaseError.outdated_input) 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" let id = "test-id"
// store a profile // store a profile
let profile = test_profile let profile = test_profile
let profile_last_update = Date.now 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 // update the same profile
let updated_profile = test_profile let updated_profile = test_profile
updated_profile.nip05 = "updated-nip05" updated_profile.nip05 = "updated-nip05"
let updated_profile_last_update = profile_last_update.addingTimeInterval(60) 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 // retrieve the profile and make sure it was updated
let retrieved_profile = database.get(id: id) let retrieved_profile = database.get(id: id)
XCTAssertEqual(retrieved_profile?.nip05, "updated-nip05") XCTAssertEqual(retrieved_profile?.nip05, "updated-nip05")
} }
func testStoreMultipleAndRemoveAllProfiles() throws { func testStoreMultipleAndRemoveAllProfiles() async throws {
XCTAssertEqual(database.count, 0) XCTAssertEqual(database.count, 0)
// store a profile // store a profile
let id = "test-id" let id = "test-id"
let profile = test_profile let profile = test_profile
let profile_last_update = Date.now 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) XCTAssertEqual(database.count, 1)
@ -106,7 +111,7 @@ class ProfileDatabaseTests: XCTestCase {
let id2 = "test-id-2" let id2 = "test-id-2"
let profile2 = test_profile let profile2 = test_profile
let profile_last_update2 = Date.now 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) XCTAssertEqual(database.count, 2)