ScalaMatsuri2022にてgRPCアプリケーションをライブコーディングするための課題プロジェクトです。
下記のみなさんの発表で取り上げられているエッセンスを、@kzmakeの解釈のもとgRPCアプリケーションとして実装したサンプルとなります。
- Scalaで始める表明プログラミング by @dnskimo
- Eff(atnos-eff)による実践的なコーディング集 by @shiroichi315
- アルプのEff独自エフェクト集 / Alp-original ’Eff’ pearls by @ma2k8
⚠ 当コードは架空のサービスを想定したものであり、所属先とは全く関係がありません。
git clone -b exercise https://github.com/kzmake/grpc-with-eff-example
よりお試しいただけます!
-
お金の引き出し(WithdrawMoney)のAPIを実装
- WithdrawMoneyの実装
- ドメイン層: Accountの実装
- 表明プログラミング(assert / required)
- ユースケース層: WithdrawMoneyInteractorの実装
- アダプター層: BankingController#withdrawの実装
- ドメイン層: Accountの実装
- WithdrawMoneyの実装
-
IdGen(Id生成)エフェクトのインタープリター修正
- インタープリターの修正
- アダプター層: uuidなID採番インタープリターの実装
- アダプター層: timestampなID採番 -> uuidなID採番切り替え
- インタープリターの修正
-
AuthZ(認可)エフェクトの実装
- 独自のAuthZ(認可)エフェクト追加
- ドメイン層: 独自エフェクトの定義
- アダプター層: インタープリターの実装
- アダプター層: リポジトリの実装修正
- 各層: _authz 追加
- 独自のAuthZ(認可)エフェクト追加
🔔 3 の認可は簡易化のため
-H "principal: alice"
として認可対象を指定できるものとします。
架空のサービスとして銀行口座サービスを想定します。
銀行口座(Account
)はエンティティであるとともに集約(AggregateRoot)を想定し、
final case class Account(id: Id[Account], balance: Money) extends AggregateRoot[Account]
のように、
- id: 銀行口座の識別子
- balance: 残高
を持つものとします。
サービスが提供するAPIを利用し、ユーザーは、
- 銀行口座 を 作成する
- 銀行口座 を 取得する
- 銀行口座 に お金 を 預け入る
- 銀行口座 から お金 を 引き出す
- 銀行口座 を 削除する
ことができるものとします。
$ tree
.
├── api
│ ├── banking/v1/banking.proto # 提供する api(grpc) の定義
│ └── gen
│ ├── go # `make api` による自動生成物: gateway用のgolangコード
│ └── openapiv2 # `make api` による自動生成物: gatewayで提供されるswagger
│
└── backend
├── banking # 銀行口座サービスコンテキスト
│ ├── domain # ドメイン層
│ ├── usercase # ユースケース層
│ ├── adapter # アダプター層
│
└── cmd # アプリケーションのエントリーポイント
├── grpc # 銀行口座サービス
└── gateway # json api を提供する grpc-gateway
buf.build / akka-grpc(scalapb) を用いて、
- API仕様(openapiv2): buf generate実行時
- gatewayのためのコード(golang + grpc-gateway): buf generate実行時
- bankingのためのコード(scala): sbt compile実行時
- バリデーションコード(protoc-gen-validate with scalapb): sbt compile実行時
を生成しています。
- クリーンアーキテクチャ
- ヘキサゴナルアーキテクチャ
- ドメイン駆動設計(DDD)
のエッセンスを取り入れ、 backend/banking
配下にレイヤーを、
- ドメイン層:
banking-domain
- ユースケース層:
banking-usecase
- アダプター層:
banking-adapter
とモジュール化しています。
$ make dev
$ curl -i http://localhost:8080/v1/accounts/11111111-1111-1111-1111-111111111111 -H "principal: alice"
HTTP/1.1 200 OK
Content-Type: application/json
Grpc-Metadata-Content-Length: 48
Grpc-Metadata-Content-Type: application/grpc+proto
Grpc-Metadata-Date: Fri, 18 Mar 2022 14:17:47 GMT
Grpc-Metadata-Server: akka-http/10.2.9
Date: Fri, 18 Mar 2022 14:17:47 GMT
Content-Length: 74
{"account":{"id":"11111111-1111-1111-1111-111111111111","balance":"1200"}}
- https://github.com/atnos-org/eff
- https://atnos-org.github.io/eff/
- https://www.exoego.net/eff/
- https://doc.akka.io/docs/akka-grpc/current/overview.html
- https://docs.buf.build/introduction
- https://scalapb.github.io/docs/validation/
- Scalaで始める表明プログラミング by @dnskimo
- Eff(atnos-eff)による実践的なコーディング集 by @shiroichi315
- アルプのEff独自エフェクト集 / Alp-original ’Eff’ pearls by @ma2k8
- Clean ArchitectureとEffで変更に強いAPIを設計する / API design by Clean Architecture ... by @kaelaela