groostav
11/02/2020, 10:57 PMfun <M, R> sendAndAwaitResponse(func: KFunction2<M, StreamObserver<R>, Unit>): suspend (request: M) -> R = { request: M -> sendAndAwaitResponse(func, request) }
// sends a message, and converts the response observer to kotlin suspension (and exception) semantics
// assumes a unary call (that is, a call with one value given to the response observer)
suspend fun <M, R> sendAndAwaitResponse(func: KFunction2<M, StreamObserver<R>, Unit>, request: M): R {
val source = RuntimeException("server replied with error on call to ${func.name} with $request")
return suspendCoroutine<R> { continuation ->
func(request, object: StreamObserver<R> {
var result: ResponseState<R> = ResponseState.NoValue
override fun onNext(value: R) {
//...
}
override fun onError(thrown: Throwable) {
//...
}
override fun onCompleted() {
//...
continuation.resumeWith(result)
}
})
}
}
// "idiomatic" usage:
sendAndAwaitResponse(grpcService::someUnaryServiceMethod)(RequestDTO.newBuilder()....)
One of the things I was hailing kotlin for is that you dont often (ever?) end up with functions-returning-lambdas as is sometimes convention in Scala --typically to help the scala type inference engine. Well here I am doing exactly that
fun <M, R> sendAndAwaitResponse(func: KFunction2<M, StreamObserver<R>, Unit>): suspend (request: M) -> R = { request: M -> sendAndAwaitResponse(func, request) }
is doing.
tl;dr kotlin > scala; if you're using grpc try the new kotlin GRPC target. Suspend funs are good.groostav
11/02/2020, 10:58 PMgroostav
11/02/2020, 10:59 PMgroostav
11/02/2020, 10:59 PM