Hi all, I am playing around with actors and channe...
# codereview
j
Hi all, I am playing around with actors and channels, and I am wondering about the best way to structure my code. I have an actor that needs to read messages from two incoming sources, and as usual it needs to process messages one at a time so it can safely update internal state without further synchronization. I have wrapped my actor in a class, and expose a
.run()
method to start its internal loop:
Copy code
class MyActor {

  suspend fun run() {
    while(true) {
      select<Unit> {
        one.onReceive { ... }
        two.onReceive { ... }
      }
    }
  } 

}
Now, I am wondering about two things. First, where do I define the necessary channels? Do I do it in some configuration code and inject them as properties through a constructor, like so:
Copy code
class MyActor(private val one: ReceiveChannel<Query>, private val two: ReceiveChannel<Command>)
Or do I define them in the actor itself, and expose them for outside clients to use?
Copy code
class MyActor {
  private val _one = Channel<Query>()

  val one: SendChannel<Query>
    get() = _one
}
My second question is related - is it a good idea (or even idiomatic) to use Channels to define the API to my actor? Or is it better/more common to offer message functions hiding the channels for the client, like
Copy code
suspend fun query(query: Query) {
    one.send(query)
  }
Thanks for any feedback!
g
Just as side note that can be useful for you, check this PR to kotlinx.coroutines that introduces concept of type safe actors: https://github.com/Kotlin/kotlinx.coroutines/pull/485
j
Oh this is very relevant, I will study the implementation. Thanks!