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

com.github.insanusmokrassar.AutoPostTelegramBot.utils.extensions.BroadcastChannel.kt Maven / Gradle / Ivy

package com.github.insanusmokrassar.AutoPostTelegramBot.utils.extensions

import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.channels.BroadcastChannel
import kotlinx.coroutines.experimental.channels.ReceiveChannel
import java.util.concurrent.TimeUnit

fun  BroadcastChannel.subscribeChecking(
    throwableHandler: (Throwable) -> Boolean = {
        it.printStackTrace()
        true
    },
    by: suspend (T) -> Boolean
): ReceiveChannel {
    return openSubscription().also {
        launch {
            while (isActive && !it.isClosedForReceive) {
                try {
                    val received = it.receive()

                    launch {
                        try {
                            if (!by(received)) {
                                it.cancel()
                            }
                        } catch (e: Throwable) {
                            if (!throwableHandler(e)) {
                                it.cancel()
                            }
                        }
                    }
                } catch (e: CancellationException) {
                    break
                }
            }
            it.cancel()
        }
    }
}

fun  BroadcastChannel.subscribe(
    throwableHandler: (Throwable) -> Boolean = {
        it.printStackTrace()
        true
    },
    by: suspend (T) -> Unit
): ReceiveChannel {
    return subscribeChecking(throwableHandler) {
        by(it)
        true
    }
}

fun  ReceiveChannel.debounce(delayMs: Long, awaitedSubscriptions: Int = 256): BroadcastChannel {
    val channel = BroadcastChannel(awaitedSubscriptions)
    var lastReceived: Pair? = null
    var job: Job? = null
    launch {
        while (isActive && !isClosedForReceive) {
            val received = receive()

            lastReceived = Pair(System.currentTimeMillis() + delayMs, received)

            job ?:let {
                job = launch {
                    try {
                        var now = System.currentTimeMillis()
                        while (isActive && lastReceived?.first ?: now >= now) {
                            delay((lastReceived ?.first ?: now) - now, TimeUnit.MILLISECONDS)
                            now = System.currentTimeMillis()
                        }

                        lastReceived?.second?.also {
                            channel.send(it)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    } finally {
                        job = null
                    }
                }
            }
        }
        cancel()
    }
    return channel
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy