Akka gRPCとSlickの学習記録

grpc-gateway, grpc-webをいい加減に触ろう、ということでScalaでgRPCサーバを構築することにした。 Akkaに多少馴染みが出てきたのでAkka gRPCを使うことにする。

Akka gRPC

https://developer.lightbend.com/guides/akka-grpc-quickstart-scala/

Akka gRPCのQuickstartのページがあり、基本的にこのままで動く。 gRPCはHttp/2ベースでSSL前提なので証明書が必要になる。リンクが貼られてるサンプルコードの中にそのへんのファイルとか記述があるのでコピペしたら動いた。

実際に動かすとなったら証明書周りどうするんだろ。 リリースまで行かなかったけど、以前導入することになりそうだったときはバックエンド間での通信だからInsecureでいいよね、ということで対象外だった気がする。

何にせよとりあえずScalaでのgRPCサーバの構築自体はいけた。 Greeterにクライアントアプリから接続してもつまらないので、こういうときの定番モノであるToDoアプリを作ることにする。

ということでprotoファイルをgistにあげた。まぁ単純なCRUD操作がある感じ。 example ToDo service proto · GitHub

Akka gRPCのコードに対しては特に書くところも無いな。 強いて言えば複数Serviceを動かすときはPartialFunctionとして、それを連結して動かす感じになる模様。 doc.akka.io

ToDoアプリを作る以上、何かしらデータベースが必要になる。 ちょっと前に作ったアプリでScalaからRedisを操作する辺りはやったので、いい加減にSlickを触ることにする。

Slick

スリックなのかシリックなのかスィリックなのかよく分からないやつ。スィリックって読んでる。 MySQLを用意するのもめんどっちいのでH2で済ませる。H2もちゃんと触ったことが無かった。

ドキュメントを読みながら一通り頭から流していく。 scala-slick.org scala-slick.org

コード生成しなくていいかな、と思ってたけど、サンプルコードを見てもわけが分からないのでおとなしくslick-codegenを入れて動かすべきだった。

個人的にドキュメントに載ってるコードはなかなか不親切で

( for( c <- coffees; if c.price < limit ) yield c.name ).result

coffees とかどこからどう出てきた何の型の値なの っていうところとか、多少分かれば空気読んでなんとかなるけど初めにこれ読んでも意味分からんのでは。 と思って見返したらすぐあとにCoffeesの型定義とval coffeesの初期化部分のコード載ってたわ。ちゃんと見ないとダメだな。。。 という感じで飛ばし飛ばしで見てたせいで全然Slickが動かせなくてまぁ時間がかかった。

TableQueryに対してもろもろ操作して生成したDBIOActionをdb.runに突っ込んでクエリを実行する、っていう大雑把な理解をした。

H2

H2がよく分からなくて困ったところもあった。オンメモリで動作するっていうのは意識にあったものの、思ったよりすぐ消えるのでよく分からない。 DB_CLOSE_DELAY=-1をつけろっていうのをStackoverflowで見かけたので従ってなんとか動くようになったりとか。 最終的に

url = "jdbc:h2:mem:todo;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;INIT=runscript from 'app/src/main/sql/create.sql'"

というURL定義になった。 DATABASE_TO_UPPER=false これをしないとテーブル名だったりカラム名が勝手にアッパーケースになるのか…

create.sqlDDLを書いたり、初期値用のINSERT文を書いといたら、なぜかINSERT文が2回発行されてて重複したレコードができて謎だった。 この辺どこからどう実行されてるのか調べるのが骨が折れてもう… PHPならブレークポイント貼ってIDE上から該当プロセスを実行してしまえばある程度追えるのだけど、JavaScalaはそういうことがしづらくて困るなー。

gRPCサーバ側の実装ができたので、次はクライアントサイドの実装をしていく。