fix: handle more network errors, and large refactors

This commit is contained in:
LavaDesu 2025-08-02 01:35:59 +10:00
parent ce8425d6a7
commit 8c0bff3bc4
Signed by: cilly
GPG key ID: 6500251E087653C9
8 changed files with 286 additions and 169 deletions

View file

@ -0,0 +1,48 @@
package moe.lava.banksia.util
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.lava.banksia.error
class CacheMap<K, V>(
coroutineScope: CoroutineScope,
val expiryMinutes: Int = 5,
private val innerMap: MutableMap<K, V> = mutableMapOf()
) : MutableMap<K, V> by innerMap {
val keyExpiries = mutableMapOf<K, Int>()
var counter = 0
init {
coroutineScope.launch {
while (true) {
delay(60000)
counter += 1
keyExpiries
.filterValues { expiry -> expiry >= counter }
.keys
.forEach { key ->
innerMap.remove(key)
keyExpiries.remove(key)
}
}
}
}
override fun put(key: K, value: V): V? {
keyExpiries.put(key, counter + expiryMinutes + 1)
return innerMap.put(key, value)
}
override fun putAll(from: Map<out K, V>) {
keyExpiries.putAll(from.map { it.key to (counter + expiryMinutes + 1) })
innerMap.putAll(from)
}
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
get() {
error("CacheMap", ".entries accessed, cloning..", IllegalStateException())
return this.entries.toMutableSet()
}
}

View file

@ -0,0 +1,65 @@
package moe.lava.banksia.util
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.AbstractFlow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import moe.lava.banksia.log
import kotlin.experimental.ExperimentalTypeInference
@OptIn(ExperimentalCoroutinesApi::class)
class LoopFlow<T>(private val block: suspend FlowCollector<T>.() -> Unit) : AbstractFlow<T>() {
private var delayMs: Long = 5000
private var init: (suspend FlowCollector<T>.() -> Unit)? = null
private var waiter: (suspend () -> Unit)? = null
override suspend fun collectSafely(collector: FlowCollector<T>) {
init?.invoke(collector)
while (true) {
waiter?.invoke()
collector.block()
delay(delayMs)
}
}
companion object {
fun <T> Flow<T>.delayFor(delay: Long) = apply {
@Suppress("UnusedFlow")
if (this is LoopFlow)
this.delayMs = delay;
else
throw IllegalStateException()
}
fun <T> Flow<T>.initWith(block: suspend FlowCollector<T>.() -> Unit) = apply {
@Suppress("UnusedFlow")
if (this is LoopFlow)
this.init = block;
else
throw IllegalStateException()
}
fun <T> Flow<T>.waitFor(waiter: suspend () -> Unit) = apply {
@Suppress("UnusedFlow")
if (this is LoopFlow)
this.waiter = waiter;
else
throw IllegalStateException()
}
fun <T> Flow<T>.waitUntilSubscribed(other: MutableStateFlow<*>) = waitFor {
val blocked = other.subscriptionCount.value == 0
if (blocked)
log("LoopFlow", "blocking flow")
other.subscriptionCount.first { it > 0 }
if (blocked)
log("LoopFlow", "unblocking flow")
}
}
}
@OptIn(ExperimentalTypeInference::class)
fun <T> loopFlow(@BuilderInference block: suspend FlowCollector<T>.() -> Unit) = LoopFlow(block)