Home > Blockchain >  How to delay the elements the we send to a Channel?
How to delay the elements the we send to a Channel?

Time:01-16

Let's say we have a Channel like this

private val channel = Channel<String>(1)

And we are listening to the Channel elements like this

channel.receiveAsFlow().collect { myStr ->
    println(myStr)
}

If I run something like this

private val scope = CoroutineScope(Dispatchers.Main   SupervisorJob())
...
fun sendMessage(myMessage: String) {
   scope.launch {
      channel.send(myMessage)
   }
}
...
sendMessage("a")
sendMessage("b")
sendMessage("c")
sendMessage("d")

The output is going to be

a
b
c
d

Now, what I'm trying to achieve is that if I send "b" it delays the processing of the elements in the channel for 1 second.

For example, if I do

...
sendMessage("a")
sendMessage("b")
sendMessage("c")
sendMessage("b")
sendMessage("d")
sendMessage("e")

The output that I would expect would be like

a // prints immediately
b // prints right after a
c // prints after 1 second
b // prints right after c
d // prints after 1 second
e // prints right after d

My question is, how would I achieve this behavior? I've been trying to add delay() here and there, but I didn't have any luck.

CodePudding user response:

Here's an idea, but it feels a little hacky to me. trySend would not work with this. I'm not sure how to make trySend make sense with your criteria, because it's supposed to return immediately with a result about whether the value posted.

Here, send() suspends until the possible delay is over. If you don't want to wait for it, you'd have to launch a coroutine each time you send something.

Since the Channel "constructor" is not a true constructor, you can't subclass it. My workaround is to create a class that uses it as a delegate.

val backingChannel = Channel<String>(1)
val channel = object: Channel<String> by backingChannel {
    var delayNext = false
    val mutex = Mutex()
    override suspend fun send(element: String) = mutex.withLock {
        if (delayNext) {
            delay(1000)
        }
        delayNext = element == "b"
        backingChannel.send(element)
    }
}
  •  Tags:  
  • Related