refactor: add relayHints seam to ICacheProvider (Phase 2 prep)

The shared user/event finder filter functions read LocalCache.relayHints
statically to discover which relays likely hold a user's metadata or a missing
event. To let those functions move to commonMain, expose the HintIndexer
(a quartz type) on ICacheProvider. Implement it on Android LocalCache
(override the existing field), add one to DesktopLocalCache, and satisfy the
four commonTest stub caches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-08-10 11:38:09 +03:00
co-authored by Claude Opus 4.8
parent 89b2a273a0
commit 5a245c9f58
7 changed files with 25 additions and 1 deletions
@@ -479,7 +479,7 @@ object LocalCache : ILocalCache, ICacheProvider, Dao {
@Volatile
var lnurlEndpointResolver: LnurlEndpointResolver? = null
val relayHints = HintIndexer()
override val relayHints = HintIndexer()
/**
* Cashu mint URL directory, populated passively as
@@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
/**
* Cache provider interface for accessing cached Notes, Users, and Channels.
@@ -41,6 +42,13 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
* - Platform-agnostic model layer
*/
interface ICacheProvider {
/**
* NIP-hints index (event/address/pubkey → relay) accumulated from consumed
* events. Used by the shared user/event finder assemblers to discover which
* relays are likely to hold a given user's metadata or a missing event.
*/
val relayHints: HintIndexer
/**
* Gets a channel by Note reference.
* Used for resolving relay hints for channel messages.
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
@@ -173,6 +174,8 @@ class ThreadAssemblerTest {
) : ICacheProvider {
override fun getAnyChannel(note: Note): Channel? = null
override val relayHints = HintIndexer()
override fun getUserIfExists(pubkey: HexKey): User? = null
override fun countUsers(predicate: (String, User) -> Boolean): Int = 0
@@ -33,6 +33,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -82,6 +83,8 @@ class ConcordChannelListLeaveTest {
private class StubCache : ICacheProvider {
override fun getAnyChannel(note: Note): Channel? = null
override val relayHints = HintIndexer()
override fun getUserIfExists(pubkey: HexKey): User? = null
override fun countUsers(predicate: (String, User) -> Boolean): Int = 0
@@ -33,6 +33,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -80,6 +81,8 @@ class ConcordListLateArrivalTest {
override fun getAnyChannel(note: Note): Channel? = null
override val relayHints = HintIndexer()
override fun getUserIfExists(pubkey: HexKey): User? = null
override fun countUsers(predicate: (String, User) -> Boolean): Int = 0
@@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -113,6 +114,8 @@ class ReplyContextTest {
) : ICacheProvider {
override fun getAnyChannel(note: Note): Channel? = null
override val relayHints = HintIndexer()
override fun getUserIfExists(pubkey: HexKey): User? = users[pubkey]
override fun countUsers(predicate: (String, User) -> Boolean): Int = 0
@@ -35,6 +35,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.crypto.checkSignature
import com.vitorpamplona.quartz.nip01Core.crypto.verify
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
@@ -90,6 +91,9 @@ class DesktopLocalCache : ICacheProvider {
val addressableNotes = LargeSoftCache<String, AddressableNote>()
private val deletedEvents = ConcurrentHashMap.newKeySet<HexKey>()
/** NIP-hints index accumulated from consumed events (event/address/pubkey → relay). */
override val relayHints = HintIndexer()
val eventStream = DesktopCacheEventStream()
/** Local relay store for persisting events to SQLite. Set from Main.kt on account login. */