53 lines
2.0 KiB
Kotlin
53 lines
2.0 KiB
Kotlin
package com.mkfunproj.mobilemkch.data
|
|
|
|
import android.content.Context
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.withContext
|
|
import kotlinx.serialization.encodeToString
|
|
import kotlinx.serialization.json.Json
|
|
import java.io.File
|
|
|
|
class Cache(private val context: Context) {
|
|
private val json = Json
|
|
private val dir: File by lazy { File(context.cacheDir, "mkch_cache").apply { mkdirs() } }
|
|
|
|
suspend fun <T> set(key: String, value: T, encoder: (T) -> String, ttlSeconds: Long) = withContext(Dispatchers.IO) {
|
|
val file = File(dir, safeName(key))
|
|
val wrapper = CacheWrapper(System.currentTimeMillis(), ttlSeconds, encoder(value))
|
|
file.writeText(json.encodeToString(wrapper))
|
|
}
|
|
|
|
suspend fun <T> get(key: String, decoder: (String) -> T): T? = withContext(Dispatchers.IO) {
|
|
val file = File(dir, safeName(key))
|
|
if (!file.exists()) return@withContext null
|
|
val wrapper = runCatching { json.decodeFromString(CacheWrapper.serializer(), file.readText()) }.getOrNull()
|
|
?: return@withContext null
|
|
val ageSec = (System.currentTimeMillis() - wrapper.timestampMs) / 1000
|
|
if (ageSec > wrapper.ttlSeconds) return@withContext null
|
|
return@withContext decoder(wrapper.payload)
|
|
}
|
|
|
|
suspend fun <T> getStale(key: String, decoder: (String) -> T): T? = withContext(Dispatchers.IO) {
|
|
val file = File(dir, safeName(key))
|
|
if (!file.exists()) return@withContext null
|
|
val wrapper = runCatching { json.decodeFromString(CacheWrapper.serializer(), file.readText()) }.getOrNull()
|
|
?: return@withContext null
|
|
return@withContext decoder(wrapper.payload)
|
|
}
|
|
|
|
suspend fun delete(key: String) = withContext(Dispatchers.IO) {
|
|
File(dir, safeName(key)).delete()
|
|
}
|
|
|
|
private fun safeName(key: String) = key.hashCode().toString(16) + ".json"
|
|
}
|
|
|
|
@kotlinx.serialization.Serializable
|
|
private data class CacheWrapper(
|
|
val timestampMs: Long,
|
|
val ttlSeconds: Long,
|
|
val payload: String
|
|
)
|
|
|
|
|