Need a little code review. I have a bunch of “comm...
# coroutines
e
Need a little code review. I have a bunch of “commands” that are sent through a channel and handled by various “command handlers” (which basically run a suspend function). Some of the commands could run parallel to each other but some can’t because for instance they mutate the sameish state (play && pause commands for instance). I have now “grouped” the commands and this is my implementation:
Copy code
// Handle commands
LaunchedEffect(state, player) {
  coroutineScope {
    val groups = PlayerCommandGroup.entries.map {
      // Create a channel per group and launch a coroutine to consume commands from it.
      // Within a command group, commands run sequentially.
      Channel<PlayerCommand>(Channel.BUFFERED).also {
        launch {
          for (command in it) command.execute(player, state)
        }
      }
      }
    // Command groups, however, run parallel to each other.
    // When a command is received, identify its group and send the command to group's channel.
    for (command in state.commands) groups[command.group.ordinal].trySend(command)
  }
}
Does this make sense? Is there another way to say: as commands come into this channel send them into “different buckets” for processing. where within each bucket they are processed sequentially?
k
I think it makes sense. One thing I would do to improve this is to do
entries.associateWith
versus using the ordinal as an implicit key. Also, it seems strange that you're using
trySend
versus send.
Also I'm not quite sure why you're wrapping all of this in a
coroutineScope
since the receiver on the lambda in the LaunchedEffect is a scope
e
If you launch stuff into the coroutine scope of a launched effect, it does not keep the effect function suspended. But then I guess I could just await cancellation 👍🏾
For
trySend
I am trying to make the distinction that the iteration is synchronous. In this case its the same behavior as
send
since the state.commands channel is buffered, but thats not clear at the call site. send would have a slightly different connotation, ie: for each command, suspend until its “processed” (which could mean add to buffer & just return OR wait until destination handles it), vs trySend which I understand as: for each command, just try to hand it over to the channel
> I could just await cancellation Actually the state.commands iteration will suspend the launched effect so even await cancelllation not necessary
☝️ 1
k
Yeah the extra scope here is unnecessary