receiving a stream of stock ticker values for a symbol
gRPC is typically used contract-first:
syntax = "proto3";
package ticker;
service TickerService {
// Monitor a symbol
rpc MonitorSymbol (TickerSymbol)
returns (stream StockValue)
{}
}
message TickerSymbol {
string name = 1;
}
message StockValue {
string name = 1;
uint32 value = 2;
}
Akka gRPC
Add the plugin to your build:
// project/plugins.sbt
addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % "1.0.0")
And build the project:
$ sbt compile
To generate API classes:
$ find target/scala-2.13/src_managed | grep TickerService
target/scala-2.13/src_managed/main/ticker/TickerServiceHandler.scala
target/scala-2.13/src_managed/main/ticker/TickerService.scala
The generated API looks like this:
trait TickerService {
/**
* Monitor a symbol
*/
def monitorSymbol(in: Symbol): Source[Value, NotUsed]
}
We implement it:
class TickerServiceImpl extends TickerService {
val random = Random
override def monitorSymbol(in: TickerSymbol): Source[StockValue, NotUsed] =
Source.fromIterator(() => new Iterator[StockValue]() {
override def hasNext = true
override def next(): StockValue = StockValue(in.name, random.nextInt(500))
})
}
And embed it in a simple Akka HTTP server:
object Main extends App {
implicit val system = ActorSystem("ticker")
Http().bindAndHandleAsync(
TickerServiceHandler(new TickerServiceImpl),
"127.0.0.1",
8080
)
}
You can now connect to the service:
$ grpcurl -d '{"name": "foo"}' -plaintext \
-import-path /home/aengelen/dev/akka-grpc-intro-video/src/main/protobuf \
-proto ticker.proto \
localhost:8080 ticker.TickerService.MonitorSymbol
{
"name": "foo",
"value": -1725700895
}
{
"name": "foo",
"value": -341515636
}
{
"name": "foo",
...