Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go_GraphQL_in_LINE_SPOT.pdf

 Go_GraphQL_in_LINE_SPOT.pdf

Denny Tsai (LINE Taiwan)

Golang Taipei Gathering #40
https://www.meetup.com/golang-taipei-meetup/events/260166791/

53850955f15249a1a9dc49df6113e400?s=128

LINE Developers
PRO

April 23, 2019
Tweet

Transcript

  1. Go GraphQL in LINE SPOT Golang Taipei Gathering #40

  2. Hello, I'm Denny. I work at LINE .

  3. None
  4. None
  5. 2019 Q3

  6. API Gateway with Go & GraphQL for Microservices

  7. API Gateway Go GraphQL

  8. Client to Monolith

  9. Client to Microservices HTTP HTTP HTTP HTTP HTTP HTTP

  10. Client to Microservices HTTP HTTP HTTP gRPC Thrift xRPC

  11. Client to API Gateway to Microservices backend for frontend

  12. Client to API Gateway

  13. REST API

  14. https://api.github.com/search/repositories?q=language:go&sort=stars&order=desc { "items": [ { "id": 23096959, "node_id": "MDEwOlJlcG9zaXRvcnkyMzA5Njk1OQ==", "name":

    "go", "full_name": "golang/go", "owner": { "login": "golang" }, "url": "https://api.github.com/repos/golang/go", "description": "The Go programming language", "issues_url": "https://api.github.com/repos/golang/go/issues{/number}", "stargazers_count": 56341 } ] }
  15. https://api.github.com/repos/golang/go/issues [ { "url": "https://api.github.com/repos/golang/go/issues/31459", "number": 31459, "title": "cmd/link: Apple's

    symbols tool unable to read DWARF data from c-archive go.o", "user": { "login": "tmm1", "avatar_url": "https://avatars2.githubusercontent.com/u/2567?v=4", }, "state": "open" }, { "url": "https://api.github.com/repos/golang/go/issues/31458", "number": 31458, "title": "cmd/go: mod meta tag causes infinite loop in GOPROXY", "user": { "login": "marwan-at-work", "avatar_url": "https://avatars0.githubusercontent.com/u/16294261?v=4", }, "state": "open" } ]
  16. Client to API Gateway

  17. Multiple Client Types to API Gateway

  18. Consumer centric API

  19. GraphQL

  20. Query language

  21. Single endpoint

  22. Response shape defined by the client

  23. Transport agnostic

  24. { repository( owner: "golang" name: "go" ) { name issues(

    first: 2 orderBy: { field: CREATED_AT direction: DESC } ) { totalCount nodes { number title } } } } { "data": { "repository": { "name": "go", "issues": { "totalCount": 30761, "nodes": [ { "number": 31459, "title": "cmd/link: Apple's symbols tool ..." }, { "number": 31458, "title": "cmd/go: mod meta tag causes ..." } ] } } } }
  25. { repository( owner: "golang" name: "go" ) { name issues(

    first: 2 orderBy: { field: CREATED_AT direction: DESC } ) { totalCount nodes { number title } } } } { "data": { "repository": { "name": "go", "issues": { "totalCount": 30761, "nodes": [ { "number": 31459, "title": "cmd/link: Apple's symbols tool ..." }, { "number": 31458, "title": "cmd/go: mod meta tag causes ..." } ] } } } }
  26. Queries and Mutations

  27. GraphQL schema is typed

  28. query { repository( owner: String! name: String! ): Repository }

    type Repository { name: String! issues( orderBy: IssueOrder first: Int ): IssueConnection! } type IssueConnection { totalCount: Int! nodes: [Issue] } type Issue { number: Int! title: String! } { repository( owner: "golang" name: "go" ) { name issues( first: 2 orderBy: { field: CREATED_AT direction: DESC } ) { totalCount nodes { number title } } } } type IssueOrder { field: IssueOrderField! direction: OrderDirection! } enum IssueOrderField { CREATED_AT UPDATED_AT COMMENTS } enum OrderDirection { ASC DESC }
  29. mutation { createIssue( input: CreateIssueInput! ): CreateIssuePayload } type CreateIssuePayload

    { clientMutationId: String issue: Issue } input CreateIssueInput { repositoryId: ID! title: String! body: String assigneeIds: [ID!] milestoneId: ID labelIds: [ID!] projectIds: [ID!] clientMutationId: String } mutation { createIssue( input: { repositoryId: "..." title: "New issue" body: "This is a new issue" } ) { clientMutationId issue { number title } } }
  30. graphql.org

  31. Tooling

  32. GraphiQL

  33. GraphQL Playground

  34. Create a GraphQL server with Go

  35. graphql-go/graphql graph-gophers/graphql-go 99designs/gqlgen

  36. gqlgen

  37. Schema first

  38. Type safe

  39. Less boilerplate

  40. Create a schema type Query { posts: [Post] post(id: Int!):

    Post } type Post { id: Int! title: String! body: String! }
  41. Initialize with gqlgen ➜ apigateway go run github.com/99designs/gqlgen init Exec

    "go run ./server/server.go" to start GraphQL server ➜ apigateway tree . ├── generated.go ├── go.mod ├── go.sum ├── gqlgen.yml ├── models_gen.go ├── resolver.go ├── schema.graphql └── server └── server.go
  42. Resolver Interface type QueryResolver interface { Posts(ctx context.Context) ([]*Post, error)

    Post(ctx context.Context, id int) (*Post, error) }
  43. Resolvers type Resolver struct{} func (r *Resolver) Query() QueryResolver {

    return &queryResolver{r} } type queryResolver struct{ *Resolver } func (r *queryResolver) Posts(ctx context.Context) ([]*Post, error) { panic("not implemented") } func (r *queryResolver) Post(ctx context.Context, id int) (*Post, error) { panic("not implemented") }
  44. Generated models type Post struct { ID int `json:"id"` Title

    string `json:"title"` Body string `json:"body"` }
  45. Configuration schema: - schema.graphql exec: filename: generated.go model: filename: models_gen.go

    resolver: filename: resolver.go type: Resolver models: Post: model: apigateway.Post
  46. Generated server const defaultPort = "8080" func main() { port

    := os.Getenv("PORT") if port == "" { port = defaultPort } http.Handle("/", handler.Playground("GraphQL playground", "/query")) http.Handle("/query", handler.GraphQL(apigateway.NewExecutableSchema(...))) log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":"+port, nil)) }
  47. Create a GraphQL schema Initialize with gqlgen Implement resolvers Update

    GraphQL schema Generate new code with gqlgen Implement new resolvers
  48. Demo

  49. Authentication Quotas/Rate limiting Request logging ...

  50. Hello, I'm YourName. I work at LINE .

  51. Thanks!