Fixes the fact that SortedSets can have duplicated objects in parallel adds.
Moves to concurrent sets with a Comparator that checks the object's reference to remove duplications in the set when events from addressables differ
This commit is contained in:
@@ -32,11 +32,11 @@ import com.vitorpamplona.amethyst.commons.model.privateChats.ChatroomList
|
||||
import com.vitorpamplona.amethyst.commons.services.nwc.NwcPaymentTracker
|
||||
import com.vitorpamplona.amethyst.isDebug
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState
|
||||
import com.vitorpamplona.amethyst.model.observables.CreatedAtIdHexComparator
|
||||
import com.vitorpamplona.amethyst.model.observables.EventListMatchingFilter
|
||||
import com.vitorpamplona.amethyst.model.observables.NoteListMatchingFilter
|
||||
import com.vitorpamplona.amethyst.service.BundledInsert
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.note.dateFormatter
|
||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||
@@ -307,7 +307,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
(addressableMatches + noteMatches)
|
||||
}
|
||||
|
||||
return limitedSet.toSortedSet(DefaultFeedOrder)
|
||||
return limitedSet.toSortedSet(CreatedAtIdHexComparator)
|
||||
}
|
||||
|
||||
fun observeNotes(filter: Filter): Flow<List<Note>> =
|
||||
|
||||
+26
@@ -23,6 +23,32 @@ package com.vitorpamplona.amethyst.model.observables
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
|
||||
val CreatedAtIdHexComparator: Comparator<Note> =
|
||||
Comparator { note1, note2 ->
|
||||
// Sort by created_at and idhex, but define uniqueness by reference
|
||||
if (note1 === note2) return@Comparator 0
|
||||
|
||||
if (note1 == null) return@Comparator 1 // null is greater, moves to last
|
||||
if (note2 == null) return@Comparator -1 // null is greater, moves to last
|
||||
|
||||
val createdAt1 = note1.createdAt()
|
||||
val createdAt2 = note2.createdAt()
|
||||
|
||||
if (createdAt1 == createdAt2) {
|
||||
val event1 = note1.event
|
||||
val event2 = note2.event
|
||||
|
||||
if (event1 == null && event2 == null) return@Comparator 0
|
||||
if (event1 == null) return@Comparator 1 // null is greater, moves to last
|
||||
if (event2 == null) return@Comparator -1 // null is greater, moves to last
|
||||
|
||||
event1.id.compareTo(event2.id)
|
||||
} else {
|
||||
// Descending, inverts
|
||||
compareValues(createdAt2, createdAt1)
|
||||
}
|
||||
}
|
||||
|
||||
object CreatedAtComparator : Comparator<Note> {
|
||||
override fun compare(
|
||||
first: Note?,
|
||||
|
||||
+4
-4
@@ -23,10 +23,9 @@ package com.vitorpamplona.amethyst.model.observables
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.Observable
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import java.util.SortedSet
|
||||
import java.util.concurrent.ConcurrentSkipListSet
|
||||
|
||||
/**
|
||||
* Creates a list of events (regular and addressable)
|
||||
@@ -39,7 +38,7 @@ class EventListMatchingFilter(
|
||||
private val update: (List<Event>) -> Unit,
|
||||
) : Observable {
|
||||
// Keeping this here blocks it from being cleared from memory
|
||||
var currentResults: SortedSet<Note> = sortedSetOf<Note>(DefaultFeedOrder)
|
||||
var currentResults: ConcurrentSkipListSet<Note> = ConcurrentSkipListSet(CreatedAtIdHexComparator)
|
||||
|
||||
override fun new(
|
||||
event: Event,
|
||||
@@ -51,6 +50,7 @@ class EventListMatchingFilter(
|
||||
if (limit != null && currentResults.size > limit) {
|
||||
currentResults.remove(currentResults.last())
|
||||
}
|
||||
|
||||
update(currentResults.mapNotNull { it.event })
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class EventListMatchingFilter(
|
||||
}
|
||||
|
||||
fun init() {
|
||||
currentResults = cache.filter(filter)
|
||||
currentResults = ConcurrentSkipListSet(cache.filter(filter))
|
||||
update(currentResults.mapNotNull { it.event })
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -23,10 +23,9 @@ package com.vitorpamplona.amethyst.model.observables
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.Observable
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import java.util.SortedSet
|
||||
import java.util.concurrent.ConcurrentSkipListSet
|
||||
|
||||
/**
|
||||
* Creates a list of notes (regular and addressable)
|
||||
@@ -39,7 +38,7 @@ class NoteListMatchingFilter(
|
||||
private val cache: LocalCache,
|
||||
private val update: (List<Note>) -> Unit,
|
||||
) : Observable {
|
||||
var currentResults: SortedSet<Note> = sortedSetOf<Note>(DefaultFeedOrder)
|
||||
var currentResults: ConcurrentSkipListSet<Note> = ConcurrentSkipListSet(CreatedAtIdHexComparator)
|
||||
|
||||
override fun new(
|
||||
event: Event,
|
||||
@@ -64,7 +63,7 @@ class NoteListMatchingFilter(
|
||||
}
|
||||
|
||||
fun init() {
|
||||
currentResults = cache.filter(filter)
|
||||
currentResults = ConcurrentSkipListSet(cache.filter(filter))
|
||||
update(currentResults.toList())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user