Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve client API for client streaming. #31

Open
jcornaz opened this issue Feb 12, 2019 · 0 comments
Open

Improve client API for client streaming. #31

jcornaz opened this issue Feb 12, 2019 · 0 comments

Comments

@jcornaz
Copy link

jcornaz commented Feb 12, 2019

Reading https://github.com/rouzwawi/grpc-kotlin#client I'm a bit surprised that the streaming from client to server are done by calling send on the result of the function.

Personally I'd rather make the function taking a ReceiveChannel.

Here is how the example in readme would look like:

// === Client streaming call ==================================================================

coroutineScope {
  val oneReply = greeter.greetClientStream(produce { // <-- greetClientStream would suspend
    send(req("Caroline"))
    send(req("David"))
  })
  println("single reply = ${oneReply.reply}")
}

// === Bidirectional call =====================================================================

coroutineScope {
  val responses = greeter.greetBidirectional(produce {
  	delay(200)
  	send(req("Eve"))
  
  	delay(200)
  	send(req("Fred"))
  
  	delay(200)
  	send(req("Gina"))
  })
  
  launch {
    var n = 0
    for (greetReply in responses) {
      println("r$n = ${greetReply.reply}")
      n++
    }
    println("no more replies")
  }
}

Advantages of this style:

  • It is more consistent with how it looks like on the server side.
  • Client streaming call is more consistent with Unary call, since they both suspend. (Which make sense, because both return a value and not a channel. See Function returning ReceiveChannel should not be marked with suspend #30)
  • It is safer because:
    • it is not possible to forget to close() the stream.
    • it is not possible to forget to call await().
    • thanks to coroutineScope we get automatic cancellation of all streams in case of failure of one job.
  • Bi directional API is less confusing and provide a clearer separation of the outgoing and incoming streams. (currently the same object is used to send and receive elements)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant