kotlin 中的通用 grpc 请求
Generic grpc requests in kotlin
class API {
val nonBlockingStub: HealthcareAPIGrpc.HealthcareAPIStub //Generated Java GRPC Stub
suspend fun exampleRequest(params: Params) : ReturnedResult = suspendCancellableCoroutine { routine ->
val obs = object : StreamObserver<ReturnedResult> {
override fun onNext(value: ReturnedResult?) {
routine.resume(value!!)
}
override fun onError(t: Throwable?) {
routine.resumeWithException(t!!)
}
override fun onCompleted() {
}
}
nonBlockingStub.exampleRequest(params, obs)
}
}
所以我正在开发一个 Kotlin android 应用程序,它有一个在 java 中生成的 grpc 客户端。最近我不得不移动所有 API 请求以使用 kotlin 协程。对于每个请求,我都必须复制粘贴这个 exampleRequest 函数。
我很好奇是否有可能制作一个通用函数来执行此操作,接受一些参数并调用底层存根函数
理想情况下,应该有一个存根生成器生成适当的调用作为 suspend
/Flow
方法,但您仍然可以使用专用辅助函数抽象大部分转换:
fun <T> grpcFlow(
@BuilderInference block: suspend (StreamObserver<T>) -> Unit
): Flow<T> = callbackFlow {
// Use ClientCallStreamObserver to support cancellation
val observer = object : ClientCallStreamObserver<T>() {
override fun onNext(value: T) {
sendBlocking(value)
}
override fun onError(t: Throwable) {
cancel(CancellationException("GRPC Error", t))
}
override fun onCompleted() = channel.close()
}
block(observer)
awaitClose {
observer.cancel("flow cancellation", null)
}
}
那么你的 API 就变成了:
class API {
val nonBlockingStub: HealthcareAPIGrpc.HealthcareAPIStub
suspend fun exampleRequest(params: Params) = grpcFlow {
// @BuilderInference should ensure the correct type is used
nonBlockingStub.exampleRequest(params, it)
}.single() // Since we only expect a single response value.
// And for returns (stream ReturnedResult)
suspend fun exampleStreamingRequest(params: Params) = gcpcFlow {
nonBlockingStub.exampleStreamingRequest(params, it)
} // Flow<ReturnedResult>
}
class API {
val nonBlockingStub: HealthcareAPIGrpc.HealthcareAPIStub //Generated Java GRPC Stub
suspend fun exampleRequest(params: Params) : ReturnedResult = suspendCancellableCoroutine { routine ->
val obs = object : StreamObserver<ReturnedResult> {
override fun onNext(value: ReturnedResult?) {
routine.resume(value!!)
}
override fun onError(t: Throwable?) {
routine.resumeWithException(t!!)
}
override fun onCompleted() {
}
}
nonBlockingStub.exampleRequest(params, obs)
}
}
所以我正在开发一个 Kotlin android 应用程序,它有一个在 java 中生成的 grpc 客户端。最近我不得不移动所有 API 请求以使用 kotlin 协程。对于每个请求,我都必须复制粘贴这个 exampleRequest 函数。
我很好奇是否有可能制作一个通用函数来执行此操作,接受一些参数并调用底层存根函数
理想情况下,应该有一个存根生成器生成适当的调用作为 suspend
/Flow
方法,但您仍然可以使用专用辅助函数抽象大部分转换:
fun <T> grpcFlow(
@BuilderInference block: suspend (StreamObserver<T>) -> Unit
): Flow<T> = callbackFlow {
// Use ClientCallStreamObserver to support cancellation
val observer = object : ClientCallStreamObserver<T>() {
override fun onNext(value: T) {
sendBlocking(value)
}
override fun onError(t: Throwable) {
cancel(CancellationException("GRPC Error", t))
}
override fun onCompleted() = channel.close()
}
block(observer)
awaitClose {
observer.cancel("flow cancellation", null)
}
}
那么你的 API 就变成了:
class API {
val nonBlockingStub: HealthcareAPIGrpc.HealthcareAPIStub
suspend fun exampleRequest(params: Params) = grpcFlow {
// @BuilderInference should ensure the correct type is used
nonBlockingStub.exampleRequest(params, it)
}.single() // Since we only expect a single response value.
// And for returns (stream ReturnedResult)
suspend fun exampleStreamingRequest(params: Params) = gcpcFlow {
nonBlockingStub.exampleStreamingRequest(params, it)
} // Flow<ReturnedResult>
}