chore: improve event syncing #29
@@ -24,7 +24,7 @@ kotlin {
|
|||||||
implementation(libs.jetbrains.navigation3.ui)
|
implementation(libs.jetbrains.navigation3.ui)
|
||||||
implementation(libs.jetbrains.lifecycle.viewmodelNavigation3)
|
implementation(libs.jetbrains.lifecycle.viewmodelNavigation3)
|
||||||
implementation(libs.androidx.core.splashscreen)
|
implementation(libs.androidx.core.splashscreen)
|
||||||
implementation("su.reya:nostr-sdk-kmp:0.3.1")
|
implementation("su.reya:nostr-sdk-kmp:0.3.2")
|
||||||
implementation("io.coil-kt.coil3:coil-compose:3.4.0")
|
implementation("io.coil-kt.coil3:coil-compose:3.4.0")
|
||||||
implementation("io.coil-kt.coil3:coil-network-okhttp:3.4.0")
|
implementation("io.coil-kt.coil3:coil-network-okhttp:3.4.0")
|
||||||
implementation("io.github.kalinjul.easyqrscan:scanner:0.7.0")
|
implementation("io.github.kalinjul.easyqrscan:scanner:0.7.0")
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ kotlin {
|
|||||||
implementation(libs.androidx.lifecycle.runtimeCompose)
|
implementation(libs.androidx.lifecycle.runtimeCompose)
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
||||||
implementation("su.reya:nostr-sdk-kmp:0.3.1")
|
implementation("su.reya:nostr-sdk-kmp:0.3.2")
|
||||||
implementation("com.squareup.okio:okio:3.16.2")
|
implementation("com.squareup.okio:okio:3.16.2")
|
||||||
}
|
}
|
||||||
androidMain.dependencies {
|
androidMain.dependencies {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import rust.nostr.sdk.extractRelayList
|
|||||||
import rust.nostr.sdk.initLogger
|
import rust.nostr.sdk.initLogger
|
||||||
import rust.nostr.sdk.nip17ExtractRelayList
|
import rust.nostr.sdk.nip17ExtractRelayList
|
||||||
import rust.nostr.sdk.nip59MakeGiftWrapAsync
|
import rust.nostr.sdk.nip59MakeGiftWrapAsync
|
||||||
import kotlin.coroutines.cancellation.CancellationException
|
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
object NostrManager {
|
object NostrManager {
|
||||||
@@ -65,7 +64,8 @@ object NostrManager {
|
|||||||
|
|
||||||
val BOOTSTRAP_RELAYS = listOf(
|
val BOOTSTRAP_RELAYS = listOf(
|
||||||
"wss://relay.primal.net",
|
"wss://relay.primal.net",
|
||||||
"wss://purplepag.es"
|
"wss://relay.ditto.pub",
|
||||||
|
"wss://user.kindpag.es",
|
||||||
)
|
)
|
||||||
|
|
||||||
val INDEXER_RELAY = listOf(
|
val INDEXER_RELAY = listOf(
|
||||||
@@ -286,12 +286,14 @@ class Nostr {
|
|||||||
|
|
||||||
launch(Dispatchers.Default) {
|
launch(Dispatchers.Default) {
|
||||||
for (event in giftWrapQueue) {
|
for (event in giftWrapQueue) {
|
||||||
val rumor = extractRumor(event) ?: continue
|
val rumor = extractRumor(event)
|
||||||
processedCount++
|
processedCount++
|
||||||
|
|
||||||
// Trigger new message notification
|
// Trigger new message notification
|
||||||
if (rumor.createdAt().asSecs() >= now.asSecs()) {
|
if (rumor != null) {
|
||||||
onNewMessage(rumor)
|
if (rumor.createdAt().asSecs() >= now.asSecs()) {
|
||||||
|
onNewMessage(rumor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sync state
|
// Update sync state
|
||||||
@@ -390,7 +392,7 @@ class Nostr {
|
|||||||
private suspend fun getMutualContacts(pubkeys: List<PublicKey>) {
|
private suspend fun getMutualContacts(pubkeys: List<PublicKey>) {
|
||||||
try {
|
try {
|
||||||
val kind = Kind.fromStd(KindStandard.CONTACT_LIST)
|
val kind = Kind.fromStd(KindStandard.CONTACT_LIST)
|
||||||
val filter = Filter().kind(kind).authors(pubkeys).limit(200u)
|
val filter = Filter().kind(kind).authors(pubkeys).limit(pubkeys.size.toULong())
|
||||||
val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose)
|
val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose)
|
||||||
|
|
||||||
val target = mutableMapOf<RelayUrl, List<Filter>>()
|
val target = mutableMapOf<RelayUrl, List<Filter>>()
|
||||||
@@ -485,8 +487,6 @@ class Nostr {
|
|||||||
setCachedRumor(event.id(), unsignedEvent)
|
setCachedRumor(event.id(), unsignedEvent)
|
||||||
|
|
||||||
return unsignedEvent
|
return unsignedEvent
|
||||||
} catch (e: CancellationException) {
|
|
||||||
throw e
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
println("Failed to unwrap gift ${event.id().toHex()}: ${e.message}")
|
println("Failed to unwrap gift ${event.id().toHex()}: ${e.message}")
|
||||||
return null
|
return null
|
||||||
@@ -647,7 +647,7 @@ class Nostr {
|
|||||||
|
|
||||||
suspend fun fetchMetadataBatch(keys: List<PublicKey>) {
|
suspend fun fetchMetadataBatch(keys: List<PublicKey>) {
|
||||||
try {
|
try {
|
||||||
val limit = keys.size.toULong() * 4u
|
val limit = keys.size.toULong() * 2u
|
||||||
val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose)
|
val opts = SubscribeAutoCloseOptions().exitPolicy(ReqExitPolicy.ExitOnEose)
|
||||||
|
|
||||||
// Construct a filter for metadata events
|
// Construct a filter for metadata events
|
||||||
@@ -656,16 +656,13 @@ class Nostr {
|
|||||||
.authors(keys)
|
.authors(keys)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
|
|
||||||
// Construct a target that includes all filters
|
// Construct request target
|
||||||
val target =
|
val target = mutableMapOf<RelayUrl, List<Filter>>()
|
||||||
ReqTarget.manual(
|
NostrManager.BOOTSTRAP_RELAYS.forEach { relay ->
|
||||||
mapOf(
|
target[RelayUrl.parse(relay)] = listOf(filter)
|
||||||
RelayUrl.parse("wss://purplepag.es") to listOf(filter),
|
}
|
||||||
RelayUrl.parse("wss://relay.primal.net") to listOf(filter),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
client?.subscribe(target = target, closeOn = opts)
|
client?.subscribe(target = ReqTarget.manual(target), closeOn = opts)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw IllegalStateException("Failed to fetch metadata batch: ${e.message}", e)
|
throw IllegalStateException("Failed to fetch metadata batch: ${e.message}", e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,16 +213,20 @@ class NostrViewModel(
|
|||||||
val timeout = 500L // 500ms timeout for batching
|
val timeout = 500L // 500ms timeout for batching
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
// Get the first pubkey
|
||||||
val firstKey = metadataRequestChannel.receive()
|
val firstKey = metadataRequestChannel.receive()
|
||||||
batch.add(firstKey)
|
batch.add(firstKey)
|
||||||
|
|
||||||
|
// Get current time
|
||||||
val lastFlushTime = Clock.System.now().toEpochMilliseconds()
|
val lastFlushTime = Clock.System.now().toEpochMilliseconds()
|
||||||
|
|
||||||
while (batch.isNotEmpty()) {
|
while (batch.isNotEmpty()) {
|
||||||
|
// Get the next pubkey
|
||||||
val nextKey = withTimeoutOrNull(timeout.milliseconds) {
|
val nextKey = withTimeoutOrNull(timeout.milliseconds) {
|
||||||
metadataRequestChannel.receive()
|
metadataRequestChannel.receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add the key if it's not null
|
// Only add the pubkey if it's not null
|
||||||
if (nextKey != null) batch.add(nextKey)
|
if (nextKey != null) batch.add(nextKey)
|
||||||
|
|
||||||
// Get current time
|
// Get current time
|
||||||
|
|||||||
Reference in New Issue
Block a user