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:
davotoula
2026-05-07 20:52:52 +02:00
parent c9f6762751
commit 474a957f2b
4 changed files with 13 additions and 3 deletions
@@ -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>())
@@ -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>()