Caliban is a library for GraphQL in Scala. It was designed with the goal of reducing boilerplate to a minimum while exposing a purely functional interface. In this talk, we’ll discover how to create a simple GraphQL API from the ground up, then we’ll dig into advanced features such as query optimization and middlewares. Finally, we will take a look at the recently released GraphQL client support.
2. WHO AM I?
> Pierre Ricadat aka @ghostdogpr
>
!
exiled to
"
> Developer at devsisters
> Contributor to ZIO
> Creator of Caliban
自己紹介
フランス出身韓
Caliban作者
4. GRAPHQL IN A NUTSHELL
> query language for APIs
> server exposes a typed schema
> client requests and receives only what they want
> client and server can use any programming language
> good tooling
GraphQLの
API のためのクエリ言語、スキーマは型付き
5. GRAPHQL SCHEMA
type Query {
user(id: ID): User
users: [User!]!
}
type User {
id: ID!
name: String!
age: Int
}
GraphQLスキーマ
9. DEFINING A SCHEMA
case class User(
id: UUID,
name: String,
age: Option[Int]
)
type User {
id: ID!
name: String!
age: Int
}
スキーマ定義
10. DEFINING A SCHEMA
case class UserArgs(id: UUID)
case class Query (
user: UserArgs => Option[User]
users: List[User]
)
type Query {
user(id: ID): User
users: [User!]!
}
スキーマ定義
12. DEFINING A RESOLVER
val query = Query(
args => userService.getUser(args.id),
userService.getAllUsers
)
val api = graphQL(RootResolver(query))
リゾルバーの定義
14. TEST YOUR API
val query = "query { user(id: "xxx") { name age } }"
for {
interpreter <- api.interpreter
result <- interpreter.execute(query)
} yield result
APIをテストする
15. SERVE YOUR API
> http4s
> Akka HTTP
> Play Framework
> Finch
val route: HttpRoutes[Task] = Http4sAdapter.makeHttpService(interpreter)
APIをサーバーで動かす
16. N + 1 PROBLEM
query {
order(id: 12345) {
name
products {
name
}
}
}
17. NAIVE
for {
order <- getOrder(id)
products <- ZIO.foreachPar(order.pIds)(getProduct)
} yield Order(order.name, products)
n + 1 requests
そのままだと・・・
N+1回のリクエスト
18. OPTIMIZED
for {
order <- getOrder(id)
products <- ZQuery.foreachPar(order.pIds)(getProduct)
} yield Order(order.name, products)
2 requests
最適化すると
2回のリクエスト
19. ZQUERY
case class GetProduct(id: Int) extends Request[Throwable, Product]
val ProductDataSource =
DataSource.fromFunctionBatchedM("ProductDataSource")(
requests => dbService.getProducts(requests.map(_.id))
)
def getProduct(id: Int): ZQuery[Any, Throwable, Product] =
ZQuery.fromRequest(GetProduct(id))(ProductDataSource)
> See zio-query
ZQueryを使うと
21. BUILTIN WRAPPERS
val api = graphQL(...) @@
maxDepth(30) @@
maxFields(200) @@
timeout(10 seconds) @@
printSlowQueries(1 second)
> Apollo Tracing, Apollo Caching, Apollo Persisted
Queries, etc.
組み
Apolloのトレース、キャシュ、永
22. MORE FEATURES
> combine APIs
> annotations
> code generation tool
> schema diff
> Apollo Federation
他の機能
APIの結合、アノテーション、コード生成ツール等
23. CALIBAN CLIENT
> no boilerplate
> no more string copy-pasting
> no need for aliases, fragments, etc
Calibanクライアント
無ボイラープレート、alias や fragment もいらない
26. STEP 3: RUNNING QUERIES
val request = query.toRequest(uri)
SttpClient.send(request)
> Response is already parsed into Scala types
> Use the sttp backend of your choice (including Scala.js)
クエリの
レスポンスはScalaの型としてパース /Scala.jsを含み、
好きなsttpバックエンドを使用可能
27. CURRENT STATE
> Recently celebrated 1st birthday
> Already 520 stars on github
> Built by 45 contributors
#
現在の
開 1年 /520スター/45コントリビューター/パフォーマ
ンス改善