fix: chunk large cached events to avoid Preferences 8KB limit on desktop

java.util.prefs.Preferences (desktop Settings backend) has an 8KB
per-value limit. Schedule JSON exceeds this. Now splits into 8000-char
chunks stored as cached_events_chunk_<account>_<i>, with a count key.
Maintains backward compat with old single-value format.
This commit is contained in:
2026-07-08 18:12:19 +02:00
parent d93cae0816
commit cc4b0a1ecf
@@ -9,10 +9,16 @@ import kotlinx.serialization.json.Json
class ScheduleCache(private val settings: Settings) {
companion object {
private const val CHUNK_SIZE = 8000
}
private val json = Json { ignoreUnknownKeys = true }
private val eventListSerializer = ListSerializer(Event.serializer())
private fun eventsKey(account: String) = "cached_events_$account"
private fun eventsChunkCountKey(account: String) = "cached_events_count_$account"
private fun eventsChunkKey(account: String, index: Int) = "cached_events_chunk_${account}_$index"
private fun agegroupKey(account: String) = "filters_agegroup_$account"
private fun subgroupKey(account: String) = "filters_subgroup_$account"
private fun typeFilterKey(account: String) = "filters_typefilter_$account"
@@ -20,11 +26,31 @@ class ScheduleCache(private val settings: Settings) {
@OptIn(ExperimentalTime::class)
fun saveEvents(account: String, events: List<Event>) {
settings.putString(eventsKey(account), json.encodeToString(eventListSerializer, events))
val jsonStr = json.encodeToString(eventListSerializer, events)
val chunks = jsonStr.chunked(CHUNK_SIZE)
settings.remove(eventsKey(account))
settings.putInt(eventsChunkCountKey(account), chunks.size)
chunks.forEachIndexed { i, chunk ->
settings.putString(eventsChunkKey(account, i), chunk)
}
settings.putLong(timestampKey(account), Clock.System.now().toEpochMilliseconds())
}
fun loadEvents(account: String): List<Event>? {
val chunkCount = settings.getIntOrNull(eventsChunkCountKey(account))
if (chunkCount != null && chunkCount > 0) {
val jsonStr = (0 until chunkCount).mapNotNull { i ->
settings.getStringOrNull(eventsChunkKey(account, i))
}.joinToString("")
if (jsonStr.isEmpty()) return null
return try {
json.decodeFromString(eventListSerializer, jsonStr)
} catch (e: Exception) {
null
}
}
val jsonString = settings.getStringOrNull(eventsKey(account)) ?: return null
return try {
json.decodeFromString(eventListSerializer, jsonString)
@@ -58,6 +84,11 @@ class ScheduleCache(private val settings: Settings) {
}
fun clearCache(account: String) {
val chunkCount = settings.getIntOrNull(eventsChunkCountKey(account)) ?: 0
for (i in 0 until chunkCount) {
settings.remove(eventsChunkKey(account, i))
}
settings.remove(eventsChunkCountKey(account))
settings.remove(eventsKey(account))
settings.remove(timestampKey(account))
settings.remove(agegroupKey(account))