refactor(relay): drop LocalRelayConfig and local relay runtime forwarding
Removes LocalRelayConfig, LocalRelayWritePolicy, the LOCAL value in RelaySetType, and isLocalRelayUrl from RelayConfig.kt. Strips local relay state, forwarding paths, lifecycle pause/resume, and the own-notes OutboxRouter branch from the relay layer.
This commit is contained in:
@@ -277,15 +277,6 @@ class OutboxRouter(
|
||||
targetedRelays.addAll(relayPool.getRelayUrls())
|
||||
}
|
||||
|
||||
// Also query local relay for own notes
|
||||
if (pubkey == relayPool.localRelayUserPubkey) {
|
||||
val localUrl = relayPool.getLocalRelayUrl()
|
||||
if (localUrl != null) {
|
||||
relayPool.sendToLocalRelay(ClientMessage.req(subId, filter))
|
||||
targetedRelays.add(localUrl)
|
||||
}
|
||||
}
|
||||
|
||||
return targetedRelays
|
||||
}
|
||||
|
||||
|
||||
@@ -2,22 +2,11 @@ package com.wisp.app.relay
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
enum class LocalRelayWritePolicy { OWN_NOTES, TAGGED, ALL_NOTES }
|
||||
|
||||
@Serializable
|
||||
data class LocalRelayConfig(
|
||||
val url: String,
|
||||
val enabled: Boolean = true,
|
||||
val writePolicy: LocalRelayWritePolicy = LocalRelayWritePolicy.OWN_NOTES,
|
||||
val kinds: Set<Int> = setOf(1, 1059, 9735)
|
||||
)
|
||||
|
||||
enum class RelaySetType(val displayName: String, val eventKind: Int) {
|
||||
GENERAL("General", 10002),
|
||||
DM("DM", 10050),
|
||||
SEARCH("Search", 10007),
|
||||
BLOCKED("Blocked", 10006),
|
||||
LOCAL("Local", 0)
|
||||
BLOCKED("Blocked", 10006)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -67,18 +56,5 @@ data class RelayConfig(
|
||||
return true
|
||||
}
|
||||
|
||||
private val LOCAL_HOST_REGEX = Regex(
|
||||
"^ws://(" +
|
||||
"localhost|" +
|
||||
"127\\.0\\.0\\.1|" +
|
||||
"10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
|
||||
"192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
|
||||
"172\\.(1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|" +
|
||||
"[\\w.-]+:\\d+" + // any host with explicit port
|
||||
")(:\\d+)?(/.*)?$"
|
||||
)
|
||||
|
||||
/** Returns true if the URL is a local/private relay (ws:// with localhost, loopback, or private IP). */
|
||||
fun isLocalRelayUrl(url: String): Boolean = LOCAL_HOST_REGEX.matches(url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ class RelayLifecycleManager(
|
||||
Log.d("RLC", "[Lifecycle] onAppPause — connectedCount=${relayPool.connectedCount.value}")
|
||||
relayPool.appIsActive = false
|
||||
relayPool.healthTracker?.closeAllSessions()
|
||||
relayPool.pauseLocalRelay()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +111,6 @@ class RelayLifecycleManager(
|
||||
// Set suppression window to prevent network-change reconnects from
|
||||
// firing shortly after this resume and causing a double reconnect.
|
||||
resumeReconnectUntilMs = System.currentTimeMillis() + RESUME_SUPPRESSION_MS
|
||||
relayPool.resumeLocalRelay()
|
||||
reconnect(force = force)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,11 +47,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
private var blockedUrls = emptySet<String>()
|
||||
fun getBlockedUrls(): Set<String> = blockedUrls
|
||||
|
||||
// --- Local relay ---
|
||||
private var localRelay: Relay? = null
|
||||
private var localRelayConfig: LocalRelayConfig? = null
|
||||
@Volatile var localRelayUserPubkey: String? = null
|
||||
|
||||
/** URLs tagged as recipient DM delivery relays (tier 2 for AUTH). */
|
||||
private val dmDeliveryTargets: MutableSet<String> = java.util.concurrent.ConcurrentHashMap.newKeySet()
|
||||
|
||||
@@ -409,10 +404,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
}
|
||||
_events.tryEmit(msg.event)
|
||||
_relayEvents.tryEmit(RelayEvent(msg.event, relay.config.url, msg.subscriptionId))
|
||||
// Forward to local relay (fire-and-forget)
|
||||
if (localRelay != null && relay !== localRelay && shouldForwardToLocalRelay(msg.event)) {
|
||||
localRelay?.send(ClientMessage.event(msg.event))
|
||||
}
|
||||
subEventCounts.getOrPut(msg.subscriptionId) { java.util.concurrent.atomic.AtomicInteger(0) }.incrementAndGet()
|
||||
if (msg.subscriptionId.startsWith("feed")) {
|
||||
val count = ++feedEventCounter
|
||||
@@ -607,10 +598,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
if (isEvent && appIsActive) healthTracker?.onEventSent(relay.config.url, message.length)
|
||||
}
|
||||
}
|
||||
// Also forward to local relay for own published events
|
||||
if (isEvent && localRelay != null && localRelayConfig?.enabled == true) {
|
||||
localRelay?.send(message)
|
||||
}
|
||||
return sentCount
|
||||
}
|
||||
|
||||
@@ -846,7 +833,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
*/
|
||||
fun connectEphemeralRelay(url: String) {
|
||||
if (url in blockedUrls) return
|
||||
if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return
|
||||
if (!RelayConfig.isValidUrl(url)) return
|
||||
if (ephemeralRelays.containsKey(url) || relayIndex.containsKey(url)) return
|
||||
if (ephemeralRelays.size >= MAX_EPHEMERAL) return
|
||||
ephemeralRelays.computeIfAbsent(url) {
|
||||
@@ -870,7 +857,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
): Boolean {
|
||||
if (url in blockedUrls) return false
|
||||
if (!skipBadCheck && healthTracker?.isBad(url) == true) return false
|
||||
if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return false
|
||||
if (!RelayConfig.isValidUrl(url)) return false
|
||||
|
||||
// Check cooldown for failed relays
|
||||
val cooldownUntil = relayCooldowns[url]
|
||||
@@ -1199,7 +1186,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
*/
|
||||
fun preConnectEphemeral(url: String) {
|
||||
if (url in blockedUrls) return
|
||||
if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return
|
||||
if (!RelayConfig.isValidUrl(url)) return
|
||||
if (ephemeralRelays.containsKey(url)) return
|
||||
if (ephemeralRelays.size >= MAX_EPHEMERAL) return
|
||||
val relay = Relay(RelayConfig(url, read = true, write = false), client, scope)
|
||||
@@ -1272,97 +1259,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Local relay management ---
|
||||
|
||||
fun updateLocalRelay(config: LocalRelayConfig?, userPubkey: String?) {
|
||||
localRelayUserPubkey = userPubkey
|
||||
val oldRelay = localRelay
|
||||
val oldUrl = oldRelay?.config?.url
|
||||
|
||||
if (config == null || !config.enabled) {
|
||||
// Remove local relay
|
||||
if (oldRelay != null) {
|
||||
oldRelay.forceDisconnect()
|
||||
cancelRelayJobs(oldRelay.config.url)
|
||||
relayIndex.remove(oldRelay.config.url)
|
||||
localRelay = null
|
||||
localRelayConfig = null
|
||||
Log.d("RLC", "[Pool] local relay removed: $oldUrl")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
localRelayConfig = config
|
||||
|
||||
if (oldUrl == config.url && oldRelay != null) {
|
||||
// URL unchanged — just update config, reconnect if needed.
|
||||
// Re-enable auto-reconnect in case the relay was paused via pauseLocalRelay().
|
||||
oldRelay.reconnectEnabled = true
|
||||
if (!oldRelay.isConnected) oldRelay.connect()
|
||||
return
|
||||
}
|
||||
|
||||
// Disconnect old if URL changed
|
||||
if (oldRelay != null) {
|
||||
oldRelay.forceDisconnect()
|
||||
cancelRelayJobs(oldRelay.config.url)
|
||||
relayIndex.remove(oldRelay.config.url)
|
||||
}
|
||||
|
||||
// Create new local relay connection
|
||||
val relayConfig = RelayConfig(config.url, read = true, write = true)
|
||||
val relay = Relay(relayConfig, client)
|
||||
localRelay = relay
|
||||
relayIndex[config.url] = relay
|
||||
collectMessages(relay)
|
||||
|
||||
relay.connect()
|
||||
Log.d("RLC", "[Pool] local relay connected: ${config.url}")
|
||||
}
|
||||
|
||||
/** Disconnect local relay socket but preserve references for cheap resume. */
|
||||
fun pauseLocalRelay() {
|
||||
val relay = localRelay ?: return
|
||||
relay.reconnectEnabled = false
|
||||
relay.disconnect()
|
||||
Log.d("RLC", "[Pool] local relay paused: ${relay.config.url}")
|
||||
}
|
||||
|
||||
/** Reconnect local relay if still configured and enabled. Safe to call repeatedly. */
|
||||
fun resumeLocalRelay() {
|
||||
val relay = localRelay ?: return
|
||||
val cfg = localRelayConfig ?: return
|
||||
if (!cfg.enabled) return
|
||||
relay.reconnectEnabled = true
|
||||
relay.resetBackoff()
|
||||
if (!relay.isConnected) relay.connect()
|
||||
Log.d("RLC", "[Pool] local relay resumed: ${relay.config.url}")
|
||||
}
|
||||
|
||||
fun getLocalRelayUrl(): String? = localRelayConfig?.url
|
||||
|
||||
/** Send a message to the local relay if configured and connected. Fire-and-forget. */
|
||||
fun sendToLocalRelay(message: String): Boolean {
|
||||
val relay = localRelay ?: return false
|
||||
if (localRelayConfig?.enabled != true) return false
|
||||
return relay.send(message)
|
||||
}
|
||||
|
||||
private fun shouldForwardToLocalRelay(event: NostrEvent): Boolean {
|
||||
val config = localRelayConfig ?: return false
|
||||
if (!config.enabled) return false
|
||||
if (localRelay == null) return false
|
||||
if (event.kind !in config.kinds) return false
|
||||
return when (config.writePolicy) {
|
||||
LocalRelayWritePolicy.OWN_NOTES -> event.pubkey == localRelayUserPubkey
|
||||
LocalRelayWritePolicy.TAGGED -> {
|
||||
event.pubkey == localRelayUserPubkey ||
|
||||
event.tags.any { it.size >= 2 && it[0] == "p" && it[1] == localRelayUserPubkey }
|
||||
}
|
||||
LocalRelayWritePolicy.ALL_NOTES -> true
|
||||
}
|
||||
}
|
||||
|
||||
fun disconnectAll() {
|
||||
relays.forEach { it.forceDisconnect() }
|
||||
relays.clear()
|
||||
@@ -1374,9 +1270,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) {
|
||||
ephemeralRelays.clear()
|
||||
ephemeralLastUsed.clear()
|
||||
relayCooldowns.clear()
|
||||
localRelay?.forceDisconnect()
|
||||
localRelay = null
|
||||
localRelayConfig = null
|
||||
relayIndex.clear()
|
||||
relayJobs.values.forEach { it.cancel() }
|
||||
relayJobs.clear()
|
||||
|
||||
Reference in New Issue
Block a user