Code review:
- @Volatile ScheduledPostNotifier.channel: two workers firing in the same window can race on ensureChannel from different IO threads. createNotificationChannel is idempotent, but the field write needs a visibility fence so both threads see the cached reference. - @Volatile PoolEventOutbox.eventOutbox map ref + PoolEventOutboxState .relaysRemaining set ref. The new pendingPublishRelaysFor polling path reads these from the WorkManager IO thread; mutations still happen on NostrClient's IO scope. Pre-existing visibility gap that this poll surface exposed; @Volatile is the minimal fix. - ScheduledPostsScreen.SectionLabel: read the locale from LocalConfiguration.current.locales[0] (the Compose-resolved locale) rather than Locale.getDefault() (the system locale, which can drift from app config and breaks Turkish I/i casing).
This commit is contained in:
+5
@@ -31,6 +31,11 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
class PoolEventOutbox {
|
||||
// @Volatile so the polling path (INostrClient.pendingPublishRelaysFor)
|
||||
// sees current state from threads that didn't write the map. Mutations
|
||||
// still happen on NostrClient's IO scope; this only closes the
|
||||
// visibility gap for cross-thread readers.
|
||||
@Volatile
|
||||
private var eventOutbox = mapOf<HexKey, PoolEventOutboxState>()
|
||||
val relays = MutableStateFlow(setOf<NormalizedRelayUrl>())
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
class PoolEventOutboxState(
|
||||
val event: Event,
|
||||
var relaysRemaining: Set<NormalizedRelayUrl>,
|
||||
@Volatile var relaysRemaining: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
private var failures = mapOf<NormalizedRelayUrl, Tries>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user