Skip to content

xiaodongw/grpc-kt

Repository files navigation

GRPC-Kotlin

Travis

This is a GRPC stub & compiler for Kotlin Coroutine. By using Kotlin Coroutine, your code is totally asynchronous and non-blocking, but still being written in a synchronous way make it easier to read and maintain.

The generated service base and client stub share the same service interface, so they can be easily swapped for dependency injection and test mocking.

Check GRPC-RX for RxJava2 binding.

Getting started

  • In your project, configure Gradle to use the grpc-kt stub and compiler plugin.
dependencies {
  compile "com.github.xiaodongw:grpc-kt-stub:0.3.0"
}

protobuf {
  protoc {
    artifact = "com.google.protobuf:protoc:3.5.1"
  }
  plugins {
    grpc {
      artifact = 'com.github.xiaodongw:protoc-gen-grpc-kt:0.3.0'
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {}
    }
  }
}
class EchoServiceImpl : EchoGrpcKt.EchoImplBase() {
  override suspend fun unary(req: EchoProto.EchoReq): EchoProto.EchoResp {
    return EchoProto.EchoResp.newBuilder()
      .setId(req.id)
      .setValue(req.value)
      .build()
  }

  ...

  override suspend fun bidiStreaming(req: ReceiveChannel<EchoProto.EchoReq>): ReceiveChannel<EchoProto.EchoResp> {
    return GlobalScope.produce {
      for (reqMsg in req) {
        val respMsg = EchoProto.EchoResp.newBuilder()
          .setId(reqMsg.id)
          .setValue(reqMsg.value)
          .build()
        send(respMsg)
      }
    }
  }
}
  • Client side
val stub = EchoGrpcKt.newStub(channel)

// unary
runBlocking {
  val req = EchoProto.EchoReq.newBuilder()
    .setId(1)
    .setValue("Hello")
    .build()
  val resp = stub.unary(req)
}

// bidirectional streaming
runBlocking {
  val req: ReceivingChannel<EchoProto.EchoReq> = ...
  val resp = stub.bidiStreaming(req)
  for(msg in resp) {
    // do something with the msg
  }
}