Files
amethyst/commons
Claude 5c2f93f82f refactor: replace stately with LargeCache + KmpLock
Address review feedback: the project already has LargeCache (in quartz,
with jvmAndroid/appleMain/linuxMain actuals) as its KMP concurrent-map
abstraction — it's used pervasively in the model layer. Adding stately
duplicated that capability with an external dep.

- Comparable-key maps switch to LargeCache:
  * ChessEventCollector.moves (String key)
  * ChessEventCollectorManager.collectors (String key)
  * ChessRelayFetchHelper.events (String key)
  * ChessRelayFetchHelper.relayEventCounts: LargeCache<NormalizedRelayUrl,
    AtomicInt> with getOrCreate { AtomicInt(0) }.addAndFetch(1) — replaces
    the stately .block { compute } increment idiom. getOrCreate is atomic
    via ConcurrentSkipListMap.putIfAbsent so all threads end up
    incrementing the same AtomicInt instance.
  * ChessLobbyLogic.recentlyLoadedGames (String key)

- The SubscriptionManager pair (MutableComposeSubscriptionManager,
  ComposeSubscriptionManager) keeps a plain mutableMapOf — T :
  MutableQueryState is generic and not Comparable, so LargeCache's
  ConcurrentSkipListMap backing would ClassCastException at put time.
  Concurrency comes from a KmpLock-guarded map.

- Set-shaped uses switch to KmpLock + mutableSetOf:
  * ChessEventCollector.processedEventIds
  * ChessRelayFetchHelper.eoseReceived
  * ChessLobbyLogic.dismissedGameIds + seenEventIds (the bounded LRU
    keeps insertion-order eviction; mutableSetOf returns LinkedHashSet
    on every KMP target).

- UserRelaysCache.flow's lock: stately Lock -> KmpLock.

Adds expect class KmpLock() with jvmAndroid actual that wraps
ReentrantLock. iOS actual (NSLock) will land with the iOS target.
Mirrors the WeakReference pattern from the previous PR.

Drops stately-concurrent-collections 2.1.0 from libs.versions.toml and
commons/build.gradle.kts (no remaining consumers).
2026-05-24 21:10:35 +00:00
..