FileSystemCache

class FileSystemCache<V : Any>(directory: File, encode: (V) -> String, decode: (String) -> V, ioContext: CoroutineContext = Dispatchers.IO, currentTimeMillis: () -> Long = System::currentTimeMillis, maxSizeBytes: Long? = DEFAULT_MAX_SIZE_BYTES) : TimestampedCache<V> , PersistentCache<V>

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

directory

the storage directory; created on first write.

encode

serializes a value to text.

decode

parses text produced by encode back into a value.

ioContext

context for blocking file I/O; defaults to Dispatchers.IO.

currentTimeMillis

time source, injectable for deterministic tests.

maxSizeBytes

maximum disk usage in bytes for owned cache files. Defaults to 50 MB. Pass null for unbounded (not recommended for production).

Constructors

Link copied to clipboard
constructor(directory: File, encode: (V) -> String, decode: (String) -> V, ioContext: CoroutineContext = Dispatchers.IO, currentTimeMillis: () -> Long = System::currentTimeMillis, maxSizeBytes: Long? = DEFAULT_MAX_SIZE_BYTES)

Functions

Link copied to clipboard
open override fun changes(): Flow<CacheChange>

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.

Link copied to clipboard
open suspend override fun entry(key: CacheKey): CacheEntry<V>?

Atomically returns the value and its timestamp for key, or null if absent.

Link copied to clipboard
open suspend override fun removeAll()

Removes every entry.

Link copied to clipboard
open suspend override fun removeValue(key: CacheKey)

Removes any value stored for key.

Link copied to clipboard
open suspend override fun setValue(value: V, key: CacheKey)

Stores value for key, stamping it with the current time.

open suspend override fun setValue(value: V, key: CacheKey, timestamp: Long)

Stores value for key stamped with the given epoch-millisecond timestamp.

Link copied to clipboard
open suspend override fun timestamp(key: CacheKey): Long?

Returns the epoch-millisecond timestamp recorded for key, or null if absent.

Link copied to clipboard
open suspend override fun value(key: CacheKey): V?

Returns the value stored for key, or null if absent.