io.rouz.grpc.Adapters.kt Maven / Gradle / Ivy
package io.rouz.grpc
import io.grpc.Context
import io.grpc.stub.StreamObserver
import kotlin.coroutines.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
class ManyToOneCall(
private val request: StreamObserver,
private val response: Deferred
) : StreamObserverSendAdapter(request),
Deferred by response
class ManyToManyCall(
private val request: StreamObserver,
private val response: ReceiveChannel
) : StreamObserverSendAdapter(request),
ReceiveChannel by response
open class StreamObserverSendAdapter(private val streamObserver: StreamObserver) {
fun close(cause: Throwable? = null): Boolean {
if (cause != null) {
streamObserver.onError(cause)
} else {
streamObserver.onCompleted()
}
return true
}
fun send(element: E) {
streamObserver.onNext(element)
}
}
class ContinuationStreamObserver(
private val continuation: Continuation
) : StreamObserver {
override fun onNext(value: E) {
continuation.resume(value)
}
override fun onError(t: Throwable) {
continuation.resumeWithException(t)
}
override fun onCompleted() {}
}
class StreamObserverDeferred(
private val deferred: CompletableDeferred = CompletableDeferred()
) : StreamObserver, Deferred by deferred {
override fun onNext(value: E) {
deferred.complete(value)
}
override fun onError(t: Throwable) {
deferred.completeExceptionally(t)
}
override fun onCompleted() { /* nothing */
}
}
class StreamObserverChannel(
private val channel: Channel = Channel(Channel.UNLIMITED)
) : StreamObserver, ReceiveChannel by channel {
override fun onNext(value: E) {
channel.offer(value)
}
override fun onError(t: Throwable?) {
channel.close(cause = t)
}
override fun onCompleted() {
channel.close(cause = null)
}
}
class ContextCoroutineContextElement : ThreadContextElement {
companion object Key : CoroutineContext.Key
private val grpcContext: Context = Context.current()
override val key: CoroutineContext.Key
get() = Key
override fun updateThreadContext(context: CoroutineContext): Context =
grpcContext.attach()
override fun restoreThreadContext(context: CoroutineContext, oldState: Context) =
grpcContext.detach(oldState)
}