All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.ReceiveChannel.kt Maven / Gradle / Ivy

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
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy