-
Notifications
You must be signed in to change notification settings - Fork 6
/
Demo8FetchAuthorBooksRelation.scala
70 lines (55 loc) · 2.42 KB
/
Demo8FetchAuthorBooksRelation.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package demos
import model._
import sangria.execution._
import sangria.execution.deferred._
import sangria.macros.derive._
import sangria.marshalling.circe._
import sangria.schema._
import sangria.slowlog.SlowLog
import common.CustomScalars._
import common.GraphQLRoutes.simpleServer
import scala.concurrent.ExecutionContext.Implicits.global
/**
* Efficiently load author books information with Fetch API.
* This represents 1:m relationship between author and his/her books.
*/
object Demo8FetchAuthorBooksRelation extends App {
// STEP: Define GraphQL Types & Schema
val authorFetcher = Fetcher.caching(
(ctx: BookRepo with AuthorRepo, ids: Seq[String]) ⇒
ctx.authors(ids))(HasId(_.id))
implicit lazy val BookType: ObjectType[Unit, Book] =
deriveObjectType[Unit, Book](
DeprecateField("authorId", "Please use `author` field instead."),
AddFields(
Field("author", OptionType(AuthorType),
resolve = c ⇒ authorFetcher.defer(c.value.authorId))))
// NEW: define author-book relation
val booksByAuthor = Relation[Book, String]("booksByAuthor", book ⇒ Seq(book.authorId))
// NEW: define fetcher to load books by author ID in batches
val bookFetcher = Fetcher.relCaching(
(ctx: BookRepo with AuthorRepo, ids: Seq[String]) ⇒
ctx.books(ids),
(ctx: BookRepo with AuthorRepo, relIds: RelationIds[Book]) ⇒
ctx.booksByAuthors(relIds(booksByAuthor)))(HasId(_.id))
implicit lazy val AuthorType = deriveObjectType[Unit, Author](
// NEW: add `books` field & defer its loading to fetcher
AddFields(
Field("books", ListType(BookType),
resolve = c ⇒ bookFetcher.deferRelSeq(booksByAuthor, c.value.id))))
implicit val BookSortingType = deriveEnumType[BookSorting.Value]()
val QueryType = ObjectType("Query", fields[BookRepo with AuthorRepo, Unit](
Field("books", ListType(BookType),
resolve = c ⇒ c.ctx.allBooks())))
val schema = Schema(QueryType)
// STEP: Create akka-http server and expose GraphQL route
val repo = InMemoryDbRepo.createDatabase
simpleServer { (query, operationName, variables, _, tracing) ⇒
Executor.execute(schema, query, repo,
variables = variables,
operationName = operationName,
// NEW: add `bookFetcher` to a `DeferredResolver`
deferredResolver = DeferredResolver.fetchers(authorFetcher, bookFetcher),
middleware = if (tracing) SlowLog.apolloTracing :: Nil else Nil)
}
}