Migrates channel notes to LargeCache

This commit is contained in:
Vitor Pamplona
2024-03-21 08:51:23 -04:00
parent 64909bfb32
commit 67202c32d4
8 changed files with 38 additions and 28 deletions
@@ -22,9 +22,11 @@ package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.vitorpamplona.amethyst.commons.data.LargeCache
import com.vitorpamplona.amethyst.service.NostrSingleChannelDataSource import com.vitorpamplona.amethyst.service.NostrSingleChannelDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.ui.components.BundledUpdate import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.note.toShortenHex import com.vitorpamplona.amethyst.ui.note.toShortenHex
import com.vitorpamplona.quartz.encoders.ATag import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.Hex import com.vitorpamplona.quartz.encoders.Hex
@@ -33,7 +35,6 @@ import com.vitorpamplona.quartz.encoders.toNote
import com.vitorpamplona.quartz.events.ChannelCreateEvent import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.LiveActivitiesEvent import com.vitorpamplona.quartz.events.LiveActivitiesEvent
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import java.util.concurrent.ConcurrentHashMap
@Stable @Stable
class PublicChatChannel(idHex: String) : Channel(idHex) { class PublicChatChannel(idHex: String) : Channel(idHex) {
@@ -110,7 +111,7 @@ abstract class Channel(val idHex: String) {
var updatedMetadataAt: Long = 0 var updatedMetadataAt: Long = 0
val notes = ConcurrentHashMap<HexKey, Note>() val notes = LargeCache<HexKey, Note>()
open fun id() = Hex.decode(idHex) open fun id() = Hex.decode(idHex)
@@ -145,7 +146,7 @@ abstract class Channel(val idHex: String) {
} }
fun addNote(note: Note) { fun addNote(note: Note) {
notes[note.idHex] = note notes.put(note.idHex, note)
} }
fun removeNote(note: Note) { fun removeNote(note: Note) {
@@ -163,18 +164,18 @@ abstract class Channel(val idHex: String) {
fun pruneOldAndHiddenMessages(account: Account): Set<Note> { fun pruneOldAndHiddenMessages(account: Account): Set<Note> {
val important = val important =
notes.values notes.filter { key, it ->
.filter { it.author?.let { it1 -> account.isHidden(it1) } == false } it.author?.let { author -> account.isHidden(author) } == false
.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) }
.reversed() .sortedWith(DefaultFeedOrder)
.take(1000) .take(500)
.toSet() .toSet()
val toBeRemoved = notes.values.filter { it !in important }.toSet() val toBeRemoved = notes.filter { key, it -> it !in important }
toBeRemoved.forEach { notes.remove(it.idHex) } toBeRemoved.forEach { notes.remove(it.idHex) }
return toBeRemoved return toBeRemoved.toSet()
} }
} }
@@ -1780,9 +1780,9 @@ object LocalCache {
removeFromCache(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
if (toBeRemoved.size > 100 || it.value.notes.size > 100) { if (toBeRemoved.size > 100 || it.value.notes.size() > 100) {
println( println(
"PRUNE: ${toBeRemoved.size} messages removed from ${it.value.toBestDisplayName()}. ${it.value.notes.size} kept", "PRUNE: ${toBeRemoved.size} messages removed from ${it.value.toBestDisplayName()}. ${it.value.notes.size()} kept",
) )
} }
} }
@@ -171,7 +171,8 @@ open class Note(val idHex: String) {
event is LiveActivitiesEvent event is LiveActivitiesEvent
) { ) {
(event as? ChannelMessageEvent)?.channel() (event as? ChannelMessageEvent)?.channel()
?: (event as? ChannelMetadataEvent)?.channel() ?: (event as? ChannelCreateEvent)?.id ?: (event as? ChannelMetadataEvent)?.channel()
?: (event as? ChannelCreateEvent)?.id
?: (event as? LiveActivitiesChatMessageEvent)?.activity()?.toTag() ?: (event as? LiveActivitiesChatMessageEvent)?.activity()?.toTag()
?: (event as? LiveActivitiesEvent)?.address()?.toTag() ?: (event as? LiveActivitiesEvent)?.address()?.toTag()
} else { } else {
@@ -96,7 +96,7 @@ class ParticipantListBuilder {
it.replyTo?.forEach { addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet) } it.replyTo?.forEach { addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet) }
} }
LocalCache.getChannelIfExists(baseNote.idHex)?.notes?.values?.forEach { LocalCache.getChannelIfExists(baseNote.idHex)?.notes?.forEach { key, it ->
addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet) addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet)
} }
@@ -31,10 +31,11 @@ class ChannelFeedFilter(val channel: Channel, val account: Account) : AdditiveFe
// returns the last Note of each user. // returns the last Note of each user.
override fun feed(): List<Note> { override fun feed(): List<Note> {
return channel.notes.values return sort(
.filter { account.isAcceptable(it) } channel.notes.filterIntoSet { key, it ->
.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) account.isAcceptable(it)
.reversed() },
)
} }
override fun applyFilter(collection: Set<Note>): Set<Note> { override fun applyFilter(collection: Set<Note>): Set<Note> {
@@ -56,15 +56,12 @@ class ChatroomListKnownFeedFilter(val account: Account) : AdditiveFeedFilter<Not
.selectedChatsFollowList() .selectedChatsFollowList()
.mapNotNull { LocalCache.getChannelIfExists(it) } .mapNotNull { LocalCache.getChannelIfExists(it) }
.mapNotNull { it -> .mapNotNull { it ->
it.notes.values it.notes.filter { key, it -> account.isAcceptable(it) && it.event != null }
.filter { account.isAcceptable(it) && it.event != null } .sortedWith(DefaultFeedOrder)
.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) .firstOrNull()
.lastOrNull()
} }
return (privateMessages + publicChannels) return (privateMessages + publicChannels).sortedWith(DefaultFeedOrder)
.sortedWith(compareBy({ it.createdAt() }, { it.idHex }))
.reversed()
} }
override fun updateListWith( override fun updateListWith(
@@ -48,9 +48,8 @@ open class DiscoverLiveFeedFilter(
} }
override fun feed(): List<Note> { override fun feed(): List<Note> {
val allChannelNotes = val allChannelNotes = LocalCache.channels.values.mapNotNull { LocalCache.getNoteIfExists(it.idHex) }
LocalCache.channels.values.mapNotNull { LocalCache.getNoteIfExists(it.idHex) } val allMessageNotes = LocalCache.channels.values.map { it.notes.filter { key, it -> it.event is LiveActivitiesEvent } }.flatten()
val allMessageNotes = LocalCache.channels.values.map { it.notes.values }.flatten()
val notes = innerApplyFilter(allChannelNotes + allMessageNotes) val notes = innerApplyFilter(allChannelNotes + allMessageNotes)
@@ -32,6 +32,17 @@ class LargeCache<K, V> {
fun size() = cache.size fun size() = cache.size
fun isEmpty() = cache.isEmpty()
fun containsKey(key: K) = cache.containsKey(key)
fun put(
key: K,
value: V,
) {
cache.put(key, value)
}
fun getOrCreate( fun getOrCreate(
key: K, key: K,
builder: (key: K) -> V, builder: (key: K) -> V,