com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.ReceiveChannel.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of TelegramBotAPI Show documentation
Show all versions of TelegramBotAPI Show documentation
It is one more project which wish to be useful and full Telegram Bots API bridge for Kotlin
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
private sealed class DebounceAction {
abstract val value: T
}
private data class AddValue(override val value: T) : DebounceAction()
private data class RemoveJob(override val value: T, val job: Job) : DebounceAction()
fun ReceiveChannel.debounceByValue(
delayMillis: Long,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
resultBroadcastChannelCapacity: Int = 32
): ReceiveChannel {
val outChannel = Channel(resultBroadcastChannelCapacity)
val values = HashMap()
val channel = Channel>(Channel.UNLIMITED)
scope.launch {
for (action in channel) {
when (action) {
is AddValue -> {
val msg = action.value
values[msg] ?.cancel()
lateinit var job: Job
job = launch {
delay(delayMillis)
outChannel.send(msg)
channel.send(RemoveJob(msg, job))
}
values[msg] = job
}
is RemoveJob -> if (values[action.value] == action.job) {
values.remove(action.value)
}
}
}
}
scope.launch {
for (msg in this@debounceByValue) {
channel.send(AddValue(msg))
}
}
return outChannel
}
typealias AccumulatedValues = Pair>
fun ReceiveChannel>.accumulateByKey(
delayMillis: Long,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
resultBroadcastChannelCapacity: Int = 32
): ReceiveChannel> {
val outChannel = Channel>(resultBroadcastChannelCapacity)
val values = HashMap>()
val jobs = HashMap()
val channel = Channel>>(Channel.UNLIMITED)
scope.launch {
for (action in channel) {
val (key, value) = action.value
when (action) {
is AddValue -> {
jobs[key] ?.cancel()
(values[key] ?: mutableListOf().also { values[key] = it }).add(value)
lateinit var job: Job
job = launch {
delay(delayMillis)
values[key] ?.let {
outChannel.send(key to it)
channel.send(RemoveJob(key to value, job))
}
}
jobs[key] = job
}
is RemoveJob -> if (values[key] == action.job) {
values.remove(key)
jobs.remove(key)
}
}
}
}
scope.launch {
for (msg in this@accumulateByKey) {
channel.send(AddValue(msg))
}
}
return outChannel
}