https://kotlinlang.org logo
#coroutines
Title
# coroutines
s

serebit

04/08/2019, 7:57 PM
Got a question, a choice between two possible answers. The end result should be a system that can halt for a certain period of time if one of the channels within that system receives a signal to do so. The scenario: Several rendezvous channels are run simultaneously, each within their own coroutine, and each corresponding to an API route. When a request for that route is called, it is sent to the appropriate channel, which processes the request and returns the response via a second channel. After this, it checks for a route-specific ratelimit header, and if it finds this header, it delays for that period of time before processing the next request. The problem: The system also needs to be able to tell every channel to halt for that period of time IF a specific “global” header is present in a response. Solution 1️⃣ Hold a nullable
BroadcastChannel<Unit>
on the top level. Every channel will call subscribe and receive on this channel at the start of processing a request. The variable will usually be null, but if a “global” header is received, it will be set to
BroadcastChannel(1)
, and the channel where this header was received will delay for the given amount of time before setting the variable to null and calling
send(Unit)
, unsuspending all the waiting channels. Solution 2️⃣ Hold the global delay target as a unix millis, or null, at the top level. Every channel will delay for the amount it time it takes to get to that unix millis if it is not null. If a channel receives the global header, it sets the global unix millis and delays for that period of time before setting it back to null.
1️⃣ 1
2️⃣ 1
o

octylFractal

04/08/2019, 9:07 PM
why not have an always-available
BroadcastChannel<Long>
that holds a delay if one is needed, and is empty otherwise. your channels can use
poll
to determine if they need to wait -- either the Long is there, and they wait until it (like 2), or it is
null
and they do not wait
s

serebit

04/08/2019, 9:17 PM
Apparently
BroadcastChannel
doesn’t have a
poll
method
o

octylFractal

04/08/2019, 9:20 PM
no, because it's a send channel
you call it on the ReceiveChannel from subscribe
s

serebit

04/08/2019, 9:22 PM
Ah, gotcha. I’ll look into that, sounds like a decent idea. Main concern is that channels are created dynamically, so what happens if a channel subscribes after the delay is sent over the broadcast?
o

octylFractal

04/08/2019, 9:25 PM
hmm, that makes 2️⃣ sound like the better option, though I'm a little against it due to the static/global state. One thing to make sure of is that the global variable is thread-safe, but otherwise that's the best I can think of without knowing the full code
There are some differences besides the implementation of the global limit, but those are less important
o

octylFractal

04/08/2019, 9:36 PM
I feel like it would be better design to initialize all of the route-channels at startup, rather than on first request
that would eliminate the problem of subscribing post-delay, but perhaps that's not an option for your API design
otherwise, I think I like 2️⃣, but it does need something like
AtomicLong
or other thread-safe measures
s

serebit

04/08/2019, 9:37 PM
That’s not possible, unfortunately. This is a client implementation of the Discord API, which has dynamic creation of entities, so we’d have to create
Long.MAX_VALUE
route channels and then some
4 Views