Fix infinite loading spinner regression
Root cause: 1. `lookup` looks up a note by its note id, and saving its note key 2. `lookup` then returns early (i.e. does not loading anything from the network) since it found the note 3. On the view, once it borrows the note from NostrDB (a query using its NoteKey), the query fails (Most likely due to transaction inheritance and the fact that the inherited transaction may be an older snapshot of the database without the note), causing the view loading logic to fail silently, leading to the infinite loading spinner The issue was addressed by performing a single query during lookup and copying the note contents directly at that point to avoid this transaction inheritance issue. In the future we should consider a more comprehensive fix to address other instances where this may happen. I opened https://github.com/damus-io/damus/issues/3607 for this future work. Changelog-Fixed: Fixed an issue where notes would keep loading indefinitely in some cases Closes: https://github.com/damus-io/damus/issues/3498 Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
@@ -416,8 +416,8 @@ extension NostrNetworkManager {
|
||||
/// to all connected relays. The `timeout` parameter is a total deadline for both phases.
|
||||
func lookup(noteId: NoteId, to targetRelays: [RelayURL]? = nil, timeout: Duration? = nil) async throws -> NdbNoteLender? {
|
||||
// Since note ids point to immutable objects, we can do a simple ndb lookup first
|
||||
if let noteKey = try? self.ndb.lookup_note_key(noteId) {
|
||||
return NdbNoteLender(ndb: self.ndb, noteKey: noteKey)
|
||||
if let note = try? self.ndb.lookup_note_and_copy(noteId) {
|
||||
return NdbNoteLender(ownedNdbNote: note)
|
||||
}
|
||||
|
||||
// Not available in local ndb, stream from network
|
||||
@@ -760,4 +760,4 @@ extension NostrNetworkManager {
|
||||
/// Preload metadata for authors and referenced profiles
|
||||
case preload
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ struct EventLoaderView<Content: View>: View {
|
||||
let relayHints: [RelayURL]
|
||||
@State var event: NostrEvent?
|
||||
@State var subscription_uuid: String = UUID().description
|
||||
@State var loadingTask: Task<Void, Never>? = nil
|
||||
let content: (NostrEvent) -> Content
|
||||
|
||||
/// Creates an event loader view.
|
||||
@@ -34,32 +33,21 @@ struct EventLoaderView<Content: View>: View {
|
||||
let event = damus_state.events.lookup(event_id)
|
||||
_event = State(initialValue: event)
|
||||
}
|
||||
|
||||
func unsubscribe() {
|
||||
self.loadingTask?.cancel()
|
||||
}
|
||||
|
||||
func subscribe() {
|
||||
self.loadingTask?.cancel()
|
||||
self.loadingTask = Task {
|
||||
let targetRelays = relayHints.isEmpty ? nil : relayHints
|
||||
#if DEBUG
|
||||
if let targetRelays, !targetRelays.isEmpty {
|
||||
print("[relay-hints] EventLoaderView: Loading event \(event_id.hex().prefix(8))... with \(targetRelays.count) relay hint(s): \(targetRelays.map { $0.absoluteString })")
|
||||
}
|
||||
#endif
|
||||
let lender = try? await damus_state.nostrNetwork.reader.lookup(noteId: self.event_id, to: targetRelays)
|
||||
lender?.justUseACopy({ event = $0 })
|
||||
#if DEBUG
|
||||
if let targetRelays, !targetRelays.isEmpty {
|
||||
print("[relay-hints] EventLoaderView: Event \(event_id.hex().prefix(8))... loaded: \(event != nil)")
|
||||
}
|
||||
#endif
|
||||
|
||||
func load() async {
|
||||
let targetRelays = relayHints.isEmpty ? nil : relayHints
|
||||
#if DEBUG
|
||||
if let targetRelays, !targetRelays.isEmpty {
|
||||
print("[relay-hints] EventLoaderView: Loading event \(event_id.hex().prefix(8))... with \(targetRelays.count) relay hint(s): \(targetRelays.map { $0.absoluteString })")
|
||||
}
|
||||
}
|
||||
|
||||
func load() {
|
||||
subscribe()
|
||||
#endif
|
||||
let lender = try? await damus_state.nostrNetwork.reader.lookup(noteId: self.event_id, to: targetRelays)
|
||||
lender?.justUseACopy({ event = $0 })
|
||||
#if DEBUG
|
||||
if let targetRelays, !targetRelays.isEmpty {
|
||||
print("[relay-hints] EventLoaderView: Event \(event_id.hex().prefix(8))... loaded: \(event != nil)")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -70,11 +58,11 @@ struct EventLoaderView<Content: View>: View {
|
||||
ProgressView().padding()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
.task {
|
||||
guard event == nil else {
|
||||
return
|
||||
}
|
||||
self.load()
|
||||
await self.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user