Hasura

加速你的應用開發

從前端到後端

202X 年 還要浪費多少時間寫 CRUD?

邊緣人再也不怕

Side Project

沒隊友 QQ

  • 從 API 到 Resources
  • 什麼是 Hasura
  • Hasura Demo

今日

Restful API

增 (Create)

查 (Read)

改 (Update)

刪 (Delete)

每個 endpoint 背後對應的是 ...

每個 endpoint 的背後是...

伺服器端的
某個資源

domain.com/customers

domain.com/customers/1/orders

像這裡是 DB 的某張表

(resources )

增 (Create)

查 (Read)

改 (Update)

刪 (Delete)

POST

GET

PUT

DELETE

SQL
語法

HTTP

請求方法

endpoint 的背後是...

Restful API

後端工程師表示...

 

CRUD 到很厭世、

懷疑人生

 

前端工程師表示...

打這支 endpoint 會回傳什麼資料啊?文件呢???

現在這個畫面我要打哪幾隻 API 才能拿到所有資料啊??

這個欄位會回傳什麼型別給我啊?

一定會是 List (array)  嗎?還是有可能是 null

我不確定耶~程式碼是不是多做點 fallback 啊?

我要怎麼樣打 API 會比較有效率?哪些可以先 cache somewhere

我現在到底有多少隻 endpoint 啊?

我想要xxx資料,要打哪隻 API 啊?

 

疑問多到

懷疑人生

 

假如我想要很多資源...

RESTful API : 需要打很多次 request

為了取得所有 resources

如何拿到某本及該作者的所有資訊?

假如我想要很多資源...

GraphQL API : 1次 request,取得所有 resources

如何拿到某本及該作者的所有資訊?

GraphQL vs REST

endpoints




domain.com/graphql




domain.com/customers
domain.com/customers/{id}/orders
domain.com/products
domain.com/articles
domain.com/device-management
domain.com/device-management/managed-devices
domain.com/device-management/managed-devices/{id}
domain.com/device-management/managed-devices/{id}/scripts
domain.com/device-management/managed-devices/{id}/scripts/{id}

GraphQL vs REST

GraphQL 怎麼取得資源?

接 1 組 datasource

接 多 組 

REST API

GraphQL 怎麼取得資源?

如何拿到某本及該作者的所有資訊?

GraphQL 怎麼取得資源?

如何拿到某本及該作者的所有資訊?

圖像化 描述、定義好 商業需求 與Resource 之前的關係

取得實際 Resource

GraphQL 怎麼取得資源?

如何拿到某本及該作者的所有資訊?

前端透過 Query (等於 REST 的 GET)取得所需的資料

Query 什麼?

前、後端 討論出的 Schema

GraphQL 怎麼取得資源?

如何拿到某本及該作者的所有資訊?

前端透過 Query (等於 REST 的 GET)取得所需的資料

Query 什麼?

前、後端 討論出的 Schema

// schema.js
const Query = `
  type Query {
    author(id: Int!): Author
    book(id: Int!): Book
  }
`;
// author.js
export const typeDef = `
  type Author {
    id: Int!
    name: String
    books: [Book]
  }
`;
// book.js
export const typeDef = `
  type Book {
    title: String
    author: Author
  }
`;

那 Schema 怎麼取得資源呢?

定義 Schema 時,同時也定義 Type了

GraphQL 怎麼取得資源?

如何拿到某本及該作者的所有資訊?

// schema.js
const Query = `
  type Query {
    author(id: Int!): Author
    book(id: Int!): Book
  }
`;
// author.js
export const typeDef = `
  type Author {
    id: Int!
    name: String
    books: [Book]
  }
`;
// book.js
export const typeDef = `
  type Book {
    title: String
    author: Author
  }
`;

那 Schema 怎麼取得資源呢?

寫 Resolver

const resolvers = {
  Query: {
    author(parent, args, context, info) {
      return authors.find(user => user.id === args.id);
    }
  }
}

const authors = [
  { id: '1', name: '金庸' },
  { id: '2', name: '村上春樹'},
  { id: '3', name: '李琴峰' }
]

const server = new ApolloServer({
  typeDefs,
  resolvers,
  dataSources: () => ({
    authorAPI: new AuthorAPI(),
    bookAPI: new BookAPI()
  })
});

server.listen().....

未處理 author 的books

db connect

api call

所以 GraphQL 是什麼?

所以 GraphQL 是什麼?

  • 把 Business Domain 建立成圖像化(Graph)模型
     
  • 好的 Schema 設計,使你能輕易描述 Business
{
  accounts {
    inbox {
      unreadEmailCount
    }
  }
}
{
  mainAccount {
    drafts(first: 20) {
      ...previewInfo
    }
  }
}

fragment previewInfo on Email {
  subject
  bodyPreviewSentence
}

所有帳號下的信箱的未讀信件的數量

主帳號前 20 篇草稿的預覽資訊

所以 GraphQL 是什麼?

GraphQL vs REST (2019)

GraphQL vs ... (2020)

後端工程師表示...

搞屁啊~ 從原本溝通 endpoint, response payload

感覺我現在好像還要多寫個 GraphQL schema

現在只不過變成改討論 schema, type

但我還不是要另外寫 resolver 來取得 resources

頂多可能格式或形狀能更符合業務需求

還有資料型別這件事能早點來出來討論

這樣我是不是寫原本的 endpoint 還比較省事?!

不過 Schema 好像就可以直接作為文件了?!

QwQ

有人能幫我開 GraphQL schema 嗎?

有人能幫我寫 GraphQL resolver 嗎?

救星出現:

Hasura

Hasura

Hasura

Hasura

Table 開好

Query, Mutation 都幫你串好了

也包含 filter, pagination, aggregation 

db constraint 也一併被考慮進去

Show Me the code

Table 開好

# 建立一張 Table book
- id
- isbn
- name
- author_id -> author.id
- book_tag id

# 建立一張 Table author
- id
- name

# 建立一張 Table tag
- id
- name

# 建立一張 Table book_tag
- id
- tag_id -> tag.id
- book_id -> book.id

# 建立一張 View
- book name
- author name
- tag name

假設我想寫一張 View

Query, Mutation 一樣沒問題

Hasura

驗證身份

可以整合 Webhook, JWT

驗證身份

可以整合 Webhook, JWT

分級授權

可以針對欄位,某個 record 的某個 column,保護

Row level Permission 

Column level Permission

Role Permission

商業邏輯

商業邏輯

使用 Hasura Cloud 好處

使用 Hasura Cloud 好處

N + 1 效能問題也順便幫你想到了

SELECT id,name FROM artists;  
# 跑 1 次

SELECT title FROM albums WHERE artist_id = <artist-id>
# n 個 artisit 跑 n 次

X

SELECT artists.name as name
FROM artists
JOIN albums
ON (artists.id = albums.artist_id)

O

Security

Performance

Reliability

Performance 的挑戰

How to do Server-side Caching?

One common concern with GraphQL, especially when comparing it to REST, are the difficulties to maintain server-side cache. With REST, it’s easy to cache the data for each endpoint, since it’s sure that the structure of the data will not change.

With GraphQL on the other hand, it’s not clear what a client will request next, so putting a caching layer right behind the API doesn’t make a lot of sense.

Server-side caching still is a challenge with GraphQL. More info about caching can be found on the GraphQL website.

Performance 的挑戰

Response Caching

Caching GraphQL queries at the server side needs a different approach compared to a typical REST API architecture. In REST, you can cache queries at the HTTP layer using GET requests and serve it in front of a CDN. Typically GraphQL queries are POST requests and caching needs to be handled differently.

Query Caching: Hasura already offers query caching in the OSS version, where the internal representation of the fully qualified GraphQL AST is cached, so that it’s plan need not be computed again. For Postgres, Hasura makes use of Prepared Statements to make query execution faster. Read more about Hasura's fast GraphQL query execution.

Data Caching: Hasura Cloud goes a step further and adds support for data caching on top of the query caching that's already available. Hasura has enough information about the data models across data sources, and the authorization rules at the application level letting users cache authenticated GraphQL API calls that works for shared data.

Cache invalidation is handled by using a TTL configuration so that state data is refreshed within a time interval. So clients can query with a @cached directive for data caching.

Learn more about the usage of @cached directive in this video - An approach to automated caching for public & private GraphQL APIs.


Hasura

By 陳Ken

Hasura

  • 539