FileSystemCache
A durable PersistentCache that stores each entry as a file under directory.
Mirrors SwiftyNetwork's disk-backed cache. Values are turned into text by the caller-supplied encode/decode pair (e.g. kotlinx.serialization's Json.encodeToString/decodeFromString), so :cache stays free of any serialization dependency. Each file stores the epoch-millisecond timestamp on its first line followed by the encoded value, so it is a TimestampedCache and promotes into a memory layer without losing age (see LayeredCache).
File I/O runs on ioContext and is guarded by a Mutex. Writes use a same-directory temporary file and atomic replacement, so a process interruption leaves either the old complete entry or the new complete entry. Only files this cache wrote (suffixed SUFFIX) are touched, so the directory may be shared. A malformed or unreadable file reads back as null rather than throwing.
When maxSizeBytes is set (default 50 MB), writes evict the least recently used entries (reads and writes both refresh an entry's last-modified time) until total disk usage for owned cache files is within the limit. The entry being written is evicted last, so it only goes when it alone exceeds the limit. The running total is tracked in memory, so the directory is only rescanned when a write crosses the limit; give each instance its own directory if you rely on the bound. Pass maxSizeBytes = null to disable the limit (unbounded growth). Eviction emits CacheChange.Removed for keys this instance has read or written; files from an earlier process cannot be mapped back from their hashed names until they are read.
Parameters
the storage directory; created on first write.
serializes a value to text.
parses text produced by encode back into a value.
context for blocking file I/O; defaults to Dispatchers.IO.
time source, injectable for deterministic tests.
maximum disk usage in bytes for owned cache files. Defaults to 50 MB. Pass null for unbounded (not recommended for production).
Functions
A hot stream of CacheChanges for this cache. The default is an empty flow, so caches that cannot observe mutations are simply non-reactive; observable caches override this.
Removes any value stored for key.