From e56e4f79a99ef3b5dca56f47a7e8e31b2ba53d63 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 12 May 2026 13:21:01 +0000 Subject: [PATCH] perf(observeNoteModifications): sample(500) to absorb edit bursts A heavily-edited note can fire `edits.stateFlow` hundreds of times during initial relay sync; without throttling, each emission still hits the IO scan even though `distinctUntilChanged` would collapse most of them downstream. `sample(500)` keeps only the most recent state per ~half second, so the IO `findLatestModificationForNote` runs at most ~twice a second per note instead of once per arrival. --- .../service/relayClient/reqCommand/event/EventObservers.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/EventObservers.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/EventObservers.kt index 1f7a8e31e7..96fa4a6f1a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/EventObservers.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/EventObservers.kt @@ -363,9 +363,11 @@ fun observeNoteOts( // Resolves the actual modification list off the main thread and filters identical results, // so the caller's LaunchedEffect only fires when the list of edits truly changes. +// `sample(500)` collapses bursts — a heavily-edited note can emit hundreds of times during +// initial relay sync, and we only need the last state per ~half second. // Returns `null` until the first IO resolution completes — callers should treat that as // "still loading" and not flip their UI to "no edits". -@OptIn(ExperimentalCoroutinesApi::class) +@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class) @Composable fun observeNoteModifications( note: Note, @@ -379,6 +381,7 @@ fun observeNoteModifications( .flow() .edits .stateFlow + .sample(500) .mapLatest { LocalCache.findLatestModificationForNote(note) } .distinctUntilChanged() .flowOn(Dispatchers.IO)