From 57c33ae06a29aff53299b9aeda12dc4d62098d4e Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sat, 26 Aug 2023 12:59:41 -0400 Subject: [PATCH] Improves User filters by merging lastEOSEs into a single filter. --- .../service/NostrSingleUserDataSource.kt | 108 +++++++++++------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt index 2b99cb20b..a4fc612d0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt @@ -12,61 +12,60 @@ import com.vitorpamplona.quartz.events.StatusEvent object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") { var usersToWatch = setOf() - fun createUserFilter(): List? { + fun createUserMetadataFilter(): List? { if (usersToWatch.isEmpty()) return null - return usersToWatch.filter { it.info?.latestMetadata == null }.map { - TypedFilter( - types = COMMON_FEED_TYPES, - filter = JsonFilter( - kinds = listOf(MetadataEvent.kind), - authors = listOf(it.pubkeyHex), - limit = 1 - ) - ) - } - } - - fun createUserStatusFilter(): List? { - if (usersToWatch.isEmpty()) return null - - val minLatestEOSEs = mutableMapOf() - usersToWatch.forEach { - it.latestEOSEs.forEach { - val minEose = minLatestEOSEs[it.key] - if (minEose == null) { - minLatestEOSEs.put(it.key, EOSETime(it.value.time)) - } else if (it.value.time < minEose.time) { - minEose.time = it.value.time - } - } - } + val firstTimers = usersToWatch.filter { it.info?.latestMetadata == null }.map { it.pubkeyHex } return listOf( TypedFilter( types = COMMON_FEED_TYPES, filter = JsonFilter( - kinds = listOf(StatusEvent.kind), - authors = usersToWatch.map { it.pubkeyHex }, - since = minLatestEOSEs + kinds = listOf(MetadataEvent.kind, StatusEvent.kind), + authors = firstTimers, + limit = 10 * firstTimers.size ) ) ) } - fun createUserReportFilter(): List? { + fun createUserMetadataFilter(minLatestEOSEs: Map): TypedFilter? { if (usersToWatch.isEmpty()) return null - return usersToWatch.map { - TypedFilter( - types = COMMON_FEED_TYPES, - filter = JsonFilter( - kinds = listOf(ReportEvent.kind), - tags = mapOf("p" to listOf(it.pubkeyHex)), - since = it.latestEOSEs - ) + return TypedFilter( + types = COMMON_FEED_TYPES, + filter = JsonFilter( + kinds = listOf(StatusEvent.kind), + authors = usersToWatch.map { it.pubkeyHex }, + since = minLatestEOSEs ) - } + ) + } + + fun createUserStatusFilter(minLatestEOSEs: Map): TypedFilter? { + if (usersToWatch.isEmpty()) return null + + return TypedFilter( + types = COMMON_FEED_TYPES, + filter = JsonFilter( + kinds = listOf(StatusEvent.kind), + authors = usersToWatch.map { it.pubkeyHex }, + since = minLatestEOSEs + ) + ) + } + + fun createUserReportFilter(minLatestEOSEs: Map): TypedFilter? { + if (usersToWatch.isEmpty()) return null + + return TypedFilter( + types = COMMON_FEED_TYPES, + filter = JsonFilter( + kinds = listOf(ReportEvent.kind), + tags = mapOf("p" to usersToWatch.map { it.pubkeyHex }), + since = minLatestEOSEs + ) + ) } val userChannel = requestNewChannel() { time, relayUrl -> @@ -80,15 +79,38 @@ object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") { } } - val userChannelOnce = requestNewChannel() { time, relayUrl -> + val userChannelFirstTimers = requestNewChannel() { time, relayUrl -> // Many relays operate with limits in the amount of filters. // As information comes, the filters will be rotated to get more data. invalidateFilters() } override fun updateChannelFilters() { - userChannel.typedFilters = listOfNotNull(createUserStatusFilter(), createUserReportFilter()).flatten().ifEmpty { null } - userChannelOnce.typedFilters = listOfNotNull(createUserFilter()).flatten().ifEmpty { null } + val minLatestEOSEs = mutableMapOf() + val neverGottenAnEOSE = mutableSetOf() + usersToWatch.forEach { + if (it.latestEOSEs.isEmpty()) { // first time + neverGottenAnEOSE.add(it.pubkeyHex) + } else { + it.latestEOSEs.forEach { + val minEose = minLatestEOSEs[it.key] + if (minEose == null) { + minLatestEOSEs.put(it.key, EOSETime(it.value.time)) + } else if (it.value.time < minEose.time) { + minEose.time = it.value.time + } + } + } + } + + userChannel.typedFilters = listOfNotNull( + createUserMetadataFilter(minLatestEOSEs), + createUserStatusFilter(minLatestEOSEs), + createUserReportFilter(minLatestEOSEs) + ).ifEmpty { null } + userChannelFirstTimers.typedFilters = listOfNotNull( + createUserMetadataFilter() + ).flatten().ifEmpty { null } } fun add(user: User) {