Files
amethyst/.claude/skills/nostr-expert/references/large-cache.md
T
Claude 60edd473c7 Refreshes .claude/ skill library: fixes stale refs, adds 4 new skills
- Updates CLAUDE.md tech stack to current versions (Compose 1.10.3, Kotlin 2.3.20).
- Reframes kotlin-multiplatform iOS as mature; adds secp256k1-kmp 0.23.0 references.
- Updates desktop-expert Main.kt references (code grew from ~270 to 1341 lines and
  NavigationRail moved to ui/deck/SinglePaneLayout.kt); replaces obsolete
  "hardcoded ctrl = true" anti-pattern note with accurate isMacOS branching.
- Removes compose-desktop.md (superseded by desktop-expert/).
- Adds nostr-expert references: nip19-bech32, event-factory, crypto-and-encryption,
  large-cache. Adds kotlin-expert/common-utilities, compose-expert/rich-text-parsing,
  android-expert/image-loading.
- New skills: account-state (Account + LocalCache), relay-client (subscriptions,
  filter assemblers, preloaders), feed-patterns (FeedFilter + FeedViewModel family),
  auth-signers (NostrSigner across internal / NIP-46 / NIP-55).
2026-04-21 21:00:45 +00:00

3.2 KiB

LargeCache: Platform-Aware In-Memory Store

quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/cache/LargeCache.kt provides a thread-safe key-value cache with a functional iteration API. Used everywhere Amethyst needs to hold many events, users, or derived state in memory.

Files

  • LargeCache.ktexpect class LargeCache<K, V> and its factory createLargeCache().
  • ICacheOperations.kt — interface the cache exposes: forEach, filter, map, mapNotNull, groupBy, maxOrNullOf, sumOf, count, any, firstOrNull, etc.
  • CacheCollectors.kt — functional collector helpers used by the cache API.

Actual implementations

  • Android (androidMain) — backed by a ConcurrentHashMap (and optionally androidx.collection.LruCache variants for size-bounded caches).
  • JVM/Desktop (jvmMain) — ConcurrentHashMap directly.
  • iOS (iosMain) — NSMapTable/Kotlin concurrent map wrapper.

Core API

val cache: LargeCache<HexKey, Note> = LargeCache()

cache.put(id, note)
cache.get(id)                         // V?
cache.getOrCreate(id) { Note(id) }    // atomic compute-if-absent
cache.containsKey(id)
cache.remove(id)
cache.size()

// Functional iteration — thread-safe snapshot semantics
cache.forEach { key, value -> ... }
cache.filter { key, value -> value.kind == 1 }
cache.map { key, value -> value.pubKey }
cache.count { _, v -> v.isUnread }
cache.maxOrNullOf { _, v -> v.createdAt }
cache.groupBy { _, v -> v.kind }

The important contract: functional operations iterate a consistent snapshot, so you can filter inside a coroutine without racing concurrent writers. This is why LocalCache (the Amethyst event store) can be scanned to build a feed while relays are still inserting.

When to Use

  • Event / note storesLocalCache.notes: LargeCache<HexKey, Note>.
  • User profilesLocalCache.users: LargeCache<HexKey, User>.
  • Address → event lookups for addressable (parameterized replaceable) events.
  • Shared-secret caches (see SharedKeyCache.kt — a similar pattern at smaller scale).

When Not to Use

  • Small maps (<100 entries) — regular mutableMapOf is fine.
  • Off-process state (DB, disk) — use the store/ event DB, not LargeCache.
  • Hot one-shot lookups — if you're already inside a Flow pipeline, chain operators rather than maintaining a parallel cache.

Gotchas

  • getOrCreate vs putgetOrCreate is atomic and safe under contention; get then put is a race.
  • Iteration during mutation is safe but the snapshot may include or exclude a concurrent write. Don't rely on a just-put value being visible inside a currently-running forEach.
  • Don't store Flows inside LargeCache. Cache values should be immutable / thread-safe objects. For reactive state, keep a StateFlow next to the cache and emit on writes.
  • No TTL / eviction by default. If you need bounded size, wrap with LruCache or build an explicit eviction loop keyed off a secondary structure.
  • amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt — the canonical user of LargeCache<HexKey, Note> and LargeCache<HexKey, User>.
  • nip44Encryption/SharedKeyCache.kt — smaller domain-specific cache using the same pattern.